Flutter中如何从第三方应用跳转回自有应用并获取支付响应?
Flutter UPI支付后跳转回应用并获取支付响应
核心思路
要实现UPI支付完成后跳转回自有应用并获取响应,需要结合Deep Link配置和UPI支付URL的回调参数,同时在Flutter端监听Deep Link的唤醒事件来解析支付结果。
1. 配置应用的Deep Link
首先需要给你的Flutter app配置专属的Deep Link,让UPI应用能在支付完成后唤起你的app。
Android 配置(AndroidManifest.xml)
在android/app/src/main/AndroidManifest.xml的主Activity标签内添加以下intent-filter:
<intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <!-- 替换成你的专属scheme,比如myinvoiceapp:// --> <data android:scheme="myinvoiceapp" /> </intent-filter>
iOS 配置(Info.plist)
在ios/Runner/Info.plist中添加以下配置:
<!-- 允许调用UPI应用的scheme --> <key>LSApplicationQueriesSchemes</key> <array> <string>upi</string> </array> <!-- 配置Deep Link的URL Scheme --> <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <!-- 替换成你的专属scheme,比如myinvoiceapp --> <string>myinvoiceapp</string> </array> </dict> </array>
2. 构造带回调的UPI支付URL
在构造UPI支付链接时,必须添加callback参数,指定支付完成后跳转回你的app的Deep Link。示例URL格式:
String upiUrl = 'upi://pay?' 'pa=merchant@upi&' // 收款方UPI ID 'pn=商家名称&' // 收款方名称 'am=100.00&' // 支付金额 'tn=发票支付:#INV123&' // 交易备注 'tr=UNIQUE_TXN_ID_123&' // 唯一交易ID(自己生成,用于后续核对) 'callback=myinvoiceapp://payment-callback'; // 你的Deep Link回调地址
3. 启动UPI支付并监听回调
使用url_launcher启动UPI链接,同时借助app_links包监听Deep Link的唤醒事件(url_launcher本身无法直接接收回调,需要依赖Deep Link监听库)。
添加依赖
在pubspec.yaml中添加:
dependencies: url_launcher: ^6.2.4 app_links: ^3.4.2
初始化监听
在你的主页面或者支付页面初始化Deep Link监听:
import 'package:app_links/app_links.dart'; import 'package:url_launcher/url_launcher.dart'; class PaymentPage extends StatefulWidget { const PaymentPage({super.key}); @override State<PaymentPage> createState() => _PaymentPageState(); } class _PaymentPageState extends State<PaymentPage> { final AppLinks _appLinks = AppLinks(); StreamSubscription<Uri>? _linkSubscription; @override void initState() { super.initState(); // 监听Deep Link唤醒事件 _initDeepLinkListener(); } void _initDeepLinkListener() { _linkSubscription = _appLinks.uriLinkStream.listen((Uri? uri) { if (uri != null && uri.path == '/payment-callback') { // 解析回调参数 String? status = uri.queryParameters['status']; String? txnId = uri.queryParameters['txnId']; String? tr = uri.queryParameters['tr']; // 之前传入的唯一交易ID // 根据status处理支付结果 if (status == 'success') { // 更新发票状态为已支付,跳转回发票列表页等 print('支付成功,交易ID:$txnId'); } else if (status == 'failure') { print('支付失败'); } } }); } // 启动UPI支付的方法 Future<void> launchUpiPayment() async { String upiUrl = 'upi://pay?' 'pa=merchant@upi&' 'pn=商家名称&' 'am=100.00&' 'tn=发票支付:#INV123&' 'tr=UNIQUE_TXN_ID_123&' 'callback=myinvoiceapp://payment-callback'; final Uri uri = Uri.parse(upiUrl); if (await canLaunchUrl(uri)) { await launchUrl(uri); } else { throw '无法启动UPI应用'; } } @override void dispose() { _linkSubscription?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('支付发票')), body: Center( child: ElevatedButton( onPressed: launchUpiPayment, child: const Text('通过UPI支付'), ), ), ); } }
4. 注意事项
- 回调参数兼容性:不同UPI应用(Google Pay、PhonePe、Paytm)对回调参数的格式可能略有差异,建议测试主流应用,确保能正确解析
status、txnId等核心参数。 - 交易唯一性:
tr参数必须是唯一的,用于后续核对支付记录,避免重复支付或状态混乱。 - 后台校验:前端获取的支付状态仅作参考,必须通过后端调用UPI官方接口校验交易的真实状态,防止伪造回调。
内容的提问来源于stack exchange,提问作者ramit_acube
相关产品推荐
相关产品推荐

