支付宝沙箱创建小程序支付订单提示ISV权限不足
结论
问题不在网关地址,也不是 access_token 获取失败。出现 ISV权限不足,通常有两种原因:发起 alipay.trade.create 请求的应用尚未开通小程序支付能力,或者应用、沙箱商家账号和授权令牌的归属关系不一致。
alipay.system.oauth.token 返回的是用户授权信息。成功获取令牌,只能说明用户授权流程正常,不能证明当前 APPID 有权创建支付订单。
原因分析
创建支付宝小程序支付订单至少涉及三类相互独立的权限:
-
用户授权
通过
alipay.system.oauth.token换取access_token和user_id,用于识别付款用户。 -
应用支付能力
调用
alipay.trade.create的应用,必须在支付宝开放平台添加并启用对应的支付能力。小程序可以登录或获取用户信息,不等于已经具备交易权限。 -
商家或第三方应用授权
如果应用以 ISV(第三方服务商)模式代商家调用接口,还需要完成商家应用授权,并在请求中传入有效的
app_auth_token。用户的access_token不能替代app_auth_token。
所以,即使沙箱网关、签名和用户授权均正常,只要支付产品没有开通,或调用身份不匹配,接口仍会返回 ISV权限不足。
排查与解决步骤
1. 检查小程序支付能力
登录支付宝开放平台,找到沙箱小程序 2021000117610050 对应的应用,查看“产品绑定”“功能列表”或“能力管理”中的支付能力。
需要确认:
- 已添加适用于小程序场景的支付产品或支付能力;
- 该能力已经生效,不处于待签约、待审核或未生效状态;
- 签约主体与当前沙箱商家账号一致;
alipay.trade.create包含在已开通产品的接口范围内。
如果控制台中没有相应能力,需要先添加,并完成沙箱环境要求的签约或授权流程。
2. 确认调用的是沙箱应用
请求中的 app_id 必须是:
2021000117610050
还要确认:
- 使用的是该沙箱应用对应的应用私钥;
- 支付宝公钥或支付宝公钥证书来自同一个沙箱应用;
- 请求发送到沙箱网关;
- 没有在沙箱请求中混入正式环境的 APPID、证书、商家账号或令牌。
典型的沙箱网关地址是:
https://openapi-sandbox.dl.alipaydev.com/gateway.do
网关地址正确,只能说明请求发到了沙箱,不能解决产品权限问题。
3. 区分两种令牌
用户授权令牌和商家应用授权令牌不能混用:
| 令牌 | 获取接口 | 主要用途 |
|---|---|---|
access_token | alipay.system.oauth.token | 获取用户信息、识别授权用户 |
app_auth_token | alipay.open.auth.token.app | ISV 代商家调用开放接口 |
创建小程序支付订单时,一般需要把用户授权返回的 user_id 填入 buyer_id。access_token 本身通常不是 alipay.trade.create 的业务参数。
如果由第三方应用代商家创建订单,还需要在公共请求参数中传入商家授权得到的 app_auth_token。
4. 核对应用模式
如果是商家自研小程序,需要确认支付能力直接开通在该小程序及其所属商家主体下。
如果是第三方应用或服务商应用,则需要逐项确认:
- 商家已经完成应用授权;
app_auth_token属于当前沙箱商家;- 授权关系仍然有效;
- 授权应用与请求中的
app_id一致; - 被授权商家也具备相应的支付产品权限。
报错中的 ISV 不一定说明网关配置有问题。更常见的情况是,支付宝按第三方应用调用链校验权限时,没有找到有效的授权关系。
Java 调用示例
下面的示例只保留了关键参数。私钥、公钥、订单号和金额需要替换为实际的沙箱数据。
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi-sandbox.dl.alipaydev.com/gateway.do",
"2021000117610050",
APP_PRIVATE_KEY,
"json",
"UTF-8",
ALIPAY_PUBLIC_KEY,
"RSA2"
);
AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
request.setNotifyUrl("https://example.com/alipay/notify");
AlipayTradeCreateModel model = new AlipayTradeCreateModel();
model.setOutTradeNo("TEST_ORDER_202609090001");
model.setTotalAmount("0.01");
model.setSubject("沙箱小程序支付测试");
model.setBuyerId(BUYER_USER_ID);
request.setBizModel(model);
// 商家自研应用通常直接调用
AlipayTradeCreateResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
System.out.println("trade_no: " + response.getTradeNo());
} else {
System.out.println("code: " + response.getCode());
System.out.println("sub_code: " + response.getSubCode());
System.out.println("sub_msg: " + response.getSubMsg());
}
如果采用 ISV 代商家调用模式,需要传入商家的 app_auth_token。不同版本的 Java SDK 可能采用不同的重载方法,常见写法如下:
AlipayTradeCreateResponse response =
alipayClient.execute(request, null, APP_AUTH_TOKEN);
具体写法应以当前使用的支付宝 Java SDK 方法签名为准。
建议保留的排查信息
完成上述检查后如果仍然报错,向支付宝技术支持提交问题时,应提供以下信息:
- 沙箱小程序 APPID;
- 接口名称
alipay.trade.create; - 完整的
code、sub_code和sub_msg; - 响应中的
request_id; - 请求时间;
- 是否使用了
app_auth_token; - 当前应用是商家自研应用还是第三方应用;
- 控制台中支付能力及签约状态的截图。
不要公开应用私钥、AES 密钥,以及完整的 access_token 或 app_auth_token。
注意事项
- 成功获取
access_token,不代表支付权限已经开通。 buyer_id应使用当前支付宝环境返回的用户 ID,不能混用正式环境中的用户数据。- 沙箱应用、沙箱商家账号、密钥和授权令牌必须属于同一套环境。
- 如果控制台显示支付能力已经生效,但接口仍返回权限错误,需要根据响应中的
sub_code和request_id,请支付宝侧查询具体的权限链路。仅凭ISV权限不足,无法继续判断问题是支付产品未开通、商家未授权,还是应用归属不一致。
备注:内容仅供参考。
