Android开发:从Chrome网页返回Activity时如何获取处理结果
Android 从Chrome网页返回时的网银支付状态校验实现
核心原则先摆前面:所有前端/网页侧回传的支付状态仅可做UI层的即时提示,绝对不能作为最终支付结果的判定依据,最终状态必须以自家服务端和网银/支付机构的对账结果为准,避免参数篡改、伪造回调导致资损。
具体实现逻辑
1. 提前配置回调通道
优先用专属DeepLink作为网页跳转回应用的通道,不要依赖页面栈的自然返回:
- 在AndroidManifest.xml中给接收支付结果的Activity配置专属intent-filter,注意设置独立的、辨识度高的scheme,避免和其他应用撞名:
<activity android:name=".PayResultActivity" android:exported="true" android:launchMode="singleTop"> <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="youruniquepayscheme" android:host="payresult" /> </intent-filter> </activity>
- 和网银侧约定:用户支付完成、主动取消支付时,网页自动跳转到你配置的DeepLink地址,格式参考
youruniquepayscheme://payresult?outOrderNo=本地订单号&tempStatus=success/cancel - Android 11及以上版本需要在Manifest中补充包查询权限,否则无法校验Chrome来源:
<queries> <package android:name="com.android.chrome" /> <package android:name="com.chrome.beta" /> <package android:name="com.chrome.dev" /> </queries>
2. 回调接收时的前置校验
在接收回调的Activity中,重写onCreate和onNewIntent方法处理回调Intent,先做三层前置校验,过滤非法请求:
// 本地记录的当前正在支付的订单号,发起支付时赋值 private var currentPayOrderNo: String? = null override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) handlePayCallback(intent) } private fun handlePayCallback(intent: Intent?) { // 第一层:校验调用来源,只认Chrome的回调,拦截其他恶意应用伪造的跳转 val referer = intent?.getStringExtra(Intent.EXTRA_REFERRER) val validChromePackages = listOf( "com.android.chrome", "com.chrome.beta", "com.chrome.dev", "com.google.android.apps.chrome" ) if (referer == null || validChromePackages.none { referer.contains(it) }) { handlePayError() return } val callbackUri = intent.data val callbackOrderNo = callbackUri?.getQueryParameter("outOrderNo") // 第二层:校验订单号一致性,防止串单 if (callbackOrderNo.isNullOrEmpty() || callbackOrderNo != currentPayOrderNo) { handlePayError() return } // 第三层:不使用网页回传的tempStatus做最终判定,立刻请求服务端查询真实状态 queryRealPayStatusFromServer(callbackOrderNo) }
3. 兜底逻辑(处理用户未等网页回调直接返回的场景)
很多用户会在支付操作完成后,直接按返回键/切应用回到App,不会等网页触发DeepLink跳转,必须加生命周期兜底:
- 发起支付跳Chrome时,将当前待支付的订单号持久化到ViewModel或本地数据库,不要存在容易被系统回收的临时变量里
- 监听支付流程所在Activity的
onResume生命周期:如果页面回到前台时存在待校验的支付订单,直接触发服务端订单状态查询,不要直接判定为支付取消 - 查询服务端时建议加1-2次轮询(间隔2s左右),避免网银侧状态同步延迟导致查询结果不准
避坑要点
- 不要直接读取Chrome回传参数里的success/cancel字段更新订单状态,这类参数可以被抓包篡改、被恶意应用伪造
- 不要在用户从Chrome返回时直接弹窗提示“支付已取消”,必须等服务端查询结果返回后再做提示,避免用户实际支付成功却被误判取消
- DeepLink的scheme不要用过于通用的命名(比如直接用pay、callback这类),避免和其他应用配置冲突导致被恶意拦截
内容的提问来源于stack exchange,提问作者rNkL
相关产品推荐
相关产品推荐

