文档目录
微信支付插件

简介

本技术文档面向 DouPHP 的微信支付插件,覆盖 JSAPI 支付、扫码(Native)支付、H5 支付以及小程序支付的接入方式。文档从系统架构、数据流、处理逻辑、安全机制到调试排错进行系统化说明,帮助开发者快速理解并正确集成微信支付能力。

项目结构

微信支付插件位于 plugin/wxpay 目录下,采用“提供者 + 服务 + SDK”的分层组织:

  • 插件清单:声明插件分组与提供类
  • 提供者:实现统一支付接口,负责路由到具体支付方式
  • 服务:封装统一下单、通知处理、查询、退款等业务流程
  • SDK:微信官方示例 SDK,包含配置、API、JSAPI/Native/H5 工具类
  • 回调处理器:继承 SDK 的 WxPayNotify,完成验签、二次确认与订单推进
  • 二维码生成:用于 PC 端扫码支付展示 code_url
graph TB
A["前端/商户系统"] --> B["WxpayProvider<br/>统一入口"]
B --> C["WxpayService<br/>业务编排"]
C --> D["SDK: WxPay.Api<br/>统一下单/查询"]
C --> E["SDK: JsApiPay/NativePay<br/>JSAPI/Native"]
C --> F["SDK: wechatAppPay<br/>H5(MWEB)"]
C --> G["Internal\\NotifyCallback<br/>异步通知处理"]
G --> H["PaymentService<br/>标记成功/更新订单"]

核心组件

  • 插件清单 manifest.php:声明插件组 payment 与提供类 Dou\Plugin\Wxpay\WxpayProvider
  • 提供者 WxpayProvider:实现 ReconcilablePaymentProviderInterface 与 PollablePaymentProviderInterface,暴露 start/notify/finish/status/query 等方法
  • 服务 WxpayService:按 UA 自动选择 JSAPI/H5/Native;封装统一下单、通知、查询、轮询;构建 SDK 配置与日志
  • 通知回调 NotifyCallback:继承 WxPayNotify,重写 Queryorder/NotifyProcess,完成签名校验、二次查询与订单推进
  • SDK 配置 WxPay.Config:从全局配置读取 APPID/MCHID/KEY/证书路径等
  • 二维码 qrcode.php:将 code_url 转为二维码图片供 PC 扫码

架构总览

微信支付插件通过统一入口 WxpayProvider 接收请求,交由 WxpayService 根据环境自动选择支付方式:

  • 微信客户端(MicroMessenger)→ JSAPI 支付
  • 移动端(IS_MOBILE)→ H5 支付(MWEB)
  • 其他 → Native 扫码支付

所有支付方式共用同一异步通知地址,由 NotifyCallback 完成验签与二次确认,最终调用 PaymentService 推进订单状态。

sequenceDiagram
participant U as "用户"
participant P as "WxpayProvider"
participant S as "WxpayService"
participant WX as "微信支付API"
participant N as "NotifyCallback"
participant PS as "PaymentService"
U->>P : 发起支付(start)
P->>S : start(request)
alt 微信内
S->>WX : 统一下单(JSAPI)
WX-->>S : 预支付参数
S-->>U : 返回JSAPI参数(前端拉起支付)
else 移动端
S->>WX : 统一下单(H5/MWEB)
WX-->>S : mweb_url
S-->>U : 重定向至mweb_url
else PC
S->>WX : 统一下单(NATIVE)
WX-->>S : code_url
S-->>U : 展示二维码+轮询status
end
WX-->>N : 异步通知(notify)
N->>N : 验签+二次查询
N->>PS : markSucceeded(paymentSn, transactionId)
PS-->>N : 成功
N-->>WX : 返回success

详细组件分析

支付方式与流程

  • JSAPI 支付(微信内)
    • 通过 JsApiPay 获取 Openid,构造 WxPayUnifiedOrder 提交统一下单,返回 JSAPI 参数由前端拉起支付
    • 成功后跳转订单页
  • H5 支付(移动端浏览器)
    • 使用 wechatAppPay 统一下单,trade_type=MWEB,返回 mweb_url,前端重定向完成支付
    • 支付完成后回跳 finish 路由
  • Native 扫码支付(PC)
    • 统一下单 trade_type=NATIVE,获取 code_url,通过 qrcode.php 生成二维码
    • 前端定时轮询 status 接口,查询交易状态并推进订单
flowchart TD
Start(["开始"]) --> UA{"UA判断"}
UA --> |MicroMessenger| JSAPI["JSAPI下单"]
UA --> |移动端| H5["H5(MWEB)下单"]
UA --> |其他| NATIVE["Native扫码下单"]
JSAPI --> JSAPIUI["前端拉起支付"]
H5 --> H5REDIR["重定向到mweb_url"]
NATIVE --> QR["生成二维码"]
JSAPIUI --> WaitNotify["等待异步通知"]
H5REDIR --> WaitNotify
QR --> Poll["轮询status"]
WaitNotify --> Verify["验签+二次查询"]
Poll --> Check{"是否SUCCESS?"}
Check --> |是| Mark["markSucceeded"]
Check --> |否| Continue["继续轮询"]
Verify --> Mark
Mark --> End(["结束"])

统一下单与参数生成

  • 统一下单字段
    • out_trade_no:使用 dou_order_payment.payment_sn
    • total_fee:金额×100(分)
    • notify_url:统一回调地址
    • trade_type:JSAPI/NATIVE/MWEB
    • body/attach/goods_tag/time_start/time_expire 等辅助信息
  • 各方式差异
    • JSAPI:需设置 Openid
    • H5:需 spbill_create_ip,返回 mweb_url
    • Native:返回 code_url,配合轮询

