PAYATHON 2026

iOS 生活号支付成功后如何点击按钮返回第三方 App?

支付老李

结论

支付成功页无法直接控制 iOS“返回上一个 App”。通常的处理方式是让第三方 App 注册自定义 URL Scheme 或 Universal Link,再在支付成功页提供“返回 App”按钮。用户点击按钮后,页面通过对应链接唤起 App。

URL Scheme 配置相对简单。Universal Link 的安全性更好,但需要配置域名和 apple-app-site-association。支付宝客户端内置 WebView 能否直接唤起第三方 App,还会受到支付宝版本、安全策略和域名配置等因素影响,需要通过真机测试确认。

实现步骤

1. 为 iOS App 注册 URL Scheme

在 Xcode 中依次打开:

Target → Info → URL Types

新增一个 URL Type,例如:

URL Schemes: merchantapp

完成配置后,可以使用下面的链接尝试唤起 App:

merchantapp://payment/result?orderId=202609090001

Scheme 应采用能够代表自身业务的唯一名称。不要使用过于通用的值,以免与其他 App 冲突。

也可以直接在 Info.plist 中配置:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>merchantapp</string>
        </array>
    </dict>
</array>

2. 在支付成功页添加返回按钮

支付完成后,将页面跳转到商户自己的成功页,并提供一个由用户主动点击的按钮:

<button type="button" id="openApp">返回 App</button>

<script>
document.getElementById('openApp').addEventListener('click', function () {
    const orderId = '202609090001';
    const url =
        'merchantapp://payment/result?orderId=' +
        encodeURIComponent(orderId);

    window.location.href = url;
});
</script>

跳转操作应放在按钮的真实点击事件中执行。部分 WebView 会限制页面加载后自动唤起外部 App,因此不要依赖 setTimeout,也不要在页面初始化时自动跳转。

3. 在 App 中接收回跳链接

如果没有使用 Scene 生命周期,可以在 AppDelegate 中处理:

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

    let components = URLComponents(
        url: url,
        resolvingAgainstBaseURL: false
    )

    let orderId = components?
        .queryItems?
        .first(where: { $0.name == "orderId" })?
        .value

    handlePaymentReturn(orderId: orderId)
    return true
}

如果使用了 Scene 生命周期,则在 SceneDelegate 中处理:

func scene(
    _ scene: UIScene,
    openURLContexts URLContexts: Set<UIOpenURLContext>
) {
    guard let url = URLContexts.first?.url,
          url.scheme == "merchantapp",
          url.host == "payment",
          url.path == "/result" else {
        return
    }

    let components = URLComponents(
        url: url,
        resolvingAgainstBaseURL: false
    )

    let orderId = components?
        .queryItems?
        .first(where: { $0.name == "orderId" })?
        .value

    handlePaymentReturn(orderId: orderId)
}

在 handlePaymentReturn 中,可以跳转到订单详情页,并向业务服务器重新查询订单状态。

条件允许时,可以将返回地址设计为 HTTPS Universal Link,例如:

https://pay.example.com/app/payment/result?orderId=202609090001

支付成功页中的跳转代码如下:

<button type="button" id="openApp">返回 App</button>

<script>
document.getElementById('openApp').addEventListener('click', function () {
    const orderId = '202609090001';

    window.location.href =
        'https://pay.example.com/app/payment/result?orderId=' +
        encodeURIComponent(orderId);
});
</script>

使用 Universal Link 需要完成以下配置:

  • 在 App 中启用 Associated Domains。
  • 添加 applinks:pay.example.com。
  • 在对应域名部署正确的 apple-app-site-association 文件。
  • 在 App 中通过 NSUserActivity 接收链接。

第三方 App 内置 WebView 对 Universal Link 的处理并不完全一致。有些环境会直接打开目标 App,有些环境可能仍停留在网页中,因此必须针对实际使用的支付宝客户端版本进行真机测试。必要时,可以同时提供 URL Scheme,并显示“已完成支付,返回 App 查看订单”的操作指引。

不要根据回跳参数认定支付成功

下面的链接只能说明用户点击了返回按钮,不能作为到账凭证:

merchantapp://payment/result?status=success

URL Scheme 参数可以伪造。App 被唤起后,应使用 orderId 或商户订单号请求自己的服务端。服务端再根据支付宝异步通知或主动查询结果,确认真实的支付状态。

推荐流程如下:

用户点击返回 App
        ↓
App 获取 orderId
        ↓
App 请求商户服务端查询订单
        ↓
服务端返回可信支付状态
        ↓
App 展示支付成功、处理中或失败

如果服务端暂时还没有收到异步通知,可以在短时间内进行有限次数的轮询,同时向用户显示“支付结果确认中”,不要直接将订单判定为支付失败。

注意事项

  • iOS 没有供网页调用的“返回发起支付 App”通用接口,只能通过 URL Scheme 或 Universal Link 重新唤起指定 App。
  • Scheme、域名、路径和参数名称需要由 App 与 H5 页面提前约定。
  • 不要将用户标识、支付密钥或其他敏感信息写入回跳 URL。
  • orderId 必须与当前登录用户关联,服务端还需要检查该用户是否有权查看对应订单。
  • 如果唤起失败,应保留订单结果页面,并提示用户手动返回或打开 App。
  • 如果支付宝 WebView 拦截第三方 Scheme,需要按照当前支付宝开放平台的接入规则检查域名、安全策略和客户端限制。不同版本的实际表现不能只通过浏览器测试判断。
  • 真机测试应覆盖 App 已启动、处于后台、被完全关闭和未安装等场景。

备注:内容仅供参考。