文档目录
支付组件

简介

本文件面向 DouPHP 小程序支付组件,系统梳理微信支付、支付宝支付的实现方式,覆盖下单发起、安全验签、异步回调、主动对账、订单状态同步、退款处理等关键流程。文档同时说明小程序端的支付交互、错误处理机制以及与第三方支付平台的集成要点和安全注意事项。

项目结构

支付能力由“插件层 + 核心服务层 + 小程序前端”三部分构成:

  • 插件层:按支付方式拆分(微信 wxpay、支付宝 alipay),提供 Provider 门面与 Service 业务逻辑,封装第三方 SDK。
  • 核心服务层:统一支付台账与状态机(PaymentService),负责幂等、订单联动、退款分账等。
  • 小程序前端:下单页与订单详情页,调用后端接口完成支付与结果展示。
graph TB
subgraph "小程序端"
M_Checkout["订单结算页<br/>checkout.ts"]
M_Show["订单详情/支付入口<br/>show.ts"]
end
subgraph "后端核心"
P_Svc["PaymentService<br/>统一支付台账/状态机"]
end
subgraph "支付插件"
W_Provider["WxpayProvider<br/>微信支付门面"]
W_Service["WxpayService<br/>JSAPI/NATIVE/H5 发起+回调+轮询"]
A_Provider["AlipayProvider<br/>支付宝门面"]
A_Service["AlipayService<br/>电脑网站支付发起+回调+对账"]
end
M_Checkout --> |创建订单并跳转收银台| P_Svc
M_Show --> |发起支付/查询| P_Svc
P_Svc --> W_Provider
P_Svc --> A_Provider
W_Provider --> W_Service
A_Provider --> A_Service
W_Service --> |异步通知/轮询| P_Svc
A_Service --> |异步通知/对账| P_Svc

核心组件

  • 微信支付插件
    • Provider:对外暴露 start/notify/finish/status/query 等能力,适配小程序与 H5/PC 场景。
    • Service:根据 UA 自动选择 JSAPI/NATIVE/H5;统一 notify 验签;支持 Native 扫码轮询与主动对账。
  • 支付宝插件
    • Provider:对外暴露 start/notify/finish/query。
    • Service:电脑网站支付发起;notify/finish 验签后推进支付成功;query 主动对账。
  • 统一支付服务
    • PaymentService:维护 payment 行(payment_sn、gateway、amount、status)、订单联动(PAID)、钱包混合支付、退款分账、幂等与事务保障。

架构总览

支付主流程(以微信支付为例):

  • 小程序下单:前端 checkout.ts 提交订单信息,后端创建 pending 的 payment,返回收银台或支付参数。
  • 发起支付:WxpayService 根据 UA 选择 JSAPI/NATIVE/H5,生成支付参数或二维码。
  • 异步通知:微信回调到统一 notify,内部 NotifyCallback 验签并二次查询确认,成功后调用 PaymentService.markSucceeded。
  • 轮询兜底:NATIVE 扫码通过 status 轮询查询交易状态,命中 SUCCESS 即推进支付成功。
  • 主动对账:定时任务或管理端触发 query,统一映射为 succeeded/pending/closed/notFound。
sequenceDiagram
participant U as "用户"
participant MP as "小程序前端<br/>checkout.ts / show.ts"
participant PS as "PaymentService"
participant WP as "WxpayProvider"
participant WS as "WxpayService"
participant WX as "微信支付网关"
U->>MP : 点击“去支付”
MP->>PS : 创建订单并生成 payment(pending)
PS-->>MP : 返回 payment_sn / 收银台URL
MP->>WP : 发起支付(start)
WP->>WS : 路由到 JSAPI/NATIVE/H5
WS->>WX : 统一下单(含 notify_url)
WX-->>WS : 返回支付参数/二维码
WS-->>MP : 渲染支付按钮/二维码
WX-->>WS : 异步通知(notify)
WS->>WS : 验签 + 二次查询
WS->>PS : markSucceeded(payment_sn, transaction_id)
PS-->>MP : 订单状态变为已支付

