调用 alipay.trade.wap.pay 提示 ACCESS_FORBIDDEN
结论
已经开通”手机网站支付”却仍然返回 ACQ.ACCESS_FORBIDDEN,应先检查实际调用的接口是否与已签约产品一致,而不是先排查签名。
返回报文的根节点是:
"alipay_trade_precreate_response"
这说明支付宝实际处理的是 alipay.trade.precreate,并非问题中提到的 alipay.trade.wap.pay。
这两个接口用于不同的支付场景:
alipay.trade.wap.pay:手机网站支付,通常返回可跳转至支付宝收银台的表单或 URL。alipay.trade.precreate:当面付预创建,通常用于生成付款二维码。
如果商户只开通了手机网站支付,实际发送的却是 alipay.trade.precreate,而对应的应用或商户没有当面付相关权限,就会返回:
ACQ.ACCESS_FORBIDDEN
优先检查实际调用的方法
除了业务代码中声明的方法名,还要确认最终发往支付宝网关的 method 参数。
调用手机网站支付时,该参数应为:
method=alipay.trade.wap.pay
如果请求或响应中出现以下内容,说明实际调用的是预创建接口:
method=alipay.trade.precreate
"alipay_trade_precreate_response"
常见原因有:
- 使用了错误的 SDK Request 类。
- 复制了扫码支付或当面付的示例代码。
- 公共支付封装内部固定调用
alipay.trade.precreate。 - 网关请求参数中的
method被覆盖。 - 日志对应的是另一笔接口请求或另一套应用配置。
使用正确的 SDK Request 类
以 Java SDK 为例,手机网站支付需要使用 AlipayTradeWapPayRequest,不能使用 AlipayTradePrecreateRequest。
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do",
appId,
merchantPrivateKey,
"json",
"UTF-8",
alipayPublicKey,
"RSA2"
);
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
request.setReturnUrl("https://example.com/payment/return");
request.setNotifyUrl("https://example.com/payment/notify");
request.setBizContent("""
{
"out_trade_no": "ORDER_202609090001",
"total_amount": "0.01",
"subject": "测试订单",
"product_code": "QUICK_WAP_WAY",
"quit_url": "https://example.com/payment/cancel"
}
""");
AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);
if (response.isSuccess()) {
String form = response.getBody();
// 将 form 返回给浏览器,浏览器会跳转到支付宝收银台
} else {
System.out.println(response.getCode());
System.out.println(response.getSubCode());
System.out.println(response.getSubMsg());
}
其中需要特别确认:
"product_code": "QUICK_WAP_WAY"
不要误用预创建接口:
AlipayTradePrecreateRequest request =
new AlipayTradePrecreateRequest();
如果业务本身需要生成线下付款二维码,可以继续使用 alipay.trade.precreate,但要另外确认商户已经签约当面付,并且当前应用有权调用该产品接口。
检查产品签约状态
“商户已开通某项支付产品”不等于”当前应用可以调用对应接口”,以下信息需要分别核对:
-
签约主体是否正确
确认手机网站支付签约在当前收款支付宝商户账号下,而不是另一个商户账号。 -
产品是否已经生效
不能只确认申请已经提交,还要查看产品是否处于已开通、已生效或可用状态。具体状态名称可能随支付宝后台调整。 -
签约产品是否与接口匹配
调用alipay.trade.wap.pay时,应检查手机网站支付;调用alipay.trade.precreate时,则要检查当面付或该接口对应的产品权限。 -
应用绑定关系是否正确
确认请求中的app_id属于已签约主体,并且已经关联相应的支付产品或能力。 -
商户账号是否存在限制
如果接口、产品和应用都能对应上,但调用仍然提示无权限,还要检查商户状态、产品状态,以及是否存在风控或行业限制。这类限制通常无法单从代码侧判断。
检查应用权限和配置
应以实际请求中的 app_id 为准,不能只看后台当前打开的是哪个应用。
建议逐项检查:
app_id是否与支付宝开放平台中的目标应用一致。- 应用是否已上线,或者是否处于允许调用生产接口的状态。
- 应用是否已配置并启用所需的支付能力。
- 商户签约账号是否与应用所属账号匹配。
- 生产环境是否误用了沙箱
app_id。 - 沙箱环境是否误用了生产应用或生产网关。
- 多套配置并存时,服务器是否加载了旧的
app_id。 - 第三方应用代商户调用时,授权关系是否有效。
- 使用
app_auth_token时,该授权是否属于当前商户和当前应用,并包含目标接口所需的权限。
普通商户通过自有应用直接调用时,通常不需要 app_auth_token。只有第三方应用代表其他商户调用时,才需要重点检查应用授权和令牌。
检查环境是否混用
生产环境通常使用:
https://openapi.alipay.com/gateway.do
沙箱环境需要配套使用沙箱网关、应用、账号和密钥。以下混用方式都可能导致调用失败:
- 生产网关搭配沙箱
app_id。 - 沙箱网关搭配生产
app_id。 - 当前应用的私钥搭配了另一个应用的
app_id。 - 证书模式下使用了另一套应用证书。
- 测试环境和生产环境读取了同一份错误配置。
不过,密钥或证书不匹配通常会引发验签、签名或应用身份类错误。当前请求已经进入业务处理,并返回 ACQ.ACCESS_FORBIDDEN,因此应优先检查接口和产品权限,不必反复更换密钥。
根据响应根节点确认接口
支付宝响应的根节点通常与实际调用的方法对应。例如:
{
"alipay_trade_wap_pay_response": {
"code": "10000",
"msg": "Success"
}
}
该响应对应:
alipay.trade.wap.pay
当前响应则是:
{
"alipay_trade_precreate_response": {
"code": "40004",
"msg": "Business Failed",
"sub_code": "ACQ.ACCESS_FORBIDDEN",
"sub_msg": "ACCESS_FORBIDDEN"
}
}
它对应:
alipay.trade.precreate
因此,响应根节点可以用来判断实际调用的接口。建议在请求发出前记录以下非敏感信息:
gateway
app_id
method
charset
sign_type
timestamp
biz_content
商户私钥、完整授权令牌及其他敏感凭据不要写入公开日志。
推荐排查顺序
按以下顺序排查通常更快:
- 从最终请求参数中确认
method。 - 根据响应根节点确认实际处理的 API。
- 检查 SDK Request 类是否为
AlipayTradeWapPayRequest。 - 检查
product_code是否为QUICK_WAP_WAY。 - 确认请求实际使用的
app_id。 - 核对该应用与手机网站支付产品的绑定关系及生效状态。
- 核对签约商户主体与收款主体。
- 检查生产环境和沙箱环境是否混用。
- 如果是第三方代调用,再检查
app_auth_token和商户授权。 - 如果确认发送的是
alipay.trade.wap.pay,而且权限配置无误,可携带请求时间、app_id、接口名、支付宝返回的错误码及请求流水信息,联系支付宝技术支持核查后台权限。
就当前案例而言,最可能的情况是:代码实际调用了 alipay.trade.precreate,但商户只开通了手机网站支付。可以将接口改为 alipay.trade.wap.pay;如果业务确实需要 alipay.trade.precreate,则要补充对应的产品签约和应用权限。
备注:内容仅供参考。
