Flutter支付集成插件flutter_hl_vnpay的使用

Flutter支付集成插件flutter_hl_vnpay的使用

flutter_hl_vnpay 是一个用于 Flutter 的VNPay插件,帮助开发者构建现代多平台应用。

开始使用

iOS

ios/Runner/Info.plist 文件中添加以下配置:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    <key>NSAllowsArbitraryLoadsInWebContent</key>
    <true/>
</dict>

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLName</key>
        <string>com.hlsolutions.hoishipper</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>hlsolutions</string>
        </array>
    </dict>
</array>

Android

使用步骤

1. 添加依赖

在项目的 pubspec.yaml 文件中添加以下依赖:

dependencies:
  flutter_hl_vnpay: ^2.0.1
  crypto: 2.1.5

2. 获取依赖

运行命令以获取依赖项:

$ flutter pub get

3. 导入库

在 Dart 代码中导入以下库:

import 'package:flutter/services.dart';
import 'package:flutter_hl_vnpay/flutter_hl_vnpay.dart';
import 'package:crypto/crypto.dart';

4. 使用VNPay

以下是一个完整的示例,展示了如何使用 flutter_hl_vnpay 插件进行支付:

import 'package:flutter/material.dart';
import 'dart:convert';
import 'dart:async';

import 'package:flutter/services.dart';
import 'package:flutter_hl_vnpay/flutter_hl_vnpay.dart';
import 'package:crypto/crypto.dart';

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

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

class _MyAppState extends State<MyApp> {
  String _paymentResultCodeCode = 'Unknown';

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

  // 平台消息是异步的,所以我们初始化在一个异步方法中。
  _onBuyCoinPressed() async {
    String paymentResultCodeCode;
    // 平台消息可能会失败,所以我们使用 try/catch PlatformException。
    try {
      String url = 'http://sandbox.vnpayment.vn/paymentv2/vpcpay.html';
      String tmnCode = 'SOLUTION'; // 从VNPay获取
      String hashKey = 'VQWLEXBMLOWVLSCJWRBCIOFRPTOROYCQ'; // 从VNPay获取

      final params = <String, dynamic>{
        'vnp_Command': 'pay',
        'vnp_Amount': '3000000',
        'vnp_CreateDate': '20210315151908',
        'vnp_CurrCode': 'VND',
        'vnp_IpAddr': '192.168.15.102',
        'vnp_Locale': 'vn',
        'vnp_OrderInfo': '5fa66b8b5f376a000417e501 pay coin 30000 VND',
        'vnp_ReturnUrl': 'https://hl-solutions.vercel.app/orders/order-return', // 您的服务器 https://sandbox.vnpayment.vn/apis/docs/huong-dan-tich-hop/#code-returnurl
        'vnp_TmnCode': tmnCode,
        'vnp_TxnRef': DateTime.now().millisecondsSinceEpoch.toString(),
        'vnp_Version': '2.0.0'
      };

      final sortedParams = FlutterHlVnpay.instance.sortParams(params);
      final hashDataBuffer = new StringBuffer();
      sortedParams.forEach((key, value) {
        hashDataBuffer.write(key);
        hashDataBuffer.write('=');
        hashDataBuffer.write(value);
        hashDataBuffer.write('&');
      });
      final hashData = hashDataBuffer.toString().substring(0, hashDataBuffer.length - 1);
      final query = Uri(queryParameters: sortedParams).query;
      print('hashData = $hashData');
      print('query = $query');

      var bytes = utf8.encode(hashKey + hashData.toString());
      final vnpSecureHash = sha256.convert(bytes);
      final paymentUrl = "$url?$query&vnp_SecureHashType=SHA256&vnp_SecureHash=$vnpSecureHash";
      print('paymentUrl = $paymentUrl');
      paymentResultCodeCode = (await FlutterHlVnpay.instance.show(paymentUrl: paymentUrl, tmnCode: tmnCode, scheme: 'hlsolutions')).toString();
    } on PlatformException {
      paymentResultCodeCode = 'Failed to get payment result code';
    }

    // 如果小部件在异步平台消息飞行时被从树中移除,我们希望丢弃回复而不是调用
    // setState 来更新我们的非存在的外观。
    if (!mounted) return;

    setState(() {
      _paymentResultCodeCode = paymentResultCodeCode;
    });
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('插件示例应用'),
        ),
        body: Center(
          child: Column(
            children: [
              Text('结果码: $_paymentResultCodeCode\n'),
              RaisedButton(
                onPressed: this._onBuyCoinPressed,
                child: Text('10.000 VND'),
              )
            ],
          ),
        ),
      ),
    );
  }
}

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

