Key Notes

  • Debit init call is allowed only in the ACTIVE state of the subscription.
  • Cancel/Revoke flows are only allowed after the subscription is ACTIVE.
  • Recurring debit payment will be skipped if cancellation/revoke flow is triggered after notification callback and before the Debit Execute call.
  • Recurring debit payment will succeed if Cancellation/Revoke flow is triggered after the Debit Execute call and before the Debit Execute callback.
  • If Revoke flow is triggered then cancel flow will throw an exception, and vice versa is also true.
anchor image
Copied !
anchor image
Copied !
  1. Code Snippet to fetch the PhonePe App version code installed in the user’s device.
Java
public long getPhonePeVersionCode(Context context) { String PHONEPE_PACKAGE_NAME_UAT = "com.phonepe.app.preprod"; String PHONEPE_PACKAGE_NAME_PRODUCTION = "com.phonepe.app"; PackageInfo packageInfo = null; long phonePeVersionCode = -1L; try { packageInfo = getPackageManager().getPackageInfo(PHONEPE_PACKAGE_NAME_UAT,PackageManager.GET_ACTIVITIES); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { phonePeVersionCode = packageInfo.getLongVersionCode(); } else { phonePeVersionCode = packageInfo.versionCode; } } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, String.format("failed to get package info for package name = {%s}, exception message = {%s}", PHONEPE_PACKAGE_NAME_UAT, e.getMessage())); } return phonePeVersionCode; }
  1. Add the below line to your AndroidManifest.xml file
    Note: If you declare a element in your app’s manifest file, then the app associated with that package name appears in the results of any query to PackageManager that matches a component from that app.
Sample Queries in AndroidManifest.xml
<queries> <package android:name="com.phonepe.app" /> // PhonePe Prod <package android:name="com.phonepe.app.preprod" /> // PhonePe UAT <package android:name="net.one97.paytm" /> // Paytm <package android:name="in.org.npci.upiapp" /> // BHIM </queries>
anchor image
Copied !

Method to check whether the PhonePe UPI app is installed on the android device and supports Mandate:

