Flutter支付插件upi_pay_x的使用

发布于 1周前 作者 sinazl 来自 Flutter

Flutter支付插件upi_pay_x的使用

upi_pay_x 插件可以用于通过 UPI(Unified Payments Interface)进行支付。本指南将详细介绍如何在 Flutter 应用中集成和使用 upi_pay_x 插件。

安装插件

首先,在你的 pubspec.yaml 文件中添加 upi_pay_x 依赖:

dependencies:
  upi_pay_x:

然后运行 flutter pub get 来安装依赖。

iOS 配置

在 iOS 中,你需要修改 Info.plist 文件以包含必要的配置。将以下代码替换到 ios/Runner/Info.plist 文件中:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CADisableMinimumFrameDurationOnPhone</key>
	<true/>
	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>upi_pay_example</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>$(FLUTTER_BUILD_NAME)</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>$(FLUTTER_BUILD_NUMBER)</string>
	<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>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>UILaunchStoryboardName</key>
	<string>LaunchScreen</string>
	<key>UIMainStoryboardFile</key>
	<string>Main</string>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UIViewControllerBasedStatusBarAppearance</key>
	<false/>
</dict>
</plist>

使用示例

以下是一个完整的示例代码,展示了如何在 Flutter 应用中使用 upi_pay_x 插件进行支付。

import 'dart:io';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:upi_pay_x/upi_pay.dart';

void main() => runApp(App());

class App extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('UPI Pay X'),
        ),
        body: Screen(),
      ),
    );
  }
}

class Screen extends StatefulWidget {
  [@override](/user/override)
  _ScreenState createState() => _ScreenState();
}

class _ScreenState extends State<Screen> {
  String? _upiAddrError;

  final _upiAddressController = TextEditingController();
  final _amountController = TextEditingController();
  List<ApplicationMeta>? _apps;

  [@override](/user/override)
  void initState() {
    super.initState();

    _amountController.text = "1";

    Future.delayed(Duration(milliseconds: 0), () async {
      _apps = await UpiPay.getInstalledUpiApplications(
          statusType: UpiApplicationDiscoveryAppStatusType.all);
      setState(() {});
    });
  }

  [@override](/user/override)
  void dispose() {
    _amountController.dispose();
    _upiAddressController.dispose();
    super.dispose();
  }

