文档目录
支付插件开发示例

简介

本示例基于仓库中已有的支付宝与微信支付插件,系统梳理支付插件的通用架构与实现模式,覆盖支付发起、回调处理、状态同步、主动对账、安全签名验证、订单状态管理等关键环节。同时提供“如何从零创建一个新支付插件”的分步指南,并给出调试技巧、测试方法与常见问题解决方案,帮助开发者快速集成新的支付网关。

项目结构

支付能力以“插件”形式组织,每个支付渠道一个独立插件目录,包含:

  • Provider:对外暴露统一接口(start/notify/finish/query/status)
  • Service:具体业务逻辑(对接 SDK、组装参数、验签、调用支付网关)
  • manifest:声明插件元数据与 Provider 类
  • Internal:可选的内部辅助类(如微信异步通知回调)
graph TB
subgraph "支付宝插件"
A1["AlipayProvider"] --> A2["AlipayService"]
A3["manifest.php"] --> A1
end
subgraph "微信支付插件"
W1["WxpayProvider"] --> W2["WxpayService"]
W3["Internal/NotifyCallback.php"] --> W2
W4["manifest.php"] --> W1
end
subgraph "核心服务"
P["PaymentService"]
end
A2 --> P
W2 --> P

核心组件

  • 支付提供者(Provider)
    • 定义插件标识、元信息(名称、描述、配置项、支持客户端类型)
    • 暴露标准方法:start(发起支付)、notify(异步通知)、finish(同步完成)、query(主动对账)、status(轮询查询,仅部分渠道)
  • 支付服务(Service)
    • 负责与具体支付网关 SDK 交互
    • 构建请求参数、生成支付链接或二维码
    • 校验回调签名、二次确认交易状态
    • 通过 PaymentService 推进支付单与订单状态
  • 支付核心服务(PaymentService)
    • 统一的状态机推进、幂等处理、原始报文存储、订单联动更新

架构总览

支付流程由前端触发,经路由进入对应插件的 Provider,再委托 Service 完成网关交互;支付成功后,支付方通过 notify 回调通知,Service 验签后调用 PaymentService 标记成功并联动订单状态;对于无法及时回调的场景,提供 query 主动对账与 status 轮询机制保障最终一致性。

sequenceDiagram
participant U as "用户浏览器"
participant R as "路由/控制器"
participant P as "Provider(支付宝/微信)"
participant S as "Service(支付宝/微信)"
participant G as "支付网关SDK"
participant PS as "PaymentService"
U->>R : 选择支付方式并下单
R->>P : start(PaymentRequest)
P->>S : start(request)
S->>G : 创建订单/生成支付链接或二维码
G-->>S : 返回支付入口或二维码
S-->>R : 返回前端渲染内容
R-->>U : 展示支付页面/二维码
Note over U,G : 用户在支付端完成付款
G-->>S : notify(异步通知)
S->>S : 验签 + 二次确认
S->>PS : markSucceeded(paymentSn, transactionId, raw)
PS-->>S : 成功/失败
S-->>R : 返回响应
R-->>U : 跳转完成页
alt 未收到回调或需兜底
R->>S : query(status)
S->>G : 查询交易状态
G-->>S : 返回状态
S->>PS : 根据结果推进状态
end

详细组件分析

支付宝插件

  • 插件清单
    • 声明插件分组与 Provider 类
  • Provider
    • 暴露 pluginId、meta、start、notify、finish、query
    • meta 中定义了 APPID、应用私钥、支付宝公钥等配置项
  • Service
    • start:加载 SDK,构造页面支付请求,返回支付页面 URL
    • notify:使用 SDK 验签,提取 out_trade_no 与 trade_no,调用 PaymentService 标记成功
    • finish:验签通过后尝试标记成功并发送邮件通知,最后跳转用户订单页
    • query:按 paymentSn 作为 out_trade_no 查询交易状态,映射为成功/关闭/待支付/不存在等结果
classDiagram
class AlipayProvider {
+pluginId() string
+meta() array
+start(request) string
+notify(payload) string
+finish(payload) string
+query(request) PaymentQueryResult
}
class AlipayService {
+start(request) string
+notify(payload) string
+finish(payload) string
+query(request) PaymentQueryResult
-buildConfig() array
-encodeRaw(data) string
-responseToArray(response) array|null
}
AlipayProvider --> AlipayService : "委托"

微信支付插件

  • 插件清单
    • 声明插件分组与 Provider 类
  • Provider
    • 暴露 pluginId、meta、start、notify、finish、status、query
    • meta 中定义了 AppID、AppSecret、商户号、API 密钥等配置项
  • Service
    • start:按 UA 自动选择 JSAPI/H5/Native 三种模式
    • notify:统一验签并通过内部 NotifyCallback 进行二次确认与状态推进
    • finish:直接跳转用户订单页
    • status:Native 扫码场景下,按 paymentSn 轮询查询微信订单状态
    • query:主动对账,将微信返回状态映射为成功/关闭/待支付/不存在等结果
  • Internal/NotifyCallback
    • 继承 SDK 的 WxPayNotify,重写 Queryorder 与 NotifyProcess
    • 验签通过后二次查询确认,调用 PaymentService 标记成功并发送邮件通知
