iOS PG SDK Integration

The steps to integrate iOS PG SDK on the native iOS App.
1. PreRequisites
2. iOS PG SDK setup
3. iOS PG App Side Implementation
4. iOS PG Server Side Implementation

1. PreRequisites

  1. XCode 12.5 or newer
  2. Cocoapod
  3. Onboarded on PhonePe as a Merchant (Given a MerchantID, & Saltkeys to generate the checksum on your servers)
  4. PhonePeAppId (Refer App Side - Step 2)

2. iOS PG SDK setup

The PhonePePayment framework is needed for the SDK to work for both PreProd (Testing) and Production (Deployment) environments.

Step 1. The PhonePePayment SDK is available through CocoaPods [Refer to this link ]

👍

iOS - PreProd App

Download the PhonePe iOS app for test environment v5.8.50.1004-PREPROD - here

Step 2. Installation

To install it, simply add the following line to your Podfile:

pod 'PhonePePayment'

then run

pod install
Step 3. Import the framework in your project using "import PhonePePayment"

🚧

Remove the "DirectPaymentSDK" from your project if you have already integrated and wanted to migrate to CocoaPods.

3. iOS PG App Side Implementation

Step 1. In your Info.plist, create or append a new Array type node LSApplicationQueriesSchemes to append the following values:
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>ppemerchantsdkv1</string>
    <string>ppemerchantsdkv2</string>
    <string>ppemerchantsdkv3</string>
    <string>paytmmp</string>
    <string>gpay</string>
</array>
2210
Step 2. Update PhonePe App Id

Add PhonePeAppId key with value as string in your app’s Info.plist as shown in the below screenshot for analytics purposes.

🚧

To Get AppId

Share the Apple Team Id with the integration team[[email protected]] to generate the AppId to be used.

2188
Step 3. Create DeepLink Schema

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)

2194
Step 4. Create DPSTransactionRequest Object

Using the Payload from your server, create a DPSTransactionRequest object, with callbackURL as the URLType created in the step above.
Example: callBackURL : iOSIntentIntegration

Step 5. Initialize the PG SDK

Initialize the PhonePeDPSDK and pass the DPSTransactionRequest object to the SDK. After the payment is complete and a callback is received back to your app on the completionHandler, check the status of the transaction with your backend.

let headers: [String: String] = [:]
headers.updateValue("<Pass the Callback URL>", forKey: "X-CALLBACK-URL")
headers.updateValue("<Pass the Callback Mode>", forKey: "X-CALL-MODE")  //Mode will be POST.

let request : DPSTransactionRequest = DPSTransactionRequest (
    body : base64EncodedString,
    apiEndPoint : apiEndPoint,
    checksum : payloadChecksum,
    headers : headers,
    callBackURL : "iOSIntentIntegration"
);

PhonePeDPSDK(environment: .uat, enableLogging: true)
            .startPG(transactionRequest: request, on: self, animated: true) 
{ _, result in
    let text = "\(result)"
    print(text)
  print("Completion:---------------------")
    // Indicates the UI Callback is given back to the Merchant app. 
    //Now, check the status with your server and update it to the user accordingly
}

👍

To Enable Debug Logs

Update the PhonePeDPSDK.enableDebugLogs = true or enableLogging flag to true in startPG method.

Step 6. Setup the Environment

Set the environment as .uat to test in the PreProd environment. While moving to the Production, set the environment as .production.

Step 7. In your AppDelegate, check for callback from the PhonePe app and if found, pass it to the SDK.
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
    let handled = PhonePeDPSDK.checkDeeplink(url, options: options)
    if handled {
       // Phonepe is handling this, no need for any processing
       return true
   }
   //Process your own deeplinks here
   return true
}

4. iOS PG Server Side Implementation

