---
description: Technical integration of iOS UPI SDK with the app
---

# Integration

#### **Cocoapods integration**

Add the following lines into your Podfile

```
// make sure to add below-mentioned line to use dynamic frameworks
use_frameworks!

// Add this to include our SDK
pod 'PayUIndia-UPI'
```

#### _Swift Package Manager Integration_

You can integrate PayUIndia-UPIKit, PayUIndia-UPICoreKit with your app or SDK in two ways:

1. Via Xcode - Go to File-> Add Package-> [**https://github.com/payu-intrepos/payu-upi-ios-sdk**](https://github.com/payu-intrepos/payu-upi-ios-sdk)\

2. Via Package.Swift - Add below line in Package.swift dependencies

&#x20;  <mark style="color:blue;">**.package(name: "PayUIndia-UPI", url: "**</mark>[<mark style="color:blue;">**https://github.com/payu-intrepos/payu-upi-ios-sdk**</mark>](https://github.com/payu-intrepos/payu-upi-ios-sdk)<mark style="color:blue;">**", from: "6.1.0")**</mark>



## UPICore

You can integrate UPI Collet and UPIIntent with your own UI using UPICore

#### **Cocoapods integration**

Add the following lines into your Podfile

```
// make sure to add below-mentioned line to use dynamic frameworks
use_frameworks!

// Add this to include our SDK
pod 'PayUIndia-UPICore'
```

#### Swift Package Manager Integration

You can integrate PayUIndia-UPIKit, PayUIndia-UPICoreKit with your app or SDK in two ways:

1. Via Xcode - Go to File-> Add Package-> [**https://github.com/payu-intrepos/payu-upi-ios-sdk**](https://github.com/payu-intrepos/payu-upi-ios-sdk)\

2. Via Package.Swift - Add below line in Package.swift dependencies

&#x20;  <mark style="color:blue;">**.package(name: "PayUIndia-UPICore", url: "**</mark>[<mark style="color:blue;">**https://github.com/payu-intrepos/payu-upi-ios-sdk**</mark>](https://github.com/payu-intrepos/payu-upi-ios-sdk)<mark style="color:blue;">**", from: "6.1.0")**</mark>

## Make UPI Payments

1.  Set environment to test or production. You can also set debugging level to get logs from the SDK

    ```swift
    PayUUPICore.shared.environment = .production
    PayUUPICore.shared.logLevel = .error //Other option is verbose. Logs are disabled by default
    ```
2.  Set mandatory payment parameters required for the payment, please **import PayUParamsKit**

    ```swift
          let paymentParams = PayUPaymentParam(
                key: "ibibogames", //Your merchant key for the current environment
                transactionId: randomString(length: 6), //Your unique ID for this trasaction
                amount: self.amountTextField.text ?? "1", //Amount of transaction
                productInfo: "iPhone", // Description of the product
                firstName: "Vipin", // First name of the user
                email: "johnappleseed@apple.com", // Email of the useer
                phone: "9123456789", // "10 digit phone number here"
                surl: "https://payu.herokuapp.com/ios_success", // Success URL. Not used but required due to mandatory check in API.
                furl: "https://payu.herokuapp.com/ios_failure", // Failure URL. Not used but required due to mandatory check in API.
                environment: .production // Production or Test . Not used but required due to mandatory parameter.
            )
            //User defined parameters.
            //You can save additional details with each txn if you need them for your business logic.
            //You will get these details back in payment response and transaction verify API
            //Like, you can add SKUs for which payment is made.
            //You can keep all udf fields blank if you do not have any requirement to save your custom txn specific data at PayU's end
            paymentParams.udfs = PayUUserDefines()
            paymentParams.udfs?.udf1 = ""
            paymentParams.udfs?.udf2 = ""
            paymentParams.udfs?.udf3 = ""
            paymentParams.udfs?.udf4 = ""
            paymentParams.udfs?.udf5 = ""
            paymentParams.userCredential = "yIlrx4:myUserEmail@payu.in" // "merchantKey:user'sUniqueIdentifier"
            let upi = UPI()​
            upi.beneficiaryAccountNumber = accNoTextField.text //for tpv transaction
            upi.beneficiaryAccountIFSC = ifscTextField.text​//for tpv transaction
            paymentParams.paymentOption = upi
    ```
3.  Set callbacks to receive actionable events from SDK

    1.  `paymentCompletion` - You receive the payment response here.&#x20;

        ```swift
        PayUUPICore.shared.paymentCompletion = { [weak self] result in
                DispatchQueue.main.async { [weak self] in
                    guard let self = self else {return}
                    self.navigationController?.popToRootViewController(animated: false)

                    switch result {
                    case .success(let response):
                        Helper.showAlert(String(describing: response), onController: self)

                    case .failure(let error):
                        Helper.showAlert(String(describing: error.rawValue), onController: self)
                    }
                }
        }
        ```
    2.  `backPressed` - If user has not yet initiated the transaction and she presses back button from the UPI payment options page, this callback is triggered. You can dismiss SDK's UI screen here.

        ```swift
        PayUUPICore.shared.backPressed = {[weak self] in
            self?.navigationController?.popToRootViewController(animated: true)
        }
        ```
    3.  `onEnteringVPA` - For validating the VPA entered by the user, we need to hit PayU's validate VPA api. This api needs hash. In this callback, you will get the vpa entered by the user. Use this value to generate required hash. When the hash is received from your server, send us the updated post params with the new hash.\


        ```swift
        PayUUPICore.shared.onEnteringVPA = {[weak self] vpa, completion in
            guard let self = self else { return }

            (self.paymentParams?.paymentOption as? UPI)?.vpa = vpa
            self.fetchHashes(withParams: self.paymentParams!) { result in
                switch result {
                case .success:
                    completion(.success(self.paymentParams!))
                case .failure(let error):
                    print("Could not fetch hashes \(error.description)")
                    completion(.failure(.noInternet()))
                }
            }
        }
        ```


4. Fetch hashes and save them in `paymentParams` object
   * You need to set `hashes` property in `paymentParams`. Hashes authenticates that API request originates from the original source and not from any Man in the middle. Property `hashes` is of type `PPKHashes`
   * `PPKHashes` has 3 properties. Each of these 3 is used for a distinct API call. These 3 properties are defined below:
     1. `paymentOptionsHash`: This is required to get available upi payment options from which payment can be made.
     2. `paymentHash`: This is required to create transaction at PayU's end.
     3. `validateVPAHash`: This is required by validateVPA API in upi collect flow to check if provided VPA is registered with a bank account and is active or not. Not required in intent transactions.&#x20;
   * You need to provide first 2 hashes before asking SDK to initiate the payment. Hashes must be generated only on your server as it needs a secret key (also known as salt). Your app must never contain salt.
   * Please see [this documentation](../../hash-generation) to generate hashes on your server.
     * _Command_ and _var1_ values for generating `paymentRelatedDetailsForMobileSDKHash` & `validateVPAHash` are given below
     * | Hash for param       | Command                                     | var1                                                            |
       | -------------------- | ------------------------------------------- | --------------------------------------------------------------- |
       | `paymentOptionsHash` | payment\_related\_details\_for\_mobile\_sdk | value of `userCredentials` (You have set it in `paymentParams`) |
       | `validateVPAHash`    | validateVPA                                 | vpa string of your user                                         |
5.  After setting value of hashes in `paymentParams`, call following method of class `PayUAPI` to get all available payment options to the you, "Merchant" :

    ```swift
    class func getUPIPaymentOptions(withPaymentParams params: PayUPaymentParams,
                                   completion: @escaping(Result<PayUUPIPaymentOptions, PayUSDKError>) ->() )
    ```

    You will get a response of type `Result` with the value of type `PayUUPIPaymentOptions` in response's success param. Sample code shown below

    ```swift
     PayUAPI.getUPIPaymentOptions(withPaymentParams: self.paymentParams!, completion: { [weak self] result in
         switch result {
         case .success(let paymentOptions):
             self?.availablePaymentOptions = paymentOptions
             completion(.success(true))
         case .failure(let error):
             print(error)
             completion(.failure(error))
         }
     })
    ```
6.  With the `PayUUPIPaymentOptions` object received above, you can populate relevant UPI options on your checkout screen. As stated at the beginning of this document, you have three options to make payment 1. Intent 2. UPI Collect 3. Fallback for Google Pay

    Inside `intent` key of `PayUUPIPaymentOptions` object, you get array of objects of type `PayUSupportedIntentApp`. These are essentially the apps which are supported by the SDK for intent payments. You can now query the SDK for payment options available for the "Current User" based on factors like if Bank/Payment-Service-Provider(PSP) apps are installed on the current user's device or not.

    ```
     public class func canUseIntent(forApp app: PayUSupportedIntentApp,
                    withUpiOptions options: PayUUPIPaymentOptions) -> Bool
     public class func canUseUpiCollect(withPaymentOptions options: PayUUPIPaymentOptions) -> Bool
     public class func canUseGpayOmni(withPaymentOptions options: PayUUPIPaymentOptions) -> Bool
     public class func canUseGpayCollect(withPaymentOptions options: PayUUPIPaymentOptions) -> Bool
    ```

    Based on your priority and availability of payment options for the current user, you can order the payment options on your checkout page. **Note:** `canUseGpayOmni` and `canUseGpayCollect` methods give you fallback options of Google Pay intent app which have approx 10% more success rate than general UPI collect payments . This means, if your user does not have Google Pay app installed, you can still show Google Pay option on your checkout and we will display these two fallback options upon Google pay selection by the user. Google Pay omni payment option takes user's phone number for UPI collect payment.
7.  If user selects intent app option, you need to create an instance of `PayUIntentPaymentVC` and following data to it.

    ```
     let paymentVC = PayUIntentPaymentVC()
     paymentVC.availableUpiOptions = upiOptions
     paymentVC.paymentApp = app //object of type 'PayUSupportedIntentApp'
     paymentVC.paymentParams = params

     navigationController?.pushViewController(paymentVC, animated: false)
    ```
8.  If user selects upi collect option or Google Pay fallback option, you need to create an instance of `PayCollectPaymentVC` by following code convenience method

    ```
     let collectVC = PayCollectPaymentVC()
    ```

    Then, you should pass following information for payment processing

    ```
     collectVC.paymentParams = params
     collectVC.screenType = type // .upi or .gpayFallback
     collectVC.availablePaymentOptions = upiOptions

     self.navigationController?.pushViewController(collectVC, animated: true)
    ```

    After the payment is done, you should get the resonse in your payment completion callback defined above `PayUUPICore.shared.paymentCompletion`
9.  Add the query schemes in info.plist

    ```
    <key>LSApplicationQueriesSchemes</key>
    <array>
    <string>phonepe</string>
    <string>tez</string>
    <string>paytm</string>
    </array>
    ```


10. Make payment through UPICore:

i) UPI Collect Flow: &#x20;

Validate vpa with paymentparam, it will give you a  callback once it has verified vpa in the completion block.

PayUAPI.validateVPA(withPaymentParams: **\<PayUPaymentParam>**, completion: **<(Result\<PayUValidateVPAModel, PayUError>) -> ()>**)

Begin payment after validating your VPA. Set up PayUPaymentResponseHandler when the payment is successfully initiated and handle the response after the payment is completed.

PayUAPI.getDataForUPICollectPayment(withPaymentParams: **\<PayUPaymentParam>**, completion: **<(Result\<PayUPureS2SModel, PayUError>) -> ()>**)

ii) UPI Intent Flow:

