Razorpay iOS Custom UI

Note:
Razorpay iOS Custom SDK is a private framework. Please do not share the SDK or this document with anyone.

We have changed the integration method with this release. We highly recommend you to use the latest SDK. Nevertheless, if you wish to use the older version, you can find the documentation here.

Note:
This framework only supports iOS version 10.0 and above.

Note:
The SDK only supports the latest version of Swift. We no longer support Swift 3. Also, the SDK only support iOS devices using 64 bit architecture i.e., iPhone 5s and above.

Download SDK#

SDK

Framework Version

Framework Compiled With

Download Link

Razorpay Custom UI (with bit code enabled)

1.3.0

Swift 5

Download Link

Usage Instructions#

Step 1: Import library to your project#

  1. Unzip the SDK attachment.
  2. Open your project in XCode and go to file under Menu and select Add files to "yourproject".
  3. Select Razorpay.framework in the directory you just unzipped.
  4. Click on the Copy items if needed checkbox.
  5. Click Add.

If you are building an Objective-C project, follow the additional steps given below:

  1. Go to Project Settings.
  2. Select Build Settings - All and Combined from the Project Settings Menu.
  3. Under Build Options, set the Always Embed Swift Standard Libraries option to TRUE.

Note:
Ensure that you have the framework added in both Embedded Binaries and Linked Frameworks and Libraries under Target settings - General.

Step 2: Initialize Razorpay SDK#

To initialize the Razorpay SDK, you will need the following:

  • API key
  • A delegate that implements RazorpayPaymentCompletionProtocol and WKNavigationDelegate
  • A WKWebView to show the bank pages
Copy import Razorpay class ViewController: UIViewController, RazorpayPaymentCompletionProtocol, WKNavigationDelegate { var webView: WKWebView! var razorpay: Razorpay! . . override func viewDidLoad() { super.viewDidLoad() . . self.razorpay = Razorpay.initWithKey("KEY", andDelegate: self, withPaymentWebView: self.webView) } }
Copy#import "Razorpay/Razorpay.h" @interface ViewController() <RazorpayPaymentCompletionProtocol, WKNavigationDelegate>{ Razorpay *razorpay; WKWebView *webView; } . . - (void)viewDidLoad { [super viewDidLoad]; . . razorpay = [Razorpay initWithKey:@"KEY" andDelegate:self withPaymentWebView:webView]; }

Step 3: Get the valid payment options applicable for your account#

Currently, the only valid option that can be passed in the function getPaymentMethods is subscription_id.

Copylet options :[String:String] = ["subscription_id": "sub_testid"] var paymentMethods :[AnyHashable:Any] = [:] var errorDescription: String = "" self.razorpay.getPaymentMethods(withOptions: options, withSuccessCallback: {methods in paymentMethods = methods }){ error in errorDescription = error } OR self.razorpay.getPaymentMethods(withOptions: nil, withSuccessCallback: {methods in paymentMethods = methods }){ error in errorDescription = error }
CopyNSDictionary *options = @{@"subscription_id": @"sub_8tkmbhhROdiVSc"}; [razorpay getPaymentMethodsWithOptions: options withSuccessCallback: ^(NSDictionary *methods){ for(NSString *key in [methods allKeys]) { NSLog(@"%@",[methods objectForKey:key]); } } andFailureCallback: ^(NSString *error){ NSLog(@"%@",error); }];

Step 4: Get subscription amount#

You can get the subscription amount against the subscription ID using the following function:

Copyvar errorDescription: String = "" var amount: UInt64 = 0 self.razorpay.getSubscriptionAmount(havingSubscriptionId: "sub_testid", withSuccessCallback: {subAmount in amount = subAmount }){ error in errorDescription = error }
Copy[razorpay getSubscriptionAmountWithHavingSubscriptionId:@"sub_8tkmbhhROdiVSc" withSuccessCallback:^(UInt64 amount){ NSLog(@"%lld",amount); }andFailureCallback: ^(NSString *error){ NSLog(@"%@",error); }];

Step 5: Create you own UI#

Once you receive the required input from the customer, pass them to our SDK which takes them to the appropriate authentication channel.

Add the following code where you want to initiate payment:

