接入前需要明确的一点:支付宝文档也是可以有错误的。

结合 接入指南 中的 Java 示例代码 与 alipay.fund.auth.order.app.freeze(线上资金授权冻结接口) 中的 PHP 版本示例,得到了一个初版的 demo。请求参数中的必选项可以参考 Java 示例,payee_logon_idpayee_user_id 是商户开通花呗支付渠道时二选一,extraParamcategory 为必选项,根据实际项目类型对应的参数填写。因为需要使用芝麻信用服务,所以,extraParam 中的信用服务ID serviceId 也是必选项。

接入指南中指明需要执行 sdkExecute 方法,但接口中各个版本的 demo 使用的都是 execute 方法。

决定先跟着 demo 走,执行 demo 报错,返回参数与接口异常示例基本一致。

{
    "alipay_fund_auth_order_app_freeze_response": {
        "code": "20000",
        "msg": "Service Currently Unavailable",
        "sub_code": "isp.unknow-error",
        "sub_msg": "系统繁忙"
    },
    "sign": "ERITJKEIJKJHKKKKKKKHJEREEEEEEEEEEE"
}

无论怎么调整参数,返回的都是这个报错结果。结合小程序前端文档里需求是支付字符串 orderStr,修改 execute 为 sdkExecute 方法。该方法实际并未请求支付宝服务器,而是在服务端根据参数生成签名并组装连接成 url 格式的字符串,最后返回前端,由小程序端发起支付(实际是预授权申请)。

前端拿到 orderStr 字符串之后发起支付后,返回报错:抱歉,芝麻信用综合评估不通过,请选择商户支持的其他方式使用服务。从字面上判断是用户的芝麻信用不符合商户设置的信用标准。反复检查支付宝后台设置的信用服务(前面用的 serviceId ,就是之前申请得到的)配置,芝麻分和免押金额毫无疑问是符合要求的。最后反复检查终于发现了问题所在:提交的 extraParam 参数中的 category 与申请的 serviceId 对应的信用服务类型不一致。原来是之前测试参数时错把 product_code 当成 category 替换了,修改之后前端可以完成预授权的调起。

预授权成功后,可以由前端调接口将成功消息返回(但似乎缺少关键的 auth_no 参数),也可以在服务端返回的 orderStr 中添加 notifyUrl 参数,通过支付宝的异步通知:

$request->setNotifyUrl($notifyUrl);

在设置了回调地址之后,又遇到了一个问题,回调一直没有接受到消息。具体解决方法:支付宝 API 收不到异步通知问题排查,我的问题主要是写错了路由类型,支付宝回调(异步通知)必须是 post 类型来接受数据

所以,回调方法中要去 post 数据,并且最后要返回 'success' 字符串,不然支付宝会间隔一段时间,重复发送通知。