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 中,可以跳转到订单详情页,并向业务服务器重新查询订单状态。
更推荐使用 Universal Link
条件允许时,可以将返回地址设计为 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 已启动、处于后台、被完全关闭和未安装等场景。
备注:内容仅供参考。
