Files
lunar-mini/server/README.md
T
goukiandDevin <158243242+devin-ai-integration[bot]@users.noreply.github.com> c161d42b06
Build and Publish Server / build (push) Successful in 2m6s
feat(server): 接入 QQ 邮箱 SMTP 发送登录验证码
- 支持 465 隐式 TLS 与 587 STARTTLS,SMTP 配置优先、Postmark 备用
- 发件人支持 QQ 域名邮箱地址(z@kepo.net),凭证仅走环境变量
- HTTP 测试覆盖发送成功与认证失败;真实发信测试需显式开启 RUN_QQ_SMTP_LIVE_TEST

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-27 23:24:46 +00:00

114 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 知命 / 祈福后端服务
基于 Go、Gin、GORM 的统一后端,提供微信小程序能力、商业版八字报告、邮箱登录、支付、订单权益和管理后台。
## 功能模块
- 微信小程序登录与生辰档案。
- QQ 邮箱 SMTP 验证码登录,支持 465 隐式 TLS 或 587 STARTTLS;Postmark 可选备用。
- Stripe `4.99 USD` 报告支付。
- Binance Pay `5 USDT` 报告支付。
- 签名 Webhook、幂等事件、退款权益撤销。
- 随机报告恢复码与不可变报告快照。
- 用户订单与报告权益查询。
- 数据库驱动的 PC 商业版订单列表和收入统计。
- PC 商业版后台只查询 `type=bazi_report`,与小程序许愿等旧业务订单逻辑隔离。
- 许愿树与百科数据。
## 快速开始
```bash
cp .env.example .env.local
go mod download
go run ./cmd
```
默认地址:`http://localhost:8080`。
生产部署可使用 systemd 直接运行二进制,商业前端静态文件放在服务目录的 `frontend/`,根路径 `/` 为商业站点,`/admin/orders` 为管理后台,`/api/*` 为后端接口。这样无需 Docker 或 Nginx,适合小内存服务器;Cloudflare 可在边缘终结 HTTPS 并回源到 80 端口。
## 测试
项目包含 HTTP API 测试,覆盖未认证拦截、Webhook 拒绝、Stripe 模拟下单、签名回调、权益发放、恢复码和快照读取。
```bash
go test ./...
```
本地测试配置使用 `server/.env.test`。如果文件包含 SMTP 凭证,必须保持 Git 忽略并限制文件权限,绝不提交到仓库。真实发信测试需显式运行 `RUN_QQ_SMTP_LIVE_TEST=1 SMTP_TEST_TO=收件地址 go test ./internal/handler -run '^TestRequestEmailLoginCodeLiveQQSMTP$' -count=1`;该命令会实际发送邮件。
## 商业支付 API
### 邮箱登录
- `POST /api/auth/email/request`
- `POST /api/auth/email/verify`
### 支付与报告
- `POST /api/commerce/checkout` — 创建 Stripe 或 Binance Pay 订单。
- `POST /api/commerce/webhooks/stripe` — Stripe 签名通知。
- `POST /api/commerce/webhooks/binance-pay` — Binance Pay 签名通知。
- `GET /api/commerce/orders/:orderNo` — 查询本人订单。
- `GET /api/commerce/reports/:reportId/access` — 查询报告权益。
- `GET /api/commerce/reports` — 本人已购报告。
- `GET /api/commerce/reports/recover/:accessCode` — 使用恢复码读取购买时快照。
除 Webhook 外,商业接口都要求 `Authorization: Bearer <JWT>`。
## 管理后台
- `/admin/orders` — 真实订单列表。
- `/admin/api/orders` — 按渠道、状态、订单号、邮箱、报告号查询。
- `/admin/api/orders/stats` — 订单和收入统计。
后台使用 `ADMIN_PASSWORD` 登录并写入 HttpOnly Cookie。
## 支付安全
- 金额只从 `report_products` 读取。
- Stripe 使用 Checkout Session 和 `Idempotency-Key`。
- Stripe Webhook 校验 HMAC 签名与 5 分钟时间窗口。
- Binance Pay 下单使用 HMAC-SHA512。
- Binance Pay Webhook 使用商户证书 RSA 公钥验签。
- Webhook 同时校验服务商订单号、金额与币种。
- `payment_events` 唯一索引保证重复回调不会重复发放权益。
- 支付、事件、恢复码和权益在数据库事务中完成。
- 退款后报告权益自动撤销。
## 数据库
新安装由 GORM AutoMigrate 创建表。已有 MySQL 数据库先备份,再单独执行:
```bash
mysql < migrations/002_commerce.sql
```
不要执行数据库 fresh 或 refresh。
## 环境变量
完整模板见 `.env.example`。邮箱登录配置 QQ SMTP:
- `SMTP_HOST=smtp.qq.com`
- `SMTP_PORT=465`(或 587)
- `SMTP_USERNAME`:完整 QQ 邮箱地址
- `SMTP_PASSWORD`:QQ 邮箱生成的 SMTP 授权码,不是邮箱登录密码
- `SMTP_FROM_EMAIL`:发件地址。生产使用 `z@kepo.net`(`kepo.net` 已通过 QQ 域名邮箱绑定,MX 为 `mxdomain.qq.com`);需在 DNS 添加 SPF 记录 `v=spf1 include:spf.mail.qq.com ~all`,否则 Gmail 等可能拒收或判为垃圾邮件
- `SMTP_TLS_MODE=implicit`(465)或 `starttls`(587)
- `SMTP_TLS_CA_FILE`:可选的自定义 CA 文件路径
QQ 邮箱需先在账户设置中开启 SMTP 服务。SMTP 配置有效时优先使用 SMTP;未配置时才尝试 Postmark。生产环境还需要:
- `JWT_SECRET`
- `ADMIN_PASSWORD`
- `PUBLIC_BASE_URL`
- `WEB_APP_URL`
- `STRIPE_SECRET_KEY`
- `STRIPE_WEBHOOK_SECRET`
- `BINANCE_PAY_API_KEY`
- `BINANCE_PAY_SECRET_KEY`
- `BINANCE_PAY_WEBHOOK_PUBLIC_KEY`
所有支付与邮件密钥必须通过部署环境注入,禁止提交到 Git。