PAYATHON 2026

手机网站支付调起支付宝时提示交易订单处理失败

支付阿杰

结论

能生成支付 HTML,只能说明支付宝 SDK 已经组装好请求参数,不能证明支付宝已成功创建交易。

调起支付后出现“交易订单处理失败,请稍后再试”,通常表示支付宝网关在校验请求时拒绝了这笔交易。可以先检查业务参数、签名和密钥配置、网关环境,以及应用是否具备手机网站支付权限。仅凭这条提示无法判断具体原因,仍需查看支付宝网关返回的 code、sub_code、sub_msg 或开放平台日志。

常见原因

1. 必填业务参数有误

手机网站支付使用 alipay.trade.wap.pay,需要重点检查以下参数:

  • out_trade_no:商户订单号不能为空,而且在同一商户下必须唯一。
  • total_amount:必须是合法的金额字符串,例如 "0.01",不能包含货币符号,也不要使用科学计数法。
  • subject:订单标题不能为空。
  • product_code:手机网站支付通常应设置为 QUICK_WAP_WAY。
  • quit_url:用户取消支付后的跳转地址。
  • return_url:同步跳转地址,应填写浏览器可以访问的完整 URL。

重复使用已经支付、已经关闭,或者前后参数不一致的 out_trade_no,也可能导致交易无法继续。

2. 应用、密钥和网关不属于同一环境

以下配置必须来自同一套环境:

  • app_id
  • 应用私钥
  • 支付宝公钥
  • 支付宝网关地址
  • 商户签约产品

例如,沙箱应用不能调用正式网关,正式应用的密钥也不能用于沙箱环境。RSA 和 RSA2 的签名方式及密钥类型同样不能混用。

常用网关如下:

正式环境:https://openapi.alipay.com/gateway.do
沙箱环境:https://openapi-sandbox.dl.alipaydev.com/gateway.do

具体使用哪个网关,应以应用当前所在的环境和支付宝开放平台配置为准。

3. 应用未签约或没有对应权限

即使 SDK 可以生成 HTML,如果应用没有开通手机网站支付、签约状态异常,或者应用与实际收款商户不匹配,支付宝网关仍可能拒绝交易。

请在支付宝开放平台确认:

  • 应用已经上线,或者当前状态允许调用接口;
  • 手机网站支付产品已经签约并生效;
  • 当前 app_id 对应的商户与收款主体一致;
  • 接口调用权限、账号状态和风控状态正常。

4. HTML 被转义或错误嵌入页面

SDK 返回的内容通常是一个自动提交的表单。服务端应将它作为 HTML 原样返回给浏览器。通过模板引擎输出时,表单标签可能被转义为普通文本。如果先将表单包装成 JSON,再由前端错误拼接,也可能破坏隐藏参数或签名。

建议明确设置响应头:

Content-Type: text/html; charset=UTF-8

不要修改 SDK 生成表单中的参数,也不要对已经签名的参数再次编码或重新排序。

5. 字符集或签名配置错误

建议统一使用:

charset=utf-8
sign_type=RSA2

还要检查以下配置:

  • 应用私钥是否与开放平台中配置的应用公钥匹配;
  • 验签时使用的是否为支付宝公钥,而不是应用公钥;
  • 私钥格式是否符合当前 SDK 的要求;
  • charset、sign_type 是否与初始化配置一致;
  • 生成签名后是否又修改过请求参数。

正确的调用示例

下面的示例使用支付宝 Java SDK。不同 SDK 版本的具体类名可能略有差异,请以项目实际依赖的版本为准。

AlipayClient alipayClient = new DefaultAlipayClient(
    "https://openapi.alipay.com/gateway.do",
    APP_ID,
    APP_PRIVATE_KEY,
    "json",
    "UTF-8",
    ALIPAY_PUBLIC_KEY,
    "RSA2"
);

AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();

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

AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo("ORDER_202609090001");
model.setTotalAmount("0.01");
model.setSubject("测试订单");
model.setProductCode("QUICK_WAP_WAY");
model.setQuitUrl("https://www.example.com/order");

request.setBizModel(model);

AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);

if (!response.isSuccess()) {
    throw new IllegalStateException(
        "支付宝请求失败,code=" + response.getCode()
        + ", subCode=" + response.getSubCode()
        + ", subMsg=" + response.getSubMsg()
    );
}

String formHtml = response.getBody();

控制器应直接输出表单 HTML:

@GetMapping(value = "/pay/alipay", produces = "text/html;charset=UTF-8")
@ResponseBody
public String pay() throws AlipayApiException {
    AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);

    if (!response.isSuccess()) {
        throw new IllegalStateException(
            response.getCode() + ": " + response.getSubMsg()
        );
    }

    return response.getBody();
}

排查步骤

  1. 为这次请求使用一个全新的 out_trade_no,并用最小合法金额测试。
  2. 确认接口是 alipay.trade.wap.pay,product_code 是 QUICK_WAP_WAY。
  3. 核对 app_id、应用私钥、支付宝公钥和网关是否来自同一环境。
  4. 确认手机网站支付产品已经签约并生效。
  5. 查看 SDK 返回对象中的 code、msg、sub_code 和 sub_msg。
  6. 在支付宝开放平台的接口调用日志中,根据请求时间、app_id 或订单号查找失败记录。
  7. 使用浏览器开发者工具检查最终提交到网关的表单,确认字段没有被模板转义、截断或二次编码。
  8. 服务端记录支付宝响应时应做好脱敏,不要打印应用私钥、完整签名或用户敏感信息。

注意事项

不能只依赖 return_url 判断支付结果。同步跳转可能被用户关闭、拦截或伪造。订单的最终状态应以 notify_url 收到的异步通知为准,并使用支付宝公钥验签,必要时再调用交易查询接口确认。

如果返回对象显示成功,但支付宝页面仍然只有通用错误,请提供脱敏后的 app_id、接口名称、请求时间、out_trade_no、网关 code/sub_code 和开放平台日志编号,以便继续定位。不要公开应用私钥、完整签名或用户身份信息。

备注:内容仅供参考。