Android应用中如何集成已安装UPI支付应用并获取支付结果?
实现Android UPI支付流程(适配印度主流应用)
一、筛选设备内已安装的目标UPI应用
首先要精准识别GPay、PhonePe、Paytm、Amazon Pay这几款应用,通过包名匹配+Scheme校验来获取有效列表:
- 先定义目标应用的包名与对应显示名称:
val targetUpiApps = mapOf( "com.google.android.apps.nbu.paisa.user" to "Google Pay", "com.phonepe.app" to "PhonePe", "net.one97.paytm" to "Paytm", "in.amazon.mShop.android.shopping" to "Amazon Pay" )
- 通过PackageManager查询支持
upi://payScheme的应用,并过滤出目标列表:
fun getInstalledUpiApps(context: Context): List<Pair<String, String>> { val upiIntent = Intent(Intent.ACTION_VIEW).apply { data = Uri.parse("upi://pay") } val resolveInfos = context.packageManager.queryIntentActivities(upiIntent, 0) return resolveInfos.mapNotNull { info -> val pkgName = info.activityInfo.packageName targetUpiApps[pkgName]?.let { appName -> Pair(appName, pkgName) } } }
将返回的列表展示为弹窗或下拉菜单,供用户选择支付应用。
二、发起UPI支付请求
用户选定应用后,构造包含支付参数的Intent并唤起对应应用:
private const val UPI_PAYMENT_REQUEST_CODE = 1001 fun launchUpiPayment(context: Context, pkgName: String, rentAmount: String, merchantVpa: String) { val payUri = Uri.Builder() .scheme("upi") .authority("pay") .appendQueryParameter("pa", merchantVpa) // 收款方VPA地址 .appendQueryParameter("pn", "你的应用名称") // 收款方名称 .appendQueryParameter("am", rentAmount) // 支付金额(例:"1500.00") .appendQueryParameter("cu", "INR") // 货币类型,固定为INR .appendQueryParameter("tn", "月租支付:${Calendar.getInstance().getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.ENGLISH)}") // 支付备注 .build() val payIntent = Intent(Intent.ACTION_VIEW).apply { data = payUri setPackage(pkgName) flags = Intent.FLAG_ACTIVITY_NEW_TASK } (context as Activity).startActivityForResult(payIntent, UPI_PAYMENT_REQUEST_CODE) }
三、接收并解析支付结果
在Activity/Fragment中通过onActivityResult(或Activity Result API)获取支付状态:
方式1:传统onActivityResult
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (requestCode == UPI_PAYMENT_REQUEST_CODE) { data?.getStringExtra("response")?.let { responseStr -> // 解析UPI返回的键值对字符串 val responseMap = responseStr.split("&").associate { param -> val parts = param.split("=") parts[0] to parts.getOrNull(1) } val payStatus = responseMap["status"]?.uppercase() val responseCode = responseMap["responseCode"] when { payStatus == "SUCCESS" && responseCode == "00" -> { // 支付成功,更新账单状态 } payStatus == "FAILURE" -> { // 支付失败,提示用户重试 } payStatus == "SUBMITTED" -> { // 支付已提交,需后端异步校验(UPI存在延迟确认情况) } else -> { // 用户取消支付或其他异常 } } } ?: run { // 用户未完成支付直接返回 } } }
方式2:Jetpack Activity Result API(推荐)
private val upiResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> result.data?.getStringExtra("response")?.let { responseStr -> // 解析逻辑与上述一致 } } // 发起支付时替换为: upiResultLauncher.launch(payIntent)
四、核心注意事项
- 异步校验必须做:前端返回的成功状态可能存在延迟或不准确,务必通过后端调用NPCI官方UPI校验接口,二次确认支付状态。
- 包名维护:目标应用的包名可能随版本更新变化,需定期验证最新包名。
- 无额外权限:仅需调用系统Intent,无需申请特殊权限。
- 真机测试:务必在印度地区的Android设备上测试,确保所有目标应用均可正常唤起并返回结果。
内容的提问来源于stack exchange,提问作者KIRAN K J
相关产品推荐
相关产品推荐

