文档 13 / 28

支付中台接入方案

PayNow · Stripe · Apple IAP · Google Play · 对账 · 风控

册别:第三册 · 技术与架构 版本:V1.0 日期:2026-08-15 状态:草稿待评审

一、支付架构总览

核心原则:自有支付底座(金币体系) + 多渠道接入。金币是内部唯一价值载体,外部支付通道只负责"钱→金币"的兑换。

1.1 支付架构图

[用户点击充值] → [Payment Service 选择通道] → [PayNow/Stripe/Apple/Google]

[外部支付完成] → [Webhook/回调] → [Payment Service 验证] → [发放金币] → [用户余额更新]

[对账系统 T+1] → [差异告警] → [人工处理]

1.2 通道对比

通道费率到账适用场景Phase
PayNow0.5%/笔实时新加坡用户首选P1
Stripe (卡)2.9%+$0.5T+2国际卡/非新加坡P1
Apple IAP30% 佣金T+30iOS 充值/订阅P1
Google Play30% 佣金T+15Android 充值/订阅P1
GrabPay1.8%/笔实时补充渠道P1.5
Touch'n Go1.5%/笔实时马来西亚P2
MoMo2.5%/笔实时越南P2
DANA/OVO2%/笔实时印尼P2
UPI1.2%/笔实时印度P3
stc pay/Mada2%/笔实时沙特/阿联酋P3

1.3 金币汇率体系

货币汇率说明
S$ (新加坡)1 S$ = 100 金币基准货币
US$ (美元)1 US$ = 135 金币Stripe 默认
RM (马来西亚)1 RM = 33 金币P2 启用
₫ (越南盾)1000 ₫ = 5 金币P2 启用
Rp (印尼盾)1000 Rp = 4 金币P2 启用
汇率每周同步一次(周一 00:00 SGT),由财务团队维护。用户充值时刻的汇率锁定,不随波动变化。

二、PayNow 接入(新加坡核心通道)

2.1 技术对接

项目规格
对接方式DBS API(直连) + XanPool(聚合备用)
协议REST API + JSON + SHA-256 签名
认证Client ID + Secret(每请求签名)
支付流程服务端创建订单 → 返回 QR → 用户扫码 → DBS 回调
QR 标准EMV QR(PayNow 标准)
限额默认 S$200/笔 → 可申请提高到 S$1000
退款不支持原路退 → 退到 Vocalink 金币余额

2.2 支付流程

// 1. 前端请求创建订单 POST /payment/charge { "package_id": "pkg_1200", "channel": "paynow" } // 2. 后端 → DBS API:创建 PayNow 订单 POST https://api.dbs.com/sg/paynow/v1/orders Headers: X-DBS-Client-Id, X-DBS-Signature Body: { "amount": 9.99, "currency": "SGD", "description": "Vocalink 1200 coins", "callback_url": "https://api.vocalink.sg/v1/payment/webhook/dbs", "reference_id": "ord_xxx" } // 3. DBS 返回 QR 数据 Response: { "order_id": "dbs_ord_123", "qr_data": "00020101021126490009SG.PAYNOW01...", "qr_image_url": "https://...", "expires_at": "2026-08-15T10:15:00Z" } // 4. 用户扫码支付 → DBS 回调 POST /payment/webhook/dbs { "order_id": "dbs_ord_123", "status": "completed", "amount": 9.99 } // 5. 后端验证签名 → 发放金币 → WebSocket 通知客户端

2.3 错误处理

错误码含义处理
6001余额不足提示"银行余额不足,换卡或换通道"
6002订单超时QR 过期 → 引导重新发起
6003签名验证失败服务器错误 → 重试 3 次
6004DBS 服务不可用降级到 Stripe
6005重复回调幂等处理(order_id 唯一)

三、Stripe 接入(国际卡)

3.1 技术对接

项目规格
SDKStripe SDK (iOS/Android/Web) + Stripe Java SDK (后端)
模式PaymentIntents API(SCA 合规)
3DS强制启用(新加坡 MAS 要求)
Webhookpayment_intent.succeeded / failed / canceled
争议Stripe Radar(AI 风控)+ 人工审核
结算T+2 到银行账户(SGD 账户)

3.2 支付流程

// 1. 后端创建 PaymentIntent StripePaymentIntent intent = stripe.paymentIntents.create( amount = 999, // 分 currency = "sgd", metadata = mapOf( "order_id" to "ord_xxx", "user_id" to "usr_xxx", "coins" to "1400" ), paymentMethodTypes = listOf("card"), description = "Vocalink 1200+200 bonus coins" ) // 2. 返回 client_secret 给前端 Response: { "client_secret": "pi_xxx_secret_yyy", "order_id": "ord_xxx" } // 3. 前端 Stripe SDK 确认支付 stripe.confirmCardPayment(clientSecret, { paymentMethod: cardElement }) // 4. Stripe Webhook → 后端 POST /payment/webhook/stripe { "type": "payment_intent.succeeded", "data": { "object": { "id": "pi_xxx", "metadata": {...} } } } // 5. 验证 + 幂等 + 发放金币

