Alipay Easy SDK 手机网站支付提示商户未授权当前接口
结论
“手机网站支付签约成功”只说明商户已经具备使用该产品的资格,不代表商户授权了服务商应用代为调用支付接口。
如果程序使用服务商的 app_id,并通过服务商调用 Factory.Payment.Wap().pay(),常见原因包括:
- 商户还没有授权服务商的第三方应用;
- 商户授权过,但授权范围不包含手机网站支付相关接口;
- 请求中没有传入有效的
app_auth_token; app_auth_token与当前服务商应用、商户或运行环境不匹配。
这类问题通常不是手机网站支付漏签,而是“产品签约”和“应用授权”没有同时完成。
为什么签约成功仍会报未授权
支付宝服务商代商户调用接口时,需要两类独立权限:
-
产品权限
服务商应用需要具备相应能力,商户也要完成手机网站支付签约。
-
代调用授权
商户需要授权服务商应用调用相应接口。授权完成后,服务商会取得与该商户对应的
app_auth_token。
如果请求使用服务商的 app_id,却没有携带该商户对应的 app_auth_token,支付宝只能识别服务商应用,无法确认它是否有权代表目标商户调用接口,因此可能返回“商户未授权当前接口”。
商户 PID、商户 user_id 和 app_auth_token 是不同的参数,不能互相替代。
解决步骤
1. 确认当前调用模式
先检查程序使用的是哪个 app_id:
- 使用商户自己的
app_id和商户私钥直接调用,属于商户直连模式,一般不需要app_auth_token。 - 使用服务商的
app_id代商户调用,属于服务商代调用模式。商户必须完成应用授权,请求中也必须传入对应的app_auth_token。
如果使用的是第二种模式,再继续检查以下配置。
2. 检查服务商应用的能力配置
登录支付宝开放平台,确认服务商应用具备手机网站支付相关能力,并且应用状态正常。
只在服务商账号下看到“已开通手机网站支付”还不够,还要确认该能力已经配置到本次请求使用的应用。需要逐项核对:
- 页面显示的应用
app_id; - 程序中配置的
appId; - 签名所用的应用私钥;
- 支付宝公钥或支付宝证书;
- 请求使用的是生产环境还是沙箱环境。
这些配置必须来自同一个应用和同一个环境。
3. 让商户完成第三方应用授权
服务商需要生成商户授权链接,并让商户使用有权限的支付宝账号完成授权。
授权范围必须包含实际调用手机网站支付接口所需的权限。商户完成产品签约后,第三方应用授权不会自动完成。
如果商户以前授权过,还要检查:
- 授权对象是否为当前服务商应用;
- 授权是否失效或已被取消;
- 应用新增支付能力后,商户是否需要重新授权;
- 授权范围是否包含本次调用的接口。
4. 获取并保存正确的 app_auth_token
商户授权成功后,服务商应通过支付宝提供的授权换令牌流程,取得该商户对应的 app_auth_token。
保存令牌时,建议至少关联以下信息:
service_app_id
merchant_user_id
app_auth_token
expires_at
environment
不同商户的令牌不能混用,沙箱环境取得的令牌也不能用于生产环境。
5. 调用支付接口时传入授权令牌
服务商代调用时,需要通过 Easy SDK 的 agent() 方法传入该商户对应的 app_auth_token。
Java 示例:
AlipayTradeWapPayResponse response = Factory.Payment
.Wap()
.agent(appAuthToken)
.pay(
subject,
outTradeNo,
totalAmount,
quitUrl,
returnUrl
);
if (ResponseChecker.success(response)) {
String pageRedirectionData = response.getBody();
// 将 pageRedirectionData 返回给浏览器,完成支付页面跳转
} else {
System.out.println("code: " + response.getCode());
System.out.println("subCode: " + response.getSubCode());
System.out.println("msg: " + response.getMsg());
System.out.println("subMsg: " + response.getSubMsg());
}
其中:
appAuthToken
必须是当前商户授权当前服务商应用后取得的令牌,不能填写商户 PID,也不能填写商户自己的 app_id。
不同语言或 Easy SDK 版本的方法签名可能不同,具体应以项目实际安装版本的 SDK 定义为准。核心要求不变:服务商代调用时必须携带 app_auth_token。
如果使用商户直连模式
如果不需要服务商代调用,可以改用商户直连模式。此时需要使用:
- 商户自己的
app_id; - 商户应用对应的私钥;
- 商户应用配置的支付宝公钥或证书;
- 商户应用自身开通的手机网站支付能力。
示例:
AlipayTradeWapPayResponse response = Factory.Payment
.Wap()
.pay(
subject,
outTradeNo,
totalAmount,
quitUrl,
returnUrl
);
这种模式通常不调用 agent()。不过,不能只删除 agent(),却仍用服务商的 app_id 代商户收款,否则调用主体还是不正确。
排查时重点查看返回字段
不要只看错误页面上的中文提示,还应记录支付宝返回的完整错误信息:
System.out.println(response.getCode());
System.out.println(response.getSubCode());
System.out.println(response.getMsg());
System.out.println(response.getSubMsg());
排查时重点确认:
- 请求中的
app_id属于服务商应用还是商户应用; - 是否传入了
app_auth_token; - 令牌对应的商户是否正确;
- 令牌是否仍然有效;
- 商户授权范围是否包含当前接口;
- 手机网站支付的签约主体是否与实际收款主体一致;
- 是否混用了沙箱和生产环境;
- 应用私钥、证书是否与
app_id配套。
注意事项
app_auth_token 是敏感凭证,不能写入前端页面、URL、公开日志或客户端代码,只能保存在服务端并由服务端使用。
目前的错误描述没有提供完整的 sub_code、请求参数和 SDK 配置,仅凭中文提示还不能确定具体缺少哪项权限。不过,在服务商应用代商户调用的情况下,应先检查商户的第三方应用授权和 app_auth_token,不必反复重新签约手机网站支付。
备注:内容仅供参考。
