PAYATHON 2026

支付宝H5支付缺失fromAPPurlScheme无法返回第三方APP

支付阿杰

结论

第三方 App 需要通过支付宝支持的 URL Scheme 拉起收银台,并在链接中传入来源 App 的 Scheme。常用参数名为区分大小写的 fromAppUrlScheme,参数值必须与第三方 App 已注册的 URL Scheme 完全一致。

如果只在 H5 页面中打开普通的 https:// 支付地址,或直接跳转到支付宝下载页、中间页,支付宝可能无法识别来源 App。即使支付成功,也可能无法自动返回原 App。

正确的链接结构

典型的支付宝客户端拉起链接如下:

alipays://platformapi/startapp?appId=20000067&url=<ENCODED_H5_PAY_URL>&fromAppUrlScheme=<APP_SCHEME>

也可以使用:

alipay://platformapi/startapp?appId=20000067&url=<ENCODED_H5_PAY_URL>&fromAppUrlScheme=<APP_SCHEME>

参数含义如下:

  • url 是经过 URL 编码的支付宝 H5 收银台地址。
  • fromAppUrlScheme 是第三方 App 注册的 Scheme,通常只填写 Scheme 名称,例如 myshop,不要随意填写回调网页地址。
  • 参数名称及大小写必须符合当前接入方案。常用写法是 fromAppUrlScheme,不要自行改成 fromAPPurlScheme。
  • appId=20000067 是常见的支付宝钱包 H5 收银台拉起入口。如果支付宝当前接入文档或返回的跳转模板使用了其他值,应以实际模板为准,不要硬编码替换。

假设第三方 App 注册的 Scheme 是 myshop,原始收银台地址为:

https://mclient.alipay.com/cashier/mobilepay.htm?trade_no=xxx

可以使用下面的 JavaScript 生成拉起地址:

const cashierUrl =
  "https://mclient.alipay.com/cashier/mobilepay.htm?trade_no=xxx";

const appScheme = "myshop";

const alipayUrl =
  "alipays://platformapi/startapp" +
  "?appId=20000067" +
  "&url=" + encodeURIComponent(cashierUrl) +
  "&fromAppUrlScheme=" + encodeURIComponent(appScheme);

window.location.href = alipayUrl;

不要直接拼接未经编码的 cashierUrl。支付地址通常包含 ?、&、= 等字符,不编码会破坏外层拉起链接的参数结构。

注册第三方 App 的 Scheme

只有系统能够通过指定 Scheme 打开第三方 App 时,fromAppUrlScheme 才会生效。假设使用:

myshop://

iOS 和 Android 都需要注册 myshop。

iOS 配置

在 Info.plist 中注册 URL Types:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLName</key>
        <string>com.example.myshop</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>myshop</string>
        </array>
    </dict>
</array>

应用还需要在相应的生命周期回调中处理 URL:

func application(
    _ app: UIApplication,
    open url: URL,
    options: [UIApplication.OpenURLOptionsKey: Any] = [:]
) -> Bool {
    guard url.scheme == "myshop" else {
        return false
    }

    // 恢复支付页面,并主动查询订单状态。
    return true
}

如果项目使用 Scene 生命周期,则应在对应的 scene(_:openURLContexts:) 回调中处理。

Android 配置

在接收返回地址的 Activity 中配置 intent-filter:

<activity
    android:name=".PaymentResultActivity"
    android:exported="true">

    <intent-filter>
        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <data android:scheme="myshop" />
    </intent-filter>
</activity>

然后在 Activity 中处理回跳 Intent:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    handlePaymentReturn(intent)
}

override fun onNewIntent(intent: Intent) {
    super.onNewIntent(intent)
    setIntent(intent)
    handlePaymentReturn(intent)
}

private fun handlePaymentReturn(intent: Intent?) {
    val uri = intent?.data ?: return
    if (uri.scheme != "myshop") return

    // 恢复支付页面,并通过服务端查询订单状态。
}

完整处理流程

可以按以下顺序配置和排查:

  1. 为第三方 App 确定一个不会与其他应用冲突的 Scheme,例如 myshop。
  2. 在 iOS 和 Android 工程中注册该 Scheme。
  3. 获取支付宝返回的真实 H5 收银台地址。
  4. 对整个 H5 收银台地址进行一次 URL 编码。
  5. 构造以 alipays:// 或 alipay:// 开头的拉起地址。
  6. 在外层拉起地址中加入 fromAppUrlScheme=myshop。
  7. 在真机上确认 myshop:// 可以单独打开第三方 App。
  8. 支付完成并返回 App 后,由 App 或服务端查询订单状态。

注意事项

不要混淆两类返回地址

fromAppUrlScheme 用于从支付宝客户端切回第三方 App。支付接口中的 return_url 通常用于支付完成后的网页跳转,两者用途不同。

只配置 return_url,不能保证支付宝客户端会返回第三方 App。只配置 fromAppUrlScheme,也不能代替支付结果通知。

支付结果必须以服务端为准

App 被重新打开只说明发生了回跳,不能据此认定支付成功。用户可能取消支付,也可能通过伪造 Scheme 主动打开 App。

应按以下方式确认支付结果:

  • 服务端接收支付宝异步通知并完成验签。
  • App 返回前台后,请求业务服务端查询订单。
  • 业务服务端调用支付宝查询接口,或读取已经确认的订单状态。
  • 不要直接信任回跳 URL 中的支付状态。

Scheme 必须完全一致

以下几处的值必须保持一致:

fromAppUrlScheme=myshop
iOS CFBundleURLSchemes: myshop
Android android:scheme="myshop"

不要在一处填写 myshop,另一处却填写 myshop://、MyShop 或带路径的完整 URL,除非当前支付宝接入文档明确要求使用这些格式。

不要重复编码

通常只需对内层 H5 收银台地址编码一次:

encodeURIComponent(cashierUrl)

如果页面再次对整个拉起链接进行编码,可能产生 %253A、%252F 等内容,导致支付宝无法正确还原收银台地址。

WebView 需要放行自定义 Scheme

如果支付页运行在 App 内的 WebView 中,WebView 遇到 alipays:// 或 alipay:// 时可能不会自动跳转。这时需要由原生层拦截链接,再交给系统打开。同时,只允许可信的支付宝 Scheme 和支付域名,避免系统执行任意外部地址。

部分浏览器、系统版本或支付宝客户端版本还可能限制没有用户手势的 Scheme 跳转。因此,最好让用户点击”打开支付宝支付”按钮触发跳转,不要在页面加载后立即自动跳转。

备注:内容仅供参考。