sequenceDiagram
participant B as "浏览器"
participant P as "WxpayProvider"
participant S as "WxpayService"
participant N as "NotifyCallback"
participant G as "微信支付SDK"
participant PS as "PaymentService"
B->>P : start(request)
P->>S : start(request)
S->>G : 统一下单(JSAPI/H5/NATIVE)
G-->>S : 返回支付参数/二维码
S-->>B : 渲染支付界面
Note over B,G : 用户完成支付
G-->>S : notify(异步通知)
S->>N : Handle(config, false)
N->>G : Queryorder(transaction_id)
G-->>N : 返回查询结果
N->>PS : markSucceeded(paymentSn, transactionId, raw)
PS-->>N : 成功
N-->>S : true
S-->>B : 空响应(微信要求)

支付核心服务(PaymentService)

  • 职责
    • 接收来自各渠道 Service 的 markSucceeded 调用,推进支付单状态机
    • 记录原始报文、交易流水号、时间戳等关键信息
    • 联动订单状态变更,确保支付与订单的一致性
  • 使用方式
    • 支付宝:在 notify/finish/query 中根据网关返回调用
    • 微信:在 notify 的 NotifyCallback 与 status/query 中根据查询结果调用

依赖关系分析

  • 插件层
    • Provider 仅做薄封装,所有业务逻辑下沉到 Service
    • manifest 将插件 ID 与 Provider 绑定,便于框架发现与注册
  • 服务层
    • Service 依赖各自渠道 SDK,负责参数组装、签名、回调处理
    • 所有渠道统一通过 PaymentService 推进状态,保证一致性与可观测性
  • 外部依赖
    • 支付宝 SDK:pagepay 相关类
    • 微信 SDK:UnifiedOrder、JsApiPay、NativePay、OrderQuery 等
graph LR
M1["alipay/manifest.php"] --> P1["AlipayProvider"]
P1 --> S1["AlipayService"]
S1 --> SDK1["支付宝SDK"]
S1 --> Core["PaymentService"]
M2["wxpay/manifest.php"] --> P2["WxpayProvider"]
P2 --> S2["WxpayService"]
S2 --> SDK2["微信支付SDK"]
S2 --> Core
S2 --> NC["NotifyCallback"]

性能与可靠性

  • 幂等与去重
    • 通过 paymentSn 作为唯一键,避免重复处理同一笔支付
  • 异步与重试
    • 异步通知可能丢失或延迟,建议配合 query 主动对账与 status 轮询兜底
  • 日志与可观测性
    • 微信插件内置日志写入 storage/log/payment/wxpay/ 目录下,便于问题定位
  • 超时与限流
    • 轮询应设置最大次数与间隔,避免无限请求
  • 安全与合规
    • 严格验签、二次确认、最小权限原则、敏感配置加密存储

故障排查指南

  • 常见错误与定位
    • 配置不完整:检查 APPID、私钥/公钥、商户号、API 密钥是否填写正确
    • 签名失败:核对签名算法、字符编码、密钥版本(RSA2)
    • 回调未到达:检查公网可达性、域名白名单、防火墙策略
    • 状态不一致:启用 query 主动对账,对比网关与本地状态
  • 日志查看
    • 微信:storage/log/payment/wxpay/ 日期.log
    • 支付宝:插件目录 log.txt(如有)
  • 调试技巧
    • 使用沙箱环境先行验证
    • 打印关键参数(paymentSn、out_trade_no、trade_no/transaction_id)
    • 逐步缩小范围:先测 start,再测 notify,最后测 query/status

结论

本仓库中的支付宝与微信支付插件展示了标准的支付插件范式:Provider 暴露统一接口,Service 专注网关集成与业务编排,PaymentService 统一推进状态。通过 notify、finish、query、status 的组合,实现了高可靠、可扩展的支付闭环。遵循本文档的最佳实践,可快速、安全地接入新的支付渠道。

附录:从零创建新支付插件步骤

  • 第一步:创建插件目录与清单
    • 新建 plugin/newpay/ 目录
    • 编写 manifest.php,声明 plugin_group 与 provider 类名
  • 第二步:实现 Provider
    • 实现 pluginId、meta(定义配置字段)、start、notify、finish、query(必要时实现 status)
    • meta 中至少包含网关所需的凭据字段(如 app_id、key、cert 路径等)
  • 第三步:实现 Service
    • start:加载 SDK,构造下单参数,返回支付入口或二维码
    • notify:验签、二次确认、调用 PaymentService::markSucceeded
    • finish:跳转用户订单页或返回完成提示
    • query:按 paymentSn 查询网关,映射为成功/关闭/待支付/不存在
  • 第四步:安全与日志
    • 严格验签与二次确认
    • 记录关键日志(请求、响应、异常堆栈)
    • 敏感配置加密存储,限制访问
  • 第五步:联调与测试
    • 沙箱环境验证 start/notify/query/status
    • 模拟网络异常、重复回调、超时等边界场景
    • 验证订单状态与支付单状态一致性
  • 第六步:上线与监控
    • 配置生产密钥与证书
    • 开启告警与审计日志
    • 定期执行对账任务,及时发现差异
添加日期:2026-10-05