Flutter基于Deep Link实现UPI支付(Paytm网关):支付完成后返回APP并验单方法
Flutter实现Paytm UPI支付后自动返回APP并校验交易状态
一、配置APP的Deep Link回调地址
要让Paytm支付完成后能跳回你的APP,需先给APP配置专属的Deep Link Scheme(示例用myapp://paymentcallback),以下是Android和iOS的配置步骤:
Android端配置
在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和Host --> <data android:scheme="myapp" android:host="paymentcallback" /> </intent-filter>
iOS端配置
- 打开
ios/Runner/Info.plist,添加允许调用Paytm的Scheme:
<key>LSApplicationQueriesSchemes</key> <array> <string>paytmmp</string> </array>
- 配置APP自身的Deep Link Scheme:
<key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>myapp</string> </array> <key>CFBundleURLName</key> <string>paymentcallback</string> </dict> </array>
二、修改Paytm UPI支付链接,添加回调参数
在原有支付Deep Link末尾追加url参数,值为你配置的APP回调Deep Link,同时带上交易号tr方便后续校验:
// 基础支付链接 String baseUrl = "paytmmp://pay?pa=paytm-67035308@paytm&pn=Reciver_NAME&mc=5812&tid=PYTM3101623366056793109&tr=3101623366056793109&am=3&cu=INR"; // 自定义回调地址,替换为你的Scheme String callbackUrl = "myapp://paymentcallback?tr=3101623366056793109"; // 拼接完整支付链接 String deepLinkUrl = "$baseUrl&url=$callbackUrl";
注意:回调参数里的
tr要和支付请求中的交易号完全一致,确保回来后能精准定位对应交易。
三、Flutter端监听Deep Link回调并处理
无需额外第三方库,直接通过Flutter原生的WidgetsBindingObserver监听APP生命周期与Deep Link:
class PaymentPage extends StatefulWidget { @override State<PaymentPage> createState() => _PaymentPageState(); } class _PaymentPageState extends State<PaymentPage> with WidgetsBindingObserver { @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); // 启动时检查是否通过Deep Link打开APP _checkInitialDeepLink(); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } // 监听APP从后台回到前台的状态,触发Deep Link检查 @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); if (state == AppLifecycleState.resumed) { _checkDeepLink(); } } // 检查APP启动时的初始Deep Link Future<void> _checkInitialDeepLink() async { final Uri? initialUri = await WidgetsBinding.instance.getInitialUri(); if (initialUri != null) { _handlePaymentCallback(initialUri); } } // 检查APP恢复时的Deep Link Future<void> _checkDeepLink() async { final Uri? uri = await WidgetsBinding.instance.getInitialUri(); if (uri != null) { _handlePaymentCallback(uri); } } // 处理支付回调,触发交易校验 void _handlePaymentCallback(Uri uri) { String? transactionId = uri.queryParameters['tr']; if (transactionId != null) { // 调用已集成的Paytm API校验交易状态 _verifyTransaction(transactionId); } } // 交易状态校验方法(替换为你的实际API调用逻辑) Future<void> _verifyTransaction(String transactionId) async { bool isSuccess = await paytmApi.verifyTransaction(transactionId); if (isSuccess) { print("交易成功,执行后续逻辑"); // 这里添加支付成功后的UI更新、业务处理 } else { print("交易失败,请重试"); // 这里添加支付失败后的提示、重试逻辑 } } // 发起支付的方法 Future<void> launchPayment() async { String baseUrl = "paytmmp://pay?pa=paytm-67035308@paytm&pn=Reciver_NAME&mc=5812&tid=PYTM3101623366056793109&tr=3101623366056793109&am=3&cu=INR"; String callbackUrl = "myapp://paymentcallback?tr=3101623366056793109"; String deepLinkUrl = "$baseUrl&url=$callbackUrl"; bool launchResult = await launchUrl(Uri.parse(deepLinkUrl)); if (!launchResult) { print('无法启动Paytm支付,请检查是否安装Paytm APP'); } } @override Widget build(BuildContext context) { return Scaffold( body: Center( child: ElevatedButton( onPressed: launchPayment, child: const Text("发起Paytm支付"), ), ), ); } }
四、关键注意事项
- 测试时需确保设备已安装Paytm APP,否则
launchUrl会返回false。 - 回调Deep Link的参数需做URL编码,避免特殊字符导致解析失败。
- 交易状态校验必须在服务器端执行,不要仅依赖客户端校验,防止数据篡改。
内容的提问来源于stack exchange,提问作者Vamshi Rahul
相关产品推荐
相关产品推荐

