Flutter ns_upi 是一个Flutter插件,用于查找手机上已安装的统一支付接口(UPI)应用程
Flutter ns_upi 是一个Flutter插件,用于查找手机上已安装的统一支付接口(UPI)应用程
描述
ns_upi
是一个Flutter插件,用于查找手机上已安装的统一支付接口(UPI)应用程序,并通过这些应用程序进行支付。该插件可以帮助开发者轻松集成UPI支付功能到他们的Flutter应用中。
快速开始
1. 添加依赖
在 pubspec.yaml
文件中添加 ns_upi
作为依赖项:
dependencies:
...
ns_upi: ^1.0.2
2. 导入包
在 Dart 文件中导入 ns_upi
包:
import 'package:ns_upi/ns_upi.dart';
3. iOS配置
在 Runner/Info.plist
文件中添加或修改 LSApplicationQueriesSchemes
键,以包含自定义查询方案。以下是一些常见的UPI应用程序的scheme列表:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>Bandhan</string>
<string>BHIM</string>
<string>CanaraMobility</string>
<string>CentUPI</string>
<string>com.amazon.mobile.shopping</string>
<string>com.ausmallfinancebank.aupay.bhimupi</string>
<string>com.jkbank.bhimjkbankupi</string>
<string>com.rbl.rblimplicitjourney</string>
<string>com.syndicate.syndupi</string>
<string>com.vijayabank.UPI</string>
<string>cred</string>
<string>dbin</string>
<string>freecharge</string>
<string>gpay</string>
<string>hdfcnewbb</string>
<string>imobileapp</string>
<string>in.cointab.app</string>
<string>in.fampay.app</string>
<string>kvb.app.upiapp</string>
<string>lotza</string>
<string>mobikwik</string>
<string>money.bullet</string>
<string>myairtel</string>
<string>myJio</string>
<string>paytm</string>
<string>payzapp</string>
<string>phonepe</string>
<string>truecaller</string>
<string>ucoupi</string>
<string>upi</string>
<string>upibillpay</string>
<string>whatsapp</string>
<string>www.citruspay.com</string>
</array>
使用方法
1. 获取已安装的应用程序列表
可以通过调用 NsUpi.getInstalledUpiApps()
方法来获取手机上已安装的UPI应用程序列表。返回的是一个 List<ApplicationMeta>
类型的列表,其中每个 ApplicationMeta
对象包含应用程序的元数据。
final List<ApplicationMeta> appMetaList = await NsUpi.getInstalledUpiApps();
2. 发起UPI交易
可以通过调用 NsUpi.initiateTransaction()
方法来发起一笔UPI交易。该方法需要提供金额、接收方名称、接收方UPI地址、交易参考号和交易备注等参数。发起交易后,用户可以选择一个已安装的UPI应用程序来完成支付。
Future<void> upiTransaction(ApplicationMeta appMeta) async {
final UpiTransactionResponse response = await NsUpi.initiateTransaction(
amount: '1.00', // 金额
app: appMeta.application, // 选择的应用程序
receiverName: 'Ajay Kumar', // 接收方名称
receiverUpiAddress: '7875056731[@paytm](/user/paytm)', // 接收方UPI地址
transactionRef: 'NONSTOPIO000001', // 交易参考号
transactionNote: 'A TEST UPI Transaction', // 交易备注
);
debugPrint(response.status); // 打印交易状态
}
完整示例Demo
以下是一个完整的Flutter应用程序示例,展示了如何使用 ns_upi
插件来发起UPI交易。
import 'dart:io';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:ns_upi/ns_upi.dart';
void main() => runApp(const App());
class App extends StatelessWidget {
const App({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('UPI Pay'),
),
body: const Screen(),
),
);
}
}
class Screen extends StatefulWidget {
const Screen({super.key});
[@override](/user/override)
State<Screen> createState() => _ScreenState();
}
class _ScreenState extends State<Screen> {
String? _upiAddrError;
final _upiAddressController = TextEditingController(text: '7875056731[@paytm](/user/paytm)');
final _amountController = TextEditingController();
bool _isUpiEditable = false;
List<ApplicationMeta>? _apps;
[@override](/user/override)
void initState() {
super.initState();
// 随机生成金额
_amountController.text =
(Random.secure().nextDouble() * 10).toStringAsFixed(2);
// 获取已安装的UPI应用程序列表
Future.delayed(const Duration(milliseconds: 0), () async {
try {
_apps = await NsUpi.getInstalledUpiApps(
statusType: UpiApplicationDiscoveryAppStatusType.all);
setState(() {});
} catch (e, s) {
debugPrint('getInstalledUpiApps error: $e, stack: $s');
}
});
}
[@override](/user/override)
void dispose() {
_amountController.dispose();
_upiAddressController.dispose();
super.dispose();
}
void _generateAmount() {
setState(() {
_amountController.text =
(Random.secure().nextDouble() * 10).toStringAsFixed(2);
});
}
Future<void> _onTap(ApplicationMeta app) async {
// 验证UPI地址
final err = _validateUpiAddress(_upiAddressController.text);
if (err != null) {
setState(() {
_upiAddrError = err;
});
return;
}
setState(() {
_upiAddrError = null;
});
// 生成交易参考号
final transactionRef = Random.secure().nextInt(1 << 32).toString();
debugPrint("Starting transaction with id $transactionRef");
debugPrint("Using app ${app.upiApplication.getAppName()}");
// 发起交易
final response = await NsUpi.initiateTransaction(
amount: _amountController.text,
app: app.upiApplication,
receiverName: 'Sharad',
receiverUpiAddress: _upiAddressController.text,
transactionRef: transactionRef,
transactionNote: 'UPI Payment',
);
debugPrint(response.toString());
}
[@override](/user/override)
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: ListView(
children: [
_vpa(),
if (_upiAddrError != null) _vpaError(),
_amount(),
if (Platform.isIOS) _submitButton(),
Platform.isAndroid ? _androidApps() : _iosApps(),
],
),
);
}
Widget _vpa() {
return Container(
margin: const EdgeInsets.only(top: 32),
child: Row(
children: [
Expanded(
child: TextFormField(
controller: _upiAddressController,
enabled: _isUpiEditable,
decoration: const InputDecoration(
border: OutlineInputBorder(),
hintText: 'address@upi',
labelText: 'Receiving UPI Address',
),
),
),
Container(
margin: const EdgeInsets.only(left: 8),
child: IconButton(
icon: Icon(
_isUpiEditable ? Icons.check : Icons.edit,
),
onPressed: () {
setState(() {
_isUpiEditable = !_isUpiEditable;
});
},
),
),
],
),
);
}
Widget _vpaError() {
return Container(
margin: const EdgeInsets.only(top: 4, left: 12),
child: Text(
_upiAddrError!,
style: const TextStyle(color: Colors.red),
),
);
}
Widget _amount() {
return Container(
margin: const EdgeInsets.only(top: 32),
child: Row(
children: [
Expanded(
child: TextField(
controller: _amountController,
readOnly: true,
enabled: false,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Amount',
),
),
),
Container(
margin: const EdgeInsets.only(left: 8),
child: IconButton(
icon: const Icon(Icons.loop),
onPressed: _generateAmount,
),
),
],
),
);
}
Widget _submitButton() {
return Container(
margin: const EdgeInsets.only(top: 32),
child: Row(
children: [
Expanded(
child: MaterialButton(
onPressed: () async => await _onTap(_apps!.last),
color: Theme.of(context).colorScheme.secondary,
height: 48,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6)),
child: Text('Initiate Transaction',
style: Theme.of(context)
.textTheme
.labelLarge!
.copyWith(color: Colors.white)),
),
),
],
),
);
}
Widget _androidApps() {
return Container(
margin: const EdgeInsets.only(top: 32, bottom: 32),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
margin: const EdgeInsets.only(bottom: 12),
child: Text(
'Pay Using',
style: Theme.of(context).textTheme.bodyLarge,
),
),
if (_apps != null) _appsGrid(_apps!.map((e) => e).toList()),
],
),
);
}
Widget _iosApps() {
return Container(
margin: const EdgeInsets.only(top: 32, bottom: 32),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
margin: const EdgeInsets.only(bottom: 24),
child: Text(
'One of these will be invoked automatically by your phone to make a payment',
style: Theme.of(context).textTheme.bodyMedium,
),
),
Container(
margin: const EdgeInsets.only(bottom: 12),
child: Text(
'Detected Installed Apps',
style: Theme.of(context).textTheme.bodyLarge,
),
),
if (_apps != null) _discoverableAppsGrid(),
Container(
margin: const EdgeInsets.only(top: 12, bottom: 12),
child: Text(
'Other Supported Apps (Cannot detect)',
style: Theme.of(context).textTheme.bodyLarge,
),
),
if (_apps != null) _nonDiscoverableAppsGrid(),
],
),
);
}
GridView _discoverableAppsGrid() {
List<ApplicationMeta> metaList = [];
for (var e in _apps!) {
if (e.upiApplication.discoveryCustomScheme != null) {
metaList.add(e);
}
}
return _appsGrid(metaList);
}
GridView _nonDiscoverableAppsGrid() {
List<ApplicationMeta> metaList = [];
for (var e in _apps!) {
if (e.upiApplication.discoveryCustomScheme == null) {
metaList.add(e);
}
}
return _appsGrid(metaList, disableOnTap: true);
}
GridView _appsGrid(List<ApplicationMeta> apps, {bool disableOnTap = false}) {
return GridView.count(
crossAxisCount: 4,
shrinkWrap: true,
mainAxisSpacing: 4,
crossAxisSpacing: 4,
physics: const NeverScrollableScrollPhysics(),
children: apps
.map(
(it) => Material(
key: ObjectKey(it.upiApplication),
child: InkWell(
onTap: disableOnTap ? null : () => _onTap(it),
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
it.iconImage(48),
Container(
margin: const EdgeInsets.only(top: 4),
alignment: Alignment.center,
child: Text(
it.upiApplication.getAppName(),
textAlign: TextAlign.center,
),
),
],
),
),
),
)
.toList(),
);
}
}
String? _validateUpiAddress(String value) {
if (value.isEmpty) {
return 'UPI VPA is required.';
}
if (value.split('@').length != 2) {
return 'Invalid UPI VPA';
}
return null;
}
更多关于Flutter ns_upi 是一个Flutter插件,用于查找手机上已安装的统一支付接口(UPI)应用程的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter ns_upi 是一个Flutter插件,用于查找手机上已安装的统一支付接口(UPI)应用程的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
针对帖子中提到的Flutter未知功能插件ns_upi
,虽然具体细节和API可能不为人知(因为这是一个假设性的或未知的插件),但我可以提供一个基于Flutter插件开发的一般性示例代码,展示如何集成和使用一个假设的UPI(Unified Payments Interface,统一支付接口)插件。请注意,以下代码是概念性的,并非针对具体的ns_upi
插件,因为该插件的具体实现细节未知。
假设的UPI插件集成示例
1. 添加依赖项
首先,假设ns_upi
插件已经在pub.dev
上发布,你可以在pubspec.yaml
文件中添加依赖项:
dependencies:
flutter:
sdk: flutter
ns_upi: ^x.y.z # 假设的版本号
然后运行flutter pub get
来获取依赖项。
2. 初始化插件
在你的Flutter应用中,你需要初始化这个插件。假设插件提供了一个UpiPlugin
类:
import 'package:flutter/material.dart';
import 'package:ns_upi/ns_upi.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter UPI Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late UpiPlugin _upiPlugin;
@override
void initState() {
super.initState();
_upiPlugin = UpiPlugin();
// 初始化插件,可能需要一些配置
// _upiPlugin.initialize(...);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Flutter UPI Demo'),
),
body: Center(
child: ElevatedButton(
onPressed: _initiateUpiPayment,
child: Text('Initiate UPI Payment'),
),
),
);
}
Future<void> _initiateUpiPayment() async {
try {
// 假设的UPI支付发起方法
String? result = await _upiPlugin.initiatePayment(
receiverVpa: 'receiver@bank', // 收款人的VPA
amount: '100.00', // 支付金额
notes: 'Payment for goods', // 备注信息
);
// 处理支付结果
if (result != null) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Payment Result: $result')),
);
}
} catch (e) {
// 处理异常
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: ${e.message}')),
);
}
}
}
3. 插件方法假设
上述代码中,我们假设ns_upi
插件有一个UpiPlugin
类,并且该类有一个initiatePayment
方法,该方法接受收款人的VPA、支付金额和备注信息作为参数,并返回一个Future,该Future在支付完成后解析为支付结果。
注意事项
- 实际插件可能不同:上述代码仅作为概念性示例,实际
ns_upi
插件的API可能完全不同。你需要查阅该插件的官方文档或源代码来了解其实际API。 - 权限和配置:UPI支付通常涉及敏感信息,因此在实际应用中,你可能需要配置必要的权限(如INTERNET、ACCESS_NETWORK_STATE等),并处理用户授权和安全性问题。
- 错误处理:在实际应用中,你需要更细致地处理各种可能的错误情况,如网络错误、用户取消支付等。
由于ns_upi
是一个假设性的插件,上述代码不能直接运行。如果你有一个具体的ns_upi
插件或类似的UPI支付插件,请查阅其官方文档以获取正确的集成和使用指南。