PAYATHON 2026

手机网站支付 API 调用 certificateExecute 报错

支付老李

结论

alipay.trade.wap.pay 是页面类接口。正常情况下,它返回的是用于跳转到支付宝收银台的 HTML,而不是 JSON。

调用 alipayClient.certificateExecute(request) 时,SDK 会按普通 API 响应解析返回内容。如果内容以 <html>、<form> 等字符开头,JSON 解析器会直接在第 1 列报错:

java.lang.IllegalArgumentException: expected value at column 1

手机网站支付应使用 pageExecute(request)。取得 HTML 后,将其原样写入 HTTP 响应,由浏览器跳转到支付宝收银台。

正确调用方式

AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();

request.setReturnUrl("https://www.example.com/pay/return");
request.setNotifyUrl("https://www.example.com/pay/notify");

AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo("ORDER_202609130001");
model.setTotalAmount("0.01");
model.setSubject("测试订单");
model.setProductCode("QUICK_WAP_WAY");

request.setBizModel(model);

String form = alipayClient.pageExecute(request).getBody();

在 Servlet 中,可以直接将返回内容写给浏览器:

response.setContentType("text/html;charset=UTF-8");
response.getWriter().write(form);
response.getWriter().flush();

使用 Spring MVC 时,也可以直接返回 HTML:

@PostMapping(value = "/pay", produces = "text/html;charset=UTF-8")
@ResponseBody
public String pay() throws AlipayApiException {
    AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
    request.setReturnUrl("https://www.example.com/pay/return");
    request.setNotifyUrl("https://www.example.com/pay/notify");

    AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
    model.setOutTradeNo("ORDER_202609130001");
    model.setTotalAmount("0.01");
    model.setSubject("测试订单");
    model.setProductCode("QUICK_WAP_WAY");

    request.setBizModel(model);

    return alipayClient.pageExecute(request).getBody();
}

是否使用证书模式,取决于 alipayClient 的初始化配置,并不意味着页面支付必须调用 certificateExecute()。只要客户端已经正确配置应用证书、支付宝公钥证书和支付宝根证书,调用 pageExecute() 时仍会使用这些证书配置。

排查步骤

1. 确认请求类型

确认请求对象是:

AlipayTradeWapPayRequest

接口名称是:

alipay.trade.wap.pay

这类接口用于生成收银台页面,因此应该调用 pageExecute()。

2. 检查实际返回内容

如果改用 pageExecute() 后仍然报错,可以记录 HTTP 状态码、响应头,以及响应正文开头的一小段内容。不要将完整的支付表单、签名或敏感参数写入公开日志。

响应以以下内容开头时,说明返回的是页面:

<form

或者:

<!DOCTYPE html>

如果收到的是网关错误页、代理错误页或登录页,则要继续检查网关地址和网络链路。

3. 检查支付宝网关地址

生产环境通常使用支付宝正式网关,沙箱环境使用对应的沙箱网关。沙箱应用、正式应用和网关地址不能混用。

还要检查配置中是否误填了业务页面地址、代理地址或其他非 API 网关地址。网关地址错误时,可能返回 HTML 错误页,从而引发同样的 JSON 解析异常。

4. 检查证书配置

使用证书模式时,以下配置必须相互匹配:

  • appId
  • 应用私钥
  • 应用公钥证书
  • 支付宝公钥证书
  • 支付宝根证书
  • 正式环境或沙箱环境

不要将证书文件与普通公钥模式的字符串配置混用。具体的初始化参数取决于支付宝 Java SDK 版本,应以对应版本提供的构造方法或配置对象为准。

5. 排除代理和拦截器影响

如果请求经过 Nginx、API 网关、公司代理或统一认证系统,需要确认中间层没有将支付宝响应替换为:

  • 502/504 错误页面;
  • 登录认证页面;
  • WAF 拦截页面;
  • 自定义异常页面。

这些页面也不是 JSON,因此同样可能触发 expected value at column 1。

注意事项

return_url 只用于支付完成后的浏览器跳转,不能作为判断订单支付成功的唯一依据。订单状态应以支付宝发送到 notify_url 的异步通知为主,同时校验签名、商户订单号、金额、应用标识等字段。

不要自行解析或修改 pageExecute() 返回的 HTML 表单。通常应将它原样输出给浏览器,否则可能破坏隐藏字段、签名参数或自动提交逻辑。

示例中的响应类型应写为:

AlipayTradeWapPayResponse

如果业务只需要输出收银台页面,也可以直接使用:

String form = alipayClient.pageExecute(request).getBody();

这种写法更符合手机网站支付接口的用途。

备注:内容仅供参考。