Seamless PhonePe Payment Integration for Flutter Developers

Integrating PhonePe payments in your Flutter app enhances user convenience by providing a popular digital wallet for transactions. Here’s a detailed step-by-step guide for integrating PhonePe in Flutter.


1. Set Up Flutter Project

Begin by ensuring you have a Flutter environment set up. If not, create a new project:

flutter create phonepe_integration

Then, open your project in an IDE of your choice.

2. Add Dependencies

To use PhonePe’s SDK in your Flutter project, add the necessary dependency to your pubspec.yaml:

dependencies:
  phonepe_payment_sdk: ^<latest_version>
  crypto: ^3.0.1

Ensure you replace <latest_version> with the latest version available. This phonepe_payment_sdk package is crucial for accessing PhonePe’s API in your Flutter code.

Run the following command to get the dependencies:

flutter pub get

3. Configure Android and iOS Permissions

Android Setup

Go to android/app/build.gradle and make sure the minSdkVersion is at least 21:

defaultConfig {
    minSdkVersion 21
}

In the AndroidManifest.xml, add the necessary permissions for internet access and PhonePe activity:

<uses-permission android:name="android.permission.INTERNET" />

<application ...>
    <activity
        android:name="com.phonepe.sdk.ui.PhonePePaymentActivity"
        android:exported="true" />
</application>

iOS Setup

For iOS, open your ios/Runner/Info.plist and add the following permissions for network access:

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

4. Platform-Specific Code Integration

You’ll need to set up platform channels to communicate between Flutter and native code.

Initialize the SDK

PhonePe’s SDK needs to be initialized before you can start any transaction. This can be done using the init() method:

PhonePePaymentSdk.init("SANDBOX", null, "<merchant_id>", true).then((val) {
  debugPrint('PhonePe SDK Initialized - $val');
  startTransaction();
}).catchError((error) {
  debugPrint('PhonePe SDK error - $error');
});

Ensure you replace <merchant_id> with your actual merchant ID.

5. Create Transaction Logic

You’ll now build the transaction logic. A typical PhonePe transaction requires merchant details, amount, and a callback URL.

Here’s how you can create and start a transaction:

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

class PhonePePg {
  int amount;
  BuildContext context;

  PhonePePg({required this.context, required this.amount});

  String merchantId = "PGTESTPAYUAT";
  String salt = "099eb0cd-02cf-4e2a-8aca-3e6c6aff0399";
  int saltIndex = 1;
  String callbackURL = "https://www.webhook.site/callback-url";
  String apiEndPoint = "/pg/v1/pay";

  void init() {
    PhonePePaymentSdk.init("SANDBOX", null, merchantId, true).then((val) {
      debugPrint('PhonePe SDK Initialized - $val');
      startTransaction();
    }).catchError((error) {
      debugPrint('PhonePe SDK error - $error');
    });
  }

  void startTransaction() {
    Map body = {
      "merchantId": merchantId,
      "merchantTransactionId": "transactionId_${DateTime.now().millisecondsSinceEpoch}",
      "merchantUserId": "user123",
      "amount": amount * 100, // in paise
      "callbackUrl": callbackURL,
      "mobileNumber": "9876543210",
      "paymentInstrument": {"type": "PAY_PAGE"}
    };

    String bodyEncoded = base64Encode(utf8.encode(jsonEncode(body)));

    var byteCodes = utf8.encode(bodyEncoded + apiEndPoint + salt);

    String checksum = "${sha256.convert(byteCodes)}###$saltIndex";

    PhonePePaymentSdk.startTransaction(bodyEncoded, callbackURL, checksum, "")
        .then((success) {
      debugPrint("Payment success $success");
      // Redirect user to your success screen
    }).catchError((error) {
      debugPrint("Payment failed $error");
    });
  }
}

6. Handling Success and Failure

Once the transaction is completed, you’ll need to handle the results, whether it succeeds or fails. You can navigate to a success or failure screen depending on the result:

PhonePePaymentSdk.startTransaction(bodyEncoded, callbackURL, checksum, "")
    .then((success) {
  debugPrint("Payment success $success");
  Navigator.pushReplacement(
    context,
    MaterialPageRoute(builder: (context) => const SuccessScreen()),
  );
}).catchError((error) {
  debugPrint("Payment failed $error");
  Navigator.pushReplacement(
    context,
    MaterialPageRoute(builder: (context) => const FailureScreen()),
  );
});

7. Testing Your Integration

You’ll want to ensure the integration works as expected before going live. Test in PhonePe’s Sandbox environment before switching to production. You can pass test merchant IDs and use the sandbox URLs for callback responses.

8. Switch to Production

Once your testing is successful, replace the SANDBOX environment and sandbox details with your live credentials:

PhonePePaymentSdk.init("PRODUCTION", null, "<production_merchant_id>", true);

Update the callback URL to the live server and ensure you’re handling sensitive data securely.


Conclusion

PhonePe integration in Flutter is straightforward when the steps are followed carefully. This guide walks you through every stage of integration, from setting up the SDK to handling transactions and managing success or failure callbacks. Testing in the sandbox environment is crucial to ensure your payment flow works seamlessly before going live.

By following these steps, you can offer a secure and convenient payment method for your Flutter users.

You may also like

Leave a Reply