SDKLess Integration (iOS)

SDKLess Intent integration for iOS.
PhonePe will give the ppe:// intent to the merchant on SDKLess integration to launch the PhonePe App.

anchor image
Copied !

To support SDKLess integration, deviceContext has to be added to the request body of the v4/debit API call.

anchor image
Copied !
{ "merchantId": "MERCHANTUAT", "transactionId": "e474af20-a2a6-46c1-9a5d-73910ae86d0b", "merchantOrderId": "", "merchantUserId": "user9999", "amount": 100, "mobileNumber": "9999999999", "paymentScope": "PHONEPE", "deviceContext": { "deviceOS": "IOS", "isPPAppPresent": true, "merchantCallBackScheme": "iOSIntentIntegration", "appSupportedSchemas": [ "ppemerchantsdkv1" ] } }
{ "request": "ewogICAgIm1lcmNoYW50SWQiOiAiTUVSQ0hBTlRVQVQiLAogICAgInRyYW5zYWN0aW9uSWQiOiAiZTQ3NGFmMjAtYTJhNi00NmMxLTlhNWQtNzM5MTBhZTg2ZDBiIiwKICAgICJtZXJjaGFudE9yZGVySWQiOiAiIiwKICAgICJtZXJjaGFudFVzZXJJZCI6ICJ1c2VyOTk5OSIsCiAgICAiYW1vdW50IjogMTAwLAogICAgIm1vYmlsZU51bWJlciI6ICI5OTk5OTk5OTk5IiwKICAgICJwYXltZW50U2NvcGUiOiAiUEhPTkVQRSIsCiAgICAiZGV2aWNlQ29udGV4dCI6IHsKICAgICAgImRldmljZU9TIjogIklPUyIsCiAgICAgICJpc1BQQXBwUHJlc2VudCI6IHRydWUsCiAgICAgICJtZXJjaGFudENhbGxCYWNrU2NoZW1lIjogImlPU0ludGVudEludGVncmF0aW9uIiwKICAgICAgImFwcFN1cHBvcnRlZFNjaGVtYXMiOiBbCiAgICAgICAgInBwZW1lcmNoYW50c2RrdjEiCiAgICAgIF0KICAgIH0KICB9" }
anchor image
Copied !
{ "merchantId": "MERCHANTUAT", "transactionId": "e474af20-a2a6-46c1-9a5d-73910ae86d0b", "merchantUserId": "user9999", "amount": 100, "mobileNumber": "9999999999", "paymentScope": "ALL_UPI_APPS", "openIntentWithApp":"PHONEPE", "deviceContext": { "deviceOS": "iOS", "merchantCallBackScheme": "iOSIntentIntegration" } }
{ "merchantId": "MERCHANTUAT", "transactionId": "e474af20-a2a6-46c1-9a5d-73910ae86d0b", "merchantUserId": "user9999", "amount": 100, "mobileNumber": "9999999999", "paymentScope": "ALL_UPI_APPS", "openIntentWithApp": "GPAY", "deviceContext": { "deviceOS": "iOS" } }

merchantCallBackScheme

The merchantCallBackScheme can be passed only for the PhonePe App (“openIntentWithApp”: “PHONEPE”) that helps to open the merchant app after the completion of the Payment.

