Flutter中唤起UPI支付应用、实现交易及底部选择弹窗方案咨询
Flutter实现UPI支付应用唤起与底部选择弹窗方案
替代废弃插件的可行方案
由于upi_pay插件已废弃,可通过url_launcher结合设备应用查询能力,自定义实现UPI应用唤起与底部选择弹窗,步骤如下:
1. 添加依赖
在pubspec.yaml中引入必要依赖:
dependencies: flutter: sdk: flutter url_launcher: ^6.2.0 # 用于唤起外部应用 device_apps: ^2.2.0 # 用于获取已安装UPI应用列表
2. 配置权限(Android)
在android/app/src/main/AndroidManifest.xml中添加应用查询权限,API 30+推荐使用精准包名查询避免审核问题:
<!-- API 30+ 推荐配置 --> <queries> <package android:name="com.google.android.apps.nbu.paisa.user" /> <!-- Google Pay --> <package android:name="com.phonepe.app" /> <!-- PhonePe --> <package android:name="net.one97.paytm" /> <!-- Paytm --> <package android:name="com.amazon.mShop.android.shopping" /> <!-- Amazon Pay --> <!-- 可添加更多常用UPI应用包名 --> </queries> <!-- 如需兼容旧版本或查询所有应用,可添加此权限(不推荐) --> <!-- <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" /> -->
3. 获取设备已安装UPI应用列表
编写方法筛选出设备上已安装的UPI应用:
import 'package:device_apps/device_apps.dart'; Future<List<Application>> getUpiApps() async { // 预定义常用UPI应用包名 final upiPackageNames = [ "com.google.android.apps.nbu.paisa.user", "com.phonepe.app", "net.one97.paytm", "com.amazon.mShop.android.shopping", "com.yesbank.lite", "com.icici.bank.imobile", ]; final List<Application> upiApps = []; for (final packageName in upiPackageNames) { if (await DeviceApps.isAppInstalled(packageName)) { final app = await DeviceApps.getApp(packageName, true); upiApps.add(app); } } return upiApps; }
4. 构造UPI支付链接
按照UPI标准协议生成支付链接:
String buildUpiPaymentUrl({ required String upiId, required String payeeName, required double amount, required String transactionNote, }) { return "upi://pay?pa=$upiId&pn=$payeeName&am=${amount.toStringAsFixed(2)}&cu=INR&tn=$transactionNote"; }
5. 实现底部应用选择弹窗
通过showModalBottomSheet展示UPI应用列表,点击后唤起对应应用发起支付:
import 'package:url_launcher/url_launcher.dart'; void showUpiAppSelector(BuildContext context, String upiUrl) async { final upiApps = await getUpiApps(); if (upiApps.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text("未检测到任何UPI支付应用")), ); return; } showModalBottomSheet( context: context, builder: (ctx) => ListView.builder( shrinkWrap: true, itemCount: upiApps.length, itemBuilder: (_, index) { final app = upiApps[index]; return ListTile( leading: app is ApplicationWithIcon ? Image.memory(app.icon, width: 40, height: 40) : const Icon(Icons.payment), title: Text(app.appName), onTap: () async { Navigator.pop(ctx); // 唤起对应应用打开UPI支付链接 await launchUrl( Uri.parse(upiUrl), mode: LaunchMode.externalApplication, ); }, ); }, ), ); }
6. 发起支付流程
在业务逻辑中调用方法启动支付:
void startUpiPayment(BuildContext context) { final upiUrl = buildUpiPaymentUrl( upiId: "merchant@upi", // 替换为实际收款方UPI ID payeeName: "测试商户", // 替换为实际收款方名称 amount: 99.00, // 交易金额 transactionNote: "商品购买", // 交易备注 ); showUpiAppSelector(context, upiUrl); }
注意事项
- iOS适配:需在
Info.plist中添加LSApplicationQueriesSchemes,包含upi及各UPI应用的scheme(如phonepe、gpay等)。 - 交易验证:前端仅能唤起支付流程,交易成功状态需通过后端对接UPI服务商的验证接口确认,避免前端造假。
- 权限审核:Google Play对
QUERY_ALL_PACKAGES权限审核严格,优先使用queries标签指定精准包名。
内容的提问来源于stack exchange,提问作者naveen_kc
相关产品推荐
相关产品推荐