isUpiRegistered()
private boolean isUpiRegistered() { String phonepePackageName = "com.phonepe.app"; //For PreProd app, "com.phonepe.app.preprod" //For Production app, "com.phonepe.app" Uri uri = Uri.parse(String.format("%s://%s", "upi", "mandate")); Intent upiUriIntent = new Intent(); upiUriIntent.setData(uri); PackageManager packageManager = getApplication().getPackageManager(); List < ResolveInfo > resolveInfoList = packageManager.queryIntentActivities(upiUriIntent, PackageManager.MATCH_DEFAULT_ONLY); if (resolveInfoList != null) { for (ResolveInfo resolveInfo: resolveInfoList) { String packageName = resolveInfo.activityInfo.packageName; if (packageName != null && !packageName.isEmpty() && phonepePackageName.matches(packageName)) { return true; } } } return false; }
anchor image
Copied !

Method to get the list of all the UPI apps installed on the android device and supports Mandate:

getInstalledUPIApps()
private ArrayList < String > getInstalledUPIApps() { ArrayList < String > upiList = new ArrayList < > (); Uri uri = Uri.parse(String.format("%s://%s", "upi", "mandate")); Intent upiUriIntent = new Intent(); upiUriIntent.setData(uri); PackageManager packageManager = getApplication().getPackageManager(); List < ResolveInfo > resolveInfoList = packageManager.queryIntentActivities(upiUriIntent, PackageManager.MATCH_DEFAULT_ONLY); if (resolveInfoList != null) { for (ResolveInfo resolveInfo: resolveInfoList) { upiList.add(resolveInfo.activityInfo.packageName); } } return upiList; }
anchor image
Copied !

Update the APP_PACKAGE** value with the package name of the UPI app selected by the user on the merchant’s checkout page to launch the mandate setup.

Java
val intent = Intent() intent.action = Intent.ACTION_VIEW intent.data = Uri.parse(redirectUrl) //PhonePe Intent redirectUrl from the response. intent.setPackage(APP_PACKAGE) //APP_PACKAGE will be the package name of the App selected by the user. startActivityForResult(intent,PHONEPE_REQUEST_CODE);
anchor image
Copied !
anchor image
Copied !

To find the appSupportedSchema + isPPAppPresent value, the below code snippet has to be used to check it or to generate deviceContext.
Usage: PhonePeContextGenerator(callbackSchema: “demoAppSchema”).getDeviceContext()

PhonePeContextGenerator (Swift)
class PhonePeContextGenerator { private let callbackSchema: String? init(callbackSchema: String?) { self.callbackSchema = callbackSchema } private struct UriSchemeConstants { static let uriScheme1 = "ppemerchantsdkv1" static let uriScheme2 = "ppemerchantsdkv2" static let uriScheme3 = "ppemerchantsdkv3" static let hyphenation = "://" } private func isPhonePeInstalled() -> Bool { DispatchQueue.main.sync { guard let openUrl1 = URL(string: UriSchemeConstants.uriScheme1 + UriSchemeConstants.hyphenation), let openUrl2 = URL(string: UriSchemeConstants.uriScheme2 + UriSchemeConstants.hyphenation), let openUrl3 = URL(string: UriSchemeConstants.uriScheme3 + UriSchemeConstants.hyphenation) else { return false } let appInstalled = UIApplication.shared.canOpenURL(openUrl1) || UIApplication.shared.canOpenURL(openUrl2) || UIApplication.shared.canOpenURL(openUrl3) return appInstalled } } private func getAppSupportedSchema() -> [String] { var supportedAppSchemas: [String] = [] DispatchQueue.main.sync { [UriSchemeConstants.uriScheme1, UriSchemeConstants.uriScheme2, UriSchemeConstants.uriScheme3].forEach { (scheme) in if let openUrl = URL(string: scheme + UriSchemeConstants.hyphenation), UIApplication.shared.canOpenURL(openUrl) { supportedAppSchemas.append(scheme) } } } return supportedAppSchemas } func getDeviceContext() -> [String: Any] { var context: [String: Any] = [:] context["appSupportedSchemas"] = getAppSupportedSchema() context["isPPAppPresent"] = isPhonePeInstalled() context["deviceOS"] = "iOS" if let schema = callbackSchema { context["merchantCallBackScheme"] = schema } return context } }
PhonePeContextGenerator (Objective C)
//Step 1: Create the swift class in the project. import UIKit @objc class PhonePeContextGenerator: NSObject { private let callbackSchema: String? @objc init(callbackSchema: String?) { self.callbackSchema = callbackSchema } private struct UriSchemeConstants { static let uriScheme1 = "ppemerchantsdkv1" static let uriScheme2 = "ppemerchantsdkv2" static let uriScheme3 = "ppemerchantsdkv3" static let hyphenation = "://" } private func isPhonePeInstalled() -> Bool { DispatchQueue.global().sync { guard let openUrl1 = URL(string: UriSchemeConstants.uriScheme1 + UriSchemeConstants.hyphenation), let openUrl2 = URL(string: UriSchemeConstants.uriScheme2 + UriSchemeConstants.hyphenation), let openUrl3 = URL(string: UriSchemeConstants.uriScheme3 + UriSchemeConstants.hyphenation) else { return false } let appInstalled = UIApplication.shared.canOpenURL(openUrl1) || UIApplication.shared.canOpenURL(openUrl2) || UIApplication.shared.canOpenURL(openUrl3) return appInstalled } } private func getAppSupportedSchema() -> [String] { var supportedAppSchemas: [String] = [] DispatchQueue.global().sync { [UriSchemeConstants.uriScheme1, UriSchemeConstants.uriScheme2, UriSchemeConstants.uriScheme3].forEach { (scheme) in if let openUrl = URL(string: scheme + UriSchemeConstants.hyphenation), UIApplication.shared.canOpenURL(openUrl) { supportedAppSchemas.append(scheme) } } } return supportedAppSchemas } @objc func getDeviceContext() -> [String: Any] { var context: [String: Any] = [:] context["appSupportedSchemas"] = getAppSupportedSchema() context["isPPAppPresent"] = isPhonePeInstalled() context["deviceOS"] = "iOS" if let schema = callbackSchema { context["merchantCallBackScheme"] = schema } return context } } //Step 2: Import the header in the .m file that you want to generate the deviceContext #import <YourProjectName-Swift.h> //Step 3: Initialize the class and call the method to get the device context. [[[PhonePeContextGenerator alloc] initWithCallbackSchema:@"demoAppSchema"] getDeviceContext];
anchor image
Copied !

isPhonePeInstalled() will return True if the PhonePe App is installed in the user’s device.

Swift
private struct UriSchemeConstants { static let uriScheme1 = "ppemerchantsdkv1" static let uriScheme2 = "ppemerchantsdkv2" static let uriScheme3 = "ppemerchantsdkv3" static let hyphenation = "://" } private func isPhonePeInstalled() -> Bool { DispatchQueue.main.sync { guard let openUrl1 = URL(string: UriSchemeConstants.uriScheme1 + UriSchemeConstants.hyphenation), let openUrl2 = URL(string: UriSchemeConstants.uriScheme2 + UriSchemeConstants.hyphenation), let openUrl3 = URL(string: UriSchemeConstants.uriScheme3 + UriSchemeConstants.hyphenation) else { return false } let appInstalled = UIApplication.shared.canOpenURL(openUrl1) || UIApplication.shared.canOpenURL(openUrl2) || UIApplication.shared.canOpenURL(openUrl3) return appInstalled } }
Objective-C
//Step 1: Create the swift class in the project. import UIKit @objc class PhonePeAppCheck: NSObject { @objc func isPhonePeInstalled() -> Bool { DispatchQueue.global().sync { guard let openUrl1 = URL(string: UriSchemeConstants.uriScheme1 + UriSchemeConstants.hyphenation), let openUrl2 = URL(string: UriSchemeConstants.uriScheme2 + UriSchemeConstants.hyphenation), let openUrl3 = URL(string: UriSchemeConstants.uriScheme3 + UriSchemeConstants.hyphenation) else { return false } let appInstalled = UIApplication.shared.canOpenURL(openUrl1) || UIApplication.shared.canOpenURL(openUrl2) || UIApplication.shared.canOpenURL(openUrl3) return appInstalled } } } //Step 2: Import the header in the .m file that you want to check for PhonePe app present. #import <YourProjectName-Swift.h> //Step 3: Initialize the class and call the method to get whether the app is installed in the device or not. [[PhonePeAppCheck alloc] isPhonePeInstalled];

anchor image
Copied !
private struct UriSchemeConstants { static let uriScheme1 = "gpay" static let hyphenation = "://" } func isGPayInstalled() -> Bool { DispatchQueue.main.sync { guard let openUrl1 = URL(string: UriSchemeConstants.uriScheme1 + UriSchemeConstants.hyphenation) else { return false } let appInstalled = UIApplication.shared.canOpenURL(openUrl1) return appInstalled } }