简体   繁体   中英

Android UPI payment intent always fails

Here is what I want to do. My app has two types of users - buyers and sellers. The seller can provide their UPI ID and buyers can use any UPI app installed on their device to pay to sellers using the provided seller UPI ID.

I am constructing a UPI payment URL as follows:

String upiPaymentUrl = upi://pay?pa=<<Seller VPA ID>>&pn=<<Payee name>>&tn=<<Txn description>>&cu=INR

I then use the following code to show all the UPI enabled apps on the phone:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(upiPaymentUrl));
Intent chooser = Intent.createChooser(intent, getString(R.string.payment_title));
startActivityForResult(chooser, Constant.REQUEST_CODE_UPIPAYMENT, null);

The selected UPI app is launched and the all the data I have given in the URI is filled properly. I then initiate the payment but the payment is always failing. When I use the UPI apps as is (without being invoked from my app) and use the same values that I use to construct the UPI URL, the payment goes through without any error. Any idea what could be causing the payment to fail when I invoke the UPI apps from my app?

Any help / suggestions will be highly appreciated!

So here is my use case. I have a marketplace app where both buyers and sellers register themselves. Sellers list their products. Buyers offers to buy the products. The seller provides UPI information (UPI ID or "all-in-one" QR code). The buyer initiates the payment using the UPI information provided by the seller via the app.

One way to do this is to register yourself as an independent developer with NCPI (infinit.co.in) and apply to use UPI. I do not know the full process yet as I am stuck at requesting access to UPI (!). My assumption is that once the access is allowed, you can register your private key with the UPI infrastructure. To initiate the payment, create the UPI deep link URL as shown below.

upi://pay?pa=<>&pn=<>&tn=<>&cu=INR

Sign this with the public key that you ship with your app. The specs to sign is available in the UPI developer document as mentioned by @JensV.

So now if you don't want to do any of the above what are the options available? I see two options : One ask sellers to provide their UPI ID and within your app allow for buyers to copy the seller UPI ID on a clip board so that they can then open any UPI payment app (GPay, Paytm etc.) and paste the UPI ID while initiating payment. Another neat way to do this is ask the seller to obtain "all-in-one" merchant QR code. Use any library (there are many) to scan the QR code and you will get a "signed" UPI URL (most of the time). Now all that you have to do is to use the Intent to start UPI application using this "signed" URL. With this method I was able to perform payment with all the apps except GPay(!).

One more information - If you do not have a way to get signed UPI URL, you can still use the raw UPI URL mentioned above. The payment will be successful only with the UPI app of the issuer. ie If the issuer of the UPI ID you are using is HDFC bank, then using "unsigned" UPI URL you can invoke the HDFC mobile banking application and make the payment. It will always succeed.

If I am able to register with UPI as developer and able to register my private key, I will update this thread to explain the process.

According to new rule of NPCI all upi app bound with minimum transaction.

If receiver upi id is registered as non business upiid than it will be not able to payment successfull.

So solution is the create new business UPI id.

You need to sign your Intent when you launch the payment via an Intent.

See the yellow marked section within this documentation: https://web.archive.org/web/20200921110005/https://www.npci.org.in/sites/default/files/UPI%20Linking%20Specs_ver%201.6.pdf

The original URL seems dead but is references by multiple sources including Google.

This would result in something like the following:

Uri uri =
    new Uri.Builder()
        .scheme("upi")
        .authority("pay")
        .appendQueryParameter("pa", "your-merchant-vpa@xxx")
        .appendQueryParameter("pn", "your-merchant-name")
        .appendQueryParameter("mc", "your-merchant-code")
        .appendQueryParameter("tr", "your-transaction-ref-id")
        .appendQueryParameter("tn", "your-transaction-note")
        .appendQueryParameter("am", "your-order-amount")
        .appendQueryParameter("cu", "INR")
        .build();

// Sign the uri as specified
String signature = someSignatureFunction(uri);

uri.buildUpon()
        .appendQueryParameter("sign", signature);

Also, the parameters mode and orgid seem to be non-optional for Intent created payments.


I'm not quite sure what you are trying to accomplish. But since the API from what I see isn't designed to be used to process "user to user" payments, I'd verify if what you're doing is actually allowed / possible. You might not be able to sign transactions that are not directed to your company, thus making this impossible.

Further enforcing this point, in order to sign the Intent you need encryption, which usually (in such systems) takes place on a server you control to reverse engineering and thus faking payments.

Disclaimer: I have no expirience with UPI, thus this answer is mostly based on guesses and not tested. I recommend looking up some more resources on UPI before releasing.


Some other resources I found:

Tested Solution: Download the Phonepe Business App. use that upi for intent payment, if it failed then call phonepe customer call and they will activate it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM