第三方代开发小程序调用支付接口时报权限不足
结论
isv.self-invoke-forbidden 表示第三方应用正以服务商自身的身份调用不允许“自调用”的支付宝开放接口。
在第三方代开发场景中,支付交易应由已授权的商家账号发起。服务商需要先取得商家的应用授权,再在服务端调用支付接口时传入该商家对应的 app_auth_token。服务商不能用自己的支付宝账号给自己的第三方应用授权,也不能省略 app_auth_token,直接调用仅支持代商家执行的接口。
报错原因
支付宝开放平台通常会区分两个主体:
- 服务商:创建第三方应用,为商家代开发并代为调用接口。
- 商家:实际收款,并授权服务商调用接口。
如果出现以下错误:
ERROR_GATEWAY: Get Alipay API Error:Insufficient Permissions - isv.self-invoke-forbidden
常见原因有:
- 调用支付接口时没有传入
app_auth_token,网关因此将请求识别为服务商自身调用。 app_auth_token来自服务商自己的支付宝账号,形成了第三方应用自授权、自调用。- 使用了其他商家的
app_auth_token,或者令牌与当前第三方应用不匹配。 - 商家尚未完成应用授权,授权已经失效,或授权范围不包含当前调用的接口。
- SDK 初始化时使用了错误的
app_id,例如混用了第三方应用、普通应用或商家小程序的应用 ID。 - 混用了沙箱和正式环境的应用、账号、网关地址或授权令牌。
这个错误通常不是前端吊起收银台的代码造成的。问题一般出在服务端创建交易时,支付宝网关无法确认有效的商家授权关系。
解决步骤
1. 确认调用模式
如果服务商通过第三方应用代商家创建交易,需要使用:
- 第三方应用的
app_id - 第三方应用对应的私钥和支付宝公钥
- 商家授权后生成的
app_auth_token
不要直接用第三方应用 ID 替换商家的应用 ID,也不要把 auth_token、用户访问令牌等其他令牌当作 app_auth_token。
2. 让商家完成应用授权
商家需要使用自己的支付宝账号进入授权页面,授权第三方应用代其调用相应接口。
商家账号与服务商账号必须属于不同的业务主体。如果服务商用自己的支付宝账号完成授权,网关可能会将其判定为自调用,并返回 isv.self-invoke-forbidden。
授权完成后,服务商应按照支付宝开放平台规定的授权流程取得并保存:
app_auth_token
app_refresh_token
expires_in
re_expires_in
具体返回字段和有效期以当前使用的授权接口及支付宝开放平台文档为准。
3. 在支付请求中传入商家的 app_auth_token
下面是 Java SDK 的示意写法。类名和方法重载可能因 SDK 版本不同而略有差异:
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do",
ISV_APP_ID,
ISV_PRIVATE_KEY,
"json",
"UTF-8",
ALIPAY_PUBLIC_KEY,
"RSA2"
);
AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
request.setBizContent("""
{
"out_trade_no": "ORDER_202609090001",
"total_amount": "0.01",
"subject": "测试订单",
"buyer_id": "支付宝用户ID"
}
""");
// 必须是当前商家授权第三方应用后取得的令牌
request.putOtherTextParam("app_auth_token", merchantAppAuthToken);
AlipayTradeCreateResponse response = alipayClient.execute(request);
if (!response.isSuccess()) {
throw new RuntimeException(
response.getCode() + ": " +
response.getSubCode() + " - " +
response.getSubMsg()
);
}
部分 SDK 提供包含 app_auth_token 参数的 execute 重载,可以根据所用版本采用以下写法:
AlipayTradeCreateResponse response =
alipayClient.execute(request, null, merchantAppAuthToken);
选择其中一种写法即可,不要通过两种方式传入不同的令牌。
4. 使用创建交易返回的交易号吊起支付
服务端成功调用 alipay.trade.create 后,需要将支付宝返回的交易号交给小程序前端:
my.tradePay({
tradeNO: tradeNo,
success: (result) => {
console.log(result);
},
fail: (error) => {
console.error(error);
}
});
前端应传入支付宝返回的交易号,例如 trade_no 对应的值,而不是商户自行生成的订单号 out_trade_no。具体字段名称以当前 SDK 的返回对象为准。
排查清单
如果已经传入 app_auth_token,但仍然报错,可以依次检查:
- SDK 中的
app_id是否确实属于第三方应用。 app_auth_token是否由目标收款商家授权产生。- 授权商家与服务商是否为同一账号或同一自调用主体。
- 令牌是否已经过期、被撤销,或因重新授权而失效。
- 商家的授权范围是否覆盖当前支付接口。
- 当前应用是否已经申请并开通所需的产品能力。
- 请求使用的是正式网关还是沙箱网关。
- 应用密钥、支付宝公钥、应用 ID 和授权令牌是否来自同一环境。
- 订单中的收款主体是否与授权商家一致。
- 服务端是否确实将
app_auth_token发送给了支付宝,而不是只将其保存在本地。
建议记录支付宝响应中的以下字段,方便定位问题:
code
msg
sub_code
sub_msg
还应保留支付宝网关返回的请求流水信息,但不要在日志中完整输出私钥、app_auth_token 或 app_refresh_token。
注意事项
app_auth_token 是商家级授权凭证。如果多个商家使用同一个第三方应用,需要按商家分别保存和读取令牌,不能共用一个固定令牌。
前端小程序不应持有 app_auth_token、应用私钥或签名逻辑。创建交易、签名以及调用支付宝开放接口,都应在服务端完成。
如果当前业务不是“第三方应用代商家调用”,而是商家使用自有小程序直接收款,需要重新核对应用类型和接入模式。此时通常不应强行采用第三方代调用流程。
如果已经确认应用、商家授权、令牌和环境完全匹配,但仍然返回 isv.self-invoke-forbidden,需要携带应用 ID、接口名称、调用时间、网关响应字段和请求流水号,联系支付宝开放平台技术支持核查具体的权限配置。不要提交应用私钥或完整的授权令牌。
备注:内容仅供参考。
