微信 商户发起催收扣款API 属于微信支付分 v3 接口,比较适合商户后续主动调起支付的场景。之前不知道从什么地方看到了这个接口,对比文档的下标 chapter6_1_19 可以判断这个接口之前是紧跟着 完结支付分订单API 后面的,现在微信已经把它从支付分文档中踢出来了。

通过 创建微信支付分订单 curl 请求后处理返回数据 获取到支付分返回数据:

$resultArr = json_decode($result['body'], true);

验签之后,根据接口返回数据做响应:

if (isset($resultArr['code'])) {
    return $this->response(false, $resultArr['message'], $resultArr);
} else {
    return $this->response(true, "", $resultArr);
}

这边 code 存在就表示会有错误,正常(成功的)情况是没有 code 返回的。

但最近突然发现,一些订单明明没有支付成功,但消费订单还是被标记成了已支付。查找相关逻辑发现,这边催收的接口因为返回了 {"trade_state":"USERPAYING"} 判断出现了 bug。因为没有 code 返回所以我当成它是支付成功了。

从词义上看,这个是说用户在支付中的意思,但微信这种不返回错误码的形式还是让我不解。找在线客服一番操作后,得到了肯定的答复:

微信在线客服聊天记录

多次观察下,这种返回应该是传说中的中间态了,短时间多次就会返回这个信息,且持续时间较长。之前是没有这个东西的,这不跟防止客户端重复提交一样的处理嘛,猜测是微信觉得这个主动接口调用次数太多,太频繁有点烦了,商户自由度太大,就管控了。

找到原因,剩下的就是适配了:

if ((isset($resultArr['code']) {
    return $this->response(false, $resultArr['message'], $resultArr);
} elseif (isset($resultArr['trade_state']) && $resultArr['trade_state'] == 'USERPAYING') {
    return $this->response(false, 'USER PAYING.', $resultArr);
}  else {
    return $this->response(true, "", $resultArr);
}