Flutter UPI SDK
This cluster aims to document all the knowledge base for UPI transactions. Implementation of most of the UPI flows is different when compared to normal transactions.
There are broadly two types of UPI transactions, Collect and Intent(Pure Intent/In-App). For collect transactions, PayU informs the payment gateway to trigger a transaction to the app linked to the provided VPA, which asks the user for approval.
For intent transactions, we delegate the transaction process to an external app like BHIM, Google Pay, etc, which lets users transfer money to a VPA specified by us. After that, we use the PG (related to the specified VPA) for verification. PayU has a pre-configured VPA (distinct on the PG-Merchant level) on which the app makes the user pay the amount. To integrate UPI SDK with React Native, see Integrate UPI SDK with Flutter.
Prerequisites for Google Pay:
- To start transacting through Google Pay™, register your business on Google using the Google Onboarding form, In this registration process, you need to add the merchant VPAs created by PayU for you. In the case of multiple VPAs, all of them need to be registered with Google.
- To enable Google Pay, contact your Point of Contact at Google. For any further queries or help with onboarding, send a mail to PayU Mobile Integration Team.
Compatibility
Android
- Min SDK Version: 21
- Compile SDK Version: 31+
- Kotlin 1.6.10
iOS
- iOS version: 11
SDK Integration
To integrate the Flutter UPI SDK, perform the following steps:
Step 1: Include the SDK in your App
The UPI SDK for Flutter is offered through Flutter pub.dev.
To add the SDK plugin use the following dependency in your app:
//Add plugin in your app
$ flutter pub add payu_upi_flutter
//Import UPI Plugin in your dart code
import 'package:payu_upi_flutter/payu_upi_flutter.dart';
Note: If you are developing for iOS, Install the pod using the following command inside “ios” folder.
//Install payu dependencies in your ios project. $ pod install
Step 2: Initialize Flutter SDK
Declare the PayUUpiFlutter
instance and initialize the object.
class _MyAppState extends State<MyApp> implements PayUUPIProtocol {
late PayUUpiFlutter payUUpiFlutter;
@override
void initState() {
super.initState();
payUUpiFlutter = PayUUpiFlutter(this);
}
}
Note: If you are developing for iOS, make sure your minimum deployment target is iOS 11.
Step 3. Implement the Callback protocol
- Implement PayUPIProtocol to receive hash and transaction callback.
class _MyAppState extends State<MyApp> implements PayUUPIProtocol
- Implement the following methods in your class to receive the callbacks.
@override
onPayUUPIMakePayment(Map response) {
String eventType = response[PayUEventType.eventType];
switch(eventType) {
case PayUEventType.onPaymentSuccess: {
String eventResponse = parsePayUResponse(response);
//handle PayU response
}
break;
case PayUEventType.onPaymentFailure: {
String eventResponse = parsePayUResponse(response);
//handle PayU response
}
break;
case PayUEventType.onErrorReceived: {
String eventResponse = parsePayUResponse(response);
//handle PayU response
}
break;
case PayUEventType.onPaymentTerminate:
{
String eventResponse = parsePayUResponse(response);
//handle PayU response
}
break;
default: {
//handle unknown events
}
break;
}
}
@override
onPayUUPIValidateVPA(Map response) {
String eventType = response[PayUEventType.eventType];
switch(eventType) {
case PayUEventType.onValidateSuccess: {
String eventResponse = parsePayUResponse(response);
//handle PayU response
}
break;
case PayUEventType.onErrorReceived: {
String eventResponse = parsePayUResponse(response);
//handle PayU response
}
break;
default: {
//handle unknown events
}
break;
}
}
String parsePayUResponse(Map response){
var eventResponse = response[PayUEventType.eventResponse];
return eventResponse != null ? eventResponse.toString() : "";
}
Step 4: Setup Payment Hashes
Warning: Always generate the hash at your backend to ensure security.
Hash is required to authenticate the request and to make sure MiTM has not happened while data was traveling over the network. You have to set the hash in the hash parameter during the creation of payment parameters. Use the following format to generate the hash:
sha512(key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||||SALT)
TPV HashFor TPV transactions, use the following format to generate the hash:
sha512(key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||||beneficiarydetail|SALT)
The beneficiarydetail parameter value will be at last or the last value to be appended.
{"beneficiaryAccountNumber":<Account No>,"ifscCode":<IFSC>}
Here is a sample hash value for your reference:
smsplus|1695662774012|1|Info|Abc|[[email protected]](mailto:[email protected])|udf1|udf2|udf3|udf4|udf5|||||| {"beneficiaryAccountNumber":"1234567890","ifscCode":"IFSC0000024"}|1b1b0
SI HashFor SI Trasnaction, use the following format to generate the hash :-
SHA512(key|txnid|amount|productinfo|firstname|email|udf1|udf2|udf3|udf4|udf5||||||si_details|SALT)
Here is sample hash value for reference :-
3TnMpV|PayU_1752232075823|1|Info|Abc|[[email protected]](mailto:[email protected])|udf1|udf2|udf3|udf4|udf5||||||\{"paymentStartDate":"2025-07-28","paymentEndDate":"2028-08-28","billingAmount":"100.00","billingCurrency":"INR","billingCycle":"MONTHLY","billingInterval":1,"billingRule":"MAX"}|g0nGFe03
Step 5: Generate Payment Parameters
Set up the payment parameters for the SDK to initiate a transaction request. Use the following sample code for a quick integration:
var additionalParam = {
PayUAdditionalParamKeys.udf1: <user defined value 1>,
PayUAdditionalParamKeys.udf2: <user defined value 2>,
PayUAdditionalParamKeys.udf3: <user defined value 3>,
PayUAdditionalParamKeys.udf4: <user defined value 4>,
PayUAdditionalParamKeys.udf5: <user defined value 5>,
};
var payUPaymentParams = {
key: <Merchant Key>,
amount: <Amount>,
product_info: <Product Info>,
first_name: <First Name>,
email: <Email>,
phone: <Phone>,
ios_surl: <SURL>,
ios_furl: <FURL>,
android_surl: <SURL>,
android_furl: <FURL>,
environment: <String>, //0 => Production 1 => Test
user_credentials: <unique user identifier>
transaction_id:<Transaction ID>,
additional_param: additionalParam,
hash: <Pass Hash Value>,
beneficiary_account_number: <Beneficiary Account Number>,
beneficiary_ifsc: <ifsc code>,
payment_mode:<String> // for Intent flow use "INTENT", for collect flow use "upi",
disable_intent_seamless_failure: <String>, // -1 | 0 ,
// package_name parameter used for Android only
package_name: <String>, //package name for the specific UPI intent (i.e. 'net.one97.paytm') //
// intent_app parameter used for IOS only
intent_app : <String>, //scheme name for the specific UPI intent (i.e. 'phonepe') //
};
var si_params = {
"is_free_trial": "0",
"si": '1',
"si_details": {
"is_free_trial": "0",
"billing_amount": '100.00', //Required
"billing_currency": 'INR',
"billing_cycle": //Required
'MONTHLY', // YEARLY | MONTHLY | WEEKLY | DAILY | ONCE | ADHOC
"billing_interval": 1, //Required
"payment_start_date": '2025-07-28', //Required
"payment_end_date": '2028-08-28', //Required
"billing_limit": 'ON', //ON, BEFORE, AFTER
"billing_rule": 'MAX', //MAX, EXACT
}
};
Payment Parameters
Parameter | Description | Notes |
---|---|---|
key
|
| Cannot be null or empty |
transaction_id
|
| Cannot be null or empty and should be unique for each transaction. The maximum allowed length is 25 characters. It cannot contain special characters like: -_/ |
amount
|
| Cannot be null or empty and should be a valid double-stringified example: “100.0” |
product_info
|
| Cannot be null or empty |
first_name
|
| Cannot be null or empty |
email
|
| Cannot be null or empty |
phone
|
| There should be a valid phone number |
ios_surl
|
| Should be a valid URL |
ios_furl
|
| Should be a valid URL |
android_surl
|
| Should be a valid URL |
android_furl
|
| Should be a valid URL |
environment
|
| "0" for Production and "1" for Test |
user_credentials
|
| |
beneficiary_ifsc
|
| |
beneficiary_account_number | Users bank account number for TPV transaction. |
Step 6: Initiate the payment
Initialise and launch the SDK by calling the following code snippet:
payUUpiFlutter.makeUPIPayment(params: <PayU Payment Params>);
Step 7: VPA validation
Initialise and launch the Flutter UPI SDK by calling the following code snippet to validate the VPA
validateVPA() async {
// ignore: prefer_interpolation_to_compose_strings
var vpaHash = HashService.calculateHash(PayUTestCredentials.merchantKey +
'|' +
"validateVPA" +
'|' +
PayUTestCredentials.vpa +
'|' +
PayUTestCredentials.merchantSalt);
var params = PayUParams.createPayUPaymentParams(PayUPaymentModeKeys.upi);
params[PayUPaymentParamKey.vpa] = PayUTestCredentials.vpa;
params[PayUPaymentParamKey.hashes] = {
PayUPaymentParamKey.validate_vpa: vpaHash
};
var data = await payUUpiFlutter.validateVPA(params: params);
showAlertDialog(context, "Validate VPA", "$data");
}
Response
The sample response of a VPA validation request is similar to the following:
{
"status": "SUCCESS",
"vpa": "9999999999@upi",
"isVPAValid": 0,
"payerAccountName": "PayUNeer",
"isAutoPayVPAValid": 0,
"isAutoPayBankValid": "NA"
}
Step 8: List the UPI apps
Initialise and launch the Flutter UPI SDK by calling the following code snippet to get the list of UPI apps installed on Android and iOS devices
intentApps() async {
var data = await payUUpiFlutter.intentApps();
showAlertDialog(context, "intentApps", "$data");
}
Response
Here is how a sample response of UPI list request looks like:
{
"data": {
"value": "net.one97.paytm",
"title": "Paytm"
}
}
For IOS, UPI Intent (Mandatory)
For fetch the Installed UPI apps, Kindly add the query schemes in theinfo.plist
:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>phonepe</string>
<string>tez</string>
<string>gpay</string>
<string>paytm</string>
<string>bhim</string>
<string>credpay</string>
</array>
Test the Integration and Go-Live
Test the integration
After the integration is complete, you must test the integration before you go live and start collecting payment. You can start accepting actual payments from your customers once the test is successful.
CalloutThe UPI in-app and UPI intent flow is not available in the Test mode.
Testing checklistThings to remember while testing an integration:
- To test the integration make sure that you are making a transaction call to the test endpoint.
- Use your test key and salt for the transaction requests. See Genearate test key and salt.
- Set the value of the
environment
parameters to1
.
You can make test payments using one of the payment methods configured at the Checkout.
Watch Out!You must only use the Test merchant Key and Test Salt to carry out a test transaction.
Test cards only for Test environmentThese test cards, UPI, and Wallet credentials must only be used in the sandbox environment. Using these test cards in production environment may cause validation error.
Test credentials for supported payment methods
Following are the payment methods supported in PayU Test mode.
Test VPA for UPI
You can use either of the following VPAs to test your UPI-related integration:
For Testing the UPI Collect flow, Please follow the below steps:-
- Once you enter the VPA click on the verify button and proceed to pay.
- In NPCI page timer will start, Don't "CLICK" on click text. Please wait on the NPCI page.
- The below link opens in the browser Paste the transaction ID at the end of the URL then click on the success/failure simulator page. After that, your app will redirect to your app with the transaction response.
https://pgsim01.payu.in/UPI-test-transaction/confirm/<Txn_id>
For Android
You can add the below metadata under the application tag in the manifest file to test the UPI Collect flow on test env:-
Ensure to remove the code from the manifest file before going live.
<application>
<meta-data android:name="payu_debug_mode_enabled" android:value="true" /> // set the value to false for production environment
<meta-data android:name="payu_web_service_url" android:value="https://test.payu.in" /> //Comment in case of Production-->
<meta-data android:name="payu_post_url" android:value="https://test.payu.in"/> //Comment in case of Production-->
</appliction>
Go-live Checklist
Go-Live Checkist
Ensure these steps before you deploy the integration in a live environment.
Collect Live Payments
After testing the integration end-to-end, after you are sure that the integration is working as expected, you can switch to live mode to start accepting payments from your customers.
Watch Out!Ensure that you are using the production merchant key and salt generated in the live mode.
Checklist 2: Configure environment() parameter
Set the value of the environment()
to 0
in the payment integration code. This enables the integration to accept live payments.
Checklist 4:- Remove/comment meta -data code from manifest file :-
For Android
You must be comment/remove the below metadata code from the manifest file to use the UPI Collect flow on Production env:-
<application>
<meta-data android:name="payu_debug_mode_enabled" android:value="true" /> // set the value to false for production environment
<meta-data android:name="payu_web_service_url" android:value="https://test.payu.in" /> //Comment in case of Production-->
<meta-data android:name="payu_post_url" android:value="https://test.payu.in"/> //Comment in case of Production-->
</appliction>
Checklist 5: Configure verify payment method
Configure the Verify payment method to fetch the payment status. We strongly recommend that you use this as a back up method to handle scenarios where the payment callback is failed due to technical error.
Checklist 6: Configure Webhook
We recommend that you configure Webhook to receive payment responses on your server. For more information, refer to Webhooks.
Sample app
The sample app for Flutter UPI SDK can be found in the following Github location:
Updated 2 days ago