Skip to content

Commit

Permalink
updated types and added validations
Browse files Browse the repository at this point in the history
  • Loading branch information
ankitdas13 committed Feb 11, 2025
1 parent 7df5b22 commit cbec7c6
Show file tree
Hide file tree
Showing 5 changed files with 244 additions and 30 deletions.
131 changes: 131 additions & 0 deletions lib/oAuthTokenClient.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import API, { INormalizeError } from "./types/api"

declare namespace OAuthTokenClient {

interface OAuthTokenBaseRequestBody {
/**
* Unique client identifier.
*/
client_id: string;
/**
* Client secret string.
*/
client_secret: string;
}

interface InitiateAuthorisationRequest extends Pick<OAuthTokenBaseRequestBody, 'client_id'>{
/**
* Specifies that the application is requesting an
* authorisation code grant. possible value is `code`.
*/
response_type: string;
/**
* Callback URL used by Razorpay to redirect after the user approves or denies the authorisation request.
* The client should whitelist the `redirect_uri`.
*/
redirect_uri: string;
/**
* Defines what access your application is requesting from the user. You can request multiple scopes
* by separating with a space.
* possible values is `read_only` or `read_write`.
*/
scope: string;
/**
* Check [doc](https://razorpay.com/docs/partners/technology-partners/onboard-businesses/integrate-oauth/integration-steps/#query-parameters) for required params
*/
state: string;
}

interface OAuthTokenTokenRequest extends OAuthTokenBaseRequestBody {
/**
* Defines the grant type for the request. possible value is `authorization_code`
*/
grant_type: string;
/**
* Specifies the same `redirect_uri` used in the authorisation request.
*/
redirect_uri?: string;
/**
* Decoded authorisation code received in the last step.
*/
code?: string;
/**
* The type of mode. possible values is `test` or `live`.
*/
mode?: string;
/**
* Used to refresh the access token when it expires.
*/
refresh_token?: string;
/**
* The type of token for the request. possible value is `access_token` or `access_token`.
*/
token_type_hint?: string;
/**
* The token whose access should be revoked.
*/
token?: string;
}

interface OAuthTokenTokenResponse {
/**
* A public key is used only for public routes such as Checkout or Payments.
*/
public_token: string;
/**
* Defines the type of access token. possible value is `Bearer`
*/
token_type: string;
/**
* Integer representing the TTL of the access token in seconds.
*/
expires_in: number;
/**
* A private key used to access sub-merchant resources on Razorpay.
* used for server-to-server calls only.
*/
access_token: string;
/**
* Used to refresh the access token when it expires.
*/
refresh_token:string;
/**
* Identifies the sub-merchant ID who granted the authorisation.
*/
razorpay_account_id: string;
}
}

declare class OAuthTokenClient extends API{
constructor()

getEntityUrl(): string;
/**
* Initiate Authorisation Using URL
* @param param - Check [doc](https://razorpay.com/docs/partners/technology-partners/onboard-businesses/integrate-oauth/integration-steps/#query-parameters) for required params
*/
generateAuthUrl(param: OAuthTokenClient.InitiateAuthorisationRequest): string;

/**
* Get access token
* @param param - Check [doc](https://razorpay.com/docs/partners/technology-partners/onboard-businesses/integrate-oauth/integration-steps/#request-parameters) for required params
*/
getAccessToken(param: OAuthTokenClient.OAuthTokenTokenRequest): Promise<OAuthTokenClient.OAuthTokenTokenResponse>;
getAccessToken(param: OAuthTokenClient.OAuthTokenTokenRequest, callback: (err: INormalizeError | null, data: OAuthTokenClient.OAuthTokenTokenResponse) => void): void

/**
* Get refresh token
* @param param - Check [doc](https://razorpay.com/docs/partners/technology-partners/onboard-businesses/integrate-oauth/integration-steps/#refresh-token-api) for required params
*/
refreshToken(param: OAuthTokenClient.OAuthTokenTokenRequest): Promise<OAuthTokenClient.OAuthTokenTokenResponse>;
refreshToken(param: OAuthTokenClient.OAuthTokenTokenRequest, callback: (err: INormalizeError | null, data: OAuthTokenClient.OAuthTokenTokenResponse) => void): void

/**
* Revoke token
* @param param - Check [doc](https://razorpay.com/docs/partners/technology-partners/onboard-businesses/integrate-oauth/integration-steps/#revoke-token-api) for required params
*/
revokeToken(param: OAuthTokenClient.OAuthTokenTokenRequest): Promise<{ message: string;}>;
revokeToken(param: OAuthTokenClient.OAuthTokenTokenRequest, callback: (err: INormalizeError | null, data: { message: string;}) => void): void
}

export = OAuthTokenClient
68 changes: 57 additions & 11 deletions lib/oAuthTokenClient.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,51 @@
const API = require('./api');
const pkg = require('../package.json')

const SCHEMAS = {
generateAuthUrl: {
client_id: "client_id is empty",
response_type: "response_type is empty",
redirect_uri: "redirect_uri is empty",
scope: "scope is empty",
state: "state is empty",
},
getAccessToken: {
client_id: "client_id is empty",
client_secret: "client_secret is empty",
grant_type: "grant_type is empty",
redirect_uri: "redirect_uri is empty",
code: "code is empty",
},
refreshToken: {
client_id: "client_id is empty",
client_secret: "client_secret is empty",
grant_type: "grant_type is empty",
refresh_token: "refresh_token is empty",
},
revokeToken: {
client_id: "client_id is empty",
client_secret: "client_secret is empty",
token_type_hint: "token_type_hint is empty",
token: "token is empty",
},
};

