iOS PG SDKLess Integration

anchor image
Copied !

SDKLess PG UPI Intent request feature for iOS.

anchor image
Copied !

To support SDKLess integration, deviceContext has to be added to the request body of the pg/v1/pay API call.

anchor image
Copied !
Sample Request - Open Intent - PHONEPE
{ "merchantId": "MERCHANTUAT", "merchantTransactionId": "MT7850590068188104", "merchantUserId": "MU933037302229373", "amount": 10000, "callbackUrl": "https://webhook.site/callback-url", "mobileNumber": "9999999999", "deviceContext": { "deviceOS": "iOS", "merchantCallBackScheme": "iOSIntentIntegration" }, "paymentInstrument": { "type": "UPI_INTENT", "targetApp": "PHONEPE" } }
Sample Request - Open Intent - GPAY
{ "merchantId": "MERCHANTUAT", "merchantTransactionId": "MT7850590068188104", "merchantUserId": "MU933037302229373", "amount": 10000, "callbackUrl": "https://webhook.site/callback-url", "mobileNumber": "9999999999", "deviceContext": { "deviceOS": "iOS", "merchantCallBackScheme": "iOSIntentIntegration", }, "paymentInstrument": { "type": "UPI_INTENT", "targetApp": "GPAY" } }
Sample Request - Open Intent - PAYTM
{ "merchantId": "MERCHANTUAT", "merchantTransactionId": "MT7850590068188104", "merchantUserId": "MU933037302229373", "amount": 10000, "callbackUrl": "https://webhook.site/callback-url", "mobileNumber": "9999999999", "deviceContext": { "deviceOS": "iOS", "merchantCallBackScheme": "iOSIntentIntegration", }, "paymentInstrument": { "type": "UPI_INTENT", "targetApp": "PAYTM" } }

Redirection after Payment Completion (For PhonePe App )

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.

Redirection after Payment Completion (Other UPI Apps)

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

