文档目录
支付宝支付插件

简介

本技术文档面向 DouPHP 的支付宝支付插件,覆盖 PC 网页支付、手机网站支付、当面付三大场景。文档从系统架构、组件职责、数据流、签名验签、加密解密、订单创建到异步通知、同步回调、主动对账等全流程进行说明,并提供测试与生产环境部署建议。所有实现均基于仓库内提供的 Provider/Service 与 SDK 封装,不引入外部未声明依赖。

项目结构

DouPHP 将三种支付宝支付方式以独立插件形式组织,每个插件包含:

  • Provider:对外暴露统一接口(start/notify/finish/query),对接框架支付管线
  • Service:业务编排,负责构建请求、调用 SDK、处理回调与状态推进
  • manifest:插件元信息,注册 Provider
  • sdk:各场景对应的支付宝 SDK 与 Builder/Service 类
graph TB
subgraph "PC网页支付"
A_Provider["AlipayProvider"] --> A_Service["AlipayService"]
A_Service --> A_SDK["pagepay SDK<br/>AlipayTradeService / Builder"]
end
subgraph "手机网站支付"
W_Provider["AlipaywapProvider"] --> W_Service["AlipaywapService"]
W_Service --> W_SDK["wappay SDK<br/>AlipayTradeService / Builder"]
end
subgraph "当面付"
F_Provider["Alipayf2fProvider"] --> F_Service["Alipayf2fService"]
F_Service --> F_SDK["f2fpay SDK<br/>AlipayTradeService / Builder"]
end
A_Service --> PaySvc["PaymentService(框架)"]
W_Service --> PaySvc
F_Service --> PaySvc

图示来源

  • plugin/alipay/AlipayProvider.php:18-110
  • plugin/alipay/AlipayService.php:44-192
  • plugin/alipaywap/AlipaywapProvider.php:18-110
  • plugin/alipaywap/AlipaywapService.php:45-203
  • plugin/alipayf2f/Alipayf2fProvider.php:19-122
  • plugin/alipayf2f/Alipayf2fService.php:45-313

核心组件

  • Provider 层
    • 统一对外方法:start(发起支付)、notify(异步通知)、finish(同步回调)、query(主动对账)
    • 提供插件元信息与配置项定义(APPID、应用私钥、支付宝公钥)
  • Service 层
    • 组装 SDK 配置(网关地址、字符集、签名算法 RSA2、回调地址)
    • 使用对应场景的 Builder 构造业务参数并调用 AlipayTradeService
    • 校验回调签名后,通过 PaymentService::markSucceeded 推进支付状态机
    • 查询交易状态并映射为 succeeded/pending/closed/notFound
  • SDK 层
    • pagepay/wappay/f2fpay 三类 SDK,分别对应 PC 网页、手机网站、当面付
    • 统一入口 AopSdk.php 初始化自动加载与缓存目录

架构总览

整体流程由“前端下单 -> 选择支付宝 -> 插件发起支付 -> 支付宝页面/扫码 -> 异步通知/同步回调 -> 本地状态更新”构成。三个插件共享同一套 Provider/Service 模式,差异仅在 SDK 子模块与交互方式(跳转 vs 二维码轮询)。

sequenceDiagram
participant U as "用户浏览器"
participant P as "插件Provider"
participant S as "插件Service"
participant SDK as "支付宝SDK"
participant PS as "PaymentService(框架)"
participant ALI as "支付宝网关"
U->>P : 发起支付(start)
P->>S : start(request)
S->>SDK : 构建Builder并调用pagePay/wapPay/qrPay
SDK->>ALI : 生成支付链接或二维码
ALI-->>U : 展示支付页/二维码
Note over U,ALI : 用户完成支付
ALI-->>S : 异步通知(notify)
S->>S : 验签(RSA2)
S->>PS : markSucceeded(paymentSn, tradeNo, raw)
PS-->>S : 成功
U->>S : 同步回调(finish)
S->>S : 验签(RSA2)
S->>PS : markSucceeded(...)
S-->>U : 返回订单页

图示来源

  • plugin/alipay/AlipayService.php:44-120
  • plugin/alipaywap/AlipaywapService.php:45-128
  • plugin/alipayf2f/Alipayf2fService.php:45-195

详细组件分析

