支付服务配置指南

本文档介绍如何配置 Vibany 项目的支付系统,支持支付宝/微信支付(国内)和 Stripe(国际)。

支持的支付方式

支付方式提供商适用地区特点
支付宝易支付 (dulupay)中国大陆用户习惯,费率低
微信支付易支付 (dulupay)中国大陆移动优先
信用卡Stripe全球国际通用
Apple PayStripe全球苹果用户首选

易支付配置(支付宝/微信)

易支付是一个聚合支付平台,支持支付宝和微信支付。

1. 注册易支付账号

访问 https://s.zhaikr.com/epay 注册商户账号。

2. 获取 API 凭证

登录易支付后台:

  1. 进入 "用户中心" → "API 信息"
  2. 记录以下信息:
    • 商户 ID (PID)
    • 平台公钥 (Public Key)
    • 商户私钥 (Private Key)

3. 配置回调地址

在易支付后台设置支付回调 URL:

https://yourdomain.com/api/public/epay/notify

重要:

  • 必须使用 HTTPS
  • 域名需已备案(中国大陆服务器)
  • 确保回调地址可以被外部访问

4. 配置环境变量

# 易支付 API 地址
PAY_API_URL=https://api.dulupay.com

# 商户 ID
PAY_PID=your_payment_id

# 平台公钥(从易支付后台获取)
PAY_PUBLIC_KEY=-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----

# 商户私钥(从易支付后台获取)
PAY_MERCHANT_PRIVATE_KEY=-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----

5. 启用/禁用支付方式

在 .env.local 中控制支付方式显示:

# 禁用微信支付
NEXT_PUBLIC_WXPAY_DISABLED=on

# 禁用支付宝
NEXT_PUBLIC_ALIPAY_DISABLED=on

# 同时禁用
NEXT_PUBLIC_WXPAY_DISABLED=on
NEXT_PUBLIC_ALIPAY_DISABLED=on

Stripe 配置(国际支付)

Stripe 支持信用卡、Apple Pay、Google Pay 等国际支付方式。

1. 注册 Stripe 账号

访问 https://stripe.com 注册账号。

2. 获取 API Keys

  1. 登录 Stripe Dashboard
  2. 进入 "Developers" → "API keys"
  3. 复制以下密钥:
    • Secret key(测试环境用 sk_test_,生产用 sk_live_)

3. 配置 Webhook

Stripe 需要配置 Webhook 来接收支付结果通知:

3.1 创建 Webhook Endpoint

  1. 在 Dashboard → Developers → Webhooks
  2. 点击 "Add endpoint"
  3. 输入 Endpoint URL:
    https://yourdomain.com/api/public/stripe/notify
    
  4. 选择要监听的事件:
    • checkout.session.completed
    • checkout.session.async_payment_succeeded
    • payment_intent.succeeded

3.2 获取 Webhook Secret

创建 Webhook 后会显示 Signing secret(格式:whsec_...),记录下来。

4. 配置环境变量

# Stripe Secret Key
# 测试环境使用 sk_test_ 开头的密钥
# 生产环境使用 sk_live_ 开头的密钥
STRIPE_SECRET_KEY=sk_test_your_stripe_secret_key

# Stripe Webhook Signing Secret
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret

5. 本地测试 Webhook

使用 Stripe CLI 在本地测试 Webhook:

# 安装 Stripe CLI
brew install stripe/stripe-cli/stripe

# 登录
stripe login

# 转发 Webhook 到本地
stripe listen --forward-to localhost:3000/api/public/stripe/notify

运行后会显示 Webhook signing secret,用于本地测试。

6. 启用/禁用 Stripe

# 禁用 Stripe 支付
NEXT_PUBLIC_STRIPE_DISABLED=on

支付流程说明