Step 1. Save the below-assigned value at your server
String apiEndPoint = "/pg/v1/pay";
Step 2. Construct the request body and encode it in Base 64 at your server as follows:
{
  "merchantId": "MERCHANTUAT",
  "merchantTransactionId": "MT7850590068188104",
  "merchantUserId": "MU933037302229373",
  "amount": 10000,
  "callbackUrl": "https://webhook.site/callback-url",
  "mobileNumber": "9999999999",
  "deviceContext": {
    "deviceOS": "IOS"
  },
  "paymentInstrument": {
    "type": "UPI_INTENT",
    "targetApp": "PHONEPE"
  }
}
{
  "merchantId": "MERCHANTUAT",
  "merchantTransactionId": "MT7850590068188104",
  "merchantUserId": "MU933037302229373",
  "amount": 10000,
  "callbackUrl": "https://webhook.site/callback-url",
  "mobileNumber": "9999999999",
  "deviceContext": {
    "deviceOS": "IOS"
  },
  "paymentInstrument": {
    "type": "UPI_INTENT",
    "targetApp": "GPAY"
  }
}
{
  "merchantId": "MERCHANTUAT",
  "merchantTransactionId": "MT7850590068188104",
  "merchantUserId": "MU933037302229373",
  "amount": 10000,
  "callbackUrl": "https://webhook.site/callback-url",
  "mobileNumber": "9999999999",
  "deviceContext": {
    "deviceOS": "IOS"
  },
  "paymentInstrument": {
    "type": "UPI_INTENT",
    "targetApp": "PAYTM"
  }
}
{
  "request": "ewogICJtZXJjaGFudElkIjogIk1FUkNIQU5UVUFUIiwKIAkibWVyY2hhbnRUcmFuc2FjdGlvbklkIjogIk1UNzg1MDU5MDA2ODE4ODEwNCIsCiAgIm1lcmNoYW50VXNlcklkIjogIk1VOTMzMDM3MzAyMjI5MzczIiwKICAiYW1vdW50IjogMTAwMDAsCiAgImNhbGxiYWNrVXJsIjogImh0dHBzOi8vd2ViaG9vay5zaXRlL2NhbGxiYWNrLXVybCIsCiAgIm1vYmlsZU51bWJlciI6ICI5OTk5OTk5OTk5IiwKICAiZGV2aWNlQ29udGV4dCI6IHsKICAgICJkZXZpY2VPUyI6ICJJT1MiCiAgfSwKICAicGF5bWVudEluc3RydW1lbnQiOiB7CiAgICAidHlwZSI6ICJVUElfSU5URU5UIiwKICAgICJ0YXJnZXRBcHAiOiAiUEhPTkVQRSIKICB9Cn0="
}
{
  "request": "ewogICJtZXJjaGFudElkIjogIk1FUkNIQU5UVUFUIiwKICAibWVyY2hhbnRUcmFuc2FjdGlvbklkIjogIk1UNzg1MDU5MDA2ODE4ODEwNCIsCiAgIm1lcmNoYW50VXNlcklkIjogIk1VOTMzMDM3MzAyMjI5MzczIiwKICAiYW1vdW50IjogMTAwMDAsCiAgImNhbGxiYWNrVXJsIjogImh0dHBzOi8vd2ViaG9vay5zaXRlL2NhbGxiYWNrLXVybCIsCiAgIm1vYmlsZU51bWJlciI6ICI5OTk5OTk5OTk5IiwKICAiZGV2aWNlQ29udGV4dCI6IHsKICAgICJkZXZpY2VPUyI6ICJJT1MiCiAgfSwKICAicGF5bWVudEluc3RydW1lbnQiOiB7CiAgICAidHlwZSI6ICJVUElfSU5URU5UIiwKICAgICJ0YXJnZXRBcHAiOiAiR1BBWSIKICB9Cn0="
}
{
  "request": "ewogICJtZXJjaGFudElkIjogIk1FUkNIQU5UVUFUIiwKICAibWVyY2hhbnRUcmFuc2FjdGlvbklkIjogIk1UNzg1MDU5MDA2ODE4ODEwNCIsCiAgIm1lcmNoYW50VXNlcklkIjogIk1VOTMzMDM3MzAyMjI5MzczIiwKICAiYW1vdW50IjogMTAwMDAsCiAgImNhbGxiYWNrVXJsIjogImh0dHBzOi8vd2ViaG9vay5zaXRlL2NhbGxiYWNrLXVybCIsCiAgIm1vYmlsZU51bWJlciI6ICI5OTk5OTk5OTk5IiwKICAiZGV2aWNlQ29udGV4dCI6IHsKICAgICJkZXZpY2VPUyI6ICJJT1MiCiAgfSwKICAicGF5bWVudEluc3RydW1lbnQiOiB7CiAgICAidHlwZSI6ICJVUElfSU5URU5UIiwKICAgICJ0YXJnZXRBcHAiOiAiUEFZVE0iCiAgfQp9"
}
Step 3. Checksum Calculation

Select one of the salts shared with you and note its index. Construct the X-verify at your server as follows:

String checksum = sha256(base64Body + apiEndPoint + salt) + ### + saltIndex;
Step 4. Check the payment status

Once the payment is completed, please call the Check Transaction Status API to validate the response received via the App. You can call the Check Transaction Status at regular intervals to fetch the response from the PhonePe server in case a response is not received in the application even after 10 minutes of initiating the application.

Step 5. Handling Payment Status

The payment status can be Successful, Failed, Pending or any of the codes. For Pending, you should retry until the status changes to Successful or Failed.