Sample Base64 Encoded Request - Open Intent - PHONEPE
{ "request": "ewogICJtZXJjaGFudElkIjogIk1FUkNIQU5UVUFUIiwKICAibWVyY2hhbnRUcmFuc2FjdGlvbklkIjogIk1UNzg1MDU5MDA2ODE4ODEwNCIsCiAgIm1lcmNoYW50VXNlcklkIjogIk1VOTMzMDM3MzAyMjI5MzczIiwKICAiYW1vdW50IjogMTAwMDAsCiAgImNhbGxiYWNrVXJsIjogImh0dHBzOi8vd2ViaG9vay5zaXRlL2NhbGxiYWNrLXVybCIsCiAgIm1vYmlsZU51bWJlciI6ICI5OTk5OTk5OTk5IiwKICAiZGV2aWNlQ29udGV4dCI6IHsKICAgICJkZXZpY2VPUyI6ICJpT1MiLAoJCSJpc1BQQXBwUHJlc2VudCI6IHRydWUsCgkJIm1lcmNoYW50Q2FsbEJhY2tTY2hlbWUiOiAiaU9TSW50ZW50SW50ZWdyYXRpb24iLAoJCSJhcHBTdXBwb3J0ZWRTY2hlbWFzIjogWwoJCSJwcGVtZXJjaGFudHNka3YxIgoJCV0KICB9LAogICJwYXltZW50SW5zdHJ1bWVudCI6IHsKICAgICJ0eXBlIjogIlVQSV9JTlRFTlQiLAogICAgInRhcmdldEFwcCI6ICJQSE9ORVBFIgogIH0KfQ==" }
Sample Base64 Encoded Request - Open Intent - GPAY
{ "request": "ewogICJtZXJjaGFudElkIjogIk1FUkNIQU5UVUFUIiwKICAibWVyY2hhbnRUcmFuc2FjdGlvbklkIjogIk1UNzg1MDU5MDA2ODE4ODEwNCIsCiAgIm1lcmNoYW50VXNlcklkIjogIk1VOTMzMDM3MzAyMjI5MzczIiwKICAiYW1vdW50IjogMTAwMDAsCiAgImNhbGxiYWNrVXJsIjogImh0dHBzOi8vd2ViaG9vay5zaXRlL2NhbGxiYWNrLXVybCIsCiAgIm1vYmlsZU51bWJlciI6ICI5OTk5OTk5OTk5IiwKICAiZGV2aWNlQ29udGV4dCI6IHsKICAgICJkZXZpY2VPUyI6ICJpT1MiLAogICAgIm1lcmNoYW50Q2FsbEJhY2tTY2hlbWUiOiAiaU9TSW50ZW50SW50ZWdyYXRpb24iLAogIH0sCiAgInBheW1lbnRJbnN0cnVtZW50IjogewogICAgInR5cGUiOiAiVVBJX0lOVEVOVCIsCiAgICAidGFyZ2V0QXBwIjogIlBBWVRNIgogIH0KfQ==" }
Sample Base64 Encoded Request - Open Intent - PAYTM
{ "request": "ewogICJtZXJjaGFudElkIjogIk1FUkNIQU5UVUFUIiwKICAibWVyY2hhbnRUcmFuc2FjdGlvbklkIjogIk1UNzg1MDU5MDA2ODE4ODEwNCIsCiAgIm1lcmNoYW50VXNlcklkIjogIk1VOTMzMDM3MzAyMjI5MzczIiwKICAiYW1vdW50IjogMTAwMDAsCiAgImNhbGxiYWNrVXJsIjogImh0dHBzOi8vd2ViaG9vay5zaXRlL2NhbGxiYWNrLXVybCIsCiAgIm1vYmlsZU51bWJlciI6ICI5OTk5OTk5OTk5IiwKICAiZGV2aWNlQ29udGV4dCI6IHsKICAgICJkZXZpY2VPUyI6ICJpT1MiLAogICAgIm1lcmNoYW50Q2FsbEJhY2tTY2hlbWUiOiAiaU9TSW50ZW50SW50ZWdyYXRpb24iLAogIH0sCiAgInBheW1lbnRJbnN0cnVtZW50IjogewogICAgInR5cGUiOiAiVVBJX0lOVEVOVCIsCiAgICAidGFyZ2V0QXBwIjogIlBBWVRNIgogIH0KfQ==" }
anchor image
Copied !
Sample Response UPI Intent - PhonePe
{ "success": true, "code": "PAYMENT_INITIATED", "message": "Payment initiated", "data": { "merchantId": "MERCHANTUAT", "merchantTransactionId": "MT7850590068188104", "instrumentResponse": { "type": "UPI_INTENT", "intentUrl": "ppe://pay?pa=MERCHANTUAT@ybl&pn=MerchantUAT&am=1.00&mam=1.00&tr=MT7850590068188104&tn=Payment%20for%20MT7850590068188104&mc=5311&mode=04&purpose=00&utm_campaign=B2B_PG&utm_medium=JUSPAYUAT&utm_source=MT7850590068188104" } } }
Sample Response UPI Intent - Gpay
{ "success": true, "code": "PAYMENT_INITIATED", "message": "Payment initiated", "data": { "merchantId": "JUSPAYUAT", "merchantTransactionId": "04b4307c-4f2a-400a-bbf4-983bf892cb92", "instrumentResponse": { "type": "UPI_INTENT", "intentUrl": "gpay://upi/pay?pa=JUSPAYUAT@ybl&pn=JUSPAYUAT&am=9.00&mam=9.00&tr=04b4307c-4f2a-400a-bbf4-983bf892cb92&tn=Payment%20for%2004b4307c-4f2a-400a-bbf4-983bf892cb92&mc=5311&mode=04&purpose=00&utm_campaign=B2B_PG&utm_medium=JUSPAYUAT&utm_source=04b4307c-4f2a-400a-bbf4-983bf892cb92" } } }
Sample Response UPI Intent - Paytm
{ "success": true, "code": "PAYMENT_INITIATED", "message": "Payment initiated", "data": { "merchantId": "JUSPAYUAT", "merchantTransactionId": "7d673027-5d0d-424b-abb5-884727db4060", "instrumentResponse": { "type": "UPI_INTENT", "intentUrl": "paytmmp://upi/pay?pa=JUSPAYUAT@ybl&pn=JUSPAYUAT&am=9.00&mam=9.00&tr=7d673027-5d0d-424b-abb5-884727db4060&tn=Payment%20for%207d673027-5d0d-424b-abb5-884727db4060&mc=5311&mode=04&purpose=00&utm_campaign=B2B_PG&utm_medium=JUSPAYUAT&utm_source=7d673027-5d0d-424b-abb5-884727db4060" } } }

Handling UPI Apps on the Checkout Page

Merchants should display only the list of the UPI Apps installed on the user’s device.

anchor image
Copied !

iOS PG SDKLess App Side Implementation

Step 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>

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)

URLScheme should match the below conditions

  • Only Alphabets (lower and upper case) and numbers are allowed.
  • We can allow special characters only like dot and Hyphen
  • The name should always start with alphabets.

The schema should be correct to redirect the app otherwise it will not redirect back to the merchant app.

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()

PhonePeContextGenerator
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 } }
anchor image
Copied !

PhonePe App

Swift
private struct UriSchemeConstants { static let uriScheme1 = "ppemerchantsdkv1" static let uriScheme2 = "ppemerchantsdkv2" static let uriScheme3 = "ppemerchantsdkv3" static let hyphenation = "://" } 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 } }

GPay App

Swift
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 } }paytmmp

Paytm App

Swift
private struct UriSchemeConstants { static let uriScheme1 = "paytmmp" static let hyphenation = "://" } func isPaytmInstalled() -> Bool { DispatchQueue.main.sync { guard let openUrl1 = URL(string: UriSchemeConstants.uriScheme1 + UriSchemeConstants.hyphenation) else { return false } let appInstalled = UIApplication.shared.canOpenURL(openUrl1) return appInstalled } }