PC 网页支付(alipay)

  • 启动支付:构造 AlipayTradePagePayContentBuilder,设置订单号、金额、标题,调用 AlipayTradeService.pagePay 返回支付表单/链接
  • 异步通知:使用 SDK 的 check 方法进行签名校验,通过后提取 out_trade_no 与 trade_no,调用 PaymentService::markSucceeded
  • 同步回调:同样验签成功后推进状态,并发送邮件通知站点管理员
  • 主动对账:使用 AlipayTradeQueryContentBuilder 查询交易状态,按 code/trade_status 映射为 succeeded/pending/closed/notFound
flowchart TD
Start(["开始"]) --> Build["构建页面支付请求<br/>setOutTradeNo/setTotalAmount/setSubject"]
Build --> CallPay["调用 pagePay<br/>返回支付表单/链接"]
CallPay --> Notify{"收到异步通知?"}
Notify -- 是 --> Verify["验签(check)"]
Verify --> Valid{"验签通过?"}
Valid -- 否 --> Fail["返回 fail"]
Valid -- 是 --> Mark["markSucceeded(paymentSn, tradeNo, raw)"]
Mark --> End(["结束"])
Notify -- 否 --> Finish{"收到同步回调?"}
Finish -- 是 --> Verify2["验签(check)"]
Verify2 --> Valid2{"验签通过?"}
Valid2 -- 否 --> Redirect["重定向至订单列表"]
Valid2 -- 是 --> Mark2["markSucceeded(...)"]
Mark2 --> Redirect
Finish -- 否 --> Query["主动对账(query)"]
Query --> Map["映射trade_status<br/>succeeded/pending/closed/notFound"]
Map --> End

图示来源

  • plugin/alipay/AlipayService.php:44-192

手机网站支付(alipaywap)

  • 启动支付:构造 AlipayTradeWapPayContentBuilder,设置超时时间、金额、订单号,调用 wapPay 输出支付页面
  • 异步通知与同步回调:与 PC 网页支付一致,使用 SDK 验签后推进状态
  • 主动对账:复用 query 逻辑,按相同规则映射结果
sequenceDiagram
participant U as "用户移动端"
participant WProv as "AlipaywapProvider"
participant WSvc as "AlipaywapService"
participant WSDK as "wappay SDK"
participant ALI as "支付宝网关"
U->>WProv : start
WProv->>WSvc : start(request)
WSvc->>WSDK : wapPay(builder, return_url, notify_url)
WSDK-->>U : 打开手机支付页
ALI-->>WSvc : notify(异步)
WSvc->>WSvc : check(data)
WSvc->>WSvc : markSucceeded(...)
U->>WSvc : finish(同步)
WSvc->>WSvc : check(data)
WSvc->>WSvc : markSucceeded(...)

图示来源

  • plugin/alipaywap/AlipaywapService.php:45-128

当面付(alipayf2f)

  • 启动支付:构造 AlipayTradePrecreateContentBuilder,调用 qrPay 获取二维码内容;页面渲染二维码并定时轮询 status 接口
  • 异步通知:使用 AopClient 的 rsaCheckV1 进行签名校验,成功后推进状态
  • 同步回调:使用 f2fpay SDK 的 check 验签后推进状态
  • 主动对账与轮询:status() 在扫码期间轮询查询交易结果;query() 用于后台对账任务
sequenceDiagram
participant U as "用户"
participant FProv as "Alipayf2fProvider"
participant FSvc as "Alipayf2fService"
participant FSDK as "f2fpay SDK"
participant QRC as "二维码页面"
participant ALI as "支付宝网关"
U->>FProv : start
FProv->>FSvc : start(request)
FSvc->>FSDK : qrPay(builder)
FSDK-->>FSvc : 返回qr_code
FSvc-->>QRC : 渲染二维码+JS轮询status
U->>AL : 扫码支付
ALI-->>FSvc : notify(异步)
FSvc->>FSvc : rsaCheckV1(data)
FSvc->>FSvc : markSucceeded(...)
QRC->>FSvc : POST status(out_trade_no)
FSvc->>FSDK : queryTradeResult(builder)
FSDK-->>FSvc : SUCCESS?
alt 已支付
FSvc->>FSvc : markSucceeded(...)
FSvc-->>QRC : SUCCESS
else 未支付
FSvc-->>QRC : FAIL
end

图示来源

  • plugin/alipayf2f/Alipayf2fService.php:45-195
  • plugin/alipayf2f/Alipayf2fService.php:257-292

依赖关系分析

  • 插件与框架
    • Provider 实现框架定义的支付提供者接口,统一接入 start/notify/finish/query
    • Service 依赖框架的 PaymentService 推进状态机,并通过 DB/Mail 等能力完成后续动作
  • 插件内部依赖
    • 每个 Service 通过 require_once 动态加载对应 SDK 的 service 与 builder 类
    • 配置读取通过 plugin()->getWithConfig 获取 APPID、私钥、公钥及回调地址
  • 外部依赖
graph LR
Prov["Provider"] --> Svc["Service"]
Svc --> SDK["AlipayTradeService / Builder"]
Svc --> PaySvc["PaymentService(框架)"]
Svc --> Cfg["plugin()->getWithConfig('xxx')"]
SDK --> GW["支付宝网关"]

图示来源

  • plugin/alipay/AlipayService.php:177-192
  • plugin/alipaywap/AlipaywapService.php:188-203
  • plugin/alipayf2f/Alipayf2fService.php:297-313

性能与可靠性

  • 异步优先:所有支付结果以支付宝异步通知为准,同步回调仅做用户体验增强
  • 幂等性:通过 paymentSn 唯一标识一次支付尝试,重复通知不会导致重复入账
  • 主动对账:当异步通知丢失时,可通过 query() 定期拉取交易状态,确保最终一致性
  • 错误处理:
    • 验签失败直接拒绝处理
    • 查询异常捕获并返回 failed,避免影响主流程
    • 配置缺失抛出 DomainException,快速失败便于定位

故障排查指南

  • 验签失败
    • 检查支付宝公钥与应用私钥是否匹配
    • 确认 sign_type 为 RSA2,charset 为 UTF-8
  • 回调未触发
    • 检查 notify_url 与 return_url 是否可被公网访问
    • 检查防火墙/反向代理是否放行支付宝回调域名
  • 查询结果为 notFound
    • 支付宝返回 code=40004 表示未找到该笔交易,需等待或重试
  • 日志与调试
    • SDK 工作目录默认 /tmp,可在 AopSdk.php 中调整 AOP_SDK_WORK_DIR
    • 开发模式 AOP_SDK_DEV_MODE=true 有助于调试

结论

本插件以统一的 Provider/Service 模式实现了 PC 网页支付、手机网站支付与当面付三种场景,借助支付宝官方 SDK 完成签名验签与交易操作,并通过框架 PaymentService 保证状态机的一致性与可追溯性。配合主动对账机制,可有效应对网络抖动与通知丢失等异常情况,满足生产环境的稳定性要求。

附录:配置与部署

配置参数

  • 通用参数(三个插件共用)
    • app_id:支付宝开放平台应用 APPID
    • merchant_private_key:应用私钥(RSA2)
    • alipay_public_key:支付宝公钥(RSA2)
    • charset:UTF-8
    • sign_type:RSA2
    • gatewayUrl:https://openapi.alipay.com/gateway.do
  • 回调地址(由 Service 自动拼接)
    • notify_url:index.php?route=plugin/{插件名}/notify
    • return_url:index.php?route=plugin/{插件名}/finish

集成步骤

  • 启用插件
    • 在管理后台启用对应支付插件,填写 APPID、私钥、公钥
  • 配置回调
    • 确保 notify_url 与 return_url 可被公网访问且路由正确
  • 验证签名
    • 使用沙箱环境先验证验签与回调链路
  • 上线切换
    • 将网关地址与密钥切换至生产环境

测试环境搭建

  • 使用支付宝沙箱账号与沙箱网关进行测试
  • 开启 AOP_SDK_DEV_MODE=true,便于查看 SDK 缓存与日志
  • 使用浏览器模拟 PC/移动端,或使用二维码工具扫描当面付二维码

生产环境部署

  • 关闭开发模式 AOP_SDK_DEV_MODE=false,提升性能
  • 合理设置 AOP_SDK_WORK_DIR 并确保可写
  • 配置防火墙与反向代理,允许支付宝回调域名访问
  • 建立对账任务,周期性调用 query() 补齐遗漏通知
添加日期:2026-10-05