-
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.
Quick Links
ANDROID - Code Snippets
Code Snippet to Get PhonePe App VersionCode
- Code Snippet to fetch the PhonePe App version code installed in the user's device.
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;
}
- 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.
<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>
Code Snippet to Check PhonePe App for Mandate
Method to check whether the PhonePe UPI app is installed on the android device and supports Mandate:
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;
}
Code Snippet to Check Supported UPI Apps for Mandate
Method to get the list of all the UPI apps installed on the android device and supports Mandate:
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;
}
E2M Recurring : Code Snippet to invoke the app-specific Intent
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.
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);
iOS - Code Snippets
Code Snippet to Generate "deviceContext"
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()
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
}
}
//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];
Code Snippet to Check if PhonePe App is Present
isPhonePeInstalled() will return True if the PhonePe App is installed in the user's device.
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
}
}
//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];