- 后端
- 金融科技
【免费下载链接】pay
可能是我用过的最优雅的 Alipay/WeChat/Unipay/江苏银行 的支付 SDK 扩展包了
微信支付官方规定:订单生成后未支付,超过 7 天将自动关闭;而通过关闭订单接口,商户可以在超时前主动对处于「未支付」状态的订单执行关单。本文以 Pay 开源支付 SDK(yansongda/pay)v2 文档中 web/docs/v2/wechat/close.md 为骨架,结合仓库源码(Provider、Shortcut、Plugin 三层实现)与测试用例,完整讲解close关闭订单的调用方式、场景参数、返回值处理与底层插件执行链,帮你快速掌握并排查线上关单问题。
方法签名与返回值
微信关闭订单在 Pay 中对应close方法,其签名与返回值如下:
| 方法名 | 参数 | 返回值 |
|---|---|---|
| close | string/array$order | Collection |
- 参数:既可以直接传入商户订单号字符串,也可以传入包含
out_trade_no等订单配置的数组; - 返回值:
Yansongda\Supports\Collection实例,可通过$collection->xxx访问服务器返回的数据。
最小调用示例
在 Pay 中先完成微信支付配置(完整配置可参考 微信概述与快速上手,需包含app_id/appid/miniapp_id、mch_id、key等基础信息),随后即可关闭订单:
$order = [ 'out_trade_no' => '1514027114', ]; // 也可以直接传入订单号字符串 // $order = '1514027114'; $result = $wechat->close($order);其中$wechat为Pay::wechat($config)返回的实例。两种传参方式等价:当传入字符串时,SDK 内部会将其作为out_trade_no处理,简化只关单个订单的场景。
订单配置参数
close的订单配置参数与微信支付官方接口无任何差别,兼容所有官方功能。所有可用参数请以官方《JSAPI 支付-关闭订单》文档(原 v2 文档中指向官方 wiki 的「请求参数」一栏)为准。
其中最关键、也是唯一必填的参数是:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| out_trade_no | string | ✅ | 商户系统内部订单号,必须是 32 个字符内、且与下单时一致的订单号 |
这一约束在源码中有明确校验:以 JSAPI 场景的 Jsapi 关闭订单插件 为例,插件从请求载荷中读取out_trade_no,若为空则直接抛出InvalidParamsException(错误码PARAMS_NECESSARY_PARAMS_MISSING),提示“Jsapi 关闭订单,参数缺少out_trade_no”。因此调用前务必确认订单号不为空且与支付下单时保持一致。
APP / 小程序订单关闭
默认情况下,close关闭的是JSAPI(公众号)订单;如果你需要关闭APP或小程序场景的订单,请传入场景标识参数:
// 关闭 APP 支付订单 $result = $wechat->close([ 'out_trade_no' => '1514027114', 'type' => 'app', ]); // 关闭小程序支付订单 $result = $wechat->close([ 'out_trade_no' => '1514027114', 'type' => 'miniapp', ]);即通过['type' => 'app']与['type' => 'miniapp']分别指定 APP 与小程序关单场景。
从当前仓库源码结构看,v3 版本已将场景分发机制统一收敛为
_action参数(jsapi/app/mini/h5/native/combine),详见下文「场景分发」小节与 微信关闭订单 v3 文档;v2 文档中的type写法保留了旧版本的调用习惯,两者表达的是同一组场景语义。
返回值与异常处理
close返回Yansongda\Supports\Collection类型的实例,你可以通过属性方式访问服务器返回的数据:
$result = $wechat->close(['out_trade_no' => '1514027114']); // 例如判断关单是否成功、读取微信返回的相关字段 // $result->xxx需要特别留意的是关闭订单接口的返回语义:微信关单接口在成功时返回 HTTP 204 状态码、响应体为空。从 微信 Provider 的 close 实现 可以看出,close在内部派发MethodCalled事件并执行关单链路后,返回的是new Collection()(空集合),而不是携带业务字段的完整响应。因此实践中判断关单是否成功,应依赖是否抛出异常而非响应内容:
- 若请求链路无异常,说明关单请求已被微信受理(HTTP 2xx);
- 若参数缺失(如无
out_trade_no),会抛出InvalidParamsException; - 若微信返回状态码异常,则由 微信响应插件 统一拦截,抛出
InvalidResponseException(错误码RESPONSE_CODE_WRONG),提示“微信返回状态码异常,请检查参数是否错误”。
调用时建议用 try/catch 包裹并记录异常,避免关单失败被静默吞掉。
源码级原理:close 的插件执行链
在 Pay v3 架构中,close最终由Yansongda\Pay\Shortcut\Wechat\CloseShortcut编排一组插件完成。以默认(JSAPI)场景为例,CloseShortcut 的 jsapiPlugins() 返回的插件链依次为:
StartPlugin → JsapiClosePlugin(组装请求:URL、方法、mchid) → AddPayloadBodyPlugin(组装请求体) → AddPayloadSignaturePlugin(对载荷签名) → AddRadarPlugin(生成 Guzzle 请求) → VerifySignaturePlugin(校验微信响应签名) → ResponsePlugin(校验 HTTP 状态码) → ParserPlugin(解析响应为 Collection)这一插件链在 CloseShortcut 测试用例 中有完整断言,可作为理解请求链路的直接证据。
场景分发
CloseShortcut::getPlugins() 是整个关单逻辑的分发中枢,它支持两类触发方式:
- 自动识别合单:只要参数中包含
combine_out_trade_no或sub_orders,就自动走合单关单插件链(对应测试 testCombineParams); _action显式指定场景:取值与 WechatAction 中 CLOSE_ 系列常量 一一对应,包括default(默认,等价于 jsapi)、app、h5、jsapi、mini、native、combine;传入未知场景(如virtual、foo)则抛出InvalidParamsException(错误码PARAMS_SHORTCUT_ACTION_INVALID),测试见 testVirtual 与 testFoo。
各场景请求地址(来自源码)
| 场景 | 插件类 | 请求接口(普通商户/服务商) |
|---|---|---|
| JSAPI(默认) | Jsapi/ClosePlugin | POST /v3/pay/transactions/out-trade-no/{out_trade_no}/close(服务商为partner路径) |
| APP | App/ClosePlugin | 同上 |
| H5 | H5/ClosePlugin | 同上 |
| 小程序 | Mini/ClosePlugin | 同上 |
| Native | Native/ClosePlugin | 同上 |
| 合单 | Combine/ClosePlugin | POST /v3/combine-transactions/out-trade-no/{combine_out_trade_no}/close |
普通商户模式下请求体仅包含mchid;而合单关单插件还会自动补上combine_appid(优先取参数中的值,否则回退到配置的公众号appid),并剔除combine_out_trade_no避免污染请求体,详见 合单关闭插件。
服务商模式说明
若你处于服务商(mode => 'service')模式下,各关单插件会在装配请求时自动切换到_service_url(/v3/pay/partner/transactions/...),且请求体由normal()变为service()组装:以 Jsapi 关闭插件的 service() 为例,会携带sp_mchid(服务商商户号)与sub_mchid(子商户商户号,优先取参数中的sub_mchid,否则回退到配置项),开发者无需手写两套请求逻辑。
相关阅读
- 微信概述与快速上手(配置、服务商模式)
- 微信支付下单 pay
- 微信订单查询 find
- 微信退款 refund
- 微信回调 callback
- v3 版本关闭订单(
_action场景分发与合单关单)
- 后端
- 金融科技
【免费下载链接】pay
可能是我用过的最优雅的 Alipay/WeChat/Unipay/江苏银行 的支付 SDK 扩展包了
相关推荐
微信支付订单关闭接口实战:Yansongda Pay SDK 的 close 方法详解与插件链源码解析
微信支付订单关闭接口实战:Yansongda Pay SDK 的 close 方法详解与插件链源码解析 本指南以仓库文档 web/docs/v2/wechat/
金融科技后端支付宝关闭订单实战指南:Yansongda Pay close 方法全场景解析
支付宝关闭订单实战指南:Yansongda Pay close 方法全场景解析 本文基于 Yansongda Pay(本仓库)讲解支付宝「关闭订单」能力:如何通
金融科技后端yansongda/pay 微信关闭订单(close)实战指南:普通订单、合单关闭与源码路由解析
yansongda/pay 微信关闭订单(close)实战指南:普通订单、合单关闭与源码路由解析 导读 本文聚焦 yansongda/pay(本仓库即该项目源码
金融科技后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考