PAYATHON 2026

支付宝沙盒网站支付报错 ACCESS_FORBIDDEN 如何解决?

支付小周

结论

ACCESS_FORBIDDEN 表示当前应用没有权限发起这笔网站支付。问题通常不在订单金额或商品名称,而在应用权限、支付接口与运行环境不匹配。

排查沙盒网站支付时,主要确认以下内容:

  • 请求是否发往沙盒网关;
  • app_id 是否属于当前沙盒应用;
  • 沙盒应用是否已配置“电脑网站支付”能力;
  • 是否调用 alipay.trade.page.pay,并将 product_code 设为 FAST_INSTANT_TRADE_PAY;
  • 应用私钥、支付宝公钥和 app_id 是否来自同一套沙盒配置;
  • 是否混用了正式环境的商户账号、买家账号或网关。

只看 appid: 2021000121686511 无法判断具体是哪项配置有误,还需要结合请求参数和支付宝开放平台中的应用能力逐项检查。

常见原因

1. 使用了错误的网关

沙盒环境应请求:

https://openapi.alipaydev.com/gateway.do

正式环境网关是:

https://openapi.alipay.com/gateway.do

如果使用沙盒 app_id 和密钥请求正式网关,或反过来混用,可能会出现权限不足、签名错误或应用不存在等问题。

2. 应用没有网站支付接口权限

网站支付主要使用以下接口:

alipay.trade.page.pay

应用还需要具备“电脑网站支付”能力。能够访问支付宝开放平台,不代表该应用可以调用所有支付接口。

进入支付宝开放平台的沙盒应用配置页面,查看应用能力或产品列表中是否包含电脑网站支付。开放平台的页面名称可能会调整,请以当前控制台显示的内容为准。

3. 接口或 product_code 使用错误

电脑网站支付通常使用以下配置:

method=alipay.trade.page.pay
product_code=FAST_INSTANT_TRADE_PAY

手机网站支付、App 支付和当面付各有对应的接口与参数,不能直接套用到电脑网站支付中。

例如:

alipay.trade.wap.pay
QUICK_WAP_WAY

这组配置对应手机网站支付,不适用于电脑网站支付。

4. 沙盒配置来自不同应用

以下配置必须属于同一个沙盒应用:

  • app_id
  • 应用私钥
  • 上传到开放平台的应用公钥
  • 根据应用公钥生成或显示的支付宝公钥

常见情况是重新生成密钥后只更新了部分配置,或者误用了另一个项目的支付宝公钥。这类问题通常表现为验签失败,但如果同时混用了环境和权限配置,也会增加排查难度。

5. 使用了不匹配的账号

沙盒支付需要使用开放平台提供的沙盒买家账号登录付款,不能直接使用真实支付宝买家账号。

还要确认当前配置的是沙盒商家应用,而不是正式应用的 app_id。

建议的排查顺序

第一步:确认请求环境

检查 SDK 初始化代码中的网关:

String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";

同时检查程序运行时实际加载的配置,不能只看配置文件。部署环境、环境变量或启动参数都可能覆盖本地配置。

可以在日志中记录以下非敏感信息:

gatewayUrl
appId
method
productCode
outTradeNo
signType

不要记录应用私钥。

第二步:确认接口参数

电脑网站支付的核心请求参数可参考:

{
  "out_trade_no": "ORDER_202609090001",
  "total_amount": "0.01",
  "subject": "沙盒测试订单",
  "product_code": "FAST_INSTANT_TRADE_PAY"
}

需要注意:

  • out_trade_no 由商户生成,并且在商户系统内必须唯一;
  • total_amount 使用字符串形式的金额;
  • subject 不能为空;
  • product_code 应设为 FAST_INSTANT_TRADE_PAY。

第三步:检查应用能力

