Last active
May 15, 2023 15:12
-
-
Save sagrawal31/3471820b4f58024990cf888ae4c87377 to your computer and use it in GitHub Desktop.
Angular & Typescript wrapper around Razorpay checkout to be quickly used in any Angular/Ionic application
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Example component file | |
*/ | |
import {Component, NgZone} from '@angular/core'; | |
import {RazorpayWrapper} from '../utils/razorpay/wrapper'; | |
@Component({ | |
selector: 'app-home', | |
templateUrl: 'home.page.html', | |
styleUrls: ['home.page.scss'] | |
}) | |
export class HomePage { | |
constructor(private ngZone: NgZone) { | |
} | |
async init() { | |
const wrapper = new RazorpayWrapper(this.ngZone); | |
const options = { | |
description: 'Foo Description', | |
key: 'rzp_test_key', // Change this | |
order_id: 'order_EGuCtoQhdlJLIf', // Change this | |
amount: 100, | |
name: 'Foo', | |
prefill: { | |
email: '[email protected]', | |
contact: '9876543210', | |
name: 'Shashank Agrawal' | |
} | |
}; | |
try { | |
const data = await wrapper.open(options); | |
console.log(data); | |
} catch (e) { | |
console.error(e); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export interface RazorpayOption { | |
name: string; | |
description?: string; | |
key: string; | |
order_id: string; | |
amount: number; | |
prefill: RazorpayPrefill; | |
modal: any; | |
notes?: any; | |
theme?: any; | |
external?: RazorpayExternalOption; | |
handler?: (response: any) => void; | |
} | |
export interface RazorpayExternalOption { | |
wallets: Array<string>; | |
handler: (response: any) => void; | |
} | |
export interface RazorpayPrefill { | |
email?: string; | |
contact?: string; | |
name?: string; | |
method?: 'card' | 'netbanking' | 'wallet' | 'emi' | 'upi'; | |
} | |
export interface RazorpayResponse { | |
razorpay_payment_id: string; | |
razorpay_order_id: string; | |
razorpay_signature: string; | |
} | |
export interface RazorpayError { | |
code: number; | |
description: string; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import {NgZone} from '@angular/core'; | |
import {RazorpayOption} from './models'; | |
/** | |
* A TypeScript and Angular wrapper around the JavaScript layer of Razorpay integration. | |
* Copied and modified from https://github.com/razorpay/razorpay-cordova/blob/master/src/browser/CheckoutProxy.js | |
* | |
* @author Shashank Agrawal | |
*/ | |
export class RazorpayWrapper { | |
private readonly SCRIPT_ID = 'rzp-js-sdk'; | |
private scriptElement: HTMLScriptElement; | |
/** | |
* @param ngZone Angular's instance of {@link NgZone} to run the resolve() & reject() operations in the context of Angular. | |
*/ | |
constructor(private ngZone: NgZone) { | |
} | |
/** | |
* Inject the script https://checkout.razorpay.com/v1/checkout.js in the <head> tag if not already. | |
* | |
* @returns a promise which will be resolved when the script is injected and loaded completely. | |
*/ | |
private injectRZPScript(): Promise<any> { | |
this.scriptElement = document.getElementById(this.SCRIPT_ID) as HTMLScriptElement; | |
if (this.scriptElement) { | |
return; | |
} | |
this.scriptElement = document.createElement('script'); | |
this.scriptElement.id = this.SCRIPT_ID; | |
const promise = new Promise((resolve, reject) => { | |
this.scriptElement.onload = () => { | |
this.ngZone.run(() => { | |
resolve(); | |
}); | |
}; | |
this.scriptElement.onerror = () => { | |
this.ngZone.run(() => { | |
reject({code: 0, description: 'Network error'}); | |
}); | |
}; | |
}); | |
this.scriptElement.src = 'https://checkout.razorpay.com/v1/checkout.js'; | |
document.head.appendChild(this.scriptElement); | |
return promise; | |
} | |
/** | |
* Open the Razorypay modal and show the payment options. | |
* | |
* @param options different options to be passed to Razorpay. | |
* @returns a promise which will be resolved on successful payment. Rejected if the modal is closed by the user or payment fails. | |
*/ | |
private openRZP(options: RazorpayOption): Promise<any> { | |
options.modal = options.modal || {}; | |
const promise = new Promise((resolve, reject) => { | |
options.modal.ondismiss = () => { | |
this.ngZone.run(() => { | |
reject({code: 2, description: 'Payment cancelled by user'}); | |
}); | |
}; | |
options.handler = (response) => { | |
this.ngZone.run(() => { | |
resolve(response); | |
}); | |
}; | |
if (options.external && options.external.wallets && options.external.wallets.length) { | |
options.external.handler = (response) => { | |
response.external_wallet_name = response.wallet; | |
this.ngZone.run(() => { | |
reject(response); | |
}); | |
}; | |
} | |
}); | |
const Razorpay = (window as any).Razorpay; | |
new Razorpay(options).open(); | |
return promise; | |
} | |
/** | |
* Entry point for the Razorpay standard checkout option. This will inject the checkout.js script (if not already) and then | |
* initiates the payment modal. | |
* | |
* @param options different options to be passed to Razorpay. | |
* @returns a promise which will be resolved on successful payment. Rejected if the modal is closed by the user or payment fails. | |
*/ | |
async open(options: RazorpayOption): Promise<any> { | |
const Razorpay = (window as any).Razorpay; | |
if (!Razorpay) { | |
await this.injectRZPScript(); | |
} | |
return await this.openRZP(options); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Glad you liked it @rohanrajpal!