First check which intent app are in current device(Gpay, Paytm, Phonepe). Then initiate payment

a) Gpay Intent Flow:

First get data using below function

PayUAPI.getDataForGpayIntentPayment(withPaymentParams: **\<PayUPaymentParam>**, completion: **<(Result\<PayUPureS2SModel, PayUError>) -> ()>**)

then make payment using below function and wait for response.

PayUThirdPartyManager.makePayment(withApp: **\<PayUSupportedIntentApp>**, withIntentModel: **\<PayUPureS2SModel>**, appSwitchingStatus: **<((Bool) -> ())((Bool) -> ())(Bool) -> ()>**)

b) Other Intent Flow:

First get data using below function

PayUAPI.getDataForIntentPayment(withPaymentParams: **\<PayUPaymentParam>**, completion: **<(Result\<PayUPureS2SModel, PayUError>) -> ()>**)

then make payment using below function and wait for response.

PayUThirdPartyManager.makePayment(withApp: **\<PayUSupportedIntentApp>**, withIntentModel: **\<PayUPureS2SModel>**, appSwitchingStatus: **<((Bool) -> ())((Bool) -> ())(Bool) -> ()>**)

{% hint style="info" %}
You will get Socket model using PayUPersistentStore.getSocketConnectionModel().
{% endhint %}