在支付宝开放平台中打开 2021000121686511 对应的沙盒应用,然后依次确认:

  1. 当前处于沙盒环境;
  2. 应用状态正常;
  3. 应用能力中包含电脑网站支付;
  4. 实际调用的接口是 alipay.trade.page.pay;
  5. 应用公钥已经正确配置。

如果控制台中没有电脑网站支付能力,或者该沙盒应用不能调用相应接口,需要在控制台添加该能力,或重新创建并配置具备此能力的沙盒应用。

第四步:重新核对密钥

使用 RSA2 时,通常采用以下配置:

sign_type=RSA2
charset=UTF-8

三类密钥的用途不同:

  • 应用私钥保存在商户服务端,用于为请求签名;
  • 应用公钥需要上传到支付宝开放平台;
  • 支付宝公钥配置在商户服务端,用于验证支付宝的响应和通知。

“支付宝公钥”不是应用公钥,也不能直接从应用私钥中复制。

第五步:检查支付宝返回的原始信息

不要只记录前端页面显示的“订单信息有错误”。还应查看 SDK 返回值、网关响应和服务端日志,重点保留:

code
sub_code
msg
sub_msg
request_id

拿到 sub_code 和 sub_msg 后,通常可以进一步判断问题来自产品权限、接口权限、应用状态还是环境配置。

Java 调用示例

下面是沙盒电脑网站支付的基本调用示例。密钥和地址需要替换为自己的配置:

import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.response.AlipayTradePagePayResponse;

public class AlipaySandboxPagePay {

    public static void main(String[] args) throws Exception {
        String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
        String appId = "2021000121686511";
        String appPrivateKey = "YOUR_APP_PRIVATE_KEY";
        String alipayPublicKey = "YOUR_ALIPAY_PUBLIC_KEY";

        AlipayClient alipayClient = new DefaultAlipayClient(
                gatewayUrl,
                appId,
                appPrivateKey,
                "json",
                "UTF-8",
                alipayPublicKey,
                "RSA2"
        );

        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
        request.setReturnUrl("https://example.com/alipay/return");
        request.setNotifyUrl("https://example.com/alipay/notify");

        request.setBizContent("""
            {
              "out_trade_no": "ORDER_202609090001",
              "total_amount": "0.01",
              "subject": "沙盒网站支付测试",
              "product_code": "FAST_INSTANT_TRADE_PAY"
            }
            """);

        AlipayTradePagePayResponse response = alipayClient.pageExecute(request);

        if (response.isSuccess()) {
            // 将 body 作为 HTML 返回给浏览器,浏览器会跳转到支付宝收银台。
            System.out.println(response.getBody());
        } else {
            System.err.println("code: " + response.getCode());
            System.err.println("msg: " + response.getMsg());
            System.err.println("subCode: " + response.getSubCode());
            System.err.println("subMsg: " + response.getSubMsg());
        }
    }
}

在实际 Web 项目中,应以 text/html;charset=UTF-8 的内容类型将 response.getBody() 返回给浏览器,不要将它作为普通字符串处理,也不要再包一层 JSON。

注意事项

  • return_url 只负责支付完成后的浏览器跳转,不能作为判断支付成功的最终依据。
  • 订单状态应通过异步通知验签确认,也可以调用交易查询接口核实。
  • notify_url 通常需要使用支付宝服务器能够访问的公网 HTTPS 地址,本机 localhost 无法直接接收支付宝服务器发送的通知。
  • 修改应用公钥后,需要同步更新服务端使用的支付宝公钥,并检查程序是否仍在加载旧配置。
  • 正式环境和沙盒环境的 app_id、账号、密钥及网关不能混用。
  • 不要在日志、前端代码或代码仓库中暴露应用私钥。

如果网关、接口和参数均无误,但仍然返回 ACCESS_FORBIDDEN,应优先确认该沙盒应用是否具备电脑网站支付权限。核实时需要提供完整的 sub_code、sub_msg 和 request_id,可据此查询开放平台文档或联系支付宝技术支持确认具体的权限状态。

备注:内容仅供参考。