1. Integration Steps
Set up pod
The CheckoutPro SDK is offered through CocoaPods. To add the SDK in your app project:
Include the SDK framework in your podfile.
// make sure to add below-mentioned line to use dynamic frameworks
use_frameworks!
// Add this to include our SDK
pod 'PayUIndia-CheckoutPro'
- Install dependency using the pod install command in terminal
- Add the following imports in the class where you need to initiate a payment.
#import
#import
#import
import PayUCheckoutProKit
import PayUCheckoutProBaseKit
import PayUParamsKit
- Test the key and salt in the following environments:
- Production— Refer to Generate Production Merchant Key and Salt
- Test— Refer to Generate Test Merchant Key and Salt
Swift Package Manager Integration
You can integrate PayUIndia-Checkoutpro with your app or SDK using the following methods:
- Using Xcode: Navigate to File > Add Package menu and add the following package:
https://github.com/payu-intrepos/PayUCheckoutPro-iOS - Using Package.Swift: Add the following line in the Package.swift dependencies:
.package(name: "PayUCheckoutProKit", url: "https://github.com/payu-intrepos/PayUCheckoutPro-iOS", from: "7.2.1")
CrashReporter
In order to receive all the crashes related to our SDKs, add the following line to your AppDelegate’s didFinishLaunchingWithOptions
:
[PayUCheckoutPro start];
PayUCheckoutPro.start()
Remember
Please add NSCameraUsageDescription key in your application
Info.plist
file.
Step 2: Set up the payment hashes
Remember
Always generate the hashes on your server. Do not generate the hashes locally in your app, as it will compromise the security of the transactions.
The CheckoutPro SDK uses hashes to ensure the security of the transaction and prevent any unauthorized intrusion or modification. The CheckoutPro SDK requires two types of hashes. For more information on the two types of hashes, refer to Hash Generation for CheckoutPro SDK.
Step 3: Build the payment parameters (mandatory step)
To initiate a payment, your app must send the transaction information to the Checkout Pro SDK. To pass this information, build a payment parameter object as in the following code snippet:
PayUPaymentParam *paymentParam = [[PayUPaymentParam alloc] initWithKey:<#(NSString * _Nonnull)#>
transactionId:<#(NSString * _Nonnull)#>
amount:<#(NSString * _Nonnull)#>
productInfo:<#(NSString * _Nonnull)#>
firstName:<#(NSString * _Nonnull)#>
email:<#(NSString * _Nonnull)#>
phone:<#(NSString * _Nonnull)#>
surl:<#(NSString * _Nonnull)#>
furl:<#(NSString * _Nonnull)#>
environment:<#(enum Environment)#> /*EnvironmentProduction or EnvironmentTest*/];
paymentParam.userCredential = <#(NSString)#>; // For saving and fetching use saved card
let paymentParam = PayUPaymentParam(key: <#T##String#>,
transactionId: <#T##String#>,
amount: <#T##String#>,
productInfo: <#T##String#>,
firstName: <#T##String#>,
email: <#T##String#>,
phone: <#T##String#>,
surl: <#T##String#>,
furl: <#T##String#>,
environment: <#T##Environment#> /*.production or .test*/)
paymentParam.userCredential = <#T##String#> // For saving and fetching user’s saved card
The TransactionId parameter cannot have a special character and not more than 25 characters.
Mandatory parameters
Parameter | Description | Data Type and Validation |
---|---|---|
Keymandatory | String Merchant Key received from PayU | Cannot be null or empty |
TransactionIdmandatory | String Cannot be null or empty and should be unique for each transaction. Maximum allowed length is 25 characters. It cannot contain special characters like: -_/ | Should be unique for each transaction |
Product Infomandatory | String Information about Product | Cannot be null or empty |
First Namemandatory | String Customer’s first name | Cannot be null or empty |
Emailmandatory | String Customer’s Email ID | Cannot be null or empty |
Phonemandatory | String Customer’s phone number | Should be of 10 digits |
surlmandatory | String PayU will load this url and pass transaction response | Cannot be null or empty |
furlmandatory | String When the transaction is a failure, PayU will load this url and pass transaction response | Cannot be null or empty |
Environmentmandatory | String Environment of SDK | Should be either Swift: Environment.production or Environment.test ObjectiveC: EnvironmentProduction or EnvironmentTest |
User Credentialoptional | String This is used for the store card feature. PayU will store cards corresponding to passed user credentials and similarly, user credentials will be used to access previously saved cards | Should be a unique value Format: : Here, UserId is any id/email/phone number to uniquely identify the user |
PayUSIParamsoptional | Object of PayUSIParams. This contains SI Details. | Object of PayUSIParams |
SplitPaymentDetailsoptional | String This parameter is required for splitting the transactions. | Should be a json String |
The code block for passing the parameters is similar to the following:
If you required any value in the response then pass the below value
paymentParam.additionalParam = [[NSDictionary alloc] initWithObjectsAndKeys:
<#(NSString)#>, PaymentParamConstant.udf1,
<#(NSString)#>, PaymentParamConstant.udf2,
<#(NSString)#>, PaymentParamConstant.udf3,
<#(NSString)#>, PaymentParamConstant.udf4,
<#(NSString)#>, PaymentParamConstant.udf5,
<#(NSString)#>, PaymentParamConstant.walletURN,
nil];
paymentParam.additionalParam[PaymentParamConstant.udf1] = <#T##String#>
paymentParam.additionalParam[PaymentParamConstant.udf2] = <#T##String#>
paymentParam.additionalParam[PaymentParamConstant.udf3] = <#T##String#>
paymentParam.additionalParam[PaymentParamConstant.udf4] = <#T##String#>
paymentParam.additionalParam[PaymentParamConstant.udf5] = <#T##String#>
paymentParam.additionalParam[PaymentParamConstant.walletURN] = <#T##String#> // Required for Amul Wallet
For recurring payments (SI)
If you are integrating SI, create an object of SIParam. After creating an object, pass the object similar to the following code:
paymentParam.siParams = siParam;
paymentParam.siParams = siParam
For split settlements
If you are integrating Split Settlements, the splitPaymentDetails parameter is required to split the transactions.
After creating an object, pass the object similar to the following code:
paymentParam.splitPaymentDetails = @"";
paymentParam.splitPaymentDetails = ""
JSON request structure of splitInfo field
The sample JSON structure for the splitPaymentDetails field:
Remember
- For the absolute type split, you must ensure that the sum of amount of all splits is equal to the parent transaction amount.
- For the percentage type split, you must ensure that the sum of percentage of all splits is equal to 100. You can use any number decimal places for each split, but ensure the sum of percentage of all splits is equal to 100.
{
"type":"absolute",
"splitInfo":{
"P****Y":{
"aggregatorSubTxnId":"9a70ea0155268101001ba",
"aggregatorSubAmt":"50",
"aggregatorCharges":"20"
},
"P***K":{
"aggregatorSubTxnId":"9a70ea0155268101001bb",
"aggregatorSubAmt":"30"
}
}
}
The following fields are included in the splitPaymentDetails parameter in a JSON format to specify the split details. The fields in the JSON format are described in the following table:
Field | Description | Example |
---|---|---|
typemandatory | string Any of the following types of split is specified in this field.absolute: The absolute amount is specified for each part of the split. The absolute amount is specified in the aggregatorSubAmt field of the JSON for each child or aggregator. For a sample request and response, refer to Absolute Split During Payment percentage: The percentage of the amount is specified for each part of the split. The percentage of the amount is specified in the aggregatorSubAmt field of the JSON for each child or aggregator. For a sample request and response, refer to Split by Percentage During Payment | absolute |
splitInfomandatory | JSON This parameter must include the list of aggregator sub-transaction IDs and sub-amounts as follows:aggregatorSubTxnId: The transaction ID of the aggregator is posted in this parameter. This field is mandatory and applicable only to child merchants. aggregatorSubAmt: The transaction amount split for the aggregator is posted in this parameter. This field is mandatory. aggregatorCharges: The transaction amount split for aggregator charges is posted in this parameter. This field is optional. Note: Only the parent aggregators can have the aggregatorCharges field as part of their JSON to collect charges. The sample request structure JSON Request Structure of splitInfo Field. | The sample request structure JSON Request Structure of splitInfo Field. |
Step 4: Initiate the payment
Initialize and launch the Checkout Pro SDK by calling the following method from your UIViewController subclass:
[PayUCheckoutPro openOn:self paymentParam:paymentParam config:<#(PayUCheckoutProConfig * _Nullable)#> delegate:self];
PayUCheckoutPro.open(on: self, paymentParam: paymentParam, config: <#T##PayUCheckoutProConfig?#>, delegate: self)
Step 5: Handle the payment completion
Confirm to PayUCheckoutProDelegate and use these functions to get appropriate callbacks from the SDK:
/// This function is called when we successfully process the payment
/// @param response success response
- (void)onPaymentSuccessWithResponse:(id _Nullable)response {
}
/// This function is called when we get failure while processing the payment
/// @param response failure response
- (void)onPaymentFailureWithResponse:(id _Nullable)response {
}
/// This function is called when the user cancel’s the transaction
/// @param isTxnInitiated tells whether payment cancelled after reaching bankPage
- (void)onPaymentCancelWithIsTxnInitiated:(BOOL)isTxnInitiated {
}
/// This function is called when we encounter some error while fetching payment options or there is some validation error
/// @param error This contains error information
- (void)onError:(NSError * _Nullable)error {
}
/// Use this function to provide hashes
/// @param param NSDictionary that contains key as HashConstant.hashName & HashConstant.hashString
/// @param onCompletion Once you fetch the hash from server, pass that hash with key as param[HashConstant.hashName]
- (void)generateHashFor:(NSDictionary<NSString *, NSString *> * _Nonnull)param onCompletion:(void (^ _Nonnull)(NSDictionary<NSString *, NSString *> * _Nonnull))onCompletion {
// Send below string hashStringWithoutSalt to your backend and append the salt at the end and send the sha512 back to us, do not calculate the hash at your client side, for security is reasons, hash has to be calculated at the server side
NSString *hashStringWithoutSalt = [param objectForKey:HashConstant.hashString];
// Or you can send below string hashName to your backend and send the sha512 back to us, do not calculate the hash at your client side, for security is reasons, hash has to be calculated at the server side
NSString * hashName = [param objectForKey:HashConstant.hashName];
// Set the hash in below string which is fetched from your server
NSString *hashFetchedFromServer = <#(NSString)#>;
NSDictionary *hashResponseDict = [NSDictionary dictionaryWithObjectsAndKeys:hashFetchedFromServer, hashName, nil];
onCompletion(hashResponseDict);
}
/// This function is called when we successfully process the payment
/// - Parameter response: success response
func onPaymentSuccess(response: Any?) {
}
/// This function is called when we get failure while processing the payment
/// - Parameter response: failure response
func onPaymentFailure(response: Any?) {
}
/// This function is called when the user cancel’s the transaction
/// - Parameter isTxnInitiated: tells whether payment cancelled after reaching bankPage
func onPaymentCancel(isTxnInitiated: Bool) {
}
/// This function is called when we encounter some error while fetching payment options or there is some validation error
/// - Parameter error: This contains error information
func onError(_ error: Error?) {
}
/// Use this function to provide hashes
/// - Parameters:
/// - param: Dictionary that contains key as HashConstant.hashName & HashConstant.hashString
/// - onCompletion: Once you fetch the hash from server, pass that hash with key as param[HashConstant.hashName]
func generateHash(for param: DictOfString, onCompletion: @escaping PayUHashGenerationCompletion) {
// Send this string to your backend and append the salt at the end and send the sha512 back to us, do not calculate the hash at your client side, for security is reasons, hash has to be calculated at the server side
let hashStringWithoutSalt = param[HashConstant.hashString] ?? ""
// Or you can send below string hashName to your backend and send the sha512 back to us, do not calculate the hash at your client side, for security is reasons, hash has to be calculated at the server side
let hashName = param[HashConstant.hashName] ?? ""
// Set the hash in below string which is fetched from your server
let hashFetchedFromServer = <#T##String#>
onCompletion([hashName : hashFetchedFromServer])
}
UPI Intent (Optional)
Currently, PayU supports only PhonePe and GooglePay through Intent. Add the query schemes in theinfo.plist
:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>phonepe</string>
<string>tez</string>
<string>paytm</string>
</array>
Note
In the case of UPI intent and Collect flow, you will not receive a callback response in SURL/FURL. In this case, the format of the PayU response received will be different from other payment options that you can handle accordingly. For handling surl or furl, refer to Handling Return URLs.
If you getmihpayid
in the PayU response, consider it as a PayU ID/ ID.
Distributing your app (App Store / Ad-hoc)
PayU provides a fat framework that allows you to test your app seamlessly on the device as well as a simulator. But before archiving your app, you need to remove simulator slices from the framework. To archive your app with the PayU CheckoutPro integration, refer to Releasing the app.
Additional integration
Integrate MCP (Multi-Currency Pricing)
Before you begin
Connect with your Key Account Manager at PayU to get the following credentials:
- Merchant Access Key
- Merchant Secret Key
The following video shows the demo of an app with MCP integration:
Step 1: Pass merchant access key
Pass the following merchant access key in additional parameters of the PayUCheckoutPro Payment Parameters. For more information on Payment Parameters, refer to Integration with PayUCheckoutPro > Build the Payment Parameters.
paymentParam.additionalParam[PaymentParamConstant.merchantAccessKey] = @<Merchant-Access-Key>;
paymentParam.additionalParam[PaymentParamConstant.merchantAccessKey] = <Merchant-Access-Key>
Step 2: Generate hash For MCP
For MCP payments, SDK requires Lookup API hash which is a dynamic hash. SDK will call the generateHash()
method as explained in this section.
Lookup API hash is calculated with the HmacSHA1
signature. It requires a Merchant Secret key in calculating the hash. The following example, code demonstrates how to calculate the Lookup API hash.
- (void)generateHashFor:(NSDictionary<NSString *,NSString *> * _Nonnull)param onCompletion:(void (^ _Nonnull)(NSDictionary<NSString *,NSString *> * _Nonnull))onCompletion {
NSString *commandName = [param objectForKey:HashConstant.hashName];
NSString *hashStringWithoutSalt = [param objectForKey:HashConstant.hashString];
// get hash for "commandName" from server
// After fetching hash set its value in below variable "hashValue"
NSString *hashValue = [NSMutableString new];
if (commandName == HashConstant.mcpLookup) {
if commandName == HashConstant.mcpLookup {
//To create HMACSHA1 Signature
// Signature = HMAC-SHA1(data, key);
//Data = hashStringWithoutSalt
//Key = Mechent Secret Key shared with the merchant at the time of on-boarding
hashValue = @<HMACSHA1 signature from your server>;
} else {
hashValue = @<HMACSHA512 hash from your server>;
}
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:hashValue, commandName, nil];
onCompletion(dict);
}
func generateHash(for param: DictOfString, onCompletion: @escaping PayUHashGenerationCompletion) {
let commandName = (param[HashConstant.hashName] ?? "")
let hashStringWithoutSalt = (param[HashConstant.hashString] ?? "")
// get hash for "commandName" from server
// After fetching hash set its value in below variable "hashValue"
var hashValue = ""
if commandName == HashConstant.mcpLookup {
//To create HMACSHA1 Signature
// Signature = HMAC-SHA1(data, key);
//Data = hashStringWithoutSalt
//Key = Mechent Secret Key shared with the merchant at the time of on-boarding
hashValue = <HMACSHA1 signature from your server>
} else {
hashValue = <HMACSHA512 hash from your server>
}
onCompletion([commandName : hashValue])
}
Add custom notes
Step 1: Create a Custom Note list
Create a list of custom notes that you want to pass to the CheckoutPro SDK. For each custom note, custom_note and custom_note_category need to be passed.
var customNotes = [PayUCustomNote]()
// for specific custom_note_category
let customNote = PayUCustomNote()
customNote.note = "Please welcome note"
customNote.noteCategories = [.ccdc]
customNotes.append(customNote)
// when want to pass same custom note for multiple custom_note_category
let customNote2 = PayUCustomNote()
customNote2.note = "Please welcome note"
customNote2.noteCategories = [.ccdc , .netBanking]
customNotes.append(customNote2)
// If you want to show custom note on L1 screen, please set custom_note_category to nil
let customNote3 = PayUCustomNote()
customNote3.note = "Please welcome note"
customNote3.noteCategories = nil
customNotes.append(customNote3)
Step 2: Pass the Custom Note list to SDK
To pass the custom note list (array) created in Step 1 to the SDK, create a PayUCheckoutProConfig object and set customNotes
similar to the following code block:
let checkoutProConfig = PayUCheckoutProConfig()
config.customNotes = customNotes
Integrate convenience fee
Set up Convenience Fee
When the Convenience Fee is set for a payment mode like NB. In CheckoutPro SDK, whenever the user selects any NetBanking option then the header amount will be updated with a convenience fee. Amount breakup is accessed by clicking “View Details” in the toolbar. Below screen will be displayed that shows the breakup of the transaction amount with a convenience fee.
The above screenshot displays the amount breakup with the Convenience Fee
By default, when no convenience fee is set, an amount breakup will be similar to the following screenshot.
Integrate Closed Loop wallet
Before you begin
- Enable Closed-Loop Wallet from your Dashboard.
- Build the payment parameters with PaymentParamConstant.walletURN parameters. See Integrate with PayU checkoutpro for iOS to learn more.
The following screens show how Closed-Loop wallet payment works on the PayU payment page:
- When you enable the Closed-Loop wallet for your account, your customer sees the Closed-Loop wallet payment on top of the payment page under the SAVED OPTION tab.
- The closed-loop wallet balance is fetched and loaded (see the screenshot below) by default.
- If the balance is not loaded due to some error, an error message will be displayed (see the screenshot below). The customer can tap on the wallet option to reload the amount.
- Once the balance is loaded the customer can make the payment by clicking Pay Now.
Updated 7 days ago