Is there any working sample to integrate UPI payment gateway using Android Deep Link. I went through NPCI specifications and implemented it with no success. Transaction is n
The problem in your case is not related to UPI
but how Android manages Activity
results and Intent
s.
You cannot use the Intent.FLAG_ACTIVITY_NEW_TASK if the caller (in this case your Activity
) is requesting a result from the activity being launched (the UPI PSP in this case). [source]
So a simple solution would be to simply create the Uri
and launch the Intent
without the flag. In java that would look like:
private void launchUPI(){
// look below for a reference to these parameters
Uri uri = Uri.parse("upi://pay").buildUpon()
.appendQueryParameter("pa", "xxx@xxxxx")
.appendQueryParameter("pn", "XYZXYZ")
.appendQueryParameter("tn", "Pay for in-app purchase")
.appendQueryParameter("am", "20")
.appendQueryParameter("cu", "INR")
.build();
Intent upiPayIntent = new Intent(Intent.ACTION_VIEW);
upiPayIntent.setData(uri);
Intent chooser = Intent.createChooser(upiPayIntent, "Pay with");
if(null != chooser.resolveActivity(getPackageManager())) {
Log.d(TAG, "UPI Payment resolved to activity");
startActivityForResult(chooser, REQ_UPIPAYMENT);
} else {
Log.d(TAG, "No activity found to handle UPI Payment");
}
}
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(REQ_UPIPAYMENT == requestCode){
if(RESULT_OK == resultCode){
Log.d(TAG, "UPI Payment successfull");
} else {
Log.d(TAG, "UPI Payment failed");
}
}
}
As far the request parameters are concerned, following is a simple reference that I got from the UPI DeepLinking Specificication page.
pa
: UPI Virtual address of the payee (the one who receives the payment)pn
: Name of the payee. Can be name of merchant or store.tn
: Transaction note. A simple description of the transaction, like, payment for in-app items, bill payments, etc.am
: Monetary amount of transaction in decimal format.cu
: Currency used in the transaction. Currently only INR is supported.Using the above parameters, you can create a payment request static mode to the PSP app (apps like PayTM or bank applications).
To create a payment request in dynamic mode, you also need to add the following:
tr
: Transaction reference. Your internal reference to the transaction in your system.As the OP mentioned in the comments, to get back the response from the PSP app, like, transaction id, etc. we can use the Intent
passed in the onActivityResult()
when RESULT_OK == resultCode
.
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(REQ_UPIPAYMENT == requestCode){
if(RESULT_OK == resultCode){
Log.d(TAG, "UPI Payment successfull");
String transId = data.getStringExtra("response");
} else {
Log.d(TAG, "UPI Payment failed");
}
}
}
You can the list of all UPI apps on the device and use any app to initiate the transaction.
This is the function that you can use to fetch all the UPI apps.
private fun upiApps(context: Context): MutableList<PaymentUpiOption> {
val upiOptions = mutableListOf<PaymentUpiOption>()
// Set Parameters for UPI
val payUri = Uri.Builder()
payUri.scheme("upi").authority("pay")
payUri.appendQueryParameter("pa", "")
payUri.appendQueryParameter("pn", "")
payUri.appendQueryParameter("tid", "")
payUri.appendQueryParameter("mc", "")
payUri.appendQueryParameter("tr", "")
payUri.appendQueryParameter("tn", "")
payUri.appendQueryParameter("am", "")
payUri.appendQueryParameter("cu", "")
val paymentIntent = Intent(Intent.ACTION_VIEW)
paymentIntent.data = payUri.build()
val appList = context.packageManager.queryIntentActivities(paymentIntent, 0)
for (i in appList) {
// this is a custom model class
val paymentUpiOption = PaymentUpiOption(
i.loadLabel(context.packageManager).toString(),
i.activityInfo.packageName,
i.loadIcon(context.packageManager),
"upiTxn",
"UPI"
)
upiOptions.add(paymentUpiOption)
}
return upiOptions
}