多渠道支付系统设计文档

一、系统目标

设计一个支持微信支付、支付宝支付、苹果支付的统一支付系统,满足以下要求:

  • 支持虚拟商品支付(如金币、会员等)
  • 安全可靠(签名验证、幂等处理、防止伪造)
  • 支持支付状态回调、补单
  • 易扩展(未来支持 PayPal、Google Pay)

二、系统架构

三、主要模块

1. 统一支付订单模块(payment_order)

  • 字段:order_id、user_id、amount、channel、status、product_id、created_at、updated_at
  • 状态流转:待支付 → 已支付 → 发货完成 / 取消 / 关闭

2. 支付渠道适配器(adapter)

  • WechatAdapter:生成预支付单、处理回调、验签
  • AlipayAdapter:生成跳转参数包、处理回调、验签
  • AppleAdapter:接收客户端 receipt,调用 Apple Server 验证接口

3. 回调处理器(callback_handler)

  • 接收渠道异步回调
  • 验签、查订单、状态更新
  • 发货逻辑(通知业务系统)
  • 返回 success/failed 给渠道

4. 发货服务(deliver_service)

  • 发放金币、商品等虚拟物品
  • 保证幂等(基于 order_id 唯一发货)

5. 补单服务(补偿任务)

  • 定时任务查询超时未支付订单
  • 主动调用渠道查询接口确认订单状态
  • 状态回写到支付订单表

6. 退款处理模块(refund_service)

  • 支持用户主动申请退款(如支付后未发货)或平台发起退款
  • 流程:校验退款条件 → 创建退款单 → 调用支付渠道接口 → 更新状态
  • 支持查询退款状态(微信/支付宝接口支持)
  • 字段:refund_id、order_id、amount、reason、status、channel_refund_id
  • 退款状态流转:待处理 → 处理中 → 已退款 / 失败

7. 对账系统(reconcile_service)

  • 定期拉取渠道账单(如微信对账单、支付宝对账单)
  • 与本地订单进行核对:金额、状态、交易号
  • 输出差异报告,支持自动处理(如补发货、标记异常订单)
  • 提供人工复查接口和日志记录

8. 风控系统(risk_engine)

  • 检测异常支付行为(如频繁支付、支付失败过多、设备异常)
  • 接入用户画像、IP 黑名单、设备指纹等信息
  • 在发起支付前、回调处理时进行风控判断,可阻止发货或标记高风险
  • 风控结果可推送至运营后台用于人工介入处理


四、支付流程图

客户端请求支付
       ↓
服务端创建订单,调用渠道下单接口
       ↓
返回客户端调起支付 SDK 参数
       ↓
客户端拉起微信/支付宝/苹果支付
       ↓
支付完成后 → 渠道回调服务端
       ↓
服务端验签、确认支付成功、修改订单状态
       ↓
发货 / 通知业务模块

五、接口设计(RESTful)

1. 创建订单(统一接口)

POST /api/pay/create
{
  "product_id": "coin_100",
  "amount": 100,
  "channel": "wechat"
}

2. 苹果支付验证

POST /api/pay/apple/verify
{
  "receipt_data": "base64...",
  "order_id": "202506110001"
}

3. 渠道回调接口(服务端)

POST /api/pay/callback/wechat
POST /api/pay/callback/alipay

4. 查询订单状态

GET /api/pay/status?order_id=xxx

5. 发起退款

POST /api/pay/refund
{
  "order_id": "202506110001",
  "reason": "user_cancel",
  "amount": 100
}

6. 查询退款状态

GET /api/pay/refund/status?refund_id=xxx

六、安全设计

  • 微信/支付宝:严格验签 + IP 白名单
  • 苹果:通过 Apple 官方服务验证 receipt
  • 所有接口防重放、幂等处理
  • 所有交易记录审计日志

七、扩展与优化

  • 自动补单机制:定时查询未完成订单,自动确认状态
  • 抽象支付网关接口,便于添加更多渠道
  • 支持渠道回调重试与失败告警
  • 接入 Prometheus / Grafana 做监控

八、数据库表结构(简化)

