iOS SDK Custom UI
Instamojo SDK Custom UI Documentation
Table of Contents
- Using Custom Created UI
Using Custom Created UI
This document assumes that you have finished the basic SDK integration in your application. If you haven't done it yet, please refer to this Documention
####Note: Please contact a qualified security assessor to determine your PCI-DSS incidence and liability if you’re implementing a custom interface that collects cardholder information.
If you choose to create your own UI to collect Payment information, SDK has necessary APIs to achieve this.
Use PaymentOptions
, which uses SDK APIs to collect Payment Information, to extend and modify as per your needs.
You can change the name of the controller and the Storyboard ID to anything you like.
Changing the Caller method
Replace Instamojo.invokePaymentOptionsView(order : order)
method with the following one.
let paymentOptions = self.storyboard?.instantiateViewController(withIdentifier: "paymentOptions") as! PaymentOptions
paymentOptions.order = order
self.navigationController?.pushViewController(paymentOptions, animated: true)
Collecting Card Details
Validating Card Option
Always validate whether the current order has card payment enabled.
if order.cardOptions == nil {
//seems like card payment is not enabled. Make the necessary UI Changes.
} else{
// Card payment is enabled.
}
Creating and validating Card
deatils
Card
deatilsOnce the user has typed in all the card details and ready to proceed, you can create the Card
object.
let card = Card.init(cardHolderName: self.cardHolderNameTextField.text!, cardNumber: self.cardNumberTextField.text!, date: self.expiryDateTextField.text!, cvv: self.cvvTextField.text!, savedCard: false)
//Validate the card now
if !card.isValidCard() {
if !card.isValidCardHolderName() {
//Invalid Card Holder Name
}
if !card.isValidCardNumber() {
//Invalid Card Number
}
if !card.isValidDate() {
//Invalid Card Expiry Date
}
if !card.isValidCVV() {
//Invalid Card CVV
}
}else{
// Valid Card
}
}
Generating Juspay Browser Params using Card
Once the card details are validated, You need to generate JusPay BrowserParams with the card details given. Add JuspayRequestCallBack
protocol to your view controller
//Good time to show progress dialog while the browser params is generated
let request = Request(order: self.order, card: card, jusPayRequestCallBack: self)
request.execute()
//Call back recieved from juspay request to instamojo
func onFinish(params: BrowserParams, error: String ) {
if error.isEmpty {
DispatchQueue.main.async {
//Hide spinner
Instamojo.makePayment(params: params)
}
}else{
DispatchQueue.main.async {
// Hide Spinner
//There seems to be some problem. Please choose a different payment options
}
}
}
Collecting Netbanking Details
Validating Netbanking Option
Similar to Card Options, Netbanking options might be disabled. Check Netbanking Options for nil
if order.netBankingOptions == nil {
//seems like the Netbanking option is not enabled. Make the necessary UI Changes.
} else{
// Netbanking is enabled.
}
Displaying available Banks
The Bank and its code set can be fetched from order
itself.
order.netBankingOption.banks
The above code snippet will return a [NetBankingBanks]
Use an list view to display the available banks and collect the bank code of the bank user selects.
Generating Juspay Browser Params using bank code
Once the bank code is collected, You can generate the Juspay Browser Params using the following snippet.
//User selected a Bank. Hence proceed to Juspay
let bank = netBanks[indexPath.row] as NetBankingBanks
let submissionURL = order.netBankingOptions.url
let postData = order.netBankingOptions.getPostData(accessToken: order.authToken!, bankCode: bank.bankCode)
let browserParams = BrowserParams()
browserParams.url = submissionURL
browserParams.postData = postData
browserParams.clientId = order.clientID
browserParams.endUrlRegexes = Urls.getEndUrlRegex()
//Pass the Browser Params to start payment view controller
Instamojo.makePayment(params: browserParams)
Collecting EMI Details
Validating EMI Options
Similar to Card Options, EMI options might be disabled. Check EMI Options for nil
.
if order.emiOptions == nil {
//seems like EMI option is not enabled. Make the necessary UI Changes.
} else{
// EMI is enabled.
}
Displaying available EMI Options
For EMI, the user should be given an option to choose his/her Credit Card Bank.
The list of Banks enabled for EMI can be fetched as [EMIBank]
using the following code snippet.
let banks = order.emiOptions.emiBanks as [EMIBank]
Each EMIBank
has following fields
- Bank Name
- Bank Code
- List of rate and tenure
We recommend using a ListView
to show the List of EMIBanks available.
Once the user chooses a Bank from the list, you would need to present the user with available tenure options and the interest rate for each tenure.
To fetch the tenure and tenure's interest rate, please use the following code snippet.
let rates = selectedBank.rate
The result will fetch you [(key: Int, value: Int)]
with key = tenure
and value = interest rate
.
The map is sorted in ascending order wrt key
ie.. tenure
.
We recommend you to use a ListView
to show the tenure and its interest rate to the user.
Updating Order and Collecting Card Details
Once the user choose a tenure, please set the selected bankCode
and tenure
in order
.
self.order.emiOptions.selectedTenure = tenure
self.order.emiOptions.selectedBankCode = selectedBank.bankCode
From this point, the further steps will be same as normal Card
payment.
SDK will take the EMI
details from the order
while generating Browser Params for Juspay.
Collecting Wallet details
Validating Wallet Options
Similar to Card Options, Wallet options might be disabled. Check Wallet Options for nil
.
if order.walletOptions == nil {
//seems like Wallet option is not enabled. Make the necessary UI Changes.
} else{
// Wallet is enabled.
}
Displaying available Wallets
Enabled Wallets can be fetched from the order
as a [Wallet]
.
let wallets = order.walletOptions.wallets as [Wallet]
Each Wallet
object has three fields namely
- Wallet Name
- Wallet ID
- Wallet Image URL
We recommend using a ListView
to show the list of Wallets.
Generating Juspay Browser Params using Wallet ID
Once the user chooses a Wallet to proceed, Browser params should be generated with the selected Wallet ID.
Generate the browser params using the follwing code snippet
let wallet = wallets[indexPath.row] as Wallet
let walletID = wallet.walletID
let submissionURL = order.walletOptions.url
let postData = order.walletOptions.getPostData(accessToken: order.authToken!, walletID: walletID)
let browserParams = BrowserParams()
browserParams.url = submissionURL
browserParams.clientId = order.clientID
browserParams.postData = postData
browserParams.endUrlRegexes = Urls.getEndUrlRegex()
//Pass the Browser Params to start payment view controller
Instamojo.makePayment(params: browserParams)
Passing the result back to main view controller
Add the following code snippet in root view controller.
override func viewDidLoad() {
addNotificationToRecievePaymentCompletion()
}
func addNotificationToRecievePaymentCompletion(){
NotificationCenter.default.addObserver(self, selector: #selector(self.paymentCompletionCallBack), name: NSNotification.Name("INSTAMOJO"), object: nil)
}
func paymentCompletionCallBack() {
if UserDefaults.standard.value(forKey: "USER-CANCELLED") != nil {
//Transaction cancelled by user, back button was pressed
}
if UserDefaults.standard.value(forKey: "ON-REDIRECT-URL") != nil {
// Check the payment status with the transaction_id
}
if UserDefaults.standard.value(forKey: "USER-CANCELLED-ON-VERIFY") != nil {
//Transaction cancelled by user when trying to verify UPI payment
}
}
Collecting UPI details
Validating UPI options
Similar to Card Options, UPI options might be disabled. Check UPI Options for nil
.
if order.upiOptions == nil {
//seems like UPI option is not enabled. Make the necessary UI Changes.
} else{
// UPI is enabled.
}
Initiating collect request to user's VPA
Using an UITextField
, collect the VPA of the user. The collect request will be sent to this VPA.
Once collected, use the below code snippet to initiate the collect request. Extend UPICallBack
protocol to your view controller.
let request = Request.init(order: self.order, virtualPaymentAddress: virturalPaymentAddress!, upiCallBack: self)
request.execute()
func onSubmission(upiSubmissionResponse: UPISubmissionResponse, exception: String) {
DispatchQueue.main.async {
// Hide Spinner
if !exception.isEmpty && upiSubmissionResponse.statusCode != Constants.PendingPayment {
self.showAlert(title: "Payment Response", errorMessage: exception)
} else {
self.checkForStatusTransaction()
}
}
}
func checkForStatusTransaction() {
// Show Spinner
let request = Request.init(order: self.order, upiSubmissionResponse: self.upiSubmissionResponse, upiCallback: self)
request.execute()
}
func onStatusCheckComplete(paymentComplete: Bool, status: Int) {
DispatchQueue.main.async {
//Hide Spinner
if status == Constants.FailedPayment {
//Payment Cancelled//
} else if status == Constants.PendingPayment {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
if self.continueCheck {
// check transaction status 2 seconds later
self.checkForStatusTransaction()
}
}
} else if status == Constants.PaymentError {
//Error while making UPI Status Check request
} else {
// Payment Completed
}
}
}
Using Custom Spinner
A spinner that includes text and activity Indictor is bundled with Instamojo which can be used if required.
Initialise
let spinner = Spinner(text : "Please Wait..")
spinner.hide()
self.view.addSubview(spinner)
Show
spinner.show()
Hide
spinner.hide()
Using Custom Expiry Date Picker
A custom date picker with month and year is bundled with Instamojo which can be used if required.
Setup
Step 1 : Add a Picker View
to your view controller in Storyboard
Step 2 : Change the class of Picker View
to MonthYearPickerView
in the Identity Inspector
Step 3 : Reference outlet the MonthYearPickerView
to your view controller
Step 4 : To the UITextField
you want to extend the MonthYearPickerView
add the following snippet
expiryDateTextField.inputView = expiryPickerView
expiryPickerView.removeFromSuperview()
expiryPickerView.onDateSelected = { (month: Int, year: Int) in
let date = String(format: Constants.DateFormat, month, year)
self.expiryDateTextField.text = date
}