Flutter移动支付插件mpesa_flutter_plugin的使用

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

Flutter移动支付插件mpesa_flutter_plugin的使用

使用说明

使用此插件可以实现Lipa Na MPESA在线支付。

开始使用

  1. 在Safaricom Developer Portal上创建一个账户。
  2. 创建一个Lipa na MPESA Online应用。
  3. 获取密钥 - ConsumerKeyConsumerSecret

示例代码

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

void main() {
  MpesaFlutterPlugin.setConsumerKey('your-consumer-key');
  runApp(MyApp());
}

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

class _MyAppState extends State<MyApp> {
  Future<void> startCheckout({required String userPhone, required double amount}) async {
    dynamic transactionInitialisation;
    try {
      transactionInitialisation =
          await MpesaFlutterPlugin.initializeMPesaSTKPush(
              businessShortCode: '174379', // 使用您的商店编号,如果交易类型是CustomerBuyGoodsOnline
              transactionType: TransactionType.CustomerPayBillOnline, // 或者CustomerBuyGoodsOnline用于Till号码
              amount: amount,
              partyA: userPhone,
              partyB: '174379',
              callBackURL: Uri(
                  scheme: 'https', host: 'sandbox.safaricom.co.ke', path: '/callback'),
              accountReference: 'order-number',
              phoneNumber: userPhone,
              baseUri: Uri(scheme: 'https', host: 'sandbox.safaricom.co.ke'),
              transactionDesc: 'purchase',
              passKey: 'your-passkey');

      print("TRANSACTION RESULT: $transactionInitialisation");

      // 更新数据库以保存初始化数据
      return transactionInitialisation;
    } catch (e) {
      print("CAUGHT EXCEPTION: $e");
    }
  }

  List<Map<String, dynamic>> itemsOnSale = [
    {
      "image": "image/shoe.jpg",
      "itemName": "Breathable Oxford Casual Shoes",
      "price": 1.0
    }
  ];

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primaryColor: Colors.brown[450],
        primarySwatch: Colors.brown,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Mpesa Payment plugin'),
        ),
        body: ListView.builder(
          itemBuilder: (BuildContext context, int index) {
            return Card(
              elevation: 4.0,
              child: Container(
                decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(10.0),
                    color: Colors.brown),
                height: MediaQuery.of(context).size.height * 0.35,
                child: Column(
                  children: [
                    Container(
                      decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(10.0)),
                      child: Image.asset(
                        itemsOnSale[index]["image"],
                        fit: BoxFit.cover,
                      ),
                      height: MediaQuery.of(context).size.height * 0.25,
                      width: MediaQuery.of(context).size.width * 0.95,
                    ),
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: [
                        Container(
                          width: MediaQuery.of(context).size.width * 0.45,
                          child: Text(
                            itemsOnSale[index]["itemName"],
                            overflow: TextOverflow.ellipsis,
                            style: TextStyle(fontSize: 14.0, color: Colors.black),
                          ),
                        ),
                        Text(
                          "Ksh. ${itemsOnSale[index]["price"].toString()}",
                          style: TextStyle(
                              fontSize: 18.0, color: Colors.white, fontWeight: FontWeight.bold),
                        ),
                        ElevatedButton(
                          style: ElevatedButton.styleFrom(
                            padding: EdgeInsets.symmetric(
                                horizontal: 5, vertical: 2),
                          ),
                          onPressed: () async {
                            var providedContact = await _showTextInputDialog(context);

                            if (providedContact != null) {
                              if (providedContact.isNotEmpty) {
                                startCheckout(userPhone: providedContact, amount: itemsOnSale[index]["price"]);
                              } else {
                                showDialog(
                                    context: context,
                                    builder: (context) {
                                      return AlertDialog(
                                        title: const Text('Empty Number!'),
                                        content: Text(
                                            'You did not provide a number to be charged.'),
                                        actions: [
                                          ElevatedButton(
                                            child: const Text('Cancel'),
                                            onPressed: () =&gt; Navigator.pop(context),
                                          ),
                                        ],
                                      );
                                    });
                              }
                            }
                          },
                          child: Text("Checkout"))
                        )
                      ],
                    )
                  ],
                ),
              ),
            );
          },
          itemCount: itemsOnSale.length,
        ),
      ),
    );
  }

  final _textFieldController = TextEditingController();

  Future&lt;String?&gt; _showTextInputDialog(BuildContext context) async {
    return showDialog(
        context: context,
        builder: (context) {
          return AlertDialog(
            title: const Text('M-Pesa Number'),
            content: TextField(
              controller: _textFieldController,
              decoration: const InputDecoration(hintText: '+254...'),
            ),
            actions: [
              ElevatedButton(
                child: const Text('Cancel'),
                onPressed: () =&gt; Navigator.pop(context),
              ),
              ElevatedButton(
                child: const Text('Proceed'),
                onPressed: () =&gt; Navigator.pop(context, _textFieldController.text),
              ),
            ],
          );
        });
  }
}

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