CREATE TABLE payment_order (
  order_id      VARCHAR(32) PRIMARY KEY,
  user_id       BIGINT NOT NULL,
  channel       VARCHAR(20),
  amount        INT,
  status        VARCHAR(20),
  product_id    VARCHAR(32),
  channel_txn   VARCHAR(64),
  created_at    DATETIME,
  updated_at    DATETIME
);

九、系统整体设计要点

1.统一支付抽象接口

  • 抽象统一接口(如:PayService)屏蔽支付渠道差异。
  • 每个支付渠道实现一个独立的适配器或驱动(如 WeChatPayService, AliPayService, ApplePayService)。
type PayService interface {
    CreateOrder(params OrderRequest) (PayResponse, error)
    HandleCallback(data []byte) (CallbackResult, error)
    QueryOrder(orderID string) (OrderStatus, error)
}

2.幂等性保证

  • 每个订单生成后不可重复处理(防止回调多次触发、客户端重试多次创建等)。
  • 推荐使用 Redis + 唯一事务号做幂等控制。
  • 回调处理中要 先检查订单状态是否已处理

3.统一订单系统

  • 建立统一订单表(例如:payment_orders),结构统一管理,不区分渠道。
  • 字段示例:
    • order_id、user_id
    • amount、channel(wechat/alipay/apple)
    • status(未支付/已支付/失败)
    • external_txn_id(微信/支付宝交易号)
    • created_at、paid_at

4.安全性设计

  • 支付请求签名、参数校验。
  • 微信/支付宝有 RSA 或 MD5 签名;苹果 IAP 要验证 receipt。
  • 服务器之间通信需要做 IP 白名单、Token 或密钥校验。
  • 防止金额被客户端伪造,价格应服务端为准。

5.异步通知 + 补单机制

  • 所有支付渠道都使用 异步回调 通知支付成功。
  • 系统必须支持 回调重试补单查询机制(如订单超时但实际支付了)。
  • 每个订单应支持后台主动查询(Query API)校验状态。

6.Apple Pay 特殊处理

  • 客户端先拿到 receipt,传给服务端;
  • 服务端请求 Apple 验证服务器(生产/沙箱)验证该 receipt;
  • 需要处理多次验证、试用期、自动续费等复杂场景;
  • 推荐:对 Apple 订单建立额外的验证任务队列 + 异常监控。

十、模块划分建议

/pay
├── controller
│   └── pay_controller.go          // 下单、回调入口
├── service
│   ├── pay_service.go             // 调度统一接口
│   ├── wechat_pay.go              // 微信实现
│   ├── alipay.go                  // 支付宝实现
│   └── apple_pay.go               // 苹果支付实现
├── model
│   └── payment_order.go           // 订单模型定义
├── repository
│   └── payment_repo.go            // 订单读写
└── util
    └── signature.go               // 签名生成/验证

整体流程总览图

      [客户端请求支付]
               │
               ▼
   ┌── Step 1:创建支付订单 ───────────────┐
   │                                     │
   │         服务端生成统一订单(支付单) │
   │         并调用各渠道下单接口        │
   └────── 返回支付凭证/跳转链接 ──────┘
               │
               ▼
   ┌── Step 2:客户端发起支付 ─────────────┐
   │   调起微信/支付宝/苹果支付 SDK       │
   └──────────────────────────────────────┘
               │
               ▼
   ┌── Step 3:支付渠道异步回调 ───────────┐
   │   微信/支付宝服务器 → 通知服务端      │
   │   Apple → 客户端拿到 receipt,        │
   │          传给服务端验证              │
   └──────────────────────────────────────┘
               │
               ▼
   ┌── Step 4:服务端确认支付状态 ────────┐
   │  - 更新订单状态                      │
   │  - 通知业务模块发货 / 送金币         │
   └──────────────────────────────────────┘

Step 1:创建订单(统一接口)

1、客户端发起支付请求:

{
  "amount": 100,
  "pay_channel": "wechat", // or alipay / apple
  "product_id": "coin_100"
}

