Add the following lines into your Podfile
// make sure to add below-mentioned line to use dynamic frameworksuse_frameworks!​// Add this to include our SDKpod 'PayUIndia-UPI'
Make UPI Payments
Set environment to test or production. You can also set debugging level to get logs from the SDK
PayUUPICore.shared.environment = .productionPayUUPICore.shared.logLevel = .error //Other option is verbose. Logs are disabled by default
Set mandatory payment parameters required for the payment
do {paymentParams = try PayUPaymentParams(merchantKey: "smsplus", //Your merchant key for the environment set in step 1transactionId: "1iYJfaskjf890", //Your unique ID for this trasactionamount: "64999", //Amount of transactionproductInfo: "iPhone", // Description of the productfirstName: "Vipin", // First name of the useremail: "[email protected]", // Email of the useer//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.udf1: "SKU1|SKU2|SKU3",//You can keep all udf fields blank if you do not have any requirement to save txn specific dataudf2: "",udf3: "",udf4: "",udf5: "")​// Example userCredentials - "merchantKey:user'sUniqueIdentifier"paymentParams?.userCredentials = "smsplus:[email protected]"// Success URL. Not used but required due to mandatory check.paymentParams?.surl = "https://payu.herokuapp.com/ios_success"// Failure URL. Not used but required due to mandatory check.paymentParams?.furl = "https://payu.herokuapp.com/ios_failure"paymentParams?.phoneNumber = "9123456789" // "10 digit phone number here"} catch let error {print("Could not create post params due to: \(error.localizedDescription)")}
Set callbacks to receive actionable events from SDK
paymentCompletion
- You receive the payment response here.
PayUUPICore.shared.paymentCompletion = { [weak self] result inDispatchQueue.main.async { [weak self] inguard 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)}}}
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.
PayUUPICore.shared.backPressed = {[weak self] inself?.navigationController?.popToRootViewController(animated: true)}
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.
PayUUPICore.shared.onEnteringVPA = {[weak self] vpa, completion inguard let self = self else { return }​self.paymentParams?.vpa = vpaself.fetchHashes(withParams: self.paymentParams!) { result inswitch result {case .success:completion(.success(self.paymentParams!))case .failure(let error):print("Could not fetch hashes \(error.description)")completion(.failure(.noInternet()))}}}
​
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 PayUHashes
PayUHashes
has 3 properties. Each of these 3 is used for a distinct API call. These 3 properties are defined below:
paymentRelatedDetailsForMobileSDKHash
: This is required to get available upi payment options from which payment can be made.
paymentHash
: This is required to create transaction at PayU's end.
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.
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 to generate hashes on your server.
Command and var1 values for generating paymentRelatedDetailsForMobileSDKHash
& validateVPAHash
are given below
Hash for param | Command | var1 |
| payment_related_details_for_mobile_sdk | value of |
| validateVPA | vpa string of your user |
After setting value of hashes in paymentParams
, call following method of class PayUAPI
to get all available payment options to the you, "Merchant" :
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
PayUAPI.getUPIPaymentOptions(withPaymentParams: self.paymentParams!, completion: { [weak self] result inswitch result {case .success(let paymentOptions):self?.availablePaymentOptions = paymentOptionscompletion(.success(true))case .failure(let error):print(error)completion(.failure(error))}})
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) -> Boolpublic class func canUseUpiCollect(withPaymentOptions options: PayUUPIPaymentOptions) -> Boolpublic class func canUseGpayOmni(withPaymentOptions options: PayUUPIPaymentOptions) -> Boolpublic 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.
If user selects intent app option, you need to create an instance of PayUIntentPaymentVC
and following data to it.
let paymentVC = PayUIntentPaymentVC()paymentVC.availableUpiOptions = upiOptionspaymentVC.paymentApp = app //object of type 'PayUSupportedIntentApp'paymentVC.paymentParams = params​navigationController?.pushViewController(paymentVC, animated: false)
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 paymentVC = PayUIntentPaymentVC()
Then, you should pass following information for payment processing
collectVC.paymentParams = paramscollectVC.screenType = type // .upi or .gpayFallbackcollectVC.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
Add the query schemes in info.plist
<key>LSApplicationQueriesSchemes</key><array><string>phonepe</string><string>tez</string></array>
​