1 回复

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


当然,以下是一个关于如何在Flutter项目中使用mpesa_flutter_plugin插件来实现M-Pesa移动支付的代码示例。请注意,这个插件的具体实现和API可能会根据版本更新有所变化,因此请参考最新的官方文档以确保准确性。

首先,确保你已经在pubspec.yaml文件中添加了mpesa_flutter_plugin依赖:

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

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

接下来,在你的Flutter项目中,你可以按照以下步骤使用M-Pesa移动支付功能:

  1. 导入插件并初始化

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

import 'package:mpesa_flutter_plugin/mpesa_flutter_plugin.dart';
  1. 配置M-Pesa参数

在调用M-Pesa支付功能之前,你需要设置一些必要的参数,如消费者信息、业务短代码、账户信息等。这些参数通常根据你的M-Pesa开发者账户配置。

// 示例参数配置
Map<String, String> stkPushParams = {
  'BusinessShortCode': '你的业务短代码', // 替换为你的M-Pesa业务短代码
  'Password': '你的API密码', // 替换为你的M-Pesa API密码
  'Timestamp': DateTime.now().millisecondsSinceEpoch.toString(),
  'TransactionType': 'C2B',
  'Amount': '100', // 支付金额
  'PartyA': '消费者的MSISDN', // 替换为消费者的手机号码
  'PartyB': '你的业务短代码', // 通常与BusinessShortCode相同
  'CallbackURL': '你的回调URL', // 替换为你的回调URL
  'AccountReference': '可选的账户参考信息',
  'Remark': '支付备注信息',
};

注意:Timestamp字段需要格式化为UNIX时间戳(毫秒级)。

  1. 发起支付请求

使用插件提供的stkPushSimulationstkPush方法来发起支付请求。stkPushSimulation通常用于测试环境,而stkPush用于生产环境。

void initiateMpesaPayment() async {
  try {
    // 使用stkPush方法进行支付请求(生产环境)
    // var response = await MpesaFlutterPlugin.stkPush(stkPushParams);
    
    // 使用stkPushSimulation方法进行支付请求(测试环境)
    var response = await MpesaFlutterPlugin.stkPushSimulation(stkPushParams);
    
    print('M-Pesa Payment Response: $response');
    
    // 根据响应处理支付结果
    if (response['ResponseCode'] == '0') {
      // 支付成功处理逻辑
      print('Payment successful!');
    } else {
      // 支付失败处理逻辑
      print('Payment failed: ${response['ResponseDescription']}');
    }
  } catch (e) {
    // 异常处理
    print('Error initiating M-Pesa payment: $e');
  }
}
  1. 在UI中调用支付功能

你可以在一个按钮点击事件中调用initiateMpesaPayment函数来触发支付流程。

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('M-Pesa Payment Example'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: initiateMpesaPayment,
            child: Text('Initiate Payment'),
          ),
        ),
      ),
    );
  }
}

这个示例展示了如何在Flutter应用中使用mpesa_flutter_plugin插件来发起M-Pesa移动支付请求。请确保你替换了所有占位符参数为你的实际M-Pesa开发者账户信息,并根据需要调整支付逻辑。

注意:在实际部署之前,请务必在M-Pesa开发者门户中测试你的集成,并确保遵守所有相关的安全最佳实践和支付规定。

回到顶部