2、服务端处理逻辑

  • 验证参数(用户合法、商品有效、金额正确)
  • 生成统一支付订单(payment_order)
  • 调用渠道支付服务:
    • 微信:生成预支付单,返回 prepay_id
    • 支付宝:生成跳转链接或参数包
    • 苹果:等待客户端提供 receipt

3、返回结果给客户端(供 SDK 使用):

{
  "pay_params": { ... }, // SDK 调起参数
  "order_id": "202506110001"
}

Step 2:客户端调起支付(前端负责)

  • 微信 / 支付宝使用 SDK 或 Web 页面调起;
  • 苹果 IAP 使用 StoreKit 发起支付流程;
  • 苹果支付完成后,客户端上传 receipt 给服务端

Step 3:支付回调 & 验签处理

所有渠道都通过“服务端通知”最终确认支付是否成功。

微信 / 支付宝

  • 渠道服务器回调服务端 URL(POST 请求),携带订单号、金额、签名等;
  • 服务端验签、查订单、对比金额;
  • 修改订单状态:待支付 → 已支付
  • 回调业务逻辑(发货、金币到账等);
  • 返回 success 响应,防止多次回调。

苹果支付

  • 客户端上传 receipt;
  • 服务端调用 Apple 验证接口;
  • 解析验证结果,确认支付成功;
  • 更新订单、发货。

Step 4:订单确认 & 发货

  • 更新订单为 已支付,记录交易号;
  • 通知业务层执行发货逻辑:
    • 发放虚拟物品、金币;
    • 记录流水;
    • 给客户端推送支付成功消息;
  • 支持幂等调用,确保只发货一次。

异常处理流程(补单、回调失败)

场景

处理方案

回调失败

支付平台会重试(最多 3~5 次),应幂等处理

用户支付成功但未收到货

后台支持查询订单状态接口,或通过补单机制查询

苹果支付未及时验证

可以将 receipt 放入异步队列,后续处理

用户多次点击付款

前端应防重 + 服务端幂等检查(order_id 唯一)

支付回调被攻击伪造

严格验签(微信/支付宝签名、Apple receipt)

支付订单状态流转图

[待支付] ──→ [支付中] ──→ [已支付]
   │                          │
   │                          └──→ [发货成功]
   │
   └──→ [已取消] / [超时关闭]

接口示意(建议暴露的 API)

接口

说明

POST /pay/create

创建支付订单

POST /pay/apple

苹果支付 receipt 验证接口

POST /pay/callback/wechat

微信回调接口

POST /pay/callback/alipay

支付宝回调接口

GET /pay/query

查询订单状态

十一、安全性设计

一、支付请求签名与验签

微信 / 支付宝签名机制(RSA / MD5 / HMAC)

1. 微信支付(HMAC-SHA256 / MD5)

  • 签名字段:appid、mch_id、nonce_str、body、total_fee 等所有参与签名字段(不含 sign)
  • 服务端生成签名:
func GenerateWechatSign(params map[string]string, apiKey string) string {
    // 1. 排序
    keys := make([]string, 0, len(params))
    for k := range params {
        if k != "sign" && params[k] != "" {
            keys = append(keys, k)
        }
    }
    sort.Strings(keys)

    // 2. 拼接参数字符串
    var buf strings.Builder
    for _, k := range keys {
        buf.WriteString(k + "=" + params[k] + "&")
    }
    buf.WriteString("key=" + apiKey)

    // 3. 签名
    h := md5.Sum([]byte(buf.String()))
    return strings.ToUpper(hex.EncodeToString(h[:]))
}
  • 微信回调时服务端需使用相同算法进行签名校验

2. 支付宝支付(RSA2)

  • 服务器需保留支付宝公钥,本地进行验签:
func VerifyAlipaySign(params map[string]string, sign, publicKey string) bool {
    // 1. 参数排序并拼接
    // 2. 使用 RSA-SHA256 验签
    // 推荐使用官方 SDK(Java / Go)
}

