revolut-connect 0.1.4 → 0.1.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2ab4ede6e2971a49dea7cccc0a36ec45af6b87e9d9e4b239b7870eab34b7a278
4
- data.tar.gz: d253ad5ca5b9b40fb8a16989fa787a93fd199a6f01621ed626c8a18dda95eaef
3
+ metadata.gz: 9010d58ab099e0739336f7645c70fa7f859aeb8742109a3f48459262221302b8
4
+ data.tar.gz: d53d5e9b0a475252d5b00eaf9984a8557c67b0e31d03eb80ea4f4f39fdacc0e8
5
5
  SHA512:
6
- metadata.gz: 7d023304718166aadb50b682fa557c0844932c8ffb0a0757666e8e9c8e9135fa1aeee5ddf774504348641d12099d7ec274fa29db100f66fc88b898b88dd4b340
7
- data.tar.gz: 16fb000e2863c830732d031353895425fd1bde52faad6f04ebf1f60f57c8af4534221442ce12a4eb0ae209a135f36da7f6cd7a522dced82cfac35487ac3b3099
6
+ metadata.gz: 638eea99c2401f8fcdf5053f4fcc664975c6e677bf67eca9a83747337bac1389138da6e8a4a8f9632552d1ef848084e6f003a324c3577a2875810989971c77e6
7
+ data.tar.gz: 4e6e92b18f575b031861890f8e7f93b0ea6070e0c9c7321a515e01e3ad52f72ce8a6250b9e9d969757fa5e5268b4bffff8423d6a104a32d3d3c13da7b4bb020b
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- revolut-connect (0.1.4)
4
+ revolut-connect (0.1.5)
5
5
  faraday (>= 2)
6
6
  faraday-retry (>= 2)
7
7
  jwt (>= 1)