详细组件分析

微信支付组件(WxpayProvider / WxpayService)

  • 能力边界
    • start:按 UA 派发 JSAPI(微信小程序内)、H5(移动端浏览器)、NATIVE(PC 扫码)。
    • notify:统一回调入口,SDK 验签 + 二次查询确认,成功后推进支付成功。
    • finish:支付完成后回跳订单页。
    • status:NATIVE 扫码轮询,按 paymentSn 主动查询微信,命中 SUCCESS 即推进支付成功。
    • query:主动对账,将微信返回状态映射为 succeeded/pending/closed/notFound。
  • 数据流
    • out_trade_no 使用 payment.payment_sn;transaction_id 作为第三方流水号落库。
    • 日志写入 storage/log/payment/wxpay/ 下按日切分的日志文件。
  • 配置项
    • appid、appsecret、mchid、key;证书路径在插件目录下。
flowchart TD
Start(["start()"]) --> UA{"UA 判断"}
UA --> |MicroMessenger| JSAPI["startJsapi()<br/>JSAPI 统一下单"]
UA --> |IS_MOBILE| H5["startH5()<br/>MWEB 统一下单"]
UA --> |其他| NATIVE["startNative()<br/>生成二维码 + 轮询"]
JSAPI --> ReturnJS["返回 JS 参数/按钮"]
H5 --> ReturnH5["返回 mweb_url + 重定向"]
NATIVE --> ReturnQR["返回二维码 + 轮询脚本"]

支付宝组件(AlipayProvider / AlipayService)

  • 能力边界
    • start:电脑网站支付,构建请求并返回页面跳转链接。
    • notify/finish:验签通过后推进支付成功;finish 时尝试发送站内通知邮件。
    • query:主动对账,将 trade_status 映射为 succeeded/pending/closed/notFound。
  • 数据流
    • out_trade_no 使用 payment.payment_sn;trade_no 作为第三方流水号。
    • 配置校验失败抛出领域异常,提示管理员补全配置。
sequenceDiagram
participant MP as "小程序前端"
participant AP as "AlipayProvider"
participant AS as "AlipayService"
participant ALI as "支付宝网关"
participant PS as "PaymentService"
MP->>AP : start(PaymentRequest)
AP->>AS : start()
AS->>ALI : 电脑网站支付下单
ALI-->>AS : 返回跳转链接
AS-->>MP : 返回 redirect URL
ALI-->>AS : 异步通知(notify)
AS->>PS : markSucceeded(payment_sn, trade_no)
PS-->>MP : 订单状态更新为已支付

统一支付服务(PaymentService)

  • 核心职责
    • 创建 payment 记录(pending),生成唯一 payment_sn。
    • 标记成功:markSucceeded 幂等推进 payment 与订单状态(PAID),累计网关已付金额。
    • 订单收尾:tryFinalizeOrder 汇总各腿金额,达到订单金额则推进 PAID。
    • 钱包支付:markSucceededByWallet 扣余额、落账、尝试收尾。
    • 退款分账:refundOrder 按渠道优先顺序拆分退款;wallet 立即退回,网关登记 pending 待人工/回调收尾。
    • 退款收尾:markRefundSucceeded 将 pending 退款升级为 succeeded,并更新支付腿状态。
  • 幂等与一致性
    • DB UNIQUE KEY(gateway, transaction_id) 防重复落库。
    • changeStatus 事务内执行高风险联动,失败不推进终态,避免不可逆错配。
flowchart TD
In(["收到支付成功事件"]) --> Find["查找 payment 记录"]
Find --> CheckState{"是否已成功?"}
CheckState --> |是| Finalize["tryFinalizeOrder(order_sn)"]
CheckState --> |否| Validate["校验订单可收款状态"]
Validate --> UpdatePay["更新 payment 为 SUCCEEDED"]
UpdatePay --> Accumulate["累计 gateway_paid"]
Accumulate --> Finalize
Finalize --> Done(["结束"])

