Skip to content

Commit

Permalink
Wrapper for OAuth URLs (#242)
Browse files Browse the repository at this point in the history
* Adding wrapper for oauth urls & updating auth mechanism

* code for generating onboarding signature

* Documentation udpate

* Adding test cases for razorpay setup

* Adding validations & test cases

* adding test cases

* Update oauth_token.md

* Updating documentation

* Update validation_config.rb
  • Loading branch information
bhavyay authored Apr 16, 2024
1 parent 9423e2b commit 45718c1
Show file tree
Hide file tree
Showing 15 changed files with 661 additions and 10 deletions.
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ Ruby 2.6.8 or later

Remember to `require 'razorpay'` before anything else.

Next, you need to setup your key and secret using the following:
Next, you need to setup your auth details. This setup can be done via two ways:

### Using Private Auth

you need to setup your key and secret using the following:

```rb
Razorpay.setup('key_id', 'key_secret')
Expand All @@ -38,6 +42,16 @@ You can set customer headers for your requests using the following:
Razorpay.headers = {"CUSTOM_APP_HEADER" => "CUSTOM_VALUE"}
```

### Using Access Token
you need to setup your access token using the following
```rb
Razorpay.setup_with_oauth('access_token')
```
You can set customer headers for your requests using the following:
```rb
Razorpay.headers = {"CUSTOM_APP_HEADER" => "CUSTOM_VALUE"}
```

You can find your API keys at <https://dashboard.razorpay.com/#/app/keys>.

If you are using rails, the right place to do this might be `config/initializers/razorpay.rb`.
Expand Down Expand Up @@ -70,6 +84,7 @@ If you are using rails, the right place to do this might be `config/initializers
- [Register NACH and Charge First Payment Together](documents/registerNach.md)
- [Payment Verification](documents/paymentVerification.md)
- [Webhook](documents/webhook.md)
- [OAuthToken](documents/oauth_token.md)

## Development

Expand Down
142 changes: 142 additions & 0 deletions documents/oauth_token.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
### OAuthToken

```rb
require "razorpay"
```

### Generate Authorize Url
```rb
body = {
submerchant_id: '<SUBMERCHANT_MID>',
timestamp: Time.now.to_i
}
onboarding_signature = Razorpay::Utility.generate_onboarding_signature(body, '<YOUR_CLIENT_SECRET>')

options = {
'client_id' => '<YOUR_CLIENT_ID>',
'redirect_uri' => 'https://example.com/razorpay_callback',
'scopes' => ["read_write"],
'state' => 'NOBYtv8r6c75ex6WZ',
'onboarding_signature' => onboarding_signature
}
authorize_url = Razorpay::OAuthToken.get_auth_url(options)
```

**Parameters:**

| Name | Type | Description |
|----------------------|--------|---------------------------------------------------------------------------------------------------------------------------------------------------------|
| client_id* | string | Unique client identifier. |
| redirect_uri* | string | Callback URL used by Razorpay to redirect after the user approves or denies the authorisation request. The client should whitelist the 'redirect_uri'. |
| scopes* | array | Defines what access your application is requesting from the user. You can request one or multiple scopes by adding them to an array as indicated above. |
| state* | string | A random string generated by your service. This parameter helps prevent cross-site request forgery (CSRF) attacks. |
| onboarding_signature | string | A cryptographic string generated by your service using generateOnboardingSignature method in Utils class. Only applicable for accounts created with pre-fill KYC |

**Response:**
```
"https://auth.razorpay.com/authorize?response_type=code&client_id=<YOUR_CLIENT_ID>&redirect_uri=https:%2F%2Fexample.com%2Frazorpay_callback&scope[]=read_only&scope[]=rx_read_write&state=NOBYtv8r6c75ex6WZ&onboarding_signature=<GENERATED_ONBOARDING_SIGNATURE>"
```

-------------------------------------------------------------------------------------------------------
### Get Access token
```rb
options = {
'client_id' => '<YOUR_CLIENT_ID>',
'client_secret' => '<YOUR_CLIENT_SECRET>',
'redirect_uri' => 'https://example.com/razorpay_callback',
'grant_type' => 'authorization_code',
'code' => '<AUTHORIZATION_CODE>',
'mode' => 'test'
}
oauth_token = Razorpay::OAuthToken.get_access_token(options)
```

**Parameters:**

| Name | Type | Description |
|----------------|--------|------------------------------------------------------------------------------------------------------------------------------|
| client_id* | string | Unique client identifier. |
| client_secret* | string | Client secret string. |
| redirect_uri* | string | Specifies the same redirect_uri used in the authorisation request. |
| grant_type* | string | Defines the grant type for the request. Possible value are:<ul><li>authorization_code</li><li>client_credentials</li></ul> |
| code* | string | Decoded authorisation code received in the last step. Note: Pass this parameter only when grant_type is 'authorization_code' |
| mode | string | The type of mode. Possible values: <ul><li>test</li><li>live (default)</li></ul> |

**Response:**
```json
{
"public_token": "rzp_test_oauth_9xu1rkZqoXlClS",
"token_type": "Bearer",
"expires_in": 7862400,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IkY1Z0NQYkhhRzRjcUpnIn0.eyJhdWQiOiJGNFNNeEgxanMxbkpPZiIsImp0aSI6IkY1Z0NQYkhhRzRjcUpnIiwiaWF0IjoxNTkyODMxMDExLCJuYmYiOjE1OTI4MzEwMTEsInN1YiI6IiIsImV4cCI6MTYwMDc3OTgxMSwidXNlcl9pZCI6IkYycVBpejJEdzRPRVFwIiwibWVyY2hhbnRfaWQiOiJGMnFQaVZ3N0lNV01GSyIsInNjb3BlcyI6WyJyZWFkX29ubHkiXX0.Wwqt5czhoWpVzP5_aoiymKXoGj-ydo-4A_X2jf_7rrSvk4pXdqzbA5BMrHxPdPbeFQWV6vsnsgbf99Q3g-W4kalHyH67LfAzc3qnJ-mkYDkFY93tkeG-MCco6GJW-Jm8xhaV9EPUak7z9J9jcdluu9rNXYMtd5qxD8auyRYhEgs",
"refresh_token": "def50200f42e07aded65a323f6c53181d802cc797b62cc5e78dd8038d6dff253e5877da9ad32f463a4da0ad895e3de298cbce40e162202170e763754122a6cb97910a1f58e2378ee3492dc295e1525009cccc45635308cce8575bdf373606c453ebb5eb2bec062ca197ac23810cf9d6cf31fbb9fcf5b7d4de9bf524c89a4aa90599b0151c9e4e2fa08acb6d2fe17f30a6cfecdfd671f090787e821f844e5d36f5eacb7dfb33d91e83b18216ad0ebeba2bef7721e10d436c3984daafd8654ed881c581d6be0bdc9ebfaee0dc5f9374d7184d60aae5aa85385690220690e21bc93209fb8a8cc25a6abf1108d8277f7c3d38217b47744d7",
"razorpay_account_id": "acc_Dhk2qDbmu6FwZH"
}
```

-------------------------------------------------------------------------------------------------------

### Get Access token using refresh token
```rb
options = {
'client_id' => '<YOUR_CLIENT_ID>',
'client_secret' => '<YOUR_CLIENT_SECRET>',
'refresh_token' => 'def5020096e1c470c901d34cd60fa53abdaf3662sa0'
}
oauth_token = Razorpay::OAuthToken.refresh_token(options)
```

**Parameters:**

| Name | Type | Description |
|----------------|-----------|--------------------------------------------|
| client_id* | string | Unique client identifier. |
| client_secret* | string | Client secret string. |
| refresh_token* | string | The previously-stored refresh token value. |

**Response:**
```json
{
"public_token": "rzp_test_oauth_9xu1rkZqoXlClS",
"token_type": "Bearer",
"expires_in": 7862400,
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6Ijl4dTF",
"refresh_token": "def5020096e1c470c901d34cd60fa53abdaf36620e823ffa53"
}
```

-------------------------------------------------------------------------------------------------------

### Revoke a token
```rb
options = {
'client_id' => '<YOUR_CLIENT_ID>',
'client_secret' => '<YOUR_CLIENT_SECRET>',
'token' => 'def5020096e1c470c901d34cd60fa53abdaf36620e823ffa53'
'token_type_hint' => 'access_token'
}
response = Razorpay::OAuthToken.revoke_token(options)
```

**Parameters:**

| Name | Type | Description |
|------------------|----------|----------------------------------------------------------------------------------------------------------|
| client_id* | string | Unique client identifier. |
| client_secret* | string | Client secret string. |
| token_type_hint* | string | The type of token for the request. Possible values: <ul><li>access_token</li><li>refresh_token</li></ul> |
| token* | string | The token whose access should be revoked. |

**Response:**
```json
{
"message": "Token Revoked"
}
```
-------------------------------------------------------------------------------------------------------

**PN: * indicates mandatory fields**
<br>
<br>
**For reference click [here](https://razorpay.com/docs/partners/platform/onboard-businesses/integrate-oauth/integration-steps)**

9 changes: 8 additions & 1 deletion lib/razorpay.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,22 @@
require 'razorpay/product'
require 'razorpay/stakeholder'
require 'razorpay/account'
require 'razorpay/oauth_token'

# Base Razorpay module
module Razorpay
class << self
attr_accessor :auth, :custom_headers
attr_accessor :auth, :custom_headers, :access_token, :auth_type
end

def self.setup(key_id, key_secret)
self.auth = { username: key_id, password: key_secret }
self.auth_type = Razorpay::PRIVATE_AUTH
end

def self.setup_with_oauth(access_token)
self.access_token = access_token
self.auth_type = Razorpay::OAUTH
end

def self.headers=(headers = {})
Expand Down
7 changes: 6 additions & 1 deletion lib/razorpay/constants.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,10 @@
module Razorpay
BASE_URI = 'https://api.razorpay.com'.freeze
TEST_URL = 'https://api.razorpay.com/'.freeze
VERSION = '3.2.1'.freeze
VERSION = '3.2.1'.freeze
AUTH_URL = 'https://auth.razorpay.com'.freeze
API_HOST = 'API'.freeze
AUTH_HOST = 'AUTH'.freeze
PRIVATE_AUTH = 'Private'.freeze
OAUTH = 'OAuth'.freeze
end
109 changes: 109 additions & 0 deletions lib/razorpay/oauth_token.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
require 'razorpay/request'
require 'razorpay/entity'
require 'razorpay/payload_validator'
require 'razorpay/validation_config'

module Razorpay
# OAuth APIs allow to you create and manage access tokens
class OAuthToken < Entity
def self.request
Razorpay::Request.new('token', Razorpay::AUTH_HOST)
end

def self.get_auth_url(options)
validate_auth_url_request(options)
uri = URI.join(Razorpay::AUTH_URL, '/authorize')

query_params = {
'response_type' => 'code',
'client_id' => options['client_id'],
'redirect_uri' => options['redirect_uri'],
'state' => options['state']
}

options['scopes'].each { |scope| query_params["scope[]"] = scope }

if options.has_key?('onboarding_signature')
query_params['onboarding_signature'] = options['onboarding_signature']
end
uri.query = URI.encode_www_form(query_params)
uri.to_s
end

def self.get_access_token(options)
validate_access_token_request(options)
r = request
r.request :post, "/token", options
end

def self.refresh_token(options)
options['grant_type'] = 'refresh_token'
validate_refresh_token_request(options)
r = request
r.request :post, "/token", options
end

def self.revoke_token(options)
validate_revoke_token_request(options)
r = request
r.request :post, "/revoke", options
end

class << self

private

def validate_auth_url_request(options)
Razorpay::PayloadValidator.validate(options, get_validations_for_auth_request_url)
end

def validate_access_token_request(options)
Razorpay::PayloadValidator.validate(options, get_validations_for_access_token_request)
end

def validate_refresh_token_request(options)
Razorpay::PayloadValidator.validate(options, get_validations_for_refresh_token_request)
end

def validate_revoke_token_request(options)
Razorpay::PayloadValidator.validate(options, get_validations_for_revoke_token_request)
end

def get_validations_for_auth_request_url
[
Razorpay::ValidationConfig.new('client_id', [:id]),
Razorpay::ValidationConfig.new('redirect_uri', [:non_empty_string, :url]),
Razorpay::ValidationConfig.new('scopes', [:non_null]),
Razorpay::ValidationConfig.new('state', [:non_empty_string])
]
end

def get_validations_for_access_token_request
[
Razorpay::ValidationConfig.new('client_id', [:id]),
Razorpay::ValidationConfig.new('client_secret', [:non_empty_string]),
Razorpay::ValidationConfig.new('redirect_uri', [:non_empty_string, :url]),
Razorpay::ValidationConfig.new('grant_type', [:token_grant])
]
end

def get_validations_for_refresh_token_request
[
Razorpay::ValidationConfig.new('client_id', [:id]),
Razorpay::ValidationConfig.new('client_secret', [:non_empty_string]),
Razorpay::ValidationConfig.new('refresh_token', [:non_empty_string]),
Razorpay::ValidationConfig.new('grant_type', [:token_grant])
]
end

def get_validations_for_revoke_token_request
[
Razorpay::ValidationConfig.new('client_id', [:id]),
Razorpay::ValidationConfig.new('client_secret', [:non_empty_string]),
Razorpay::ValidationConfig.new('token', [:non_empty_string]),
Razorpay::ValidationConfig.new('token_type_hint', [:non_empty_string])
]
end
end
end
end
Loading

0 comments on commit 45718c1

Please sign in to comment.