diff --git a/AGENTS.md b/AGENTS.md index 68bb697..6a91b83 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,7 +10,7 @@ | 技术 | 版本 | 说明 | |------|------|------| -| Rust | edition 2021 | 主力语言 | +| Rust | edition 2024 | 主力语言(Rust 1.85+ 稳定) | | actix-web | 4.11 | Web 框架 | | sqlx | 0.8.6 | PostgreSQL 连接 | | serde | 1.0 | 序列化 | @@ -60,6 +60,8 @@ static/ # 静态文件 │ │ └── ... │ └── katex/ # KaTeX 数学公式 deploy.sh # 部署脚本 +set-paid-user.sh # 设置用户付费状态 +expire-paid-user.sh # 使用户付费时间过期 .env.example # 环境变量模板 ``` @@ -154,7 +156,6 @@ APP_WECHAT_APPID=wx... [package] name = "rust-backend" version = "0.3.0" # 唯一版本定义 -edition = "2024" ``` **不再使用 `app_version` 字段**(已移除)。 @@ -220,8 +221,8 @@ created_at TIMESTAMPTZ(创建时间) id SERIAL PRIMARY KEY order_no VARCHAR UNIQUE(订单号,格式:ASD{timestamp}{random}) user_id INTEGER(外键,关联 users 表) -package_type VARCHAR(套餐类型:monthly/quarterly/annual/permanent) -amount DECIMAL(10,2)(金额,单位:元) +package_type VARCHAR(套餐类型:monthly/yearly/permanent) +amount INTEGER(金额,单位:分) status VARCHAR(订单状态:pending/paid/cancelled/expired) paid_at TIMESTAMPTZ(支付时间,可空) created_at TIMESTAMPTZ(创建时间) @@ -289,8 +290,9 @@ created_at TIMESTAMPTZ(创建时间) | 接口 | 说明 | |------|------| -| `POST /api/web-login/code` | 小程序用微信 code 换取 display_code | -| `POST /api/web-login/confirm` | 小程序确认登录(需 JWT + code) | +| `POST /api/web-login/auto-confirm` | 小程序一键确认:微信 code → openid → 创建用户 → JWT → 返回 payment_url | +| `POST /api/web-login/code` | 小程序用微信 code 换取 display_code(旧方案) | +| `POST /api/web-login/confirm` | 小程序确认登录(需 JWT + code,旧方案) | | `GET /payment/generate-code` | 网页端生成登录码(已废弃,不建议使用) | | `GET /payment/login-status` | 网页端轮询登录状态 | @@ -305,6 +307,8 @@ created_at TIMESTAMPTZ(创建时间) | `POST /payment/notify` | 支付宝异步回调通知(需 RSA 签名验证,无认证) | | `GET /payment/success` | 支付成功页(需 order_no) | | `POST /api/payment/mock-confirm` | 模拟支付确认(沙箱测试用) | +| `POST /api/payment/sync-order` | 根据订单号强制同步会员状态(幂等) | +| `GET /api/payment/orders` | 获取当前用户的订单记录 | ### 支付宝配置(可选) @@ -451,22 +455,21 @@ ORDER BY "desc" 小程序内无法直接接入支付宝支付,采用外部浏览器中转方案: ``` -小程序(升级页) → outter页面 → 外部浏览器 → /payment?code=xxx → 支付宝 +小程序(mine/升级页) → outter页面 → 外部浏览器 → /payment → 支付宝 ``` -1. 用户在小程序升级页点击「输入登录码」 -2. 小程序获取微信 code,换取 display_code -3. 小程序自动调用 `POST /api/web-login/confirm` 确认登录(无需用户操作) -4. 小程序跳转 `outter` 页面,URL 指向 `/payment?code=xxx` -5. outter 页面提示用户在外部浏览器打开 -6. 用户在手机浏览器打开 `/payment?code=xxx` -7. 网页轮询 `/payment/login-status?code=xxx`,检测到已确认后自动登录 -8. 显示套餐选择页 -9. 用户选择套餐,点击「去支付」→ 跳转到 `/payment/page?package=xxx&jwt=xxx` -10. 后端调用 `alipay.trade.page.pay` API,返回支付跳转 -11. 支付宝沙箱/正式环境展示支付页面 -12. 支付完成后,支付宝异步通知 `/payment/notify` -13. 跳转成功页 `/payment/success?order_no=xxx` +1. 用户在小程序 mine 页面点击升级入口(未付费用户) +2. 小程序调用 `POST /api/web-login/auto-confirm`(微信 code → openid → 创建用户 → JWT → payment_url) +3. 小程序跳转 `outter` 页面,URL 指向 `/payment?jwt=xxx` +4. outter 页面提示用户在外部浏览器打开 +5. 用户在手机浏览器打开 `/payment?jwt=xxx` +6. JWT 在 URL 参数中,网页自动通过 JWT 登录,获取用户信息和付费状态 +7. 未付费用户显示套餐选择页(包月/包年),已付费用户显示会员信息 +8. 用户选择套餐,点击「去支付」→ 跳转到 `/payment/page?package=xxx&jwt=xxx` +9. 后端生成订单,渲染支付宝支付表单(表单自动提交到沙箱/正式环境) +10. 支付宝沙箱/正式环境展示支付页面 +11. 支付完成后,支付宝异步通知 `/payment/notify` +12. 跳转成功页 `/payment/success?order_no=xxx`(同步确认订单,幂等) ### 登录码相关接口 @@ -509,14 +512,6 @@ Mock 登录支持 `user_id` 参数指定已有用户,或自动创建新用户 **启用真实支付**: 在 `.env` 中配置 `ALIPAY_APP_ID`、`ALIPAY_PRIVATE_KEY`、`ALIPAY_ALIPAY_PUBLIC_KEY`、`ALIPAY_GATEWAY`,重启服务后自动禁用 Mock 模式。 -### 支付模式 - -| 模式 | 来源 | 处理方式 | -|------|------|---------| -| 微信支付 | `payment_orders` | 收到微信回调后确认 | -| 邀请码 | `invitation_codes` | 核销后直接激活 | -| 管理员开通 | 直接 UPDATE | 后台手动设置 | - ### 累积计算逻辑 用户多次购买时,有效期会累加而非覆盖: @@ -543,7 +538,7 @@ let new_expires = base_time + days(pkg_days); | 环境 | 域名 | 端口 | 远程目录 | |------|------|------|---------| -| 测试 | xmclassmate.top/dev | 8080 | /root/rust/rust_backend_dev | +| 测试 | dev.xmclassmate.top | 8080 | /root/rust/rust_backend_dev | | 生产 | xmclassmate.top | 4433 | /root/rust/rust_backend | ### systemd 服务