异步通知与结果处理

  • 统一回调地址:route=plugin/wxpay/notify
  • 处理流程
    • 加载 SDK 并实例化 WxPayConfig
    • 调用 Internal\NotifyCallback::Handle 完成验签
    • 重写 Queryorder 进行二次查询确认
    • 调用 PaymentService::markSucceeded 推进订单状态
    • 发送站内邮件通知(如配置)
sequenceDiagram
participant WX as "微信支付"
participant SVC as "WxpayService"
participant CB as "NotifyCallback"
participant PS as "PaymentService"
WX->>SVC : POST /plugin/wxpay/notify
SVC->>CB : Handle(config, false)
CB->>CB : CheckSign()
CB->>CB : Queryorder(transaction_id)
CB->>PS : markSucceeded(paymentSn, transactionId, raw)
PS-->>CB : 成功
CB-->>WX : 返回success

订单查询与主动对账

  • 主动对账接口 query:以 paymentSn 作为 out_trade_no 调用 orderQuery
  • 状态映射
    • SUCCESS:成功
    • CLOSED/REVOKED/PAYERROR:关闭或失败
    • NOTPAY/USERPAYING:待支付/支付中
  • Native 轮询 status:按 paymentSn 查询并推进状态

退款申请(扩展说明)

  • 当前插件未直接暴露退款入口,但 SDK 已支持退款相关 API(如 refund),可在现有 WxpayService 基础上扩展
  • 退款需要配置证书路径(SSL_CERT_PATH/SSL_KEY_PATH),已在 buildConfig 中预留

小程序支付(接入说明)

  • 小程序支付可通过 API 层调用 WxpayService 或独立服务发起统一下单(trade_type=JSAPI),并传入小程序 openid
  • 本项目在 api/controller/user/WeixinController 中有小程序支付入口示例,可参考其调用方式
  • 注意:小程序支付需确保 appid/appsecret/openid 正确配置

依赖关系分析

  • WxpayProvider 依赖 WxpayService,对外暴露标准支付接口
  • WxpayService 依赖:
    • SDK:WxPay.Api(统一下单/查询)、WxPay.Config(配置)、WxPay.JsApiPay(JSAPI)、WxPay.NativePay(Native)、wechatAppPay(H5)
    • Internal\NotifyCallback 继承 WxPayNotify,完成通知处理
    • PaymentService 推进订单状态
  • 配置文件 WxPay.Config 从 $GLOBALS['config_from_plugin'] 读取密钥与证书路径
classDiagram
class WxpayProvider {
+start(request) string
+notify(payload) string
+finish(payload) string
+status(payload) string
+query(request) PaymentQueryResult
}
class WxpayService {
+start(request) string
+notify(payload) string
+finish(payload) string
+status(payload) string
+query(request) PaymentQueryResult
-buildConfig() array
-bootSdk(files) void
}
class NotifyCallback {
+Queryorder(transactionId) bool
+NotifyProcess(objData, config, msg) bool
}
class WxPayConfig {
+GetAppId() string
+GetMerchantId() string
+GetKey() string
+GetSSLCertPath(&a,&b) void
}
WxpayProvider --> WxpayService : "委托"
WxpayService --> WxPayConfig : "读取配置"
WxpayService --> NotifyCallback : "通知处理"

性能与可靠性

  • 轮询优化:Native 扫码在前端限制最大轮询次数与频率,避免无效请求
  • 日志记录:每次统一下单、查询、通知均写入 storage/log/payment/wxpay 日志文件,便于追踪
  • 幂等性:通知处理通过二次查询确认后再推进订单,降低重复通知风险
  • 错误处理:查询失败或状态异常时返回明确状态码,便于上层重试或告警

故障排查指南

  • 常见问题
    • 签名错误:检查 KEY 是否正确,通知 URL 是否公网可达
    • 统一下单失败:核对 appid/mchid/total_fee/spbill_create_ip 等必填字段
    • H5 无法跳转:确认 mweb_url 与 redirect_url 拼接正确
    • Native 无响应:检查 code_url 是否有效,轮询间隔与上限是否合理
  • 定位方法
    • 查看 storage/log/payment/wxpay/*.log 中的请求与响应
    • 检查 WxpayService::buildConfig 生成的配置数组是否完整
    • 使用微信商户平台订单号或交易号在后台查询订单状态

结论

DouPHP 微信支付插件通过统一的 Provider/Service 架构,结合微信官方 SDK,实现了 JSAPI、H5、Native 三种主流支付方式的无缝接入,并提供稳定的异步通知与主动对账能力。通过合理的配置与安全机制(签名验证、二次查询、日志记录),可有效保障支付流程的正确性与安全性。建议在现有基础上按需扩展退款与更多支付方式。

附录:配置项与接入方式速查

  • 配置项
    • appid:开发者ID(APPID)
    • appsecret:开发者密码(仅 JSAPI 需要)
    • mchid:商户号
    • key:API 密钥(v2)
    • SSL 证书路径:apiclient_cert.pem/apiclient_key.pem(退款等场景需要)
    • 回调地址:/index.php?route=plugin/wxpay/notify
  • 接入方式
    • JSAPI:微信内支付,需 Openid
    • H5:移动端浏览器支付,返回 mweb_url
    • Native:PC 扫码支付,返回 code_url 并轮询
    • 小程序:通过 API 层发起 JSAPI 支付(需小程序 openid)
添加日期:2026-10-05