Flutter package for integrating PhonePe Payment Gateway in your Flutter App.
This is currently based on PhonePe SDK Less integeration and only supported on Android and iOS right now.
- For UAT: You need an app called 'PhonePe Simulator' You can request the PhonePe team for the same and they will provide you
- How to setup UAT
- For Prod:
- You will have to write the api for hitting the PhonePe pay api, and share the IP of the server from where you're hitting the PhonePe API
- Example code
import crypto from "crypto"; async function pay(req: any): Promise<any> { const saltKey = process.env.SALT_KEY; const body = JSON.stringify(req.body); const payload = Buffer.from(body).toString("base64"); const gateway = "/pg/v1/pay"; const dataForChecksum = payload + gateway + saltKey; let hash = crypto.createHash("sha256"); hash.update(dataForChecksum); const hashValue = hash.digest("hex"); const xVerify = hashValue + "###" + 1; const url = process.env.PHONEPE_URL; const headers = { "Content-Type": "application/json", accept: "application/json", "X-VERIFY": xVerify, }; const response = await axios.post( url!, JSON.stringify({ request: payload }), { headers: headers } ); return response.data; }
- Note: the above code is written in typescript, you have to get the input and response in the same format for the package to work, I will try to make it more dynamic in futur, but this is it for now
- You will have to get you app whitelisted, share you package name with the PhonePe team and they will whitelist it for you.
- How to go live
- As of the initial release, iOS support for UPI Intent (Opening UPI Apps to make payment) is not working as expected so avoid using it in production. Android support is working fine.
- The standard PhonePe Checkout is Working fine on both Android and iOS.
If you don't find your upi app, add you app in the AndroidManifest.xml
file of your app.
<queries>
<package android:name="com.phonepe.app" />
</queries>
You have to add each of your UPI App in the Info.plist
file of your app. otherwise the apps will not be detected
<key>LSApplicationQueriesSchemes</key>
<array>
<string>paytmmp</string>
<string>gpay</string>
<string>ppe</string>
</array>
dependencies:
phone_pe_pg: ^0.0.1
And you are good to go for further usage
import 'package:phone_pe_pg/phone_pe_pg.dart';
PhonePePg phonePePg = PhonePePg(
isUAT: true,
saltKey: Secrets.saltKey,
saltIndex: Secrets.saltIndex,
prodUrl: yourapi/url
);
The default PhonePePg constructor takes 3 parameters:
- isUAT: This is a boolean value which is used to determine whether to use the UAT or Production environment. By default it is set to true.
- saltKey: This is the salt key provided by PhonePe. You can get it from here. Use this for UAT Testing
- saltIndex: This is the salt index provided by PhonePe. You can get it from here. Use this for UAT Testing
- prodUrl: This is the URL of your backend where you've got the api for hitting PhonePe's pay api, it should not be null or empty when isUAT is false
For making payment, you need to create a PaymentRequest
object.
The PaymentRequest
class is just a data model and has multiple properties which are as follows:
merchantId
: This is the merchant id provided by PhonePe. You can get it from here.merchantTransactionId
: This is the transaction id generated by you. It should be unique for each transaction.merchantUserId
: This is the user id of the user who is making the payment. It should be unique for each user.amount
: This is the amount of the transaction. (PhonePe Accept this in paise but you have the enter the amount in INR since I have already converted it to paise in the package)redirectUrl
: This is the url to which the user will be redirected after the transaction is completed. You can use this to show the user the status of the transaction. (NOTE: This is only used in Standard Checkout / Pay Page payment method)redirectMode: This is the method used to redirect the user to the
redirectUrl. It can be either
POSTor
GET`. (NOTE: This is only used in Standard Checkout / Pay Page payment method)callbackUrl
: This is the url to which the PhonePe will send the transaction status. You can use this to update the transaction status in your database.deviceContext
: This is the device context of the user. It is used to identify the user's OS and Callback Scheme for iOS. You can use theDeviceContext
class to create the device context. (NOTE: This is only used in UPI Intent) You can useDeviceContext.getDefaultDeviceContext({String? merchantCallBackScheme})
to get the default device context based on the current OS and You can pass themerchantCallBackScheme
for iOS.mobileNumber
: This is the mobile number of the user.paymentInstrument
: This is basically the payment type, where payment instrument is actually a abstract class. To set thepaymentInstrument
, you can use any sub class ofPaymentInstrument
class.
Current Sub Classes ofPaymentInstrument
class are:CardPaymentInstrument // For Card Payment NetBankingPaymentInstrument // For Net Banking Payment PayPagePaymentInstrument // For Standard Checkout / Pay Page Payment SavedCardPaymentInstrument // For Saved Card Payment TokenPaymentInstrument // For Token Payment UpiCollectPaymentInstrument // For UPI Collect Payment UpiIntentPaymentInstrument // For UPI Intent Payment UpiQrPaymentInstrument // For UPI QR Payment
Each of the above payment instrument take input based on the payment type, such as card, savedcard & token payment instruments will take card details and other required details, on the other hand PayPagePaymentInstrument
does not take any input.
You can further check the details of each payment instrument in the API Documentation.
Basicallly it will open the UPI Apps installed on the device to make payment. This works perfectly in Android but I'm still debugging the iOS issue. So, avoid using it in production for now.
You can get the UPI Apps by using PhonePePg.getUpiApps()
method. It returns a list of UpiApp
objects. Each UpiApp
object has the following properties:
packageName
: This is the package name of the UPI App.appName
: This is the name of the UPI App.appIcon
: This is the icon of the UPI App.iOSAppName
: This is the name of the UPI App for iOS.iOSAppScheme
: This is the scheme of the UPI App for iOS.
You can start a UPI Transaction with startUpiTranstartUpiTransactionsaction
method. It takes a single parameter paymentRequest
, which is basically a data model which will be sent in PhonePe Pay Api
Get the UPI Apps
///This will return the UPI Apps installed on the device
List<UpiAppInfo> upiApps = await PhonePePg.getUpiApps();
Create an instance of PaymentRequest
PaymentRequest paymentRequest = PaymentRequest(
amount: amount,
callbackUrl: 'https://www.xyx.com',
deviceContext: DeviceContext.getDefaultDeviceContext(
merchantCallBackScheme: merchantCallBackScheme),
merchantId: 'MerchantID'
merchantTransactionId: 'Random Transaction Id',
merchantUserId: 'Random User Id',
mobileNumber: 'Mobile Number',
//Payment Instrument for UPI Intent
paymentInstrument: UpiIntentPaymentInstrument(
targetApp: Platform.isAndroid ? selectedUPIApp.packageName! : selectedUPIApp.iOSAppName!,
//Input is the package name of the UPI App you want to use for payment from for Android and iOS App Name of the app you want to use for payment for iOS
)
);
Call the method
final result = await phonePePg.startUpiTransaction(paymentRequest);
The result is an object of UpiTransactionResponse
class
Where you can simply check the status of the transaction
The status
property which is an enum, in the UpiTransactionResponse
class can be used to check the transaction status, such as 'SUCCESS', 'FAILURE', 'PENDING'
Similarly,
You can start the transaction with pay page for credit/debit card & Netbanking transactions, You will have the set the redirectUrl
& redirectMode
of the PaymentRequest
and set the paymentInstrument
to PayPagePaymentInstrument
and then you have the push the standard checkout page (by calling the startPayPageTransaction
method) in you navigation stack,
The reason is that this payment method was needed to be implemented with webview,
The
Navigator.push(context, MaterialPageRoute(builder: (context) => phonePePg.startPayPageTransaction(
paymentRequest: paymentRequest,
onPaymentComplete: (paymentStatusResponse, error) {
Handle Response and Error //Check the example for details
}
appBar: YourCustomAppBar() //Optional,
)))
The startPayPageTransaction
method calls the pay api, then takes the url from response and loads the url in webview, once the gateway redirects to the redirect url, Check Status API is called immediately and returns the result or error with onPaymentComplete
callback
You can also check the status of transaction using Check Status API, by calling the checkStatus
method.
This method take 2 parameters:
merchandId
: This is the merchant id provided by PhonePe. You can get it from here.merchantTransactionId
: This is the transaction id generated by you and passed in thePaymentRequest
while making the transaction.
final result = await phonePePg.checkStatus(
merchantId: 'MerchantID',
merchantTransactionId: 'Random Transaction Id',
);
The response is same as the onPaymentComplete
callback of startPayPageTransaction
method.