支付宝小程序沙箱调用 AlipayTradeCreateRequest 提示 ACCESS_FORBIDDEN
结论
ACCESS_FORBIDDEN 通常说明当前应用没有调用 alipay.trade.create 的权限,或者应用、商户账号、签名与沙箱环境之间的授权关系不匹配。这个错误一般不是订单金额、标题等业务参数填写不当导致的。
接口代码无法自行开通应用权限,仅凭沙箱 AppID 2021000121688163 也不能直接获得权限。请在支付宝开放平台检查该沙箱应用是否具备相应的支付能力,并确认应用已正确绑定沙箱商户。如果后台没有相关能力的开通入口,或者配置无误后仍然被拒绝,需要携带完整错误信息联系支付宝开放平台技术支持。
先查看完整错误信息
不要只记录 ACCESS_FORBIDDEN。服务端应保留支付宝返回的完整响应,重点检查以下内容:
codemsgsub_codesub_msgrequest_id- 实际请求使用的
app_id - 请求网关地址
sub_code 和 sub_msg 通常比主错误码更能说明具体原因。如果没有完整响应,只能把问题初步归为权限或授权链路异常,无法进一步确认是未签约、账号未绑定,还是沙箱不支持该能力。
AlipayTradeCreateResponse response = alipayClient.execute(request);
System.out.println("code: " + response.getCode());
System.out.println("msg: " + response.getMsg());
System.out.println("subCode: " + response.getSubCode());
System.out.println("subMsg: " + response.getSubMsg());
System.out.println("body: " + response.getBody());
在生产环境中,不要将私钥、用户授权令牌或完整的敏感支付信息写入日志。
排查和处理步骤
1. 确认使用的是沙箱网关
沙箱应用必须请求以下沙箱网关:
https://openapi-sandbox.dl.alipaydev.com/gateway.do
如果使用沙箱 AppID 请求正式环境网关,应用身份与权限将无法对应。正式应用同样不能直接使用沙箱配置。
2. 核对实际发送的 AppID
确认 SDK 初始化时实际使用的是:
2021000121688163
除了检查配置文件,还要确认正在运行的服务没有读到其他环境变量、旧配置或正式环境的 AppID。
3. 检查应用支付能力
登录支付宝开放平台,在该沙箱应用的能力或产品配置中,检查是否已具备小程序支付以及调用 alipay.trade.create 所需的权限。
拥有沙箱 AppID 并不等于自动获得所有开放接口的权限。应用类型、产品签约状态和沙箱能力范围不同,可使用的接口也可能不同。如果控制台没有相关能力入口,应通过开放平台工单确认该应用类型是否支持此接口,不必反复修改订单参数。
4. 检查沙箱商户绑定关系
确认以下信息都属于同一套沙箱环境:
- 沙箱应用 AppID
- 沙箱商户账号
- 应用公钥及支付宝公钥
- 沙箱买家账号
- 用户标识
buyer_id
如果 buyer_id 来自正式环境、另一个沙箱应用或无关账号,即使格式正确,也可能造成授权或交易链路失败。
5. 核对密钥配置
使用支付宝公钥模式时,SDK 中应填写”支付宝公钥”,不要误填应用公钥。应用私钥也必须与开放平台中配置的应用公钥配对。
签名有误时,支付宝通常会返回更明确的验签错误。不过,排查 ACCESS_FORBIDDEN 时仍需确认以下配置:
sign_type是否为应用配置支持的类型,通常为RSA2- 字符集是否为
UTF-8 - 应用私钥是否属于当前 AppID
- 支付宝公钥是否来自当前沙箱应用配置
6. 重新生成请求后再测试
修改应用能力、绑定关系或密钥后,请重新启动服务,避免程序继续使用缓存中的旧配置。再次测试时还应更换 out_trade_no,以免重复订单号影响判断。
Java 调用示例
以下代码只展示服务端的调用结构。APP_PRIVATE_KEY、ALIPAY_PUBLIC_KEY 和 buyer_id 必须替换为当前沙箱环境中的真实配置。
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeCreateModel;
import com.alipay.api.request.AlipayTradeCreateRequest;
import com.alipay.api.response.AlipayTradeCreateResponse;
public class SandboxTradeCreateExample {
private static final String GATEWAY =
"https://openapi-sandbox.dl.alipaydev.com/gateway.do";
private static final String APP_ID = "2021000121688163";
private static final String APP_PRIVATE_KEY = "YOUR_APP_PRIVATE_KEY";
private static final String ALIPAY_PUBLIC_KEY = "YOUR_ALIPAY_PUBLIC_KEY";
public static void main(String[] args) throws AlipayApiException {
AlipayClient alipayClient = new DefaultAlipayClient(
GATEWAY,
APP_ID,
APP_PRIVATE_KEY,
"json",
"UTF-8",
ALIPAY_PUBLIC_KEY,
"RSA2"
);
AlipayTradeCreateModel model = new AlipayTradeCreateModel();
model.setOutTradeNo("sandbox_order_202609090001");
model.setTotalAmount("0.01");
model.setSubject("沙箱支付测试");
model.setBuyerId("SANDBOX_BUYER_ID");
AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
request.setBizModel(model);
AlipayTradeCreateResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
System.out.println("tradeNo: " + response.getTradeNo());
System.out.println("outTradeNo: " + response.getOutTradeNo());
} else {
System.out.println("code: " + response.getCode());
System.out.println("msg: " + response.getMsg());
System.out.println("subCode: " + response.getSubCode());
System.out.println("subMsg: " + response.getSubMsg());
System.out.println("body: " + response.getBody());
}
}
}
小程序端注意事项
AlipayTradeCreateRequest 应由服务端发起。不要在小程序前端保存应用私钥,也不要在前端直接拼装签名请求。可以按以下流程处理:
- 小程序获取用户身份信息。
- 服务端校验用户身份,取得当前环境可用的
buyer_id。 - 服务端调用
alipay.trade.create创建交易。 - 服务端将支付所需信息返回给小程序。
- 小程序调用相应的支付能力完成付款。
如果把私钥放入小程序代码,用户可以通过反编译或抓包获得私钥,进而伪造支付请求。
仍然报错时如何提交工单
如果已经确认网关、AppID、密钥、商户绑定和支付能力均无误,但接口仍返回 ACCESS_FORBIDDEN,可以向支付宝开放平台技术支持提交以下信息:
- 沙箱 AppID:
2021000121688163 - 接口名称:
alipay.trade.create - 完整的
code、msg、sub_code、sub_msg request_id- 请求发生时间
- 沙箱网关地址
- 已脱敏的请求参数
- 应用能力配置页面截图
不要在工单或公开页面中提交应用私钥。该沙箱应用能否补充相应权限,需要由支付宝开放平台根据应用类型、产品状态和沙箱支持范围确认。
备注:内容仅供参考。