3.3 退款处理

场景方式到账
用户申请退款原路退(Stripe refund API)5-10 工作日
重复扣款原路退 + 道歉补偿即时
争议/Chargeback提交证据 → Stripe 裁决60-75 天
无法原路退退到 Vocalink 金币余额即时

四、Apple In-App Purchase

4.1 产品配置

Product ID类型价格对应内容
sg.vocalink.coins.500Consumable$0.99500 金币
sg.vocalink.coins.1200Consumable$2.991200+200 金币
sg.vocalink.coins.3000Consumable$5.993000+600 金币
sg.vocalink.coins.6000Consumable$9.996000+1500 金币
sg.vocalink.vip.monthAuto-Renewable$9.99/月VIP 月订阅
sg.vocalink.vip.yearAuto-Renewable$79.99/年VIP 年订阅

4.2 验证流程

// 1. iOS 客户端完成购买 → 获取 receipt let receiptData = try! Data(contentsOf: Bundle.main.appStoreReceiptURL!) let receiptString = receiptData.base64EncodedString() // 2. 客户端发送 receipt 到后端验证 POST /payment/subscription { "plan_id": "vip_month", "channel": "apple_iap", "receipt_data": receiptString } // 3. 后端 → Apple VerifyReceipt API POST https://buy.itunes.apple.com/verifyReceipt { "receipt-data": receiptString, "password": "shared_secret" } // 4. Apple 返回验证结果 { "status": 0, "receipt": {...}, "latest_receipt_info": [{ "product_id": "sg.vocalink.vip.month", "expires_date_ms": "1718000000000" }] } // 5. 后端验证 + 发放 VIP + 记录原始交易 ID(用于续订)

4.3 订阅续订处理

事件Apple 通知后端动作
首次购买DID_CHANGE_RENEWAL_STATUS发放 VIP + 记录 original_transaction_id
续订成功DID_RENEW延长 VIP 有效期
续订失败FAILED_TO_RENEW标记 grace_period → 3 天宽限
用户取消CANCEL到期日停止 VIP
退款REFUND撤回 VIP + 扣回金币
恢复购买RESTORE重新激活 VIP

⚠️ Apple 30% 佣金影响:

Apple IAP 抽成 30%,意味着 S$9.99 套餐实际到手 S$6.99。因此:

  • Web 端充值(Stripe/PayNow)利润率比 IAP 高 ~20%
  • 引导用户"前往网页充值更划算"(但注意 Apple 审核规则 3.1.1)
  • Phase 2 起开发 Web 充值引导(合规方式)

五、Google Play Billing

5.1 产品配置

Product ID类型价格对应内容
coins_500ConsumableS$0.99500 金币
coins_1200ConsumableS$2.991200+200 金币
coins_3000ConsumableS$5.993000+600 金币
coins_6000ConsumableS$9.996000+1500 金币
vip_monthSUBSCRIPTIONS$9.99/月VIP 月订阅
vip_yearSUBSCRIPTIONS$79.99/年VIP 年订阅

5.2 验证流程

// 1. Android 客户端完成购买 → 获取 purchaseToken Purchase purchase = ...; // from BillingClient String purchaseToken = purchase.getPurchaseToken(); // 2. 发送到后端验证 POST /payment/subscription { "plan_id": "vip_month", "channel": "google_play", "purchase_token": "..." } // 3. 后端 → Google Play Developer API 验证 GET https://androidpublisher.googleapis.com/androidpublisher/v3/applications/sg.vocalink/purchases/subscriptions/vip_month/tokens/{token} Headers: Authorization: Bearer {service_account_jwt} // 4. Google 返回 { "kind": "androidpublisher#subscriptionPurchase", "paymentState": 1, "expiryTimeMillis": "1718000000000", "autoRenewing": true } // 5. 后端验证 + 发放 VIP

5.3 Google vs Apple 差异

维度AppleGoogle
佣金30%(小开发者 15%)30%(前 100 万 15%)
验证方式receipt + shared secretservice account JWT
退款用户申请 → Apple 裁决用户申请 → Google 裁决
测试Sandbox Apple IDLicense Testers
宽限期3 天 grace7 天 grace
取消设置 → 订阅Play Store → 订阅

六、对账系统

6.1 对账流程

[T+1 00:30] → [拉取各通道结算文件] → [DBS Statement / Stripe Payout / Apple Financial / Google](@)

[与内部 payments 表比对] → [匹配:标记 reconciled] → [差异:生成告警]

[差异分类] → [金额差异 → 财务调查] / [丢失交易 → 补发/追回] / [重复 → 退款]

6.2 对账规则

通道对账文件频率容差
PayNow (DBS)DBS Merchant Statement (CSV)每日S$0.01
StripeStripe Payout Report (CSV/API)每笔 payout$0.01
AppleApple Financial Report (PDF→CSV)每月$0.10
GoogleGoogle Play Payout Report每月$0.10

6.3 差异处理

差异类型原因处理
金额少 1-2%通道费率四舍五入自动调整(容差内)
交易丢失Webhook 未送达查询通道 API → 补发金币
重复发放Webhook 重复推送幂等拦截(已处理)
金额差异大汇率波动/手续费变更财务人工调查
退款未同步通道退款延迟标记 pending → 7 天复查

七、风控系统

7.1 风控规则

规则触发条件动作
高频充值同一用户 1 小时内 > 5 笔限流 + 人工审核
大额充值单笔 > S$100加强验证(3DS/短信)
异地充值IP 国家 ≠ 注册国家邮件确认 + 限流
新账号大额注册 < 24h + 充值 > S$50延迟到账(24h 观察期)
退款率异常用户退款率 > 30%标记高风险 + 限制
ChargebackStripe 收到争议冻结账号 + 收集证据
金币异常消耗1 小时内消耗 > 5000 金币临时冻结 + 验证

7.2 风控架构

# 风控引擎(Payment Service 内) class RiskEngine: def evaluate(self, payment_request): risk_score = 0 user = get_user(payment_request.user_id) # 规则 1:高频 if self._count_recent_payments(user.id, hours=1) > 5: risk_score += 30 # 规则 2:大额 if payment_request.amount_sgd > 100: risk_score += 20 # 规则 3:异地 if payment_request.ip_country != user.registered_country: risk_score += 25 # 规则 4:新账号 if (now() - user.created_at) < 24h and payment_request.amount_sgd > 50: risk_score += 35 # 决策 if risk_score >= 70: return "block", "High risk score" elif risk_score >= 40: return "review", "Manual review needed" else: return "allow", "Low risk"

7.3 PCI-DSS 合规

要求实现
不存储卡号Stripe 代持(不接触原始卡数据)
加密传输TLS 1.2+ 全链路
访问日志所有支付操作审计日志(不可篡改)
定期扫描季度漏洞扫描 + 年度渗透测试
员工培训半年一次 PCI 意识培训
网络隔离支付服务独立 VPC + 最小权限

八、退款与争议处理

8.1 退款政策

场景退款方式时限审批
未消费金币原路退(Stripe/PayNow)7 个工作日自动(< S$50)
已消费金币退到 Vocalink 余额即时客服审批
VIP 未使用按比例退(原路)7 个工作日自动
VIP 已使用按剩余天数退7 个工作日客服审批
技术问题导致全额退 + 补偿金币即时自动(标记 bug)

8.2 Chargeback 处理

阶段时间动作
收到通知Day 0标记订单 + 冻结争议金额
收集证据Day 1-7交易日志/IP/设备指纹/用户行为
提交辩护Day 7-14通过 Stripe Dashboard 提交
等待裁决Day 14-75Stripe/银行/卡组织裁决
结果处理Day 75+胜诉→解冻 / 败诉→扣款+标记用户

九、Phase 演进

Phase支付通道新增能力预期月流水
P1PayNow + Stripe + Apple + Google基础充值/订阅/退款~S$8 万
P1.5+ GrabPayWeb 充值引导 + 优惠券系统~S$12 万
P2+ Touch'n Go / MoMo / DANA多国本地支付~S$30 万
P3+ UPI / stc pay / Mada印度+中东支付~S$60 万
P4全通道企业支付/发票/B2B~S$120 万

附录

附录 A:Webhook 端点清单

URL来源验证方式
POST /v1/payment/webhook/dbsDBS PayNowSHA-256 HMAC
POST /v1/payment/webhook/stripeStripeStripe Signature (HMAC)
POST /v1/payment/webhook/appleAppleApple Root CA
POST /v1/payment/webhook/googleGoogle PlayGoogle Pub/Sub JWT

附录 B:相关文档

文档关联内容
10 API 接口规范/payment/* 接口契约
11 数据库设计payments / subscriptions 表
12 第三方服务集成Stripe/PayNow 接入概述
04 PRD充值/VIP 功能需求

附录 C:修订记录

版本日期修改内容作者
V1.02026-08-15初始版本支付团队