如何将flutter上的Phonepe支付网关与android sdk或插件集成?

问题描述 投票:0回答:3

我正在开发一个 Flutter 应用程序,我需要将 PhonePe 支付网关集成到其中。不幸的是,PhonePe 没有可用的官方 Flutter 插件。但是,PhonePe 确实提供了 Android SDK 用于集成其支付网关。

我已经阅读了 PhonePe 文档(下面提供的链接),并且正在寻找有关如何将 PhonePe 支付网关 Android SDK 集成到我的 Flutter 应用程序中的指导。*** 我对涉及编写本机的两种解决方案持开放态度Android 代码和那些不需要本机代码的代码。***

PhonePe 文档:[https://developer.phonepe.com/v1/docs/android-pg-sdk-integration]

理想情况下,我希望找到一个教程或分步说明,以易于遵循的方式解释集成过程。如果现有的 Flutter 插件或包可以简化此集成,请告诉我。

任何帮助、代码片段或对现有资源的引用将不胜感激。谢谢!

我已经使用 WebView 和 Node.js 后端成功实现了 PhonePe 结帐流程来创建结帐链接。但是,我现在需要一个更强大的 UI 来在我的 Flutter 应用程序中显示结帐过程。为了实现这一点,我需要集成PhonePe支付网关Android SDK。

flutter payment-gateway phonepe
3个回答
0
投票

在原生端实现PhonePe支付网关,并从flutter端调用。您将需要方法通道和事件通道,以便它在本机端和 flutter 端之间进行通信。在这里阅读更多内容https://docs.flutter.dev/platform-integration/platform-channels


0
投票
import 'dart:developer';

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

import 'package:crypto/crypto.dart';
import 'package:http/http.dart' as http;

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});`enter code here`

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  void _incrementCounter() async {
    final data = {
      "merchantId": "MERCHANTUAT",
      "merchantTransactionId": "MT7850590068188104",
      "merchantUserId": "MU933037302229373",
      "amount": 100,
      "callbackUrl": "https://webhook.site/callback-url",
      "mobileNumber": "9999999999",
      "deviceContext": {"deviceOS": "ANDROID"},
      "paymentInstrument": {
        "type": "UPI_INTENT",
        "targetApp": "com.phonepe.app",
        "accountConstraints": [
          {
            //Optional. Required only for TPV Flow.
            "accountNumber": "420200001892",
            "ifsc": "ICIC0000041"
          }
        ]
      }
    };

    final b64 = jsonEncode(data).toBase64;

    print(b64);

    const saltKey = "099eb0cd-02cf-4e2a-8aca-3e6c6aff0399";

    final sha = '$b64/pg/v1/pay$saltKey'.toSha256;
    print(sha);
    try {
      final res = await http.post(
        Uri.parse('https://api-preprod.phonepe.com/apis/pg-sandbox/pg/v1/pay'),
        headers: {
          'Content-Type': 'application/json',
          'X-VERIFY': '$sha###1',
        },
      );

      print(res.body.toString());
    } catch (e) {
      log(e.toString());
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        // TRY THIS: Try changing the color here to a specific color (to
        // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
        // change color while the other colors stay the same.
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: test,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }

  void test() async {
    const saltKey = "099eb0cd-02cf-4e2a-8aca-3e6c6aff0399";
    const saltIndex = 1;
    const apiEndpoint = "/pg/v1/pay";

    final jsonData = {
      "merchantId": "MERCHANTUAT",
      "merchantTransactionId": "MT7850590068188104",
      "merchantUserId": "MUID123",
      "amount": '100',
      "redirectUrl": "https://webhook.site/redirect-url",
      "redirectMode": "POST",
      "callbackUrl": "https://webhook.site/callback-url",
      "mobileNumber": "9999999999",
      "paymentInstrument": {"type": "PAY_PAGE"}
    };

    String jsonString = jsonEncode(jsonData);
    String base64Data = jsonString.toBase64;
    String dataToHash = base64Data + apiEndpoint + saltKey;
    String sHA256 = generateSha256Hash(dataToHash);

    print(base64Data);
    print('#' * 10);
    print("$sHA256###$saltIndex");

    final response = await http.post(
      Uri.parse('https://api-preprod.phonepe.com/apis/pg-sandbox/pg/v1/pay'),
      headers: {
        "accept": "application/json",
        'X-VERIFY': '$sHA256###$saltIndex',
        'Content-Type': 'application/json',
      },
      body: jsonEncode({'request': base64Data}),
    );

    log(response.body.toString());
  }

  String generateSha256Hash(String input) {
    var bytes = utf8.encode(input);
    var digest = sha256.convert(bytes);
    return digest.toString();
  }
}

/// EncodingExtensions
extension EncodingExtensions on String {
  /// To Base64
  /// This is used to convert the string to base64
  String get toBase64 {
    return base64.encode(toUtf8);
  }

  /// To Utf8
  /// This is used to convert the string to utf8
  List<int> get toUtf8 {
    return utf8.encode(this);
  }

  /// To Sha256
  /// This is used to convert the string to sha256
  String get toSha256 {
    return sha256.convert(toUtf8).toString();
  }
}

-1
投票

https://webhook.site/callback-url 此请求负载中的回调 url 是什么?

© www.soinside.com 2019 - 2024. All rights reserved.