data/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  |:-:|:-:|
6
6
  | [![Tests](https://github.com/moraki-finance/revolut-connect/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/moraki-finance/revolut-connect/actions/workflows/main.yml) | [![Codecov Coverage](https://codecov.io/github/moraki-finance/revolut-connect/graph/badge.svg?token=SKTT14JJGV)](https://codecov.io/github/moraki-finance/revolut-connect) |
7
7
 
8
- A lightweight API client for Revolut featuring authentication, permission scopes, token expiration and automatic renewal.
8
+ A lightweight API client for Revolut featuring authentication, permission scopes, token expiration and automatic renewal, webhooks, webhook events, and much more!
9
9
 
10
10
  Revolut docs: <https://developer.revolut.com/>
11
11
 
@@ -22,6 +22,7 @@ _:warning: For now this connector only supports the [Business API](https://devel
22
22
  - `Payment`
23
23
  - `Transaction`
24
24
  - `TransferReason`
25
+ - `Webhook`
25
26
 
26
27
  ## :construction: Roadmap
27
28
 
@@ -34,7 +35,6 @@ _:warning: For now this connector only supports the [Business API](https://devel
34
35
  - `Simulation` resource
35
36
  - `TeamMember` resource
36
37
  - `Transfer` resource
37
- - `Webhooks` resource
38
38
 
39
39
  ### Merchants API
40
40
 
@@ -160,9 +160,25 @@ Revolut.configure do |config|
160
160
  # Optional: The JWT for an already exchanged token.
161
161
  # Used to preload an existing auth token so that you don't have to exchange / renew it again.
162
162
  config.auth_json = ENV["REVOLUT_AUTH_JSON"]
163
+
164
+ # Optional: The revolut api version used. Generally used to hit the webhooks API as it requires api_version 2.0.
165
+ # Default: "1.0".
166
+ config.api_version = ENV["REVOLUT_API_VERSION"]
163
167
  end
164
168
  ```
165
169
 
170
+ If you're setting the `auth_json` config, rembember to call `Revolut::Auth.load_from_env` right after the configuration is set so that the gem loads this JSON you just set:
171
+
172
+ ```rb
173
+ Revolute.configure do |config|
174
+ ...
175
+ config.auth_json = ENV.fetch("REVOLUT_AUTH_JSON", nil)
176
+ end
177
+
178
+ # Load the `auth_json` value.
179
+ Revolut::Auth.load_from_env
180
+ ```
181
+
166
182
  ### Resources
167
183
 
168
184
  #### Accounts
@@ -9,26 +9,27 @@ module Revolut
9
9
  token_duration
10
10
  scope
11
11
  authorize_redirect_uri
12
- base_uri
12
+ api_version
13
13
  environment
14
14
  request_timeout
15
15
  global_headers
16
16
  ].freeze
17
17
 
18
- attr_reader(*CONFIG_KEYS)
18
+ attr_reader(*CONFIG_KEYS, :base_uri)
19
19
 
20
- def self.instance
21
- @instance ||= new
22
- end
23
-
24
- private
25
-
26
- def initialize
20
+ def initialize(**attrs)
27
21
  CONFIG_KEYS.each do |key|
28
22
  # Set instance variables like api_type & access_token. Fall back to global config
29
23
  # if not present.
30
- instance_variable_set(:"@#{key}", Revolut.config.send(key))
24
+ instance_variable_set(:"@#{key}", attrs[key] || Revolut.config.send(key))
31
25
  end
26
+
27
+ @base_uri = (environment == :sandbox) ? "https://sandbox-b2b.revolut.com/api/#{api_version}/" : "https://b2b.revolut.com/api/#{api_version}/"
28
+ end
29
+
30
+ # Instance with all the defaults
31
+ def self.instance
32
+ @instance ||= new
32
33
  end
33
34
  end
34
35
  end
data/lib/revolut/http.rb CHANGED
@@ -73,8 +73,8 @@ module Revolut
73
73
  # Request middlewares
74
74
  f.request content_type
75
75
  f.request :retry, { # Retries a request after refreshing the token if we get an UnauthorizedError
76
- max: 1,
77
76
  exceptions: [Faraday::UnauthorizedError],
77
+ methods: Faraday::Retry::Middleware::IDEMPOTENT_METHODS + %i[post patch],
78
78
  retry_block: ->(env:, options:, retry_count:, exception:, will_retry_in:) {
79
79
  Revolut::Auth.refresh(force: true)
80
80
  env.request_headers = env.request_headers.merge("Authorization" => "Bearer #{Revolut::Auth.access_token}")
@@ -0,0 +1,26 @@
1
+ module Revolut
2
+ # Reference: https://developer.revolut.com/docs/business/counterparties
3
+ class Webhook < Resource
4
+ class << self
5
+ def resources_name
6
+ "webhooks"
7
+ end
8
+
9
+ def http_client
10
+ @http_client ||= Revolut::Client.new(api_version: "2.0")
11
+ end
12
+
13
+ def rotate_signing_secret(id, **data)
14
+ response = http_client.post("/#{resources_name}/#{id}/rotate-signing-secret", data:)
15
+
16
+ new(response.body)
17
+ end
18
+
19
+ def failed_events(id)
20
+ response = http_client.get("/#{resources_name}/#{id}/failed-events")
21
+
22
+ response.body.map(&Revolut::WebhookEvent)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ require "openssl"
2
+ require "digest"
3
+
4
+ module Revolut
5
+ class WebhookEvent < Resource
6
+ shallow # do not allow any resource operations on this resource
7
+
8
+ # Constructs a new instance of the WebhookEvent class from a request object and a signing secret.
9
+ #
10
+ # @param request [ActionDispatch::Request] The request object containing the webhook event data.
11
+ # @param signing_secret [String] The signing secret used to verify the signature of the webhook event.
12
+ # @return [WebhookEvent] A new instance of the WebhookEvent class.
13
+ # @raise [Revolut::SignatureVerificationError] If the signature verification fails.
14
+ def self.construct_from(request, signing_secret)
15
+ json = request.body.read
16
+ timestamp = request.headers["Revolut-Request-Timestamp"]
17
+ header_signature = request.headers["Revolut-Signature"]
18
+ payload_to_sign = "v1.#{timestamp}.#{json}"
19
+ digest = OpenSSL::Digest.new("sha256")
20
+ signature_digest = "v1=" + OpenSSL::HMAC.hexdigest(digest, signing_secret, payload_to_sign)
21
+
22
+ if signature_digest == header_signature
23
+ new(JSON.parse(json))
24
+ else
25
+ raise Revolut::SignatureVerificationError, "Signature verification failed"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Revolut
4
- VERSION = "0.1.4"
4
+ VERSION = "0.1.5"
5
5
  end
data/lib/revolut.rb CHANGED
@@ -17,12 +17,13 @@ module Revolut
17
17
 
18
18
  class NotImplementedError < Error; end
19
19
 
20
+ class SignatureVerificationError < Error; end
21
+
20
22
  class Configuration
21
- attr_accessor :request_timeout, :global_headers, :environment, :token_duration, :scope, :auth_json
23
+ attr_accessor :request_timeout, :global_headers, :environment, :token_duration, :scope, :auth_json, :api_version
22
24
  attr_writer :client_id, :signing_key, :iss, :authorize_redirect_uri
23
- attr_reader :base_uri
24
25
 
25
- DEFAULT_BASE_URI = "https://sandbox-b2b.revolut.com/api/1.0/"
26
+ DEFAULT_API_VERSION = "1.0"
26
27
  DEFAULT_ENVIRONMENT = "sandbox"
27
28
  DEFAULT_REQUEST_TIMEOUT = 120
28
29
  DEFAULT_TOKEN_DURATION = 120 # 2 minutes
@@ -37,8 +38,8 @@ module Revolut
37
38
  @token_duration = ENV.fetch("REVOLUT_TOKEN_DURATION", DEFAULT_TOKEN_DURATION)
38
39
  @auth_json = ENV["REVOLUT_AUTH_JSON"]
39
40
  @scope = ENV["REVOLUT_SCOPE"]
41
+ @api_version = ENV.fetch("REVOLUT_API_VERSION", DEFAULT_API_VERSION)
40
42
  @environment = ENV.fetch("REVOLUT_ENVIRONMENT", DEFAULT_ENVIRONMENT).to_sym
41
- @base_uri = (environment == :sandbox) ? "https://sandbox-b2b.revolut.com/api/1.0/" : "https://b2b.revolut.com/api/1.0/"
42
43
  end
43
44
 
44
45
  def client_id
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: revolut-connect
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.4
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Mochetti
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-03-07 00:00:00.000000000 Z
11
+ date: 2024-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: jwt
@@ -86,6 +86,8 @@ files:
86
86
  - lib/revolut/resources/resource.rb
87
87
  - lib/revolut/resources/transaction.rb
88
88
  - lib/revolut/resources/transfer_reason.rb
89
+ - lib/revolut/resources/webhook.rb
90
+ - lib/revolut/resources/webhook_event.rb
89
91
  - lib/revolut/version.rb
90
92
  - sig/revolut/connect.rbs
91
93
  homepage: https://github.com/moraki-finance/revolut-connect