支付宝/微信支付流程

  1. 创建订单:用户在前端选择充值金额
  2. 生成支付链接:后端调用易支付 API 创建订单,返回支付二维码 URL
  3. 用户支付:用户扫描二维码完成支付
  4. 异步通知:易支付发送回调通知到 /api/public/epay/notify
  5. 更新订单:系统验证签名后更新订单状态并充值积分
  6. 页面跳转:支付完成后跳转到结果页面

Stripe 支付流程

  1. 创建 Checkout Session:后端调用 Stripe API 创建支付会话
  2. 跳转到 Stripe:前端重定向到 Stripe Checkout 页面
  3. 用户支付:用户在 Stripe 页面输入信用卡信息完成支付
  4. 返回网站:支付完成后返回 /payment/success 或 /payment/cancel
  5. Webhook 通知:Stripe 发送 checkout.session.completed 事件
  6. 更新订单:系统验证 Webhook 签名后更新订单并充值积分

订单和积分系统

订单状态

type OrderStatus = "PENDING" | "SUCCESS" | "FAILED" | "REFUND";
  • PENDING:订单已创建,等待支付
  • SUCCESS:支付成功,积分已充值
  • FAILED:支付失败或超时
  • REFUND:已退款

积分充值

支付成功后,系统会自动为用户充值积分:

// 充值积分函数
await rechargeUserPoints({
  userId: order.userId,
  points: order.amount,
  description: `支付宝充值 - 订单${order.id}`,
  metadata: { orderId: order.id, paymentMethod: 'alipay' }
});

交易记录

所有积分变动都记录在 wallets.extra.transactions 中:

interface Transaction {
  id: string;
  points: number;        // 正数为充值,负数为消费
  type: 'credit' | 'debit';
  description: string;
  createdAt: string;
}

故障排除

支付回调不触发

检查清单:

  • 回调 URL 配置正确且使用 HTTPS
  • 域名可访问,防火墙未拦截
  • 服务器日志中能看到回调请求
  • 签名验证通过

调试方法:

# 查看服务器日志
tail -f /var/log/nginx/access.log
tail -f ~/.pm2/logs/image-render-out.log

Stripe Webhook 验证失败

常见原因:

  1. Webhook Secret 配置错误
  2. 请求体被修改(如 Nginx 重写)
  3. 使用了错误的签名密钥

解决方案:

  1. 重新复制 Webhook Secret
  2. 确保 Nginx 不修改请求体
  3. 使用 stripe listen 本地测试

订单状态不同步

手动修复:

在 Admin 后台可以手动查看和修复订单:

  1. 进入 /admin/orders
  2. 找到问题订单
  3. 查看支付平台状态
  4. 手动同步或退款

费用说明

易支付费用

支付方式费率结算周期
支付宝约 0.6%T+1
微信支付约 0.6%T+1

Stripe 费用

地区费率结算周期
中国大陆约 3.7% + ¥1.807 天
香港3.4% + HK$2.357 天
美国2.9% + $0.302 天
国际卡+1%-

安全注意事项

1. 密钥保护

  • 不要将支付私钥提交到 Git
  • 生产环境使用 Live 密钥
  • 定期轮换密钥

2. 签名验证

所有支付回调都必须验证签名:

// 易支付签名验证
const isValid = verifyRSASignature(params);
if (!isValid) {
  return new Response('Invalid signature', { status: 400 });
}

// Stripe 签名验证
const event = stripe.webhooks.constructEvent(
  body,
  signature,
  process.env.STRIPE_WEBHOOK_SECRET!
);

3. 幂等性处理

防止重复处理同一笔支付:

// 检查订单是否已处理
if (order.status === 'SUCCESS') {
  return new Response('Order already processed', { status: 200 });
}

测试支付

易支付测试

使用小额金额(如 0.01 元)进行测试。

Stripe 测试

使用 Stripe 提供的测试卡号:

卡号场景
4242 4242 4242 4242支付成功
4000 0000 0000 0002卡片被拒绝
4000 0000 0000 9995余额不足

更多测试卡号:Stripe Testing Documentation

相关文档

© copyright Justin 2026. All rights reserved.