PAYATHON 2026

手机网页获取 alipay.trade.app.pay 应答后如何唤醒支付宝

支付阿杰

结论

alipay.trade.app.pay 是支付宝 App 支付接口。返回内容是供 Android/iOS 支付宝 SDK 使用的 orderString,不能直接拼成链接,在普通手机网页中唤醒支付宝。

如果支付入口是 H5 页面,应改用 alipay.trade.wap.pay。服务端生成并签名支付请求后,可以让浏览器跳转到支付宝网关,也可以向页面返回自动提交的 HTML 表单。

如果页面运行在自有 App 的 WebView 中,则可以通过 JSBridge 将完整的 orderString 交给原生代码,再由原生支付宝 SDK 发起支付。

为什么不能直接在网页中使用这段参数

示例中的关键参数是:

method=alipay.trade.app.pay
product_code=QUICK_MSECURITY_PAY

这说明订单是为 App 支付 SDK 创建的。它不是可以直接访问的支付地址,也不是供浏览器提交的 WAP 支付表单。

下面这种处理方式并不可靠:

location.href = 'alipays://...' + orderString;

原因主要有以下几点:

  1. App 支付的 orderString 应由支付宝客户端 SDK 解析和处理。
  2. 浏览器对自定义 URL Scheme 的支持会受到操作系统、浏览器和支付宝版本的影响。
  3. 自行拼接 Scheme 可能破坏签名参数,也不符合 H5 支付的标准接入流程。

不要尝试将 alipay.trade.app.pay 的应答转换成所谓的”支付宝唤醒链接”。

手机网页的正确处理方式

1. 服务端改用 alipay.trade.wap.pay

服务端创建支付请求时,将接口改为:

alipay.trade.wap.pay

业务参数通常包括:

{
  "out_trade_no": "201800000001201",
  "product_code": "QUICK_WAP_WAY",
  "subject": "购买套餐",
  "total_amount": "9.90",
  "quit_url": "https://example.com/order/201800000001201",
  "timeout_express": "90m"
}

参数含义如下:

  • product_code 使用 QUICK_WAP_WAY。
  • quit_url 是用户取消支付后的返回地址。
  • 公共参数中还需要设置 return_url 和 notify_url。
  • return_url 用于支付完成后的浏览器页面跳转。
  • notify_url 用于接收支付宝发给服务端的异步支付通知。

参数是否必填,以及具体的 SDK 方法名称,应以当前使用的支付宝开放平台文档和 Python SDK 版本为准。

2. 服务端生成支付表单或跳转地址

下面的伪代码展示了基本处理流程。build_alipay_wap_form 代表项目实际使用的支付宝 SDK 或签名封装:

from flask import Flask, Response

app = Flask(__name__)

@app.post("/pay")
def create_payment():
    biz_content = {
        "out_trade_no": "201800000001201",
        "product_code": "QUICK_WAP_WAY",
        "subject": "购买套餐",
        "total_amount": "9.90",
        "quit_url": "https://example.com/order/201800000001201",
        "timeout_express": "90m",
    }

    form_html = build_alipay_wap_form(
        method="alipay.trade.wap.pay",
        biz_content=biz_content,
        return_url="https://example.com/pay/return",
        notify_url="https://example.com/pay/notify",
    )

    return Response(form_html, content_type="text/html; charset=utf-8")

实际生成的内容通常是一个提交到支付宝网关的表单,例如:

<form id="alipay-form"
      method="post"
      action="https://openapi.alipay.com/gateway.do">
  <input type="hidden" name="app_id" value="你的应用 ID">
  <input type="hidden" name="method" value="alipay.trade.wap.pay">
  <input type="hidden" name="charset" value="utf-8">
  <input type="hidden" name="sign_type" value="RSA2">
  <input type="hidden" name="timestamp" value="2023-03-16 08:22:20">
  <input type="hidden" name="version" value="1.0">
  <input type="hidden" name="biz_content" value="经过正确转义的 JSON">
  <input type="hidden" name="sign" value="服务端生成的签名">
