Flutter Platform - SDK Integration
To merchants who have built their app on the Flutter platform, PhonePe provides a bridge to conveniently integrate PhonePe SDK. On this page, we will highlight the steps required to integrate PhonePe SDK with the Flutter platform for your app. This platform helps you to build a seamless and responsive checkout experience for your application.
This integration will support the following flows:
-
App Inoke Flow: In case the PhonePe app is installed, it will be launched to complete the
transaction and give the response back to your app. -
Redirection Flow: In case the PhonePe app is not installed, PhonePe SDK will open a web-view
to process transactions and give the response back to your app.
Follow the steps below to integrate PhonePe SDK in the Flutter app:
Android Project of Flutter
- Add the below code to 'repositories' section of your project level build.gradle file
// Top-level build file where you can add configuration options common to all sub-projects/modules.
allprojects {
repositories {
google()
maven {
url "https://phonepe.mycloudrepo.io/public/repositories/phonepe-intentsdk-snapshots"
}
}
}
//https://dash.readme.com/project/phonepe-docs/v1/docs/android-pg-sdk-integration Top-level build file where you can add configuration options common to all sub-projects/modules.
allprojects {
repositories {
google()
maven {
url "https://phonepe.mycloudrepo.io/public/repositories/phonepe-intentsdk-android"
}
}
}
- Add the below line to the 'dependencies' section of your app build.gradle.
implementation 'phonepe.intentsdk.android.snapshot:IntentSDK:[email protected]’
implementation 'phonepe.intentsdk.android.release:IntentSDK:[email protected]’
For, SDK version 1.6.8
We have compileSdkVersion: 28, minSdkVersion: 21, targetSdkVersion: 28
- Add below lines of code inside application tag in the AndroidManifest.xml file
<!-- Keep it false in production environment-->
<meta-data
android:name="com.phonepe.android.sdk.Debuggable"
android:value="true"/>
<!-- Keep it false in production environment-->
<meta-data
android:name="com.phonepe.android.sdk.isUAT"
android:value="true"/>
<!-- The value will be the MID-->
<meta-data
android:name="com.phonepe.android.sdk.MerchantId"
android:value="MID"/>
<!-- Get the App Id from PhonePe-->
<meta-data
android:name="com.phonepe.android.sdk.AppId"
android:value="<your app id given by PhonePe>"/>
-
Add CheckoutActivity in your project (see Appendix at the end of this document).
-
Add OnActivityResult method in CheckoutActivity class as per your response requirement in the
Flutter app.
Flutter App Code
- Import the services package in the main.dart file of the Flutter app.
import 'package:flutter/services.dart';
- Declare method channel to communicate with the native code from the Flutter App.
static const platform = const MethodChannel("Your channel name");
- In the main.dart file add the following to check whether PhonePe app is installed or Not:
void shouldShow() async{
String isPhonePeAvailable;
try{
isPhonePeAvailable = await platform.invokeMethod("shouldShow");
}catch(e){
print(e);
}
print(isPhonePeAvailable);
}
Note
Install the PhonePe PreProd app. Refer to this link.
If returns true then display the PhonePe option on the checkout page or if returns false then do not display the PhonePe option on the checkout page.
- In the main.dart file add the following code to initiate the payment process.
Pass all the parameters as shown below:
var data = <String, dynamic> {
"base64Body" : “/“* pass the base64Body value */,
"checksum" : “/“* pass the checksum value */,
"apiEndPoint" : “/“* pass the api endpoint value */,
"x-callback-url" : “/“* pass the callback url */
};
Below code calls the native method to initiate the payment process:
String uiCallbackValue;
try{
uiCallbackValue = await platform.invokeMethod("startPaymentTransaction",data);
}catch(e){
print(e);
}
-
base64EncodedBody - pass the encoded payload request
-
checksum - pass the checksum value
-
apiEndPoint - pass the endpoint
-
xCallbackUrl - This can be “” or else you can send your custom callback URL where you
will receive the server to server callback response to your custom callback URL. Once
the response is received you have to validate the checksum and invalid amount. Refer to this
link for more details. -
uiCallbackValue - This is a variable that will receive a user interface callback response
from the startPaymentTransaction method.
/This callback indicates only about completion of UI flow.
Inform your server to make the transaction
status call to get the status. Update your app with the
success/failure status./
Note
- If data returns User Completed it indicates the payment has been completed.
- If data returns User Cancelled it indicates the payment has been canceled just in case if the user presses the back button or aborts the transaction.
-
Inform merchant server about the completion of the transaction flow from merchant app
-
Merchant server should check the status with server to server callback or make the Check
Transaction Status API call to the PhonePe server to check the transaction status (Even
for User Cancelled callback) -
The app should get the transaction status from the backend
-
Based on the result, the merchant must inform the user about the success or failure status
of the transaction
References
-
For Accept Payment API, Refer to this link.
-
Use the Check Transaction Status API to check the status of the payment transaction. Refer to
this link. -
For refund API, Refer to this link.
Appendix
CheckoutAcitivity.java
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.phonepe.intent.sdk.api.PhonePe;
import com.phonepe.intent.sdk.api.PhonePeInitException;
import com.phonepe.intent.sdk.api.ShowPhonePeCallback;
import com.phonepe.intent.sdk.api.TransactionRequest;
import com.phonepe.intent.sdk.api.TransactionRequestBuilder;
import io.flutter.app.FlutterActivity;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;
import java.util.*;
public class CheckoutActivity extends FlutterActivity {
private static final String CHANNEL = "Your channel name";
private static final int DEBIT_REQUEST_CODE = 777;
MethodChannel.Result mResult;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
// Initiate the PhonePe SDK
PhonePe.init(this);
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler(new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
mResult = result;
if (call.method.equals("shouldShow")) {
try {
PhonePe.isUPIAccountRegistered(new ShowPhonePeCallback() {
@Override
public void onResponse(boolean b) {
mResult.success("" + b);
}
});
} catch (PhonePeInitException e) {
e.printStackTrace();
}
} else if (call.method.equals("startPaymentTransaction")) {
final Map < String, Object > arguments = call.arguments();
TransactionRequest mTransactionRequest;
String base64Body = (String) arguments.get("base64Body");
String checksum = (String) arguments.get("checksum");
String endPoint = (String) arguments.get("apiEndPoint");
String xCallbackUrl = (String) arguments.get("x-callback-url");
HashMap < String, String > headers = new HashMap();
headers.put("X-CHANNEL-ID", "phonepe_flutter_sdk");
if (xCallbackUrl != null && xCallbackUrl.length() != 0 && !xCallbackUrl.isEmpty()) {
headers.put("X-CALLBACK-URL", xCallbackUrl);
headers.put("X-CALL-MODE", "POST");
mTransactionRequest = new TransactionRequestBuilder()
.setData(base64Body)
.setChecksum(checksum)
.setUrl(endPoint)
.setHeaders(headers)
.build();
} else {
mTransactionRequest = new TransactionRequestBuilder()
.setData(base64Body)
.setChecksum(checksum)
.setHeaders(headers)
.setUrl(endPoint)
.build();
}
//For Intent SDK call below function
try {
startActivityForResult(PhonePe.getTransactionIntent(
mTransactionRequest), DEBIT_REQUEST_CODE);
} catch (PhonePeInitException e) {}
}
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == DEBIT_REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
mResult.success("User Completed");
} else if (resultCode == Activity.RESULT_CANCELED) {
mResult.success("User Cancelled");
}
}
}
}
Main.dart
void startPaymentTransaction() async {
var data = < String,
dynamic > {
"base64Body": " /* pass the base64 body value */ ",
"checksum": " /* pass the checksum value */ ",
"apiEndPoint": " /* pass the api endpoint */ ",
"x-callback-url": " /* pass the callback url value */ "
};
String uiCallbackValue;
try {
uiCallbackValue = await platform.invokeMethod("startPaymentTransaction", data);
} catch (e) {
print(e);
}
print(uiCallbackValue);
}
}
Updated 4 months ago