1 回复

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


flutter_hl_vnpay 是一个用于在 Flutter 应用中集成越南支付网关 VNPay 的插件。通过这个插件,开发者可以方便地在应用中集成 VNPay 支付功能,实现支付流程的自动化。

以下是如何在 Flutter 项目中使用 flutter_hl_vnpay 插件的步骤:

1. 添加依赖

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

dependencies:
  flutter:
    sdk: flutter
  flutter_hl_vnpay: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来获取依赖。

2. 导入插件

在需要使用 VNPay 的 Dart 文件中导入插件:

import 'package:flutter_hl_vnpay/flutter_hl_vnpay.dart';

3. 初始化支付

在需要进行支付的地方,初始化支付参数并启动支付流程。通常,你需要提供以下信息:

  • url: VNPay 的支付网关 URL。
  • tmnCode: 商户代码。
  • hashSecret: 用于生成签名的密钥。
  • amount: 支付金额。
  • orderInfo: 订单信息。
  • returnUrl: 支付完成后返回的 URL。
void initiateVnPayPayment() async {
  final vnPay = VnPay();

  final paymentUrl = await vnPay.generatePaymentUrl(
    url: 'https://sandbox.vnpayment.vn/paymentv2/vpcpay.html',
    tmnCode: 'YOUR_TMN_CODE',
    hashSecret: 'YOUR_HASH_SECRET',
    amount: 100000, // 金额以 VND 为单位
    orderInfo: 'Payment for Order #123',
    returnUrl: 'your_app_scheme://vnpay_return', // 自定义 scheme
  );

  final result = await vnPay.startPayment(paymentUrl);

  if (result == VnPayResult.success) {
    // 支付成功
    print('Payment successful');
  } else if (result == VnPayResult.failed) {
    // 支付失败
    print('Payment failed');
  } else if (result == VnPayResult.cancelled) {
    // 用户取消支付
    print('Payment cancelled');
  }
}

4. 处理支付结果

returnUrl 中指定的 URL 用于处理支付完成后的回调。你需要在应用的 AndroidManifest.xmlInfo.plist 中注册这个自定义的 URL scheme。

对于 Android

android/app/src/main/AndroidManifest.xml 中添加以下内容:

<activity android:name=".MainActivity">
  <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="your_app_scheme" />
  </intent-filter>
</activity>

对于 iOS

ios/Runner/Info.plist 中添加以下内容:

<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleTypeRole</key>
    <string>Editor</string>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>your_app_scheme</string>
    </array>
  </dict>
</array>

5. 监听支付结果

MainActivityAppDelegate 中监听支付结果的回调。

对于 Android

MainActivity.ktMainActivity.java 中重写 onNewIntent 方法:

import android.content.Intent
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "vnpay_channel").setMethodCallHandler { call, result ->
            if (call.method == "handleVnPayResult") {
                // 处理支付结果
            }
        }
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        // 处理支付结果
    }
}

对于 iOS

AppDelegate.swift 中重写 application(_:open:options:) 方法:

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        let controller = window?.rootViewController as! FlutterViewController
        let vnpayChannel = FlutterMethodChannel(name: "vnpay_channel", binaryMessenger: controller.binaryMessenger)
        vnpayChannel.setMethodCallHandler { (call, result) in
            if call.method == "handleVnPayResult" {
                // 处理支付结果
            }
        }
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        // 处理支付结果
        return true
    }
}

6. 处理支付回调

在 Flutter 中,你可以通过 MethodChannel 来处理支付回调:

import 'package:flutter/services.dart';

void handleVnPayResult() {
  const channel = MethodChannel('vnpay_channel');
  channel.setMethodCallHandler((call) async {
    if (call.method == 'handleVnPayResult') {
      // 处理支付结果
    }
  });
}
回到顶部