class OAuthTokenClient extends API{

constructor(options) {
constructor() {
super({
hostUrl : 'https://auth.razorpay.com',
ua: `razorpay-node@${pkg.version}`,
...options
})
}

getEntityUrl(params){
return params.url ;
}

generateAuthUrl(params) {
generateAuthUrl(params) {
const errors = this.validateInput(params, SCHEMAS.generateAuthUrl);
if (Object.keys(errors).length > 0) return errors;
const baseUrl = `${this.rq.defaults.baseURL}/authorize`;
const queryString = Object.entries(params)
.map(([key, value]) => key === "redirect_uri"
Expand All @@ -25,26 +55,42 @@ class OAuthTokenClient extends API{
return `${baseUrl}?${queryString}`;
}

getAccessToken(param = {}, callback){
getAccessToken(params = {}, callback){
const errors = this.validateInput(params, SCHEMAS.getAccessToken);
if (Object.keys(errors).length > 0) return Promise.reject(errors);
return this.post({
url: '/token',
data: param
data: params
}, callback)
}

refreshToken(param = {}, callback){
refreshToken(params = {}, callback){
const errors = this.validateInput(params, SCHEMAS.refreshToken);
if (Object.keys(errors).length > 0) return Promise.reject(errors);
return this.post({
url: '/token',
data: param
data: params
}, callback)
}

revokeToken(param = {}, callback){
return this.patch({
url: '/token',
data: param
revokeToken(params = {}, callback){
const errors = this.validateInput(params, SCHEMAS.revokeToken);
if (Object.keys(errors).length > 0) return Promise.reject(errors);
return this.post({
url: '/revoke',
data: params
}, callback)
}

validateInput(inputData, schema) {
let errors = {};
for (let field in schema) {
if (!(field in inputData) || inputData[field].trim() === "") {
errors[field] = schema[field];
}
}
return errors;
}
}

module.exports = OAuthTokenClient
3 changes: 2 additions & 1 deletion lib/razorpay.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ import documents from './types/documents'
import disputes from './types/disputes'

interface IRazorpayConfig {
key_id: string;
key_id?: string;
key_secret?: string;
headers?: RazorpayHeaders;
oauthToken?: string;
}

declare class Razorpay {
Expand Down
14 changes: 8 additions & 6 deletions lib/types/api.d.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import nodeify from '../utils/nodeify'

interface IOption {
hostUrl: string;
key_id: string;
key_secret?: string;
ua: string;
headers?: string;

interface IOption {
key_id?: string;
key_secret?: string;
headers?: RazorpayHeaders;
oauthToken?: string;
hostUrl: string;
ua: string;
}

interface IPayload<T> {
Expand Down
58 changes: 46 additions & 12 deletions test/oAuthTokenClient.spec.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"use strict";

const mocker = require("./mocker");
const OAuthTokenClient = require("../dist/oAuthTokenClient");
const OAuthTokenClient = require("../lib/oAuthTokenClient");
const { assert } = require("chai");
const { error } = require("console");

describe("OAuth", () => {
let rzpHost;
Expand Down Expand Up @@ -43,11 +44,46 @@ describe("OAuth", () => {
assert.equal(
response.__JUST_FOR_TESTS__.capturedUrl,
`${mocker.host}/token`,
"Fetch stakeholder url formed correctly"
"Access token url formed correctly"
);
done();
})
.catch((err) => console.log(err));
});

it("get access token with invalid param", (done) => {
let params = {
client_id: "XXXXXXXXXXkQ5C",
client_secret: "XXXXXXXXXXXXXXXXXXHx7rXX",
grant_type: "authorization_code",
};

mocker.mock({
url: `/token`,
method: "POST",
requestBody: params,
});

oAuth
.getAccessToken(params)
.catch(err=>{
console.log('getAccessToken', err)
assert.hasAllKeys(err, ['redirect_uri', 'code']);
done();
})
});

it("refresh access token with invalid param", (done) => {
mocker.mock({
url: `/token`,
method: "POST",
});

oAuth
.refreshToken()
.catch((err) => {
assert.hasAnyKeys(err, ['client_id'])
done();
})
});

it("refresh access token", (done) => {
Expand All @@ -70,24 +106,23 @@ describe("OAuth", () => {
assert.equal(
response.__JUST_FOR_TESTS__.capturedUrl,
`${mocker.host}/token`,
"Fetch stakeholder url formed correctly"
"Refresh access token url formed correctly"
);
done();
})
.catch((err) => console.log(err));
});

it("revoke access token", (done) => {
let params = {
client_id: "XXXXXXXXXXkQ5C",
client_secret: "XXXXXXXXXXXXXXXXXXHx7rXX",
grant_type: "refresh_token",
refresh_token: "def5020096e1c470c901d34cd60fa53abdaf3662sa0",
token_type_hint: "access_token",
token: "def5020096e1c470c901d34cd60fa53abdaf3662sa0",
};

mocker.mock({
url: `/token`,
method: "PATCH",
url: `/revoke`,
method: "POST",
requestBody: params,
});

Expand All @@ -96,11 +131,10 @@ describe("OAuth", () => {
.then((response) => {
assert.equal(
response.__JUST_FOR_TESTS__.capturedUrl,
`${mocker.host}/token`,
"Fetch stakeholder url formed correctly"
`${mocker.host}/revoke`,
"Revoke access token url formed correctly"
);
done();
})
.catch((err) => console.log(err));
});
});

0 comments on commit cbec7c6

Please sign in to comment.