razorpay 3.2.0 → 3.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +1 -1
- data/CHANGELOG.md +11 -0
- data/README.md +16 -2
- data/documents/oauth_token.md +142 -0
- data/lib/razorpay/constants.rb +6 -27
- data/lib/razorpay/oauth_token.rb +109 -0
- data/lib/razorpay/payload_validator.rb +93 -0
- data/lib/razorpay/request.rb +24 -13
- data/lib/razorpay/utility.rb +24 -0
- data/lib/razorpay/validation_config.rb +11 -0
- data/lib/razorpay.rb +8 -2
- data/test/fixtures/fake_oauth_token.json +8 -0
- data/test/fixtures/fake_revoke_token.json +3 -0
- data/test/razorpay/test_oauth_token.rb +105 -0
- data/test/razorpay/test_payload_validator.rb +61 -0
- data/test/razorpay/test_razorpay.rb +17 -0
- data/test/razorpay/test_utility.rb +34 -0
- metadata +14 -6
- data/documents/generic.md +0 -150
- data/lib/razorpay/generic.rb +0 -39
- data/test/razorpay/test_generic.rb +0 -112
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0f1899756cb2c34271a9cd8167029bb2aa56d3a07094df776feab8de024aa69b
|
4
|
+
data.tar.gz: daf3f8a28f3d5f211a1f83de9772d4f71fa3aa8b0b415bb0731846930584e11a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9458dcd7356a9017800f5ec4cdae747f17e4595ab7b9f194cb8f14c617f41b8c077497b4438afbd559ecd2f6c0f580f4de5ca5935ed7d7aa6de05679e27be535
|
7
|
+
data.tar.gz: 3377a46637db6e97d2c2435818de9d8b4782aac20d72adf4721e149c9fff2b7fbe41a83a0374090d2556cec2b996438160850d95ffa3b7f0d92a6f99d22aa024
|
data/.github/workflows/ruby.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,17 @@ Changelog for Razorpay-Ruby SDK.
|
|
4
4
|
|
5
5
|
## Unreleased
|
6
6
|
|
7
|
+
## [3.2.2] - 2024-04-16
|
8
|
+
|
9
|
+
feat: Added oauth APIs and support for access token based authentication mechanism
|
10
|
+
* Added oauth APIs (getAuthURL, getAccessToken, refreshToken, revokeToken)
|
11
|
+
* Added support for access token based authentication mechanism
|
12
|
+
* Added support for onboarding signature generation
|
13
|
+
|
14
|
+
## [3.2.1] - 2023-12-19
|
15
|
+
|
16
|
+
Rollback: Generic access point due to some performance concern
|
17
|
+
|
7
18
|
## [3.2.0] - 2023-12-11
|
8
19
|
|
9
20
|
feat: Added generic access point
|
data/README.md
CHANGED
@@ -27,7 +27,11 @@ Ruby 2.6.8 or later
|
|
27
27
|
|
28
28
|
Remember to `require 'razorpay'` before anything else.
|
29
29
|
|
30
|
-
Next, you need to setup your
|
30
|
+
Next, you need to setup your auth details. This setup can be done via two ways:
|
31
|
+
|
32
|
+
### Using Private Auth
|
33
|
+
|
34
|
+
you need to setup your key and secret using the following:
|
31
35
|
|
32
36
|
```rb
|
33
37
|
Razorpay.setup('key_id', 'key_secret')
|
@@ -38,6 +42,16 @@ You can set customer headers for your requests using the following:
|
|
38
42
|
Razorpay.headers = {"CUSTOM_APP_HEADER" => "CUSTOM_VALUE"}
|
39
43
|
```
|
40
44
|
|
45
|
+
### Using Access Token
|
46
|
+
you need to setup your access token using the following
|
47
|
+
```rb
|
48
|
+
Razorpay.setup_with_oauth('access_token')
|
49
|
+
```
|
50
|
+
You can set customer headers for your requests using the following:
|
51
|
+
```rb
|
52
|
+
Razorpay.headers = {"CUSTOM_APP_HEADER" => "CUSTOM_VALUE"}
|
53
|
+
```
|
54
|
+
|
41
55
|
You can find your API keys at <https://dashboard.razorpay.com/#/app/keys>.
|
42
56
|
|
43
57
|
If you are using rails, the right place to do this might be `config/initializers/razorpay.rb`.
|
@@ -70,7 +84,7 @@ If you are using rails, the right place to do this might be `config/initializers
|
|
70
84
|
- [Register NACH and Charge First Payment Together](documents/registerNach.md)
|
71
85
|
- [Payment Verification](documents/paymentVerification.md)
|
72
86
|
- [Webhook](documents/webhook.md)
|
73
|
-
- [
|
87
|
+
- [OAuthToken](documents/oauth_token.md)
|
74
88
|
|
75
89
|
## Development
|
76
90
|
|
@@ -0,0 +1,142 @@
|
|
1
|
+
### OAuthToken
|
2
|
+
|
3
|
+
```rb
|
4
|
+
require "razorpay"
|
5
|
+
```
|
6
|
+
|
7
|
+
### Generate Authorize Url
|
8
|
+
```rb
|
9
|
+
body = {
|
10
|
+
submerchant_id: '<SUBMERCHANT_MID>',
|
11
|
+
timestamp: Time.now.to_i
|
12
|
+
}
|
13
|
+
onboarding_signature = Razorpay::Utility.generate_onboarding_signature(body, '<YOUR_CLIENT_SECRET>')
|
14
|
+
|
15
|
+
options = {
|
16
|
+
'client_id' => '<YOUR_CLIENT_ID>',
|
17
|
+
'redirect_uri' => 'https://example.com/razorpay_callback',
|
18
|
+
'scopes' => ["read_write"],
|
19
|
+
'state' => 'NOBYtv8r6c75ex6WZ',
|
20
|
+
'onboarding_signature' => onboarding_signature
|
21
|
+
}
|
22
|
+
authorize_url = Razorpay::OAuthToken.get_auth_url(options)
|
23
|
+
```
|
24
|
+
|
25
|
+
**Parameters:**
|
26
|
+
|
27
|
+
| Name | Type | Description |
|
28
|
+
|----------------------|--------|---------------------------------------------------------------------------------------------------------------------------------------------------------|
|
29
|
+
| client_id* | string | Unique client identifier. |
|
30
|
+
| 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'. |
|
31
|
+
| 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. |
|
32
|
+
| state* | string | A random string generated by your service. This parameter helps prevent cross-site request forgery (CSRF) attacks. |
|
33
|
+
| 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 |
|
34
|
+
|
35
|
+
**Response:**
|
36
|
+
```
|
37
|
+
"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>"
|
38
|
+
```
|
39
|
+
|
40
|
+
-------------------------------------------------------------------------------------------------------
|
41
|
+
### Get Access token
|
42
|
+
```rb
|
43
|
+
options = {
|
44
|
+
'client_id' => '<YOUR_CLIENT_ID>',
|
45
|
+
'client_secret' => '<YOUR_CLIENT_SECRET>',
|
46
|
+
'redirect_uri' => 'https://example.com/razorpay_callback',
|
47
|
+
'grant_type' => 'authorization_code',
|
48
|
+
'code' => '<AUTHORIZATION_CODE>',
|
49
|
+
'mode' => 'test'
|
50
|
+
}
|
51
|
+
oauth_token = Razorpay::OAuthToken.get_access_token(options)
|
52
|
+
```
|
53
|
+
|
54
|
+
**Parameters:**
|
55
|
+
|
56
|
+
| Name | Type | Description |
|
57
|
+
|----------------|--------|------------------------------------------------------------------------------------------------------------------------------|
|
58
|
+
| client_id* | string | Unique client identifier. |
|
59
|
+
| client_secret* | string | Client secret string. |
|
60
|
+
| redirect_uri* | string | Specifies the same redirect_uri used in the authorisation request. |
|
61
|
+
| grant_type* | string | Defines the grant type for the request. Possible value are:<ul><li>authorization_code</li><li>client_credentials</li></ul> |
|
62
|
+
| code* | string | Decoded authorisation code received in the last step. Note: Pass this parameter only when grant_type is 'authorization_code' |
|
63
|
+
| mode | string | The type of mode. Possible values: <ul><li>test</li><li>live (default)</li></ul> |
|
64
|
+
|
65
|
+
**Response:**
|
66
|
+
```json
|
67
|
+
{
|
68
|
+
"public_token": "rzp_test_oauth_9xu1rkZqoXlClS",
|
69
|
+
"token_type": "Bearer",
|
70
|
+
"expires_in": 7862400,
|
71
|
+
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IkY1Z0NQYkhhRzRjcUpnIn0.eyJhdWQiOiJGNFNNeEgxanMxbkpPZiIsImp0aSI6IkY1Z0NQYkhhRzRjcUpnIiwiaWF0IjoxNTkyODMxMDExLCJuYmYiOjE1OTI4MzEwMTEsInN1YiI6IiIsImV4cCI6MTYwMDc3OTgxMSwidXNlcl9pZCI6IkYycVBpejJEdzRPRVFwIiwibWVyY2hhbnRfaWQiOiJGMnFQaVZ3N0lNV01GSyIsInNjb3BlcyI6WyJyZWFkX29ubHkiXX0.Wwqt5czhoWpVzP5_aoiymKXoGj-ydo-4A_X2jf_7rrSvk4pXdqzbA5BMrHxPdPbeFQWV6vsnsgbf99Q3g-W4kalHyH67LfAzc3qnJ-mkYDkFY93tkeG-MCco6GJW-Jm8xhaV9EPUak7z9J9jcdluu9rNXYMtd5qxD8auyRYhEgs",
|
72
|
+
"refresh_token": "def50200f42e07aded65a323f6c53181d802cc797b62cc5e78dd8038d6dff253e5877da9ad32f463a4da0ad895e3de298cbce40e162202170e763754122a6cb97910a1f58e2378ee3492dc295e1525009cccc45635308cce8575bdf373606c453ebb5eb2bec062ca197ac23810cf9d6cf31fbb9fcf5b7d4de9bf524c89a4aa90599b0151c9e4e2fa08acb6d2fe17f30a6cfecdfd671f090787e821f844e5d36f5eacb7dfb33d91e83b18216ad0ebeba2bef7721e10d436c3984daafd8654ed881c581d6be0bdc9ebfaee0dc5f9374d7184d60aae5aa85385690220690e21bc93209fb8a8cc25a6abf1108d8277f7c3d38217b47744d7",
|
73
|
+
"razorpay_account_id": "acc_Dhk2qDbmu6FwZH"
|
74
|
+
}
|
75
|
+
```
|
76
|
+
|
77
|
+
-------------------------------------------------------------------------------------------------------
|
78
|
+
|
79
|
+
### Get Access token using refresh token
|
80
|
+
```rb
|
81
|
+
options = {
|
82
|
+
'client_id' => '<YOUR_CLIENT_ID>',
|
83
|
+
'client_secret' => '<YOUR_CLIENT_SECRET>',
|
84
|
+
'refresh_token' => 'def5020096e1c470c901d34cd60fa53abdaf3662sa0'
|
85
|
+
}
|
86
|
+
oauth_token = Razorpay::OAuthToken.refresh_token(options)
|
87
|
+
```
|
88
|
+
|
89
|
+
**Parameters:**
|
90
|
+
|
91
|
+
| Name | Type | Description |
|
92
|
+
|----------------|-----------|--------------------------------------------|
|
93
|
+
| client_id* | string | Unique client identifier. |
|
94
|
+
| client_secret* | string | Client secret string. |
|
95
|
+
| refresh_token* | string | The previously-stored refresh token value. |
|
96
|
+
|
97
|
+
**Response:**
|
98
|
+
```json
|
99
|
+
{
|
100
|
+
"public_token": "rzp_test_oauth_9xu1rkZqoXlClS",
|
101
|
+
"token_type": "Bearer",
|
102
|
+
"expires_in": 7862400,
|
103
|
+
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6Ijl4dTF",
|
104
|
+
"refresh_token": "def5020096e1c470c901d34cd60fa53abdaf36620e823ffa53"
|
105
|
+
}
|
106
|
+
```
|
107
|
+
|
108
|
+
-------------------------------------------------------------------------------------------------------
|
109
|
+
|
110
|
+
### Revoke a token
|
111
|
+
```rb
|
112
|
+
options = {
|
113
|
+
'client_id' => '<YOUR_CLIENT_ID>',
|
114
|
+
'client_secret' => '<YOUR_CLIENT_SECRET>',
|
115
|
+
'token' => 'def5020096e1c470c901d34cd60fa53abdaf36620e823ffa53'
|
116
|
+
'token_type_hint' => 'access_token'
|
117
|
+
}
|
118
|
+
response = Razorpay::OAuthToken.revoke_token(options)
|
119
|
+
```
|
120
|
+
|
121
|
+
**Parameters:**
|
122
|
+
|
123
|
+
| Name | Type | Description |
|
124
|
+
|------------------|----------|----------------------------------------------------------------------------------------------------------|
|
125
|
+
| client_id* | string | Unique client identifier. |
|
126
|
+
| client_secret* | string | Client secret string. |
|
127
|
+
| token_type_hint* | string | The type of token for the request. Possible values: <ul><li>access_token</li><li>refresh_token</li></ul> |
|
128
|
+
| token* | string | The token whose access should be revoked. |
|
129
|
+
|
130
|
+
**Response:**
|
131
|
+
```json
|
132
|
+
{
|
133
|
+
"message": "Token Revoked"
|
134
|
+
}
|
135
|
+
```
|
136
|
+
-------------------------------------------------------------------------------------------------------
|
137
|
+
|
138
|
+
**PN: * indicates mandatory fields**
|
139
|
+
<br>
|
140
|
+
<br>
|
141
|
+
**For reference click [here](https://razorpay.com/docs/partners/platform/onboard-businesses/integrate-oauth/integration-steps)**
|
142
|
+
|
data/lib/razorpay/constants.rb
CHANGED
@@ -2,31 +2,10 @@
|
|
2
2
|
module Razorpay
|
3
3
|
BASE_URI = 'https://api.razorpay.com'.freeze
|
4
4
|
TEST_URL = 'https://api.razorpay.com/'.freeze
|
5
|
-
VERSION
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
"payments" => "payment",
|
12
|
-
"customers" => "customer",
|
13
|
-
"plans" => "plan",
|
14
|
-
"virtual_accounts" => "virtualAccount",
|
15
|
-
"addons" => "addon",
|
16
|
-
"subscriptions" => "subscriptions",
|
17
|
-
"subscription_registrations" => "subscription_registrations",
|
18
|
-
"transfers" => "transfers",
|
19
|
-
"payment_links" => "payment_links",
|
20
|
-
"settlements" => "settlements",
|
21
|
-
"qr_codes" => "qr_codes",
|
22
|
-
"items" => "items",
|
23
|
-
"fund_accounts" => "fund_accounts",
|
24
|
-
"webhooks" => "webhook",
|
25
|
-
"payment_methods" => "payment_methods",
|
26
|
-
"products" => "products",
|
27
|
-
"tokens" => "tokens",
|
28
|
-
"iins" => "iins",
|
29
|
-
"stakeholders" => "stakeholders",
|
30
|
-
"accounts" => "accounts"
|
31
|
-
}
|
5
|
+
VERSION = '3.2.2'.freeze
|
6
|
+
AUTH_URL = 'https://auth.razorpay.com'.freeze
|
7
|
+
API_HOST = 'API'.freeze
|
8
|
+
AUTH_HOST = 'AUTH'.freeze
|
9
|
+
PRIVATE_AUTH = 'Private'.freeze
|
10
|
+
OAUTH = 'OAuth'.freeze
|
32
11
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'razorpay/request'
|
2
|
+
require 'razorpay/entity'
|
3
|
+
require 'razorpay/payload_validator'
|
4
|
+
require 'razorpay/validation_config'
|
5
|
+
|
6
|
+
module Razorpay
|
7
|
+
# OAuth APIs allow to you create and manage access tokens
|
8
|
+
class OAuthToken < Entity
|
9
|
+
def self.request
|
10
|
+
Razorpay::Request.new('token', Razorpay::AUTH_HOST)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.get_auth_url(options)
|
14
|
+
validate_auth_url_request(options)
|
15
|
+
uri = URI.join(Razorpay::AUTH_URL, '/authorize')
|
16
|
+
|
17
|
+
query_params = {
|
18
|
+
'response_type' => 'code',
|
19
|
+
'client_id' => options['client_id'],
|
20
|
+
'redirect_uri' => options['redirect_uri'],
|
21
|
+
'state' => options['state']
|
22
|
+
}
|
23
|
+
|
24
|
+
options['scopes'].each { |scope| query_params["scope[]"] = scope }
|
25
|
+
|
26
|
+
if options.has_key?('onboarding_signature')
|
27
|
+
query_params['onboarding_signature'] = options['onboarding_signature']
|
28
|
+
end
|
29
|
+
uri.query = URI.encode_www_form(query_params)
|
30
|
+
uri.to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.get_access_token(options)
|
34
|
+
validate_access_token_request(options)
|
35
|
+
r = request
|
36
|
+
r.request :post, "/token", options
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.refresh_token(options)
|
40
|
+
options['grant_type'] = 'refresh_token'
|
41
|
+
validate_refresh_token_request(options)
|
42
|
+
r = request
|
43
|
+
r.request :post, "/token", options
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.revoke_token(options)
|
47
|
+
validate_revoke_token_request(options)
|
48
|
+
r = request
|
49
|
+
r.request :post, "/revoke", options
|
50
|
+
end
|
51
|
+
|
52
|
+
class << self
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def validate_auth_url_request(options)
|
57
|
+
Razorpay::PayloadValidator.validate(options, get_validations_for_auth_request_url)
|
58
|
+
end
|
59
|
+
|
60
|
+
def validate_access_token_request(options)
|
61
|
+
Razorpay::PayloadValidator.validate(options, get_validations_for_access_token_request)
|
62
|
+
end
|
63
|
+
|
64
|
+
def validate_refresh_token_request(options)
|
65
|
+
Razorpay::PayloadValidator.validate(options, get_validations_for_refresh_token_request)
|
66
|
+
end
|
67
|
+
|
68
|
+
def validate_revoke_token_request(options)
|
69
|
+
Razorpay::PayloadValidator.validate(options, get_validations_for_revoke_token_request)
|
70
|
+
end
|
71
|
+
|
72
|
+
def get_validations_for_auth_request_url
|
73
|
+
[
|
74
|
+
Razorpay::ValidationConfig.new('client_id', [:id]),
|
75
|
+
Razorpay::ValidationConfig.new('redirect_uri', [:non_empty_string, :url]),
|
76
|
+
Razorpay::ValidationConfig.new('scopes', [:non_null]),
|
77
|
+
Razorpay::ValidationConfig.new('state', [:non_empty_string])
|
78
|
+
]
|
79
|
+
end
|
80
|
+
|
81
|
+
def get_validations_for_access_token_request
|
82
|
+
[
|
83
|
+
Razorpay::ValidationConfig.new('client_id', [:id]),
|
84
|
+
Razorpay::ValidationConfig.new('client_secret', [:non_empty_string]),
|
85
|
+
Razorpay::ValidationConfig.new('redirect_uri', [:non_empty_string, :url]),
|
86
|
+
Razorpay::ValidationConfig.new('grant_type', [:token_grant])
|
87
|
+
]
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_validations_for_refresh_token_request
|
91
|
+
[
|
92
|
+
Razorpay::ValidationConfig.new('client_id', [:id]),
|
93
|
+
Razorpay::ValidationConfig.new('client_secret', [:non_empty_string]),
|
94
|
+
Razorpay::ValidationConfig.new('refresh_token', [:non_empty_string]),
|
95
|
+
Razorpay::ValidationConfig.new('grant_type', [:token_grant])
|
96
|
+
]
|
97
|
+
end
|
98
|
+
|
99
|
+
def get_validations_for_revoke_token_request
|
100
|
+
[
|
101
|
+
Razorpay::ValidationConfig.new('client_id', [:id]),
|
102
|
+
Razorpay::ValidationConfig.new('client_secret', [:non_empty_string]),
|
103
|
+
Razorpay::ValidationConfig.new('token', [:non_empty_string]),
|
104
|
+
Razorpay::ValidationConfig.new('token_type_hint', [:non_empty_string])
|
105
|
+
]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Razorpay
|
2
|
+
|
3
|
+
ValidationType = {
|
4
|
+
non_null: :non_null,
|
5
|
+
non_empty_string: :non_empty_string,
|
6
|
+
url: :url,
|
7
|
+
id: :id,
|
8
|
+
mode: :mode,
|
9
|
+
token_grant: :token_grant
|
10
|
+
}
|
11
|
+
|
12
|
+
# PayloadValidator allows to perform basic validations
|
13
|
+
class PayloadValidator
|
14
|
+
def self.validate(request, validation_configs)
|
15
|
+
validation_configs.each do |config|
|
16
|
+
field_name = config.field_name
|
17
|
+
config.validations.each do |validation_type|
|
18
|
+
apply_validation(request, field_name, validation_type)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class << self
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def apply_validation(payload, field, validation_type)
|
28
|
+
case validation_type
|
29
|
+
when ValidationType[:non_null]
|
30
|
+
validate_non_null(payload, field)
|
31
|
+
when ValidationType[:non_empty_string]
|
32
|
+
validate_non_empty_string(payload, field)
|
33
|
+
when ValidationType[:url]
|
34
|
+
validate_url(payload, field)
|
35
|
+
when ValidationType[:id]
|
36
|
+
validate_id(payload, field)
|
37
|
+
when ValidationType[:mode]
|
38
|
+
validate_mode(payload, field)
|
39
|
+
when ValidationType[:token_grant]
|
40
|
+
validate_grant_type(payload, field)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def validate_non_null(payload, field)
|
45
|
+
raise Razorpay::Error.new, "Field #{field} cannot be null" unless payload.key?(field) && !payload[field].nil?
|
46
|
+
end
|
47
|
+
|
48
|
+
def validate_non_empty_string(payload, field)
|
49
|
+
raise Razorpay::Error.new, "Field #{field} cannot be empty" if payload[field].to_s.strip.empty?
|
50
|
+
end
|
51
|
+
|
52
|
+
def validate_url(payload, field)
|
53
|
+
url = payload[field]
|
54
|
+
url_regex = /^(http[s]?):\/\/[^\s\/$.?#].[^\s]*$/
|
55
|
+
|
56
|
+
unless url_regex.match?(url)
|
57
|
+
error_message = "Field #{field} is not a valid URL"
|
58
|
+
raise Razorpay::Error.new, error_message
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def validate_id(payload, field)
|
63
|
+
validate_non_null(payload, field)
|
64
|
+
validate_non_empty_string(payload, field)
|
65
|
+
value = payload[field]
|
66
|
+
id_regex = /^[A-Za-z0-9]{1,14}$/
|
67
|
+
|
68
|
+
unless value.match?(id_regex)
|
69
|
+
error_message = "Field #{field} is not a valid ID"
|
70
|
+
raise Razorpay::Error.new, error_message
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def validate_mode(payload, field)
|
75
|
+
validate_non_null(payload, field)
|
76
|
+
unless ["test", "live"].include?(payload[field])
|
77
|
+
error_message = "Invalid value provided for field #{field}"
|
78
|
+
raise Razorpay::Error.new, error_message
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def validate_grant_type(payload, field)
|
83
|
+
validate_non_null(payload, field)
|
84
|
+
case payload[field]
|
85
|
+
when 'authorization_code'
|
86
|
+
validate_non_null(payload, 'code');
|
87
|
+
when 'refresh_token'
|
88
|
+
validate_non_null(payload, 'refresh_token');
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/razorpay/request.rb
CHANGED
@@ -11,20 +11,30 @@ module Razorpay
|
|
11
11
|
|
12
12
|
ssl_ca_file File.dirname(__FILE__) + '/../ca-bundle.crt'
|
13
13
|
|
14
|
-
def initialize(entity_name = nil)
|
15
|
-
self.class.base_uri(
|
14
|
+
def initialize(entity_name = nil, host = Razorpay::API_HOST)
|
15
|
+
self.class.base_uri(get_base_url(host))
|
16
16
|
@entity_name = entity_name
|
17
17
|
custom_headers = Razorpay.custom_headers || {}
|
18
18
|
predefined_headers = {
|
19
19
|
'User-Agent' => "Razorpay-Ruby/#{Razorpay::VERSION}; Ruby/#{RUBY_VERSION}"
|
20
20
|
}
|
21
|
+
|
21
22
|
# Order is important to give precedence to predefined headers
|
22
23
|
headers = custom_headers.merge(predefined_headers)
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
|
25
|
+
if Razorpay.auth_type == Razorpay::OAUTH
|
26
|
+
@options = {
|
27
|
+
timeout: 30,
|
28
|
+
headers: headers
|
29
|
+
}
|
30
|
+
headers['Authorization'] = 'Bearer ' + Razorpay.access_token
|
31
|
+
else
|
32
|
+
@options = {
|
33
|
+
basic_auth: Razorpay.auth,
|
34
|
+
timeout: 30,
|
35
|
+
headers: headers
|
36
|
+
}
|
37
|
+
end
|
28
38
|
end
|
29
39
|
|
30
40
|
def fetch(id, version="v1")
|
@@ -74,6 +84,13 @@ module Razorpay
|
|
74
84
|
self.class.send(method, url, @options)
|
75
85
|
end
|
76
86
|
|
87
|
+
def get_base_url(host)
|
88
|
+
if host == Razorpay::AUTH_HOST
|
89
|
+
return Razorpay::AUTH_URL
|
90
|
+
end
|
91
|
+
Razorpay::BASE_URI
|
92
|
+
end
|
93
|
+
|
77
94
|
# Since we need to change the base route
|
78
95
|
def make_test_request
|
79
96
|
self.class.get Razorpay::TEST_URL, @options
|
@@ -115,11 +132,5 @@ module Razorpay
|
|
115
132
|
# We got an unknown error, cast it to Error for now
|
116
133
|
raise Razorpay::Error.new, 'Unknown Error'
|
117
134
|
end
|
118
|
-
|
119
|
-
def doesEntityExist(entity)
|
120
|
-
if (Razorpay::ENTITIES_LIST.include?(entity))
|
121
|
-
warn("Warning: The entity already has a specific function. Consider using it instead.")
|
122
|
-
end
|
123
|
-
end
|
124
135
|
end
|
125
136
|
end
|
data/lib/razorpay/utility.rb
CHANGED
@@ -26,6 +26,11 @@ module Razorpay
|
|
26
26
|
verify_signature(body, signature, secret)
|
27
27
|
end
|
28
28
|
|
29
|
+
def self.generate_onboarding_signature(body, secret)
|
30
|
+
json_data = body.to_json
|
31
|
+
encrypt(json_data, secret);
|
32
|
+
end
|
33
|
+
|
29
34
|
class << self
|
30
35
|
private
|
31
36
|
|
@@ -52,6 +57,25 @@ module Razorpay
|
|
52
57
|
|
53
58
|
r.zero?
|
54
59
|
end
|
60
|
+
|
61
|
+
def encrypt(data, secret)
|
62
|
+
iv = secret[0, 12]
|
63
|
+
key = secret[0, 16]
|
64
|
+
|
65
|
+
cipher = OpenSSL::Cipher.new('aes-128-gcm')
|
66
|
+
cipher.encrypt
|
67
|
+
cipher.key = key
|
68
|
+
cipher.iv = iv
|
69
|
+
|
70
|
+
cipher.auth_data = ""
|
71
|
+
|
72
|
+
encrypted = cipher.update(data) + cipher.final
|
73
|
+
|
74
|
+
tag = cipher.auth_tag
|
75
|
+
combined_encrypted_data = encrypted + tag
|
76
|
+
|
77
|
+
encrypted_data_hex = combined_encrypted_data.unpack1("H*")
|
78
|
+
end
|
55
79
|
end
|
56
80
|
end
|
57
81
|
end
|
data/lib/razorpay.rb
CHANGED
@@ -26,16 +26,22 @@ require 'razorpay/token'
|
|
26
26
|
require 'razorpay/product'
|
27
27
|
require 'razorpay/stakeholder'
|
28
28
|
require 'razorpay/account'
|
29
|
-
require 'razorpay/
|
29
|
+
require 'razorpay/oauth_token'
|
30
30
|
|
31
31
|
# Base Razorpay module
|
32
32
|
module Razorpay
|
33
33
|
class << self
|
34
|
-
attr_accessor :auth, :custom_headers
|
34
|
+
attr_accessor :auth, :custom_headers, :access_token, :auth_type
|
35
35
|
end
|
36
36
|
|
37
37
|
def self.setup(key_id, key_secret)
|
38
38
|
self.auth = { username: key_id, password: key_secret }
|
39
|
+
self.auth_type = Razorpay::PRIVATE_AUTH
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.setup_with_oauth(access_token)
|
43
|
+
self.access_token = access_token
|
44
|
+
self.auth_type = Razorpay::OAUTH
|
39
45
|
end
|
40
46
|
|
41
47
|
def self.headers=(headers = {})
|
@@ -0,0 +1,8 @@
|
|
1
|
+
{
|
2
|
+
"public_token": "rzp_test_oauth_9xu1rkZqoXlClS",
|
3
|
+
"token_type": "Bearer",
|
4
|
+
"expires_in": 7862400,
|
5
|
+
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImp0aSI6IkY1Z0NQYkhhRzRjcUpnIn0.eyJhdWQiOiJGNFNNeEgxanMxbkpPZiIsImp0aSI6IkY1Z0NQYkhhRzRjcUpnIiwiaWF0IjoxNTkyODMxMDExLCJuYmYiOjE1OTI4MzEwMTEsInN1YiI6IiIsImV4cCI6MTYwMDc3OTgxMSwidXNlcl9pZCI6IkYycVBpejJEdzRPRVFwIiwibWVyY2hhbnRfaWQiOiJGMnFQaVZ3N0lNV01GSyIsInNjb3BlcyI6WyJyZWFkX29ubHkiXX0.Wwqt5czhoWpVzP5_aoiymKXoGj-ydo-4A_X2jf_7rrSvk4pXdqzbA5BMrHxPdPbeFQWV6vsnsgbf99Q3g-W4kalHyH67LfAzc3qnJ-mkYDkFY93tkeG-MCco6GJW-Jm8xhaV9EPUak7z9J9jcdluu9rNXYMtd5qxD8auyRYhEgs",
|
6
|
+
"refresh_token": "def50200f42e07aded65a323f6c53181d802cc797b62cc5e78dd8038d6dff253e5877da9ad32f463a4da0ad895e3de298cbce40e162202170e763754122a6cb97910a1f58e2378ee3492dc295e1525009cccc45635308cce8575bdf373606c453ebb5eb2bec062ca197ac23810cf9d6cf31fbb9fcf5b7d4de9bf524c89a4aa90599b0151c9e4e2fa08acb6d2fe17f30a6cfecdfd671f090787e821f844e5d36f5eacb7dfb33d91e83b18216ad0ebeba2bef7721e10d436c3984daafd8654ed881c581d6be0bdc9ebfaee0dc5f9374d7184d60aae5aa85385690220690e21bc93209fb8a8cc25a6abf1108d8277f7c3d38217b47744d7",
|
7
|
+
"razorpay_account_id": "acc_Dhk2qDbmu6FwZH"
|
8
|
+
}
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Razorpay
|
4
|
+
# Tests for Razorpay::OauthToken
|
5
|
+
class RazorpayOAuthTokenTest < Minitest::Test
|
6
|
+
class OAuthToken < Razorpay::Entity; end
|
7
|
+
|
8
|
+
def test_get_auth_url
|
9
|
+
options = {
|
10
|
+
'client_id' => '8DXCMTshWSWECc',
|
11
|
+
'redirect_uri' => 'https://example.com/razorpay_callback',
|
12
|
+
'state' => 'NOBYtv8r6c75ex6WZ',
|
13
|
+
'scopes' => ["read_write"]
|
14
|
+
}
|
15
|
+
|
16
|
+
expected_auth_url = "https://auth.razorpay.com/authorize?response_type=code&client_id=8DXCMTshWSWECc&redirect_uri=https%3A%2F%2Fexample.com%2Frazorpay_callback&state=NOBYtv8r6c75ex6WZ&scope%5B%5D=read_write"
|
17
|
+
auth_url = Razorpay::OAuthToken.get_auth_url(options)
|
18
|
+
assert_equal expected_auth_url, auth_url
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_request_validation_for_get_auth_url
|
22
|
+
options = {
|
23
|
+
'client_id' => '8DXCMTshWSWECc',
|
24
|
+
'redirect_uri' => 'https://example.com/razorpay_callback',
|
25
|
+
'scopes' => ["read_write"]
|
26
|
+
}
|
27
|
+
assert_raises(Razorpay::Error) do
|
28
|
+
Razorpay::OAuthToken.get_auth_url(options)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_get_access_token
|
33
|
+
options = {
|
34
|
+
'client_id' => '8DXCMTshWSWECc',
|
35
|
+
'client_secret' => 'AESSECRETKEY',
|
36
|
+
'grant_type' => 'client_credentials',
|
37
|
+
'redirect_uri' => 'http://example.com/razorpay_callback',
|
38
|
+
'mode' => 'test'
|
39
|
+
}
|
40
|
+
stub_post(/token$/,'fake_oauth_token',options)
|
41
|
+
oauth_token = Razorpay::OAuthToken.get_access_token(options)
|
42
|
+
assert_instance_of Razorpay::Entity, oauth_token, 'OAuthToken not an instance of Entity class'
|
43
|
+
assert_equal 'rzp_test_oauth_9xu1rkZqoXlClS', oauth_token.public_token, 'Public Tokens do not match'
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_get_access_token_validation_failure
|
47
|
+
options = {
|
48
|
+
'client_id' => '8DXCMTshWSWECc',
|
49
|
+
'grant_type' => 'client_credentials',
|
50
|
+
'redirect_uri' => 'http://example.com/razorpay_callback',
|
51
|
+
'mode' => 'test'
|
52
|
+
}
|
53
|
+
assert_raises(Razorpay::Error) do
|
54
|
+
Razorpay::OAuthToken.get_access_token(options)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_refresh_token
|
59
|
+
options = {
|
60
|
+
'client_id' => '8DXCMTshWSWECc',
|
61
|
+
'client_secret' => 'AESSECRETKEY',
|
62
|
+
'refresh_token' => 'def5020096e1c470c901d34cd60fa53abdaf3662sa0'
|
63
|
+
}
|
64
|
+
expected_request_payload = options.merge('grant_type': 'refresh_token')
|
65
|
+
stub_post(/token$/,'fake_oauth_token',expected_request_payload)
|
66
|
+
oauth_token = Razorpay::OAuthToken.refresh_token(options)
|
67
|
+
assert_instance_of Razorpay::Entity, oauth_token, 'OAuthToken not an instance of Entity class'
|
68
|
+
assert_equal 'rzp_test_oauth_9xu1rkZqoXlClS', oauth_token.public_token, 'Public Tokens do not match'
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_refresh_token_validation_failure
|
72
|
+
options = {
|
73
|
+
'client_id' => '8DXCMTshWSWECc',
|
74
|
+
'refresh_token' => 'def5020096e1c470c901d34cd60fa53abdaf3662sa0'
|
75
|
+
}
|
76
|
+
assert_raises(Razorpay::Error) do
|
77
|
+
Razorpay::OAuthToken.refresh_token(options)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_revoke_token
|
82
|
+
options = {
|
83
|
+
'client_id' => '8DXCMTshWSWECc',
|
84
|
+
'client_secret' => 'AESSECRETKEY',
|
85
|
+
'token_type_hint' => 'access_token',
|
86
|
+
'token' => 'eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJKQTFwODVudE1ySEpoQSIsImp0aSI6IkpPZkd0aHFDTmhqQUhTIiwiaWF0IjoxNjUxMTI0NTU0LCJuYmYiOjE2NTExMjQ1NTQsInN1YiI6IiIsImV4cCI6MTY1ODk4Njk1Miw'
|
87
|
+
}
|
88
|
+
stub_post(/revoke$/,'fake_revoke_token',options)
|
89
|
+
oauth_token = Razorpay::OAuthToken.revoke_token(options)
|
90
|
+
assert_instance_of Razorpay::Entity, oauth_token, 'OAuthToken not an instance of Entity class'
|
91
|
+
assert_equal 'Token Revoked', oauth_token.message, 'Messages do not match'
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_revoke_token_validation_failure
|
95
|
+
options = {
|
96
|
+
'client_id' => '8DXCMTshWSWECc',
|
97
|
+
'client_secret' => 'AESSECRETKEY',
|
98
|
+
'token_type_hint' => 'access_token'
|
99
|
+
}
|
100
|
+
assert_raises(Razorpay::Error) do
|
101
|
+
Razorpay::OAuthToken.revoke_token(options)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'razorpay/validation_config'
|
3
|
+
|
4
|
+
module Razorpay
|
5
|
+
# Tests for Razorpay::PayloadValidator
|
6
|
+
class RazorpayPayloadValidatorTest < Minitest::Test
|
7
|
+
def test_validate_mode
|
8
|
+
payload = {
|
9
|
+
'mode1' => 'test',
|
10
|
+
'mode2' => 'live'
|
11
|
+
}
|
12
|
+
assert_silent do
|
13
|
+
Razorpay::PayloadValidator.validate(payload, [
|
14
|
+
Razorpay::ValidationConfig.new('mode1', [:mode]),
|
15
|
+
Razorpay::ValidationConfig.new('mode2', [:mode]),
|
16
|
+
])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_mode_validation_failure
|
21
|
+
payload = {
|
22
|
+
'mode' => 'testvalue'
|
23
|
+
}
|
24
|
+
assert_raises(Razorpay::Error) do
|
25
|
+
Razorpay::PayloadValidator.validate(payload, [
|
26
|
+
Razorpay::ValidationConfig.new('mode', [:mode])
|
27
|
+
])
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_url_validation_failure
|
32
|
+
payload = {
|
33
|
+
'redirect_uri' => 'test.com'
|
34
|
+
}
|
35
|
+
assert_raises(Razorpay::Error) do
|
36
|
+
Razorpay::PayloadValidator.validate(payload, [
|
37
|
+
Razorpay::ValidationConfig.new('redirect_uri', [:url])
|
38
|
+
])
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_non_null_validation_failure
|
43
|
+
assert_raises(Razorpay::Error) do
|
44
|
+
Razorpay::PayloadValidator.validate({}, [
|
45
|
+
Razorpay::ValidationConfig.new('redirect_uri', [:non_null])
|
46
|
+
])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_id_validation_failure
|
51
|
+
payload = {
|
52
|
+
'client_id' => 'fjidhf'
|
53
|
+
}
|
54
|
+
assert_raises(Razorpay::Error) do
|
55
|
+
Razorpay::PayloadValidator.validate({}, [
|
56
|
+
Razorpay::ValidationConfig.new('client_id', [:id])
|
57
|
+
])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -49,5 +49,22 @@ module Razorpay
|
|
49
49
|
headers: headers,
|
50
50
|
times: 1
|
51
51
|
end
|
52
|
+
|
53
|
+
def test_oauth_setup
|
54
|
+
Razorpay.setup_with_oauth('access_token')
|
55
|
+
assert_equal 'access_token', Razorpay.access_token
|
56
|
+
end
|
57
|
+
|
58
|
+
# # We mock this request
|
59
|
+
def test_auth_header_and_user_agent_for_oauth
|
60
|
+
stub_get(/$/, 'hello_response')
|
61
|
+
Razorpay.setup_with_oauth('access_token')
|
62
|
+
Razorpay::Request.new('dummy').make_test_request
|
63
|
+
user_agent = "Razorpay-Ruby/#{Razorpay::VERSION}; Ruby/#{RUBY_VERSION}"
|
64
|
+
headers = { 'User-Agent' => user_agent, 'Authorization' => 'Bearer access_token' }
|
65
|
+
assert_requested :get, 'https://api.razorpay.com/',
|
66
|
+
headers: headers,
|
67
|
+
times: 1
|
68
|
+
end
|
52
69
|
end
|
53
70
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'test_helper'
|
2
|
+
require 'json'
|
2
3
|
|
3
4
|
module Razorpay
|
4
5
|
# Tests for Razorpay::Utility
|
@@ -80,5 +81,38 @@ module Razorpay
|
|
80
81
|
Razorpay::Utility.verify_webhook_signature(webhook_body, signature, secret)
|
81
82
|
end
|
82
83
|
end
|
84
|
+
|
85
|
+
def test_generate_onboarding_signature
|
86
|
+
secret = "EnLs21M47BllR3X8PSFtjtbd"
|
87
|
+
timestamp = Time.now.to_i
|
88
|
+
body = {
|
89
|
+
submerchant_id: 'NSgKfYIR2f9v2y',
|
90
|
+
timestamp: timestamp
|
91
|
+
}
|
92
|
+
encryptedData = Razorpay::Utility.generate_onboarding_signature(body, secret)
|
93
|
+
json_data = decrypt(encryptedData, secret)
|
94
|
+
body = JSON.parse(json_data)
|
95
|
+
assert_equal 'NSgKfYIR2f9v2y', body['submerchant_id'], 'Submerchant IDs do not match'
|
96
|
+
assert_equal timestamp, body['timestamp'], 'Timestamps do not match'
|
97
|
+
end
|
98
|
+
|
99
|
+
def decrypt(data, secret)
|
100
|
+
combined_encrypted_data = [data].pack("H*")
|
101
|
+
|
102
|
+
iv = secret[0, 12]
|
103
|
+
key = secret[0, 16]
|
104
|
+
tag = combined_encrypted_data[-16..]
|
105
|
+
|
106
|
+
encrypted_data = combined_encrypted_data[0...-16]
|
107
|
+
|
108
|
+
cipher = OpenSSL::Cipher.new('aes-128-gcm')
|
109
|
+
cipher.decrypt
|
110
|
+
cipher.key = key
|
111
|
+
cipher.iv = iv
|
112
|
+
cipher.auth_tag = tag
|
113
|
+
cipher.auth_data = ""
|
114
|
+
|
115
|
+
cipher.update(encrypted_data) + cipher.final
|
116
|
+
end
|
83
117
|
end
|
84
118
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: razorpay
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.2.
|
4
|
+
version: 3.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Abhay Rana
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2024-04-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: httparty
|
@@ -137,8 +137,8 @@ files:
|
|
137
137
|
- documents/customer.md
|
138
138
|
- documents/emandate.md
|
139
139
|
- documents/fund.md
|
140
|
-
- documents/generic.md
|
141
140
|
- documents/items.md
|
141
|
+
- documents/oauth_token.md
|
142
142
|
- documents/order.md
|
143
143
|
- documents/papernach.md
|
144
144
|
- documents/payment.md
|
@@ -174,11 +174,12 @@ files:
|
|
174
174
|
- lib/razorpay/errors/razorpay_error.rb
|
175
175
|
- lib/razorpay/errors/server_error.rb
|
176
176
|
- lib/razorpay/fund_account.rb
|
177
|
-
- lib/razorpay/generic.rb
|
178
177
|
- lib/razorpay/iin.rb
|
179
178
|
- lib/razorpay/invoice.rb
|
180
179
|
- lib/razorpay/item.rb
|
180
|
+
- lib/razorpay/oauth_token.rb
|
181
181
|
- lib/razorpay/order.rb
|
182
|
+
- lib/razorpay/payload_validator.rb
|
182
183
|
- lib/razorpay/payment.rb
|
183
184
|
- lib/razorpay/payment_link.rb
|
184
185
|
- lib/razorpay/payment_method.rb
|
@@ -194,6 +195,7 @@ files:
|
|
194
195
|
- lib/razorpay/token.rb
|
195
196
|
- lib/razorpay/transfer.rb
|
196
197
|
- lib/razorpay/utility.rb
|
198
|
+
- lib/razorpay/validation_config.rb
|
197
199
|
- lib/razorpay/virtual_account.rb
|
198
200
|
- lib/razorpay/webhook.rb
|
199
201
|
- razorpay-ruby.gemspec
|
@@ -221,6 +223,7 @@ files:
|
|
221
223
|
- test/fixtures/fake_instant_settlement.json
|
222
224
|
- test/fixtures/fake_invoice.json
|
223
225
|
- test/fixtures/fake_item.json
|
226
|
+
- test/fixtures/fake_oauth_token.json
|
224
227
|
- test/fixtures/fake_order.json
|
225
228
|
- test/fixtures/fake_order_transfers.json
|
226
229
|
- test/fixtures/fake_otp_generate.json
|
@@ -238,6 +241,7 @@ files:
|
|
238
241
|
- test/fixtures/fake_recurring.json
|
239
242
|
- test/fixtures/fake_refund.json
|
240
243
|
- test/fixtures/fake_refunded_payment.json
|
244
|
+
- test/fixtures/fake_revoke_token.json
|
241
245
|
- test/fixtures/fake_settlement.json
|
242
246
|
- test/fixtures/fake_settlement_on_demand.json
|
243
247
|
- test/fixtures/fake_stakeholder.json
|
@@ -295,11 +299,12 @@ files:
|
|
295
299
|
- test/razorpay/test_customer.rb
|
296
300
|
- test/razorpay/test_entity.rb
|
297
301
|
- test/razorpay/test_fund_account.rb
|
298
|
-
- test/razorpay/test_generic.rb
|
299
302
|
- test/razorpay/test_iin.rb
|
300
303
|
- test/razorpay/test_invoice.rb
|
301
304
|
- test/razorpay/test_item.rb
|
305
|
+
- test/razorpay/test_oauth_token.rb
|
302
306
|
- test/razorpay/test_order.rb
|
307
|
+
- test/razorpay/test_payload_validator.rb
|
303
308
|
- test/razorpay/test_payment.rb
|
304
309
|
- test/razorpay/test_payment_link.rb
|
305
310
|
- test/razorpay/test_plan.rb
|
@@ -366,6 +371,7 @@ test_files:
|
|
366
371
|
- test/fixtures/fake_instant_settlement.json
|
367
372
|
- test/fixtures/fake_invoice.json
|
368
373
|
- test/fixtures/fake_item.json
|
374
|
+
- test/fixtures/fake_oauth_token.json
|
369
375
|
- test/fixtures/fake_order.json
|
370
376
|
- test/fixtures/fake_order_transfers.json
|
371
377
|
- test/fixtures/fake_otp_generate.json
|
@@ -383,6 +389,7 @@ test_files:
|
|
383
389
|
- test/fixtures/fake_recurring.json
|
384
390
|
- test/fixtures/fake_refund.json
|
385
391
|
- test/fixtures/fake_refunded_payment.json
|
392
|
+
- test/fixtures/fake_revoke_token.json
|
386
393
|
- test/fixtures/fake_settlement.json
|
387
394
|
- test/fixtures/fake_settlement_on_demand.json
|
388
395
|
- test/fixtures/fake_stakeholder.json
|
@@ -440,11 +447,12 @@ test_files:
|
|
440
447
|
- test/razorpay/test_customer.rb
|
441
448
|
- test/razorpay/test_entity.rb
|
442
449
|
- test/razorpay/test_fund_account.rb
|
443
|
-
- test/razorpay/test_generic.rb
|
444
450
|
- test/razorpay/test_iin.rb
|
445
451
|
- test/razorpay/test_invoice.rb
|
446
452
|
- test/razorpay/test_item.rb
|
453
|
+
- test/razorpay/test_oauth_token.rb
|
447
454
|
- test/razorpay/test_order.rb
|
455
|
+
- test/razorpay/test_payload_validator.rb
|
448
456
|
- test/razorpay/test_payment.rb
|
449
457
|
- test/razorpay/test_payment_link.rb
|
450
458
|
- test/razorpay/test_plan.rb
|
data/documents/generic.md
DELETED
@@ -1,150 +0,0 @@
|
|
1
|
-
## Generic Access point
|
2
|
-
|
3
|
-
|
4
|
-
```rb
|
5
|
-
Razorpay.setup('key_id', 'key_secret')
|
6
|
-
```
|
7
|
-
|
8
|
-
### Method Signature
|
9
|
-
```rb
|
10
|
-
Razorpay::Generic.new(entity).do(url, method, payload, version)
|
11
|
-
```
|
12
|
-
|
13
|
-
**Parameters:**
|
14
|
-
|
15
|
-
| Name | Type | Description |
|
16
|
-
|---------------|-------------|---------------------------------------------|
|
17
|
-
| entity* | string | The endpoint to which the request will be made. (e.g., "contacts" or "accounts") |
|
18
|
-
| url* | string | Add params or query or query (e.g., "/order_000000000000001" or "?count=1") |
|
19
|
-
| method* | string | The HTTP method for the request (e.g., 'Get', 'Post', 'Put', 'Patch', 'Delete'). |
|
20
|
-
| payload | object | The data to be sent with the request.|
|
21
|
-
| version | string | Add version (e.g., "v1" or "v2") |
|
22
|
-
|
23
|
-
-------------------------------------------------------------------------------------------------------
|
24
|
-
|
25
|
-
### Create a contacts using POST
|
26
|
-
|
27
|
-
```rb
|
28
|
-
|
29
|
-
payload = {
|
30
|
-
"name": "Gaurav Kumar",
|
31
|
-
"email": "gaurav.kumar@example.com",
|
32
|
-
"contact": "9123456789",
|
33
|
-
"type": "employee",
|
34
|
-
"reference_id":"Acme Contact ID 12345",
|
35
|
-
"notes": {
|
36
|
-
"notes_key_1":"Tea, Earl Grey, Hot",
|
37
|
-
"notes_key_2":"Tea, Earl Grey… decaf.",
|
38
|
-
},
|
39
|
-
}
|
40
|
-
|
41
|
-
Razorpay::Generic.new("contacts").do("/", "Post", payload)
|
42
|
-
```
|
43
|
-
|
44
|
-
**Response:**
|
45
|
-
|
46
|
-
```json
|
47
|
-
{
|
48
|
-
"id": "cont_00000000000001",
|
49
|
-
"entity": "contact",
|
50
|
-
"name": "Gaurav Kumar",
|
51
|
-
"contact": "9123456789",
|
52
|
-
"email": "gaurav.kumar@example.com",
|
53
|
-
"type": "employee",
|
54
|
-
"reference_id": "Acme Contact ID 12345",
|
55
|
-
"batch_id": null,
|
56
|
-
"active": true,
|
57
|
-
"notes": {
|
58
|
-
"notes_key_1": "Tea, Earl Grey, Hot",
|
59
|
-
"notes_key_2": "Tea, Earl Grey… decaf."
|
60
|
-
},
|
61
|
-
"created_at": 1545320320
|
62
|
-
}
|
63
|
-
```
|
64
|
-
|
65
|
-
-------------------------------------------------------------------------------------------------------
|
66
|
-
|
67
|
-
### Fetch an order using GET
|
68
|
-
|
69
|
-
```rb
|
70
|
-
Razorpay::Generic.new("orders").do("/order_00000000000001", "Get", {})
|
71
|
-
```
|
72
|
-
|
73
|
-
**Response:**
|
74
|
-
|
75
|
-
```json
|
76
|
-
{
|
77
|
-
"amount": 307,
|
78
|
-
"amount_due": 0,
|
79
|
-
"amount_paid": 307,
|
80
|
-
"attempts": 1,
|
81
|
-
"created_at": 1695625101,
|
82
|
-
"currency": "INR",
|
83
|
-
"entity": "order",
|
84
|
-
"id": "order_00000000000001",
|
85
|
-
"notes": [],
|
86
|
-
"offer_id": null,
|
87
|
-
"receipt": "851617",
|
88
|
-
"status": "paid"
|
89
|
-
}
|
90
|
-
```
|
91
|
-
|
92
|
-
-------------------------------------------------------------------------------------------------------
|
93
|
-
|
94
|
-
### Fetch payments of a linked account using headers
|
95
|
-
|
96
|
-
```rb
|
97
|
-
Razorpay.headers = {"X-Razorpay-Account" => "acc_00000000000001"}
|
98
|
-
|
99
|
-
Razorpay::Generic.new("payments").do("/pay_00000000000001", "Get", {})
|
100
|
-
```
|
101
|
-
|
102
|
-
**Response:**
|
103
|
-
|
104
|
-
```json
|
105
|
-
{
|
106
|
-
"entity": "collection",
|
107
|
-
"count": 2,
|
108
|
-
"items": [
|
109
|
-
{
|
110
|
-
"id": "pay_00000000000001",
|
111
|
-
"entity": "payment",
|
112
|
-
"amount": 10000,
|
113
|
-
"currency": "INR",
|
114
|
-
"status": "captured",
|
115
|
-
"order_id": "order_00000000000001",
|
116
|
-
"invoice_id": null,
|
117
|
-
"international": false,
|
118
|
-
"method": "netbanking",
|
119
|
-
"amount_refunded": 0,
|
120
|
-
"refund_status": null,
|
121
|
-
"captured": true,
|
122
|
-
"description": "#JJCqaOhFihfkVE",
|
123
|
-
"card_id": null,
|
124
|
-
"bank": "YESB",
|
125
|
-
"wallet": null,
|
126
|
-
"vpa": null,
|
127
|
-
"email": "john.example@example.com",
|
128
|
-
"contact": "9999999999",
|
129
|
-
"notes": [],
|
130
|
-
"fee": 236,
|
131
|
-
"tax": 36,
|
132
|
-
"error_code": null,
|
133
|
-
"error_description": null,
|
134
|
-
"error_source": null,
|
135
|
-
"error_step": null,
|
136
|
-
"error_reason": null,
|
137
|
-
"acquirer_data": {
|
138
|
-
"bank_transaction_id": "2118867"
|
139
|
-
},
|
140
|
-
"created_at": 1649932775
|
141
|
-
}
|
142
|
-
]
|
143
|
-
}
|
144
|
-
```
|
145
|
-
|
146
|
-
-------------------------------------------------------------------------------------------------------
|
147
|
-
|
148
|
-
**PN: * indicates mandatory fields**
|
149
|
-
<br>
|
150
|
-
<br>
|
data/lib/razorpay/generic.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
require 'razorpay/request'
|
2
|
-
|
3
|
-
|
4
|
-
module Razorpay
|
5
|
-
class Generic
|
6
|
-
def initialize(entity)
|
7
|
-
@entity = entity
|
8
|
-
end
|
9
|
-
|
10
|
-
def request()
|
11
|
-
Razorpay::Request.new(@entity)
|
12
|
-
end
|
13
|
-
|
14
|
-
def do(url="", method="Get", options={}, version="v1")
|
15
|
-
r = self.request
|
16
|
-
r.doesEntityExist(@entity)
|
17
|
-
|
18
|
-
case method
|
19
|
-
when "Get"
|
20
|
-
r.get url, options, version
|
21
|
-
|
22
|
-
when "Post"
|
23
|
-
r.post url, options, version
|
24
|
-
|
25
|
-
when "Patch"
|
26
|
-
r.patch url, options, version
|
27
|
-
|
28
|
-
when "Put"
|
29
|
-
r.put url, options, version
|
30
|
-
|
31
|
-
when "Delete"
|
32
|
-
r.delete url, version
|
33
|
-
|
34
|
-
else
|
35
|
-
warn("Unsupported method or error occurred")
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,112 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
module Razorpay
|
4
|
-
# Tests for Razorpay::Addon
|
5
|
-
class RazorpayGenericTest < Minitest::Test
|
6
|
-
class Generic < Razorpay::Entity; end
|
7
|
-
|
8
|
-
def setup
|
9
|
-
@order_id = 'order_50sX9hGHZJvjjI'
|
10
|
-
@customer_id = 'cust_6vRXClWqnLhV14'
|
11
|
-
@invoice_id = 'inv_6vRZmJYFAG1mNq'
|
12
|
-
@addon_id = 'ao_IrSY3UIqDRx7df'
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_generic_should_be_defined
|
16
|
-
refute_nil Razorpay::Generic
|
17
|
-
end
|
18
|
-
|
19
|
-
# Test fetch endpoint by order entity
|
20
|
-
def test_generic_orders_should_be_fetch
|
21
|
-
stub_get(%r{orders/#{@order_id}$}, 'fake_order')
|
22
|
-
|
23
|
-
client = Razorpay::Generic.new("orders")
|
24
|
-
|
25
|
-
order = client.do(@order_id)
|
26
|
-
|
27
|
-
assert_equal 5000, order.amount
|
28
|
-
assert_equal 'INR', order.currency
|
29
|
-
assert_equal 'TEST', order.receipt
|
30
|
-
end
|
31
|
-
|
32
|
-
# Test post endpoint by order entity
|
33
|
-
def test_generic_orders_should_be_create
|
34
|
-
para_attr = {
|
35
|
-
"amount": 5000
|
36
|
-
}
|
37
|
-
|
38
|
-
stub_post("#{BASE_URI}/v1/orders/", 'fake_order', para_attr.to_json)
|
39
|
-
|
40
|
-
client = Razorpay::Generic.new("orders")
|
41
|
-
order = client.do("", "Post", para_attr.to_json)
|
42
|
-
assert_equal 5000, order.amount
|
43
|
-
assert_equal 'INR', order.currency
|
44
|
-
assert_equal 'TEST', order.receipt
|
45
|
-
end
|
46
|
-
|
47
|
-
# Test fetch endpoint by order entity
|
48
|
-
def test_generic_orders_should_be_edit
|
49
|
-
para_attr = {
|
50
|
-
"notes": {
|
51
|
-
"purpose": "Test UPI QR code notes uodate"
|
52
|
-
}
|
53
|
-
}
|
54
|
-
|
55
|
-
stub_patch("#{BASE_URI}/v1/orders/#{@order_id}", 'fake_order', para_attr.to_json)
|
56
|
-
|
57
|
-
client = Razorpay::Generic.new("orders")
|
58
|
-
order = client.do(@order_id, "Patch", para_attr.to_json)
|
59
|
-
assert_equal 5000, order.amount
|
60
|
-
assert_equal 'INR', order.currency
|
61
|
-
assert_equal 'TEST', order.receipt
|
62
|
-
end
|
63
|
-
|
64
|
-
# Test post endpoint by order entity
|
65
|
-
def test_generic_customer_should_be_create
|
66
|
-
para_attr = {
|
67
|
-
"name": "Gaurav Kumar",
|
68
|
-
"contact": 9123456780,
|
69
|
-
"email": "gaurav.kumar@example.com",
|
70
|
-
"notes": {
|
71
|
-
"notes_key_1": "Tea, Earl Grey, Hot",
|
72
|
-
"notes_key_2": "Tea, Earl Grey… decaf."
|
73
|
-
}
|
74
|
-
}
|
75
|
-
|
76
|
-
stub_post("#{BASE_URI}/v1/customers/", 'fake_customer', para_attr.to_json)
|
77
|
-
|
78
|
-
client = Razorpay::Generic.new("customers")
|
79
|
-
customer = client.do("","Post", para_attr.to_json)
|
80
|
-
assert_equal 'test@razorpay.com', customer.email
|
81
|
-
assert_equal '9876543210', customer.contact
|
82
|
-
end
|
83
|
-
|
84
|
-
# Test put endpoint by order entity
|
85
|
-
def test_generic_customer_should_be_edit
|
86
|
-
para_attr = {
|
87
|
-
"contact": 9123456780,
|
88
|
-
}
|
89
|
-
|
90
|
-
stub_put("#{BASE_URI}/v1/customers/#{@customer_id}", 'fake_customer', para_attr.to_json)
|
91
|
-
|
92
|
-
client = Razorpay::Generic.new("customers")
|
93
|
-
customer = client.do(@customer_id, "Put", para_attr.to_json)
|
94
|
-
assert_equal 'test@razorpay.com', customer.email
|
95
|
-
assert_equal '9876543210', customer.contact
|
96
|
-
end
|
97
|
-
|
98
|
-
def test_generic_delete_specific_invoice
|
99
|
-
stub_delete(%r{invoices/#{@invoice_id}$}, 'empty')
|
100
|
-
client = Razorpay::Generic.new("invoices")
|
101
|
-
invoice = client.do("#{@invoice_id}", "Delete")
|
102
|
-
refute_nil invoice
|
103
|
-
end
|
104
|
-
|
105
|
-
def test_generic_delete_addon
|
106
|
-
stub_delete(%r{addons/#{@addon_id}$}, 'empty')
|
107
|
-
client = Razorpay::Generic.new("addons")
|
108
|
-
addon = client.do("#{@addon_id}", "Delete")
|
109
|
-
refute_nil addon
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|