</form>

<script>
  document.getElementById('alipay-form').submit();
</script>

这个示例只用于说明浏览器端的提交方式。生产环境中,应由支付宝 SDK 或经过验证的服务端签名组件生成完整表单,不要在前端自行实现签名。

3. 网页跳转到服务端支付入口

前端可以提交表单,让浏览器直接进入服务端支付路由:

<form method="post" action="/pay">
  <button type="submit">支付宝支付</button>
</form>

也可以在用户点击支付按钮后进行跳转:

document.querySelector('#pay-button').addEventListener('click', () => {
  window.location.href = '/pay';
});

服务端返回 WAP 支付表单后,浏览器会进入支付宝收银台。支付宝客户端是否会被直接唤起,取决于支付宝收银台、浏览器环境和系统策略,商户页面不需要自行拼接 Scheme。

如果网页运行在自有 App 的 WebView 中

这种情况下仍可使用 alipay.trade.app.pay,但必须由原生层调用支付宝 SDK。

完整的处理链路是:

H5 页面
  → 调用 App 提供的 JSBridge
  → 原生层请求服务端创建订单
  → 服务端返回完整 orderString
  → 原生层调用支付宝 SDK
  → App 接收支付结果
  → 服务端根据异步通知确认最终状态

Android 原生代码通常采用类似下面的调用方式:

PayTask alipay = new PayTask(activity);
Map<String, String> result = alipay.payV2(orderString, true);

orderString 必须使用服务端返回的完整原始字符串。不要拆分参数后重新拼接,也不要随意执行 URL 解码,否则可能改变 +、/、= 等字符,导致验签失败。

H5 与原生层之间可以约定一个桥接方法,例如:

window.NativePay.alipayPay(orderString);

这是业务 App 自行实现的 JSBridge 接口,并非浏览器或支付宝提供的通用 JavaScript API。

签名和参数处理注意事项

不要在网页端签名

RSA2 私钥只能保存在服务端。前端代码、网页源码和 App 安装包都不适合存放应用私钥。

各端应按以下方式分工:

  • 服务端创建商户订单。
  • 服务端组织请求参数并生成 RSA2 签名。
  • 前端负责提交表单、跳转或调用原生桥接。
  • 服务端接收异步通知并验签。

不要解析后重新拼接 App 支付字符串

示例中的签名包含:

+
/
=

如果将整段字符串作为普通查询参数再次编码,或者先通过表单解析器解码再重新拼接,+ 可能被转换为空格,导致订单字符串失效。

如果必须通过 JSON 接口传递,应将它作为一个完整的字符串字段:

{
  "order_string": "timestamp=...&app_id=...&sign=...&biz_content=..."
}

原生层取出 order_string 后,应直接将其传给支付 SDK。

不要依赖同步跳转判断支付成功

return_url 只表示浏览器跳转到了返回页面,不能证明支付已经成功。用户可能关闭页面,网络也可能中断,返回参数还可能被伪造。

订单的最终状态应以下列结果为准:

  1. 服务端收到支付宝异步通知,并且验签通过;
  2. 服务端主动调用交易查询接口,确认交易状态。

服务端还应校验:

  • app_id
  • out_trade_no
  • 支付金额
  • 收款方信息
  • 交易状态

异步通知处理完成后,需要按照支付宝的要求返回成功响应。订单状态更新还必须具备幂等性,避免因重复通知而重复发货。

应该选择哪种方案

如果支付入口是 Safari、Chrome、微信内置浏览器或其他普通手机浏览器,应使用:

alipay.trade.wap.pay

如果入口是自有 App 内嵌的 H5 页面,并且 App 已经集成支付宝 SDK,可以使用:

alipay.trade.app.pay

此时 H5 只能将支付请求交给原生层,无法自行完成 App 支付。

当前这段 alipay.trade.app.pay 应答不能直接用于普通网页。更稳妥的做法是让服务端重新创建 alipay.trade.wap.pay 请求,再由手机浏览器提交支付宝返回的支付表单。

备注:内容仅供参考。