  Future<void> _onTap(ApplicationMeta app) async {
    final err = _validateUpiAddress(_upiAddressController.text);
    if (err != null) {
      setState(() {
        _upiAddrError = err;
      });
      return;
    }
    setState(() {
      _upiAddrError = null;
    });

    final transactionRef = Random.secure().nextInt(1 << 32).toString();
    print("Starting transaction with id $transactionRef");

    final a = await UpiPay.initiateTransaction(
      amount: _amountController.text,
      app: app.upiApplication,
      receiverName: 'Amir Rahi',
      receiverUpiAddress: _upiAddressController.text,
      transactionRef: transactionRef,
      transactionNote: 'UPI Payment',
      // merchantCode: '7372',
    );

    print(a);
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: 16),
      child: ListView(
        children: <Widget>[
          _vpa(),
          if (_upiAddrError != null) _vpaError(),
          _amount(),
          if (Platform.isIOS) _submitButton(),
          Platform.isAndroid ? _androidApps() : _iosApps(),
        ],
      ),
    );
  }

  Widget _vpa() {
    return Container(
      margin: EdgeInsets.only(top: 32),
      child: TextFormField(
        controller: _upiAddressController,
        decoration: InputDecoration(
          border: OutlineInputBorder(),
          hintText: 'address@upi',
          labelText: 'Receiving UPI Address',
        ),
      ),
    );
  }

  Widget _vpaError() {
    return Container(
      margin: EdgeInsets.only(top: 4, left: 12),
      child: Text(
        _upiAddrError!,
        style: TextStyle(color: Colors.red),
      ),
    );
  }

  Widget _amount() {
    return Container(
      margin: EdgeInsets.only(top: 32),
      child: TextField(
        controller: _amountController,
        readOnly: true,
        enabled: false,
        decoration: InputDecoration(
          border: OutlineInputBorder(),
          labelText: 'Amount',
        ),
      ),
    );
  }

  Widget _submitButton() {
    return Container(
      margin: EdgeInsets.only(top: 32),
      child: MaterialButton(
        onPressed: () async => await _onTap(_apps![0]),
        child: Text('Initiate Transaction',
            style: Theme.of(context)
                .textTheme
                .button!
                .copyWith(color: Colors.white)),
        color: Theme.of(context).accentColor,
        height: 48,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)),
      ),
    );
  }

  Widget _androidApps() {
    return Container(
      margin: EdgeInsets.only(top: 32, bottom: 32),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Container(
            margin: EdgeInsets.only(bottom: 12),
            child: Text(
              'Pay Using',
              style: Theme.of(context).textTheme.bodyText1,
            ),
          ),
          if (_apps != null) _appsGrid(_apps!.map((e) => e).toList()),
        ],
      ),
    );
  }

  Widget _iosApps() {
    return Container(
      margin: EdgeInsets.only(top: 32, bottom: 32),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: <Widget>[
          Container(
            margin: 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.bodyText2,
            ),
          ),
          Container(
            margin: EdgeInsets.only(bottom: 12),
            child: Text(
              'Detected Installed Apps',
              style: Theme.of(context).textTheme.bodyText1,
            ),
          ),
          if (_apps != null) _discoverableAppsGrid(),
          Container(
            margin: EdgeInsets.only(top: 12, bottom: 12),
            child: Text(
              'Other Supported Apps (Cannot detect)',
              style: Theme.of(context).textTheme.bodyText1,
            ),
          ),
          if (_apps != null) _nonDiscoverableAppsGrid(),
        ],
      ),
    );
  }

  GridView _discoverableAppsGrid() {
    List<ApplicationMeta> metaList = [];
    _apps!.forEach((e) {
      if (e.upiApplication.discoveryCustomScheme != null) {
        metaList.add(e);
      }
    });
    return _appsGrid(metaList);
  }

  GridView _nonDiscoverableAppsGrid() {
    List<ApplicationMeta> metaList = [];
    _apps!.forEach((e) {
      if (e.upiApplication.discoveryCustomScheme == null) {
        metaList.add(e);
      }
    });
    return _appsGrid(metaList);
  }

  GridView _appsGrid(List<ApplicationMeta> apps) {
    apps.sort((a, b) => a.upiApplication
        .getAppName()
        .toLowerCase()
        .compareTo(b.upiApplication.getAppName().toLowerCase()));
    return GridView.count(
      crossAxisCount: 4,
      shrinkWrap: true,
      mainAxisSpacing: 4,
      crossAxisSpacing: 4,
      // childAspectRatio: 1.6,
      physics: NeverScrollableScrollPhysics(),
      children: apps
          .map(
            (it) => Material(
              key: ObjectKey(it.upiApplication),
              // color: Colors.grey[200],
              child: InkWell(
                onTap: Platform.isAndroid ? () async => await _onTap(it) : null,
                child: SingleChildScrollView(
                  child: Column(
                    mainAxisSize: MainAxisSize.min,
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: <Widget>[
                      it.iconImage(48),
                      Container(
                        margin: 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支付插件upi_pay_x的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter支付插件upi_pay_x的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中集成并使用upi_pay_x支付插件的示例代码。upi_pay_x是一个用于UPI(Unified Payments Interface)支付的Flutter插件。请注意,实际使用时,你需要确保已经按照插件的官方文档完成了所有必要的配置和依赖项的添加。

1. 添加依赖项

首先,在你的pubspec.yaml文件中添加upi_pay_x插件的依赖项:

dependencies:
  flutter:
    sdk: flutter
  upi_pay_x: ^latest_version  # 请替换为实际的最新版本号

然后运行flutter pub get来安装依赖项。

2. 导入插件

在你的Dart文件中导入upi_pay_x插件:

import 'package:upi_pay_x/upi_pay_x.dart';

3. 初始化并调用支付功能

下面是一个基本的示例,展示了如何初始化upi_pay_x插件并调用支付功能:

import 'package:flutter/material.dart';
import 'package:upi_pay_x/upi_pay_x.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter UPI Pay Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final UpiPayX _upiPayX = UpiPayX();

  void _initiatePayment() async {
    try {
      // 初始化支付参数
      final paymentDetails = UpiPaymentDetails(
        upiId: 'your_upi_id@upi', // 替换为你的UPI ID
        payeeName: 'Payee Name',
        payeeVpa: 'payee_vpa@upi', // 替换为收款人的VPA
        transactionNote: 'Payment for goods',
        transactionRefId: 'transaction_ref_id_123456', // 一个唯一的交易参考ID
        amount: 100.0, // 支付金额,单位为卢比
        currencyCode: 'INR', // 货币代码
      );

      // 发起支付
      final result = await _upiPayX.initiatePayment(paymentDetails);

      // 处理支付结果
      if (result.status == UpiPaymentStatus.success) {
        print('Payment successful!');
      } else if (result.status == UpiPaymentStatus.failed) {
        print('Payment failed: ${result.errorMessage}');
      } else if (result.status == UpiPaymentStatus.userCancelled) {
        print('Payment cancelled by user.');
      } else {
        print('Unknown payment status: ${result.status}');
      }
    } catch (e) {
      print('An error occurred: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter UPI Pay Demo'),
      ),
      body: Center(
        child: ElevatedButton(
          onPressed: _initiatePayment,
          child: Text('Initiate Payment'),
        ),
      ),
    );
  }
}

4. 注意事项

  • 确保你已经正确配置了Android和iOS的权限和依赖项,以便插件能够正常工作。
  • upi_pay_x插件可能需要额外的配置才能与特定的银行或支付处理商兼容。请参考插件的官方文档以获取更多详细信息。
  • 在实际项目中,请务必处理所有可能的错误和异常情况,以确保用户体验的流畅性和安全性。

5. 权限配置

根据你的具体需求,你可能需要在AndroidManifest.xmlInfo.plist中添加额外的权限配置。请参考upi_pay_x插件的官方文档以获取详细的权限配置指南。

这只是一个基本的示例,实际使用时你可能需要根据具体需求进行进一步的调整和优化。

回到顶部