PAYATHON 2026

支付宝沙箱扫码付V3接口报错ACCESS_FORBIDDEN

支付小周

结论

ACCESS_FORBIDDEN 通常不是 V3 签名或接口地址有误,而是支付宝识别到当前请求中的 app_id、沙箱商户身份与接口产品权限不匹配。

gateway.do 测试成功,不代表 V3 请求使用了同一套身份,也不能说明 alipay.trade.pay 已获得授权。排查时应重点确认:

  1. V3 请求实际使用的 app_id 是否属于当前沙箱应用。
  2. 该应用绑定的沙箱商户是否已开通“当面付/条码支付”能力。
  3. 是否选对了接口。商户扫描顾客付款码使用 alipay.trade.pay;顾客扫描商户二维码通常使用 alipay.trade.precreate。

为什么测试工具成功,V3 仍然失败

gateway.do 是传统开放平台网关地址,V3 接口通过 REST 路径调用:

https://openapi-sandbox.dl.alipaydev.com/v3/alipay/trade/pay

两种调用方式可能采用不同的应用配置、证书、SDK 配置文件或授权令牌。网页测试工具往往会自动填入当前沙箱应用的信息,本地 V3 请求则可能加载了另一套 app_id 或证书。

还要确认网页工具测试的是否为同一个 API。以下接口用途不同:

  • alipay.trade.pay:商户设备读取顾客的付款码,提交 auth_code 完成支付。
  • alipay.trade.precreate:商户生成二维码,由顾客使用支付宝扫码付款。
  • alipay.trade.page.pay、alipay.trade.wap.pay:用于电脑网站或手机网站支付。

如果网页工具成功调用的是其他接口,只能说明那个接口可用,不能证明 alipay.trade.pay 已获得权限。

建议的排查顺序

1. 确认扫码方向与接口一致

如果业务流程是“顾客扫描商户展示的二维码”,应调用:

POST /v3/alipay/trade/precreate

如果业务流程是“收银设备扫描顾客的支付宝付款码”,才应调用:

POST /v3/alipay/trade/pay

不能只根据“扫码付”这个名称选择接口。扫码方向不同,对应的 API 也不同。

2. 对比两次请求的应用身份

分别记录网页测试工具和本地程序使用的以下信息:

app_id
接口名称
沙箱环境
应用证书序列号
app_auth_token(如有)

检查程序运行时最终读取到的配置,不要只看配置文件中的值。常见问题有:

  • 加载了生产环境的 app_id,请求的却是沙箱地址。
  • 使用了另一个沙箱应用的证书或私钥。
  • 环境变量覆盖了配置文件。
  • 多套配置同时存在,程序实际加载的是旧配置。
  • 服务商代调用时携带了错误的 app_auth_token。
  • 测试工具与程序调用的 API 不一致。

3. 检查沙箱应用的产品权限

进入支付宝开放平台的沙箱应用,确认权限开通在当前 app_id 上,而不是其他应用或生产应用上。

alipay.trade.pay 一般依赖当面付中的条码支付能力。某个接口出现在接口列表中,不一定表示当前沙箱商户身份已经获得对应的产品权限。权限状态发生变化后,还需要重新进入沙箱环境,确认应用与沙箱商户的绑定关系。

4. 检查 V3 证书配置

V3 证书模式通常需要正确配置:

  • 应用私钥
  • 应用公钥证书
  • 支付宝公钥证书
  • 支付宝根证书
  • 当前沙箱应用的 app_id

这些证书必须属于同一个沙箱应用,不能混用生产证书、其他应用的证书或旧证书。

证书序列号错误通常会先表现为验签或认证错误。不过,证书配置混乱也可能导致请求以非预期的应用身份发出,因此仍需逐项核对。

5. 检查请求参数是否符合条码支付场景

alipay.trade.pay 的请求体通常包含 out_trade_no、total_amount、subject、scene 和 auth_code。例如:

{
  "out_trade_no": "TEST_202609090001",
  "total_amount": "0.01",
  "subject": "沙箱条码支付测试",
  "scene": "bar_code",
  "auth_code": "沙箱买家付款码"
}

需要注意:

  • scene 应与条码支付场景一致,通常为 bar_code。
  • auth_code 必须来自当前沙箱买家环境,并及时使用。
  • out_trade_no 应保持唯一,重复测试时不能一直使用同一个订单号。
  • 金额建议使用字符串表示,以免出现浮点数精度问题。

请求体正确也无法绕过产品权限检查。如果当前身份没有获得授权,接口仍会返回 ACCESS_FORBIDDEN。

代码中应记录哪些信息

不要输出私钥、完整付款码或敏感授权令牌,但应保留必要的接口诊断信息:

log.info("alipay gateway={}", gateway);
log.info("alipay appId={}", appId);
log.info("alipay api={}", "alipay.trade.pay");
log.info("alipay outTradeNo={}", outTradeNo);
log.info("alipay httpStatus={}", httpStatus);
log.info("alipay responseBody={}", responseBody);
log.info("alipay traceId={}", responseHeaders.get("alipay-trace-id"));

使用服务商代调用时,还应确认是否携带了应用授权令牌:

log.info("use appAuthToken={}", appAuthToken != null && !appAuthToken.isBlank());

日志只需记录令牌是否存在,不要打印令牌内容。

最小化验证方法

可以建立一组条件一致的对照测试:

  1. 在网页工具中明确选择 alipay.trade.pay。
  2. 使用与本地程序完全相同的 app_id。
  3. 确认两边都连接沙箱环境。
  4. 使用同一个沙箱商户和沙箱买家。
  5. 暂时移除本地请求中非必要的服务商授权配置。
  6. 重新生成订单号和沙箱付款码后再测试。
  7. 保存完整响应、HTTP 状态码,以及响应头中的链路标识。

如果网页工具使用同一个 app_id 调用 alipay.trade.pay 可以成功,而 V3 仍返回 ACCESS_FORBIDDEN,应继续核对 V3 请求实际使用的身份信息。

如果应用、证书、商户、产品权限和接口场景都完全一致,接口仍无法调用,可以携带以下信息向支付宝开放平台技术支持查询后台授权状态:

沙箱 app_id
调用接口名称
请求时间
out_trade_no
完整错误码和错误信息
响应中的 trace/request ID
是否携带 app_auth_token

不要提交应用私钥、完整付款码或完整授权令牌。仅凭客户端报错无法确定支付宝侧具体的产品授权状态,应以开放平台后台或技术支持的查询结果为准。

备注:内容仅供参考。