9.3 KiB
支付宝付费开通会员 — 部署指南
本文档涵盖支付宝电脑网站支付功能的完整部署流程。用户注册后通过支付宝付费自动激活会员,有效期 1 年。
前置条件
- 支付宝企业/个体商户账号
- 已在 支付宝开放平台 创建应用并获取 APPID
- 应用已开通 「电脑网站支付」 产品权限(
alipay.trade.page.pay接口) - 服务器域名已配置 HTTPS(支付宝回调要求公网可达)
第一部分:支付宝开放平台配置
1. 创建应用
登录 https://open.alipay.com → 控制台 → 创建应用(或使用已有应用)。
2. 开通「电脑网站支付」产品
进入应用详情 → 产品绑定/产品管理 → 添加 「电脑网站支付」 → 提交审核。
注意:未开通此产品会导致
ACQ.ACCESS_FORBIDDEN错误。
3. 生成密钥对
进入应用详情 → 开发设置 → 接口加签方式 → 选择 RSA2(SHA256):
- 使用支付宝官方密钥工具生成 RSA2048 密钥对
- 将 应用公钥 上传到开放平台
- 上传后平台会显示 支付宝公钥(
alipayPublicKey_RSA2)
最终你会得到两样东西:
- 应用私钥:你本地保存,代码用来签名请求
- 支付宝公钥:平台返回给你,代码用来验证回调签名
应用公钥只是上传用的中间产物,代码中不需要。
第二部分:服务器配置
1. 放置密钥文件
将密钥保存为标准 PEM 格式,放到 backend/keys/ 目录:
mkdir -p /home/rongye/ProgramFiles/ViGent2/backend/keys
backend/keys/app_private_key.pem(应用私钥):
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASC...(你的私钥内容)
...
-----END PRIVATE KEY-----
backend/keys/alipay_public_key.pem(支付宝公钥):
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...(支付宝公钥内容)
...
-----END PUBLIC KEY-----
PEM 格式要求
支付宝密钥工具导出的是一行纯文本,需要转换为标准 PEM 格式:
- 必须有头尾标记(
-----BEGIN/END ...-----) - 密钥内容每 64 字符换行
- 私钥头标记为
-----BEGIN PRIVATE KEY-----(PKCS#8 格式) - 公钥头标记为
-----BEGIN PUBLIC KEY-----
如果你拿到的是一行裸密钥,用以下命令转换:
# 私钥格式化(假设裸密钥在 raw_private.txt 中)
echo "-----BEGIN PRIVATE KEY-----" > app_private_key.pem
cat raw_private.txt | fold -w 64 >> app_private_key.pem
echo "-----END PRIVATE KEY-----" >> app_private_key.pem
# 公钥格式化
echo "-----BEGIN PUBLIC KEY-----" > alipay_public_key.pem
cat raw_public.txt | fold -w 64 >> alipay_public_key.pem
echo "-----END PUBLIC KEY-----" >> alipay_public_key.pem
backend/keys/目录已加入.gitignore,不会被提交到仓库。
2. 配置环境变量
在 backend/.env 中添加:
# =============== 支付宝配置 ===============
ALIPAY_APP_ID=你的应用APPID
ALIPAY_PRIVATE_KEY_PATH=/home/rongye/ProgramFiles/ViGent2/backend/keys/app_private_key.pem
ALIPAY_PUBLIC_KEY_PATH=/home/rongye/ProgramFiles/ViGent2/backend/keys/alipay_public_key.pem
ALIPAY_NOTIFY_URL=https://vigent.hbyrkj.top/api/payment/notify
ALIPAY_RETURN_URL=https://vigent.hbyrkj.top/pay
| 变量 | 说明 |
|---|---|
ALIPAY_APP_ID |
支付宝开放平台应用 APPID |
ALIPAY_PRIVATE_KEY_PATH |
应用私钥 PEM 文件绝对路径 |
ALIPAY_PUBLIC_KEY_PATH |
支付宝公钥 PEM 文件绝对路径 |
ALIPAY_NOTIFY_URL |
异步回调地址(服务器间通信),必须公网 HTTPS 可达 |
ALIPAY_RETURN_URL |
同步跳转地址(用户支付完成后浏览器跳转回的页面) |
config.py 中还有几个可调参数(已有默认值,一般不需要加到 .env):
| 变量 | 默认值 | 说明 |
|---|---|---|
ALIPAY_SANDBOX |
false |
是否使用沙箱环境 |
PAYMENT_AMOUNT |
999.00 |
会员价格(元) |
PAYMENT_EXPIRE_DAYS |
365 |
会员有效天数 |
3. 创建数据库表
通过 Docker 在本地 Supabase 中执行:
docker exec -i supabase-db psql -U postgres -c "
CREATE TABLE IF NOT EXISTS orders (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID REFERENCES users(id) ON DELETE CASCADE,
out_trade_no TEXT UNIQUE NOT NULL,
amount DECIMAL(10, 2) NOT NULL DEFAULT 999.00,
status TEXT DEFAULT 'pending' CHECK (status IN ('pending', 'paid', 'failed')),
trade_no TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
paid_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX IF NOT EXISTS idx_orders_user_id ON orders(user_id);
CREATE INDEX IF NOT EXISTS idx_orders_out_trade_no ON orders(out_trade_no);
"
4. 安装依赖
# 后端(在 venv 中)
cd /home/rongye/ProgramFiles/ViGent2/backend
venv/bin/pip install python-alipay-sdk
前端无额外依赖需要安装。
5. Nginx 配置
确保 Nginx 将 /api/payment/notify 代理到后端。如果现有配置已覆盖 /api/ 前缀,则无需额外修改:
location /api/ {
proxy_pass http://localhost:8006;
# ... 现有配置
}
6. 重启服务
# 构建前端
cd /home/rongye/ProgramFiles/ViGent2/frontend
npx next build
# 重启
pm2 restart vigent2-backend
pm2 restart vigent2-frontend
第三部分:正式上线
测试通过后,将 backend/app/core/config.py 中的测试金额改为正式价格:
PAYMENT_AMOUNT: float = 999.00 # 正式价格
或在 backend/.env 中添加覆盖:
PAYMENT_AMOUNT=999.00
然后重启后端:
pm2 restart vigent2-backend
支付流程说明
用户注册 → 登录(密码正确但 is_active=false)
→ 后端返回 403 + payment_token
→ 前端跳转 /pay 页面
→ POST /api/payment/create-order → 返回支付宝收银台 URL
→ 前端重定向到支付宝收银台页面(支持扫码、账号登录、余额等多种支付方式)
→ 用户完成支付
→ 支付宝异步回调 POST /api/payment/notify
→ 后端验签 → 更新订单 → 激活用户(is_active=true, expires_at=+365天)
→ 支付宝同步跳转回 /pay?out_trade_no=xxx
→ 前端轮询 GET /api/payment/status/{out_trade_no}
→ 轮询到 paid → 提示成功 → 跳转登录页
→ 用户重新登录 → 成功进入系统
电脑网站支付 vs 当面付:电脑网站支付(alipay.trade.page.pay)会跳转到支付宝官方收银台页面,用户可以选择扫码、支付宝账号登录、余额等多种方式支付,体验更好。当面付(alipay.trade.precreate)仅生成一个二维码,只能扫码支付。
会员到期续费同流程:登录时检测到过期 → 返回 PAYMENT_REQUIRED → 跳转 /pay。
管理员手动激活功能不受影响,两种方式并存。
涉及文件
| 文件 | 变更类型 | 说明 |
|---|---|---|
backend/requirements.txt |
修改 | 添加 python-alipay-sdk |
backend/database/schema.sql |
修改 | 新增 orders 表 |
backend/app/core/config.py |
修改 | 支付宝配置项 |
backend/app/core/security.py |
修改 | payment_token 函数 |
backend/app/core/deps.py |
修改 | is_active 安全兜底 |
backend/app/repositories/orders.py |
新建 | orders 数据层 |
backend/app/modules/payment/__init__.py |
新建 | 模块初始化 |
backend/app/modules/payment/schemas.py |
新建 | 请求/响应模型 |
backend/app/modules/payment/service.py |
新建 | 支付业务逻辑(电脑网站支付) |
backend/app/modules/payment/router.py |
新建 | 3 个 API 端点 |
backend/app/modules/auth/router.py |
修改 | 登录返回 PAYMENT_REQUIRED |
backend/app/main.py |
修改 | 注册 payment_router |
backend/.env |
修改 | 支付宝环境变量 |
backend/keys/ |
新建 | PEM 密钥文件 |
frontend/src/shared/lib/auth.ts |
修改 | login() 处理 paymentToken |
frontend/src/shared/api/axios.ts |
修改 | PUBLIC_PATHS 加 /pay |
frontend/src/app/login/page.tsx |
修改 | paymentToken 跳转 |
frontend/src/app/register/page.tsx |
修改 | 注册成功提示文案 |
frontend/src/app/pay/page.tsx |
新建 | 付费页面(重定向到支付宝收银台) |
常见问题
RSA key format is not supported
密钥文件缺少 PEM 头尾标记或未按 64 字符换行。参考「PEM 格式要求」重新格式化。
ACQ.ACCESS_FORBIDDEN
应用未开通「电脑网站支付」产品。在支付宝开放平台 → 应用详情 → 产品管理中添加并开通。
支付宝回调不到
- 检查
ALIPAY_NOTIFY_URL是否公网 HTTPS 可达 - 检查 Nginx 是否将
/api/payment/notify代理到后端 - 支付宝回调超时(15s 未响应)会重试,共重试 8 次,持续 24 小时
支付完成后页面未跳转回来
检查 ALIPAY_RETURN_URL 配置是否正确,必须是前端 /pay 页面的完整 URL(如 https://vigent.hbyrkj.top/pay)。支付宝会在用户支付完成后将浏览器重定向到此地址,并附带 out_trade_no 等参数。
前端显示"网络错误"而非具体错误
API 函数缺少 try/catch 捕获 axios 异常。已在 auth.ts 的 register() 和 login() 中修复。