小程序端支付交互

  • 下单与收银台
    • checkout.ts:提交收货信息与优惠券后,跳转到 cashier_url(后端生成的支付入口)。
  • 订单详情支付
    • show.ts:在订单详情页发起微信支付(wx.requestPayment),成功后刷新订单状态。
sequenceDiagram
participant C as "小程序页面"
participant API as "后端接口"
participant PS as "PaymentService"
participant WX as "微信支付"
C->>API : POST order.checkout.checkout_post
API-->>C : 返回 cashier_url
C->>API : POST user.weixin.pay
API->>PS : 创建/获取 payment
PS-->>API : 返回支付参数(timeStamp/nonceStr/package/paySign)
API-->>C : 返回支付参数
C->>WX : wx.requestPayment(...)
WX-->>C : 支付结果
C->>API : 刷新订单(show)

依赖关系分析

  • 插件与核心服务解耦:Provider 仅做路由转发,Service 负责具体对接;PaymentService 提供统一状态机与订单联动。
  • 外部依赖:
    • 微信支付 SDK:WxPayConfig、WxPayApi、WxPayNotify 等。
    • 支付宝 SDK:AlipayTradeService、ContentBuilder 系列。
  • 耦合点
    • 回调中通过 payment_sn 定位支付记录,再调用 PaymentService 推进状态。
    • 订单状态推进由 OrderStatusTransition 保证合法性。
graph LR
WProv["WxpayProvider"] --> WSvc["WxpayService"]
AProv["AlipayProvider"] --> ASvc["AlipayService"]
WSvc --> PSvc["PaymentService"]
ASvc --> PSvc
PSvc --> OSt["OrderStatusTransition"]

性能与可靠性

  • 幂等性
    • 支付成功回调与对账均具备幂等保护,避免重复推进订单。
  • 容错与兜底
    • 微信 NATIVE 扫码支持轮询;支付宝支持主动对账;PaymentService 支持多次支付腿凑满才收尾。
  • 日志与可观测性
    • 微信支付日志按日写入 storage/log/payment/wxpay/;回调原文落库便于排查。
  • 并发控制
    • 钱包支付使用事务与行锁防止超扣;订单状态推进在事务内完成高风险联动。

故障排查指南

  • 常见问题
    • 配置不完整:支付宝插件会抛出领域异常提示管理员补全;微信支付需确保 appid/mchid/key 及证书路径正确。
    • 回调未生效:检查 notify_url 可达性与签名验证;查看日志与 raw_callback。
    • 订单未推进:核对订单状态是否允许收款;检查 tryFinalizeOrder 是否满足金额条件。
  • 建议步骤
    • 查看对应插件日志与数据库 order_payment.raw_callback。
    • 使用 query 接口进行主动对账,观察返回状态。
    • 若为 NATIVE 扫码,确认 status 轮询是否被前端正确调用。

结论

DouPHP 支付组件通过“插件化 + 统一服务”的架构,实现了微信支付与支付宝的统一接入与可靠交付。核心优势包括:

  • 多端适配:JSAPI/NATIVE/H5 自动识别与降级。
  • 强一致:基于 PaymentService 的状态机与事务保障,确保订单与支付台账一致。
  • 高可用:异步通知 + 轮询 + 主动对账的多重兜底机制。
  • 可扩展:新增支付方式只需实现 Provider/Service 并遵循统一 DTO 契约。

附录:配置与安全清单

  • 微信支付配置
    • 开发者 ID(AppID)、开发者密码(AppSecret)、商户号(MCHID)、API 密钥(KEY)。
    • 证书路径:apiclient_cert.pem、apiclient_key.pem。
    • 回调地址:统一 notify 路由。
  • 支付宝配置
    • APPID、应用私钥、支付宝公钥。
    • 回调地址:notify_url、return_url。
  • 安全要点
    • 所有回调必须验签并通过二次查询确认。
    • 敏感配置应加密存储,禁止硬编码。
    • 对外暴露的回调接口需限制来源与频率,记录原始报文以便审计。
    • 退款流程区分 wallet 即时退回与网关 pending 登记,最终由人工/回调收尾。
添加日期:2026-10-05