{ "request": "ewogICJtZXJjaGFudElkIjogIk1FUkNIQU5UVUFUIiwKICAidHJhbnNhY3Rpb25JZCI6ICJlNDc0YWYyMC1hMmE2LTQ2YzEtOWE1ZC03MzkxMGFlODZkMGIiLAogICJtZXJjaGFudFVzZXJJZCI6ICJ1c2VyOTk5OSIsCiAgImFtb3VudCI6IDEwMCwKICAibW9iaWxlTnVtYmVyIjogIjk5OTk5OTk5OTkiLAogICJwYXltZW50U2NvcGUiOiAiQUxMX1VQSV9BUFBTIiwKICAib3BlbkludGVudFdpdGhBcHAiOiJQSE9ORVBFIiwKICAiZGV2aWNlQ29udGV4dCI6IHsKICAgICJkZXZpY2VPUyI6ICJpT1MiLAogICAgIm1lcmNoYW50Q2FsbEJhY2tTY2hlbWUiOiAiaU9TSW50ZW50SW50ZWdyYXRpb24iCiAgfQp9" }
anchor image
Copied !
Parameter NameTypeMandatoryDescription
merchantIdSTRINGYesUnique MerchantID assigned to the merchant by PhonePe
transactionIdSTRINGYesUnique TransactionID generated by the merchant to track request to PhonePe.
transactionId length should be less than 38 characters.
merchantOrderIdSTRINGNoOrderID generated by the merchant
merchantOrderId length should be less than 48 characters.
merchantUserIdSTRINGYes[Mandatory for Web Flow]
Unique UserID generated by merchant. This is used to pre-login users authenticated on PhonePe Web flow. Un-authenticated users are redirected to PhonePe login page. Conversions are higher when this is provided. Avoid passing email/mobile number.
Skip this for guest users.
merchantUserId length should be less than 64 characters.
amountLONGYesTransaction amount in Paise.
paymentScopeSTRINGConditionalThe Payment Scope should be passed.
For PhonePe Intent, the value should be PHONEPE   For Open Intent, the value should be ALL_UPI_APPS
openIntentWithAppSTRINGConditionalFor PhonePe Intent with paymentScope= “PHONEPE”, openIntentWithApp is not required.   For Open Intent with paymentScope= “ALL_UPI_APPS”, the values should be passed be as per the app selected by the user
● PHONEPE
● GPAY
● PAYTM
mobileNumberSTRINGNoMobile number of the user
appSupportedSchemaARRAYYesThis key will contain schema supported by the PhonePe App from these 3 allowed schema lists.
deviceOSSTRINGYesThis is used to find the request device OS
Possible Value: iOS
isPPAppPresentBOOLYesThis is used to find if PhonePe App is present or not.
Possible Values:
true – If PhonePe App Present
false – If PhonePe App is not Present
merchantCallBackSchemeSTRINGOptionalThis value will be used to open the merchant app after the completion of the transaction on the PhonePe app.
Note: Works only with PhonePe App.
anchor image
Copied !
{ "success": true, "code": "SUCCESS", "message": "Your request has been successfully completed.", "data": { "redirectType": "INTENT", "redirectURL": "ppe://pay?pa=MERCHANTUAT@ybl&pn=MERCHANT&am=1.00&mam=1.00&tr=e474af20-a2a6-46c1-9a5d-73910ae86d0b&tn=Payment+for+e474af20-a2a6-46c1-9a5d-73910ae86d0b&mc=5311&mode=04&purpose=00&utm_campaign=DEBIT&utm_medium=MERCHANTUAT&utm_source=e474af20-a2a6-46c1-9a5d-73910ae86d0b&mcbs=demoAppScheme" } }
anchor image
Copied !
{ "success": true, "code": "SUCCESS", "message": "Your request has been successfully completed.", "data": { "redirectType": "OPEN_INTENT", "redirectURL": "ppe://pay?pa=SWIGGY8@ybl&pn=MERCHANT&am=1.00&mam=1.00&tr=92eef18b-110b-4d50-b609-9a5d44ff2c88&tn=Payment+for+92eef18b-110b-4d50-b609-9a5d44ff2c88&mc=5311&mode=04&purpose=00&utm_campaign=DEBIT&utm_medium=SWIGGY8&utm_source=92eef18b-110b-4d50-b609-9a5d44ff2c88&mcbs=demoAppScheme", "unavailableUpiApps": null } }
{ "success": true, "code": "SUCCESS", "message": "Your request has been successfully completed.", "data": { "redirectType": "OPEN_INTENT", "redirectURL": "gpay://upi/pay?pa=SWIGGY8@ybl&pn=MERCHANT&am=1.00&mam=1.00&tr=1cac394d-7582-4b69-9414-8b655f677a8b&tn=Payment+for+1cac394d-7582-4b69-9414-8b655f677a8b&mc=5311&mode=04&purpose=00&utm_campaign=DEBIT&utm_medium=SWIGGY8&utm_source=1cac394d-7582-4b69-9414-8b655f677a8b", "unavailableUpiApps": null } }
{ "success": true, "code": "SUCCESS", "message": "Your request has been successfully completed.", "data": { "redirectType": "OPEN_INTENT", "redirectURL": "paytmmp://upi/pay?pa=SWIGGY8@ybl&pn=MERCHANT&am=1.00&mam=1.00&tr=e224f57d-c514-47f0-b8cc-5b3cab4038af&tn=Payment+for+e224f57d-c514-47f0-b8cc-5b3cab4038af&mc=5311&mode=04&purpose=00&utm_campaign=DEBIT&utm_medium=SWIGGY8&utm_source=e224f57d-c514-47f0-b8cc-5b3cab4038af", "unavailableUpiApps": null } }

Redirection after Payment Completion

For GPay and Paytm, the redirection will be manual after the completion of the payment.

anchor image
Copied !

App Side

  1. In your Info.plist, create or append a new Array type node LSApplicationQueriesSchemes to append the following values:
Text
<key>LSApplicationQueriesSchemes</key> <array> <string>ppemerchantsdkv1</string> <string>ppemerchantsdkv2</string> <string>ppemerchantsdkv3</string> <string>paytmmp</string> <string>gpay</string> </array>
  1. Create a URLType for your app (Deeplink), if not already present.
    For example, we have used: iOSIntentIntegration. (You can create your own identifier for your app) and pass it in the deviceContext.merchantCallBackScheme of Debit request.

Server Side

  1. Save the below-assigned value to your server.
String apiEndPoint = "/v4/debit";
  1. Construct the request body with the required parameters in deviceContext and encode it in Base 64 format.
  2. Select one of the salts shared with you and note its index. Construct the X-verify (Checksum) at your server as follows:
String checksum = sha256(base64Body + apiEndPoint + salt) + ### + saltIndex;
  1. Call the Debit API with the constructed request and checksum to get the Intent URL in the response to launching the PhonePe App.
  2. Pass the received Intent or Web URL to the frontend.
  • If Intent URL is received, launch the Intent URL to initiate the payment using the PhonePe App
  • If Web URL is received, redirect the user to the web URL using web view.
  1. Once the payment is completed, please check the status of the transaction with your server. If the S2S response is not received, call the Check Transaction Status API to validate the response. You can call the Check Transaction Status at regular intervals to fetch the response from the PhonePe server.
  2. The payment status can be Successful, Failed, Pending or any of the codes. For Pending, you should retry until the status changes to Success or Failure.
anchor image
Copied !

To find 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 } }