3.苹果 IAP 凭证校验

  • 客户端提交 Base64 编码的 receipt_data
  • 后端发起 Apple 验证请求
  • func VerifyAppleReceipt(receipt string, isSandbox bool) (bool, error) {
        url := "https://buy.itunes.apple.com/verifyReceipt"
        if isSandbox {
            url = "https://sandbox.itunes.apple.com/verifyReceipt"
        }
    
        body := map[string]string{"receipt-data": receipt}
        payload, _ := json.Marshal(body)
    
        resp, err := http.Post(url, "application/json", bytes.NewBuffer(payload))
        // 解析 JSON 返回 {"status": 0, "receipt": {...}}
    }
    
  • 验证通过 status == 0,其他状态需要重试或处理异常
  • 也可使用“共享密钥”字段(password)进行验证(如订阅型商品)
  • 二、服务通信安全(API 保护)

    1. IP 白名单(网关层或接口层实现)

    • 配置反向代理(如 Nginx)或微服务网关(Traefik、Kong)限制来源 IP:
    allow 192.168.1.0/24;
    deny all;

    2. Access Token 校验(更灵活)

    服务 A 调用服务 B 时,需携带签名头:

    POST /internal/order/notify
    Authorization: Bearer {HMAC(api_key, timestamp, nonce)}
    X-Timestamp: 1680000000
    X-Nonce: abc123

    服务 B 验签流程:

    func VerifyToken(apiKey, receivedSignature, timestamp, nonce string) bool {
        base := fmt.Sprintf("%s|%s|%s", apiKey, timestamp, nonce)
        h := hmac.New(sha256.New, []byte(secret))
        h.Write([]byte(base))
        return hex.EncodeToString(h.Sum(nil)) == receivedSignature
    }

    三、客户端伪造金额的防范

    原则:价格以服务端为准

    • 客户端只能提交商品 ID(如:coin_100)
    • 服务端通过商品配置表确认价格与商品内容:
    // 后端查表获取金额
    product := db.FindProductByID("coin_100") // price = 10.00

    不允许客户端直接传入金额,否则极易被修改

    四、幂等性保证(防止多次支付 / 发货)

  • 所有操作需使用 order_id / txn_id 做幂等控制
  • 通过数据库唯一索引 + 状态字段实现原子控制
  • // 发货前先判断状态
    if order.Status == "paid" && !order.Delivered {
        // 发货逻辑 + 设置 delivered = true
    }

    五、日志 + 监控 + 告警

    • 所有验签失败、异常凭证、退款失败都需日志记录
    • 接入 Prometheus + Grafana 做指标监控
    • 回调失败、对账失败等支持钉钉/飞书告警

    相关文章

    nginx配置之nginx中的“防盗”配置

    一般我们使用nginx常用的就那么几项,简单代理、反向代理、代理转发、负载均衡、重定向,等等。但是有时候又不得不进行另外的一些配置,下面介绍几种"防盗"配置。爬虫 User-Agent...

    Nginx中想对IP做访问限制怎么做?access模块来帮忙-09

    在一个请求闯过之前的postread阶段,rewrite阶段,find_config阶段,preaccess阶段后终于来到了Access阶段了。Access阶段主要就是控制请求是否可以继续向下访问的。...

    确保 Nginx 网络服务器的安全

    在数字时代,网络安全已成为一个亟待解决的问题。随着网络攻击的增加,确保网络服务器安全对保护敏感数据和维护网站完整性至关重要。本博文将指导你如何配置 Nginx(一种流行的开源网络服务器软件),以保护服...

    一文搞懂!7种常见的限流方式!

    在实际应用中,每个系统或者服务都有其处理能力的极限(瓶颈),即便是微服务中有集群和分布式的夹持,也不能保证系统能应对任何大小的流量,因此,系统为了自保,需要对处理能力范围以外的流量进行“特殊照顾”(比...

    从开发到上线:Vite 中资源路径解析与工程化解决方案

    在现代前端开发中,Vite 已经成为了一个备受欢迎的构建工具。然而,当涉及到静态资源(如字体、图片等)的路径解析时,开发者常常会遇到一些棘手的问题。特别是在不同的开发和生产环境中,路径解析的行为可能...

    nginx upstream节点健康检查

    1、前提条件编译nginx时增加nginx_upstream_check_module模板git地址:https://github.com/yaoweibin/nginx_upstream_check...