Copylet options: [String:Any] = [ "amount": 100, // amount in paise "currency": "INR", "email": "foo@bar.com", "contact": "9090980808", "method": "card", "card[name]": "Abhinav", "card[number]": "4111111111111111", "card[expiry_month]": 06, "card[expiry_year]": 30, "card[cvv]": "123" ] razorpay.authorize(options)
CopyNSDictionary *options = @{ @"amount": @"100", // amount in paise @"currency": @"INR", @"email": @"a@b.com", @"contact": @"9797979797", @"method": @"wallet", @"wallet": @"mobikwik" };

Note#

For UPI collect requests, use the following dictionary and pass it to the authorize function as shown below:

Copy let options: [AnyHashable:Any] = [ "amount": "100", // amount in paise "currency": "INR", "email": "a@b.com", "contact": "1234567890", "method":"upi", "vpa":"test@axisbank" ] self.razorpay?.authorize(options)

where razorpay is an instance of Razorpay.

The following table defines all the supported options that can be passed to the authorize function:

Field Name

Valid in method

Sample Value

currency

all

INR

amount

all

5000

email

all

gaurav.kumar@example.com

contact

all

9123456789

method

all

card / netbanking / wallet / emi

card[name]

card / emi

Gaurav Kumar

card[number]

card / emi

4111111111111111

card[expiry_month]

card / emi

10

card[expiry_year]

card / emi

20

card[cvv]

card / emi

908

emi_duration

emi

3

bank

netbanking

SBIN

wallet

wallet

mobikwik

notes[order_id]

all

123

Note

  • notes is a read-only field that is associated with a payment and returned while fetching payment details. Razorpay can not modify this field. You can add up to 15 notes that will then be associated with the payment. For example: "notes[internal_key_1]", "notes[internal_key_2]"), etc. These are returned when you fetch payment details from the API.
  • emi is available only for certain banks. To check valid banks, valid duration and EMI rates / plans to display to the user, please visit the EMI Demo page and click EMI in the payment form. You can safely cache this data at your end since this does not change without prior notification. The monthly EMI can also be cached or can be calculated using the following formula:

Step 6: Pass the WKNavigationDelegate actions to the SDK#

SDK handles the responses from WKWebView to give you the correct status of the payment.

Copyoverride func viewDidLoad() { super.viewDidLoad() . . self.webView.navigationDelegate = self } public func webView(_ webView: WKWebView, didCommit navigation: WKNavigation!){ if razorpay != nil{ self.razorpay.webView(webView, didCommit: navigation) } } public func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError er: Error) { if razorpay != nil{ self.razorpay.webView(webView, didFailProvisionalNavigation: navigation, withError: er) } } public func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError er: Error){ if razorpay != nil{ self.razorpay.webView(webView, didFail: navigation, withError: er) } } public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!){ if razorpay != nil{ self.razorpay.webView(webView, didFinish: navigation) } }
Copy override func viewDidLoad(){ super.viewDidLoad(); . . webView.navigationDelegate = self; } - (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{ if (razorpay){ [razorpay webView:webView didCommit:navigation]; } } - (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error{ if (razorpay){ [razorpay webView:webView didFailProvisionalNavigation:navigation withError:error]; } } - (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error{ if (razorpay){ [razorpay webView:webView didFail:navigation withError:error]; } } - (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{ if (razorpay){ [razorpay webView:webView didFinish:navigation]; } }

Step 7: Handle success/error when the payment is done#

This is done by implementing the onPaymentSuccess and onPaymentError methods of the RazorpayPaymentCompletionProtocol.

We recommend giving the user an option to cancel the payment midway and pass on this action to us. You may also implement a retry action or display a relevant message at this step based on your use case.

Copyfunc onPaymentError(_ code: Int32, description str: String, andData response: [AnyHashable : Any]){ let alertController = UIAlertController(title: "FAILURE", message: str, preferredStyle: UIAlertControllerStyle.alert) let cancelAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.cancel, handler: nil) alertController.addAction(cancelAction) //self.view = view that controller manages self.view.sendSubview(toBack: self.webView) navBar.isHidden = true navBar.isUserInteractionEnabled = false self.view.window?.rootViewController?.present(alertController, animated: true, completion: nil) self.razorpay = nil } func onPaymentSuccess(_ payment_id: String, andData response: [AnyHashable : Any]){ let alertController = UIAlertController(title: "SUCCESS", message: "Payment Id \(payment_id)", preferredStyle: UIAlertControllerStyle.alert) let cancelAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.cancel, handler: nil) alertController.addAction(cancelAction) //self.view = view that controller manages self.view.sendSubview(toBack: self.webView) navBar.isHidden = true navBar.isUserInteractionEnabled = false self.view.window?.rootViewController?.present(alertController, animated: true, completion: nil) self.razorpay = nil } //MARK: Action functions @IBAction func cancel(_ sender: Any){ let alertController = UIAlertController(title: "Cancel Transaction", message: "Are you sure you want to cancel the current transaciton ? You will be taken back to checkout page, where you can choose another payment option", preferredStyle: UIAlertControllerStyle.alert) let cancelAction = UIAlertAction(title: "Do Not Cancel", style: UIAlertActionStyle.cancel, handler: nil) let okayAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.destructive, handler: { action in self.razorpay.userCancelledPayment() } ) alertController.addAction(cancelAction) alertController.addAction(okayAction) self.view.window?.rootViewController?.present(alertController, animated: true, completion: nil) }
Copy - (void)onPaymentError:(int)code description:(nonnull NSString *)str andData:(NSDictionary *)response { [self.view sendSubviewToBack:webView]; navbar.hidden = true; navbar.userInteractionEnabled = false; razorpay = nil; [[[UIAlertView alloc] initWithTitle:@"Error" message:str delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; } - (void)onPaymentSuccess:(nonnull NSString *)payment_id andData:(NSDictionary *)response { [self.view sendSubviewToBack:webView]; navbar.hidden = true; navbar.userInteractionEnabled = false; razorpay = nil; [[[UIAlertView alloc] initWithTitle:@"Payment Successful" message:payment_id delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; } -(void) cancel:(id)sender{ [[[UIAlertView alloc] initWithTitle:@"Payment Cancelled" message:@"You cancelled the payment. Please retry or let us know at your-help-email@your-domain.com in case of any difficulty." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil] show]; [self onPaymentError:-1 description:@"User Cancelled Payment" andData:@{}]; [razorpay userCancelledPayment]; }

Success handler receives a payment_id that you can use later to capture the payment.

A relevant description is provided the case of a failure.

iOS 9 Update#

iOS 9 has higher requirements for secure URLs. As many Indian banks do not comply with the requirements, you can implement the following as a workaround:

Copy <key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>

Add the above to your info.plist file. For more information click here.