☰
yansongda/pay 支付宝 V3 交易关闭接口(alipay.trade.close)实战指南
2026/10/6 7:27:44 网站建设 项目流程
  • 金融科技
  • 后端

【免费下载链接】pay

可能是我用过的最优雅的 Alipay/WeChat/Douyin/Unipay/江苏银行 的支付 SDK 扩展包了

项目地址:https://gitcode.com/gh_mirrors/pa/pay
点击查看免费下载

本文是一份针对yansongda/pay支付宝OpenAPI V3交易关闭能力的实操指南,围绕Pay::alipay()->close()讲解调用方式、订单参数直传规则、notify_url的两级配置回落逻辑,以及底层插件管道(签名、验签、响应处理)的完整执行链路。读完本文,你将能够独立完成支付宝 V3 交易关闭的接入、参数排查与响应校验。

接口速览

支付宝 V3 交易关闭对应官方 OpenAPI 的alipay.trade.close(RESTful 路径/v3/alipay/trade/close)。在yansongda/pay中,入口方法定义如下:

method说明参数返回值
close交易关闭array $orderCollection

该方法在 src/Provider/Alipay.php 中定义,内部通过__call('close', [$order])分发到对应的 Shortcut 插件管道。

快速上手

关闭交易与发起支付一样简单,直接调用close()并传入订单参数即可:

use Yansongda\Pay\Pay; Pay::config($this->config); $result = Pay::alipay()->close([ 'out_trade_no' => '1514027114', // 'trade_no' => '2013112011001004330000121536', // 支付宝交易号,与 out_trade_no 二选一 ]);

调用后返回Collection对象,可像数组一样读取字段,例如$result->get('trade_no')、$result->get('out_trade_no')。

提示:与 V2 的__call默认分流不同,V3 接口需要显式传入 V3 Shortcut 插件数组(见 支付宝 V3 API 总览),但close()的调用形态与其余 V3 接口保持一致。

订单配置参数

交易关闭接口的业务参数采用snake_case 直传模式:所有参数与支付宝官方 V3 接口请求体无任何差别,直接以订单数组的形式传入即可,无需method、biz_content等外层包装。

常用参数包括:

参数类型说明
out_trade_nostring商户订单号,与trade_no二选一(两者都传时以trade_no为准)
trade_nostring支付宝交易号,与out_trade_no二选一
operator_idstring商户操作员编号,用于风控与对账
notify_urlstring该接口 Model 独有字段,见下文"两级配置"说明

完整的参数集合请对照官方 PHP SDK 的AlipayTradeCloseModel(字段如out_trade_no、trade_no、operator_id等均可直传),本仓库不做任何字段白名单过滤,传入什么就原样放入请求体。

notify_url 的两级配置规则

notify_url是官方AlipayTradeCloseModel独有的字段,在yansongda/pay中遵循两级配置回落:

  1. 订单参数优先:调用时显式传入'notify_url' => 'https://...',则直接采用该值;
  2. 租户配置回落:订单参数未提供时,回落读取租户配置中的notify_url(对应AlipayConfig::getNotifyUrl(),见 src/Config/AlipayConfig.php);
  3. 两者均未提供:不会向请求体注入该字段。

该逻辑在 src/Plugin/Alipay/V3/Pay/ClosePlugin.php 中实现:

$rocket->mergePayload([ '_method' => 'POST', '_url' => '/v3/alipay/trade/close', 'notify_url' => $payload?->get('notify_url', $config->getNotifyUrl()), ]);

对应地,测试用例 tests/Shortcut/Alipay/V3/CloseShortcutTest.php 中显式传入notify_url后,断言其进入了最终请求 body,验证了"订单参数优先"的行为。

底层原理:插件管道执行链路

close()最终由 src/Shortcut/Alipay/V3/CloseShortcut.php 定义的插件管道完成整个请求生命周期:

return [ StartPlugin::class, // 管道启动,初始化 Rocket ClosePlugin::class, // 装载业务字段、_method、_url、notify_url AddPayloadBodyPlugin::class, // 将 payload 序列化为请求 body AddPayloadSignaturePlugin::class, // 生成 Authorization 签名头 AddRadarPlugin::class, // 组装 PSR-7 Request(URL、Headers、Body) // 管道 post 阶段逆序执行:先验签,后抛业务异常 ResponsePlugin::class, // 非 2xx 响应抛出业务异常 VerifySignaturePlugin::class,// 校验同步响应签名 ParserPlugin::class, // 解析响应为 Collection ];

请求签名(AddPayloadSignaturePlugin)

AddPayloadSignaturePlugin 生成ALIPAY-SHA256withRSA格式的Authorization头,待签名组串由 5 行构成(authString、httpMethod、requestUri、requestBody、appAuthToken),并携带毫秒级时间戳与 UUID v4 nonce。若配置或订单参数中存在_app_auth_token(第三方应用授权),会额外注入alipay-app-auth-token请求头。

请求组装(AddRadarPlugin)

AddRadarPlugin 负责组装最终 PSR-7 请求:固定携带alipay-request-id(UUID v4,用于网关侧定位请求)、User-Agent: yansongda/pay-v3、JSON Content-Type,以及签名头Authorization。请求 URL 由 AlipayTrait::getAlipayV3Url 决定:沙箱模式走 V3 专用沙箱网关,正式模式走生产网关,均拼接业务路径/v3/alipay/trade/close。

响应验签(VerifySignaturePlugin)

VerifySignaturePlugin 对齐官方 SDK 的验签策略:

  • HTTP 200 强制验签;非 200 响应仅在存在alipay-signature时验签(防篡改),无签名直接放行进入错误处理;
  • 证书模式按alipay-sn匹配本地支付宝公钥证书,缺失或不匹配直接抛InvalidSignException;
  • 校验alipay-timestamp(13 位毫秒级,允许 ±300 秒偏差,与微信 V3 的秒级时间戳不同);
  • 组串${timestamp}\n${nonce}\n${body}\n后验签,验签实现见 src/Traits/AlipayTrait.php。

业务异常处理(ResponsePlugin)

ResponsePlugin 在 post 阶段逆序执行时先于验签插件运行:当响应非 2xx 时,将错误体中的code/message并入异常消息,抛出InvalidResponseException,便于快速定位参数问题。

返回值说明

close()返回Collection,其中字段与支付宝官方 V3 接口响应体完全一致(无包裹层)。以交易关闭为例,典型返回字段包括:

  • out_trade_no:商户订单号
  • trade_no:支付宝交易号

如需获取原始响应头(如alipay-timestamp、alipay-nonce等),可从 Rocket 的 destination origin 中读取;普通业务场景直接使用Collection即可。

测试验证

仓库为交易关闭提供了完整的单元测试与 HTTP 集成测试:tests/Shortcut/Alipay/V3/CloseShortcutTest.php:

  • testNormal断言插件管道顺序,并验证 post 阶段ResponsePlugin必须位于VerifySignaturePlugin之前(保证"有签才验、再抛异常"的顺序);
  • testCloseHttp使用 Mockery 模拟 HTTP 客户端,构造带alipay-timestamp/alipay-nonce/alipay-signature/alipay-sn头的签名响应,验证notify_url进入请求 body、返回结果解析正确。

运行该文件对应的测试套件即可复现上述行为。

注意事项

  1. 参数二选一:out_trade_no与trade_no必须提供其一,两者同时提供时支付宝以trade_no为准;
  2. V3 仅证书模式:交易关闭走 V3 管道,租户必须配置app_id、app_secret_cert、app_public_cert_path、alipay_public_cert_path四项(V2/V3 共用一套AlipayConfig,详见 src/Config/AlipayConfig.php);
  3. 沙箱网关差异:V3 沙箱使用独立网关域名,与 V2 沙箱不同;
  4. 时间戳单位:V3 签名体系使用 13 位毫秒时间戳,若自行实现验签务必与微信 V3 的秒级时间戳区分;
  5. 交易状态约束:交易关闭仅对"未支付"状态的订单有效,已支付订单请使用退款(refund)或撤销(cancel)能力,相关接口见 支付宝 V3 API 总览。

以上就是支付宝 V3 交易关闭的全部接入要点。参照本文代码即可完成对接,遇到返回状态码异常时,优先核对out_trade_no/trade_no的订单状态与参数取值。

  • 金融科技
  • 后端

【免费下载链接】pay

可能是我用过的最优雅的 Alipay/WeChat/Douyin/Unipay/江苏银行 的支付 SDK 扩展包了

项目地址:https://gitcode.com/gh_mirrors/pa/pay
点击查看免费下载

相关推荐

上一篇:Webpack配置优化终极指南:Bing Chat for All Browsers多环境构建的最佳实践
下一篇:告别文本搜索困境:用pgvector实现语义化智能检索

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询