modulr-api 0.0.43 → 0.0.44

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: ae6054cef00d65fbe08c2f5d15149c92841fc2f0560abc3bca49ef64149433f9
4
- data.tar.gz: f9c1e4d5f2802ea8b312d8f5a15d33a240cd37edee3c31af61f5b7e6c1160bd9
3
+ metadata.gz: 985e67e8a7284607d6d6ab83c5961c56d7ab92a8ef4fe24713908730afe063b6
4
+ data.tar.gz: 57c5b585f5039a0c69942f0311017d1f13e0505fb2f8c9900d501948a3d448a9
5
5
  SHA512:
6
- metadata.gz: c7710dcdac3d4602edb400b9f291cceb33d76d265002163e3f9b61e4ab422c915984b96ae80646be30355ce6232a45d33872a8e39dbce77e805cad3af0ae3e73
7
- data.tar.gz: 5ef98b0579f757b2a87f7bc6bb5ce103c20d475df7f1186803d3bb84f0bf8a8c8b3e35167ac7c9d731b204c0b9bc534693e932ca3ca2896b3530c487ff41b7e4
6
+ metadata.gz: 198a8ece89370a7f720622874bf1d0f6dce08862eede48664f3405b8db19a0aa2c63cdc162f2d8e04ff846809baf64d8bb3e85a60368de9e663b10505b52c491
7
+ data.tar.gz: 7b97f877c66a30566c2fa484664ee0433fb84650b31bd4109312ece4cbee41f77d02c052f68bb5b74979011c157a4ede681354b2697699636c9ea1055dd6eb05
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- modulr-api (0.0.43)
4
+ modulr-api (0.0.44)
5
5
  faraday (~> 1.0)
6
6
  faraday_middleware (~> 1.0)
7
7
 
@@ -27,14 +27,14 @@ module Modulr
27
27
  }
28
28
  payload[:externalReference] = opts[:external_reference] if opts[:external_reference]
29
29
 
30
- response = client.post("/customers/#{customer_id}/accounts", payload)
30
+ response = client.post("/customers/#{customer_id}/accounts", payload, opts)
31
31
  attributes = response.body
32
32
 
33
33
  Resources::Accounts::Account.new(response, attributes)
34
34
  end
35
35
 
36
- def close(account_id:)
37
- client.post("/accounts/#{account_id}/close")
36
+ def close(account_id:, **opts)
37
+ client.post("/accounts/#{account_id}/close", nil, opts)
38
38
 
39
39
  nil
40
40
  end
@@ -32,7 +32,7 @@ module Modulr
32
32
  payload[:customerTrust] = opts[:customer_trust] if opts[:customer_trust]
33
33
  payload[:taxProfile] = opts[:tax_profile] if opts[:tax_profile]
34
34
 
35
- response = client.post("/customers", payload)
35
+ response = client.post("/customers", payload, opts)
36
36
  attributes = response.body
37
37
 
38
38
  Resources::Customers::Customer.new(response, attributes)
@@ -24,7 +24,7 @@ module Modulr
24
24
  destinations: destinations,
25
25
  config: config,
26
26
  }
27
- response = client.post("#{base_notification_url(opts)}/notifications", payload)
27
+ response = client.post("#{base_notification_url(opts)}/notifications", payload, opts)
28
28
  attributes = response.body
29
29
 
30
30
  Resources::Notifications::Notification.new(response, attributes)
@@ -36,7 +36,7 @@ module Modulr
36
36
  destinations: destinations,
37
37
  config: config,
38
38
  }
39
- response = client.put("#{base_notification_url(opts)}/notifications/#{id}", payload)
39
+ response = client.put("#{base_notification_url(opts)}/notifications/#{id}", payload, opts)
40
40
  attributes = response.body
41
41
 
42
42
  Resources::Notifications::Notification.new(response, attributes)
@@ -33,7 +33,7 @@ module Modulr
33
33
  payload[:endToEndReference] = opts[:e2e_reference] if opts[:e2e_reference]
34
34
  payload[:permittedScheme] = opts[:permitted_scheme] if opts[:permitted_scheme]
35
35
 
36
- response = client.post("/payments", payload)
36
+ response = client.post("/payments", payload, opts)
37
37
  attributes = response.body
38
38
 
39
39
  Resources::Payments::Payment.new(response, attributes, { network_scheme: false })
@@ -9,6 +9,12 @@ module Modulr
9
9
  @client = client
10
10
  end
11
11
 
12
+ def idempotency_headers(options)
13
+ headers = {}
14
+ headers[:idempotency_key] = options[:idempotency_key] if options[:idempotency_key]
15
+ headers
16
+ end
17
+
12
18
  def format_datetime(datetime)
13
19
  datetime.strftime("%Y-%m-%dT%H:%M:%S%z")
14
20
  end
@@ -23,7 +23,8 @@ module Modulr
23
23
  ].join(",")
24
24
  end
25
25
 
26
- def self.calculate(apikey:, apisecret:, nonce: SecureRandom.base64(30), timestamp: DateTime.now.httpdate)
26
+ def self.calculate(apikey:, apisecret:, nonce: nil, timestamp: DateTime.now.httpdate)
27
+ nonce ||= SecureRandom.base64(30)
27
28
  signature_string = "date: #{timestamp}\nx-mod-nonce: #{nonce}"
28
29
  digest = OpenSSL::HMAC.digest(
29
30
  "SHA512",
data/lib/modulr/client.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "base64"
4
+ require "openssl"
3
5
  require "faraday"
4
6
  require "faraday_middleware"
5
7
  require "json"
@@ -44,19 +46,21 @@ module Modulr
44
46
  end
45
47
 
46
48
  def get(path, options = {})
47
- execute :get, path, nil, options
49
+ request :get, path, nil, options
48
50
  end
49
51
 
50
52
  def post(path, data = nil, options = {})
51
- execute :post, path, data, options
53
+ request :post, path, data, options
52
54
  end
53
55
 
54
56
  def put(path, data = nil, options = {})
55
- execute :put, path, data, options
57
+ request :put, path, data, options
56
58
  end
57
59
 
58
- def execute(method, path, data = nil, options = {})
59
- request(method, path, data, options)
60
+ def self.idempotency_nonce(idempotency_key)
61
+ digest = OpenSSL::Digest.new("SHA256")
62
+ hash = OpenSSL::HMAC.digest(digest, ENV["MODULR_APIKEY"], idempotency_key)
63
+ Base64.urlsafe_encode64(hash)
60
64
  end
61
65
 
62
66
  def request(method, path, data = nil, options = {})
@@ -65,16 +69,19 @@ module Modulr
65
69
 
66
70
  begin
67
71
  connection.run_request(method, uri, request_options[:body], request_options[:headers]) do |request|
68
- request.params.update(options) if options
72
+ merge_query_params(request, method, options)
69
73
  end
70
74
  rescue StandardError => e
71
75
  handle_request_error(e)
72
76
  end
73
77
  end
74
78
 
75
- def request_options(_method, _path, data, _options)
79
+ alias execute request
80
+
81
+ def request_options(method, _path, data, options)
76
82
  default_options.tap do |defaults|
77
83
  add_auth_options!(defaults)
84
+ add_idempotency_headers!(defaults[:headers], method, options) if options
78
85
  defaults[:body] = JSON.dump(data) if data
79
86
  end
80
87
  end
@@ -91,9 +98,28 @@ module Modulr
91
98
 
92
99
  def auth_options(options)
93
100
  signature = Auth::Signature.calculate(apikey: @apikey, apisecret: @apisecret)
101
+
94
102
  options[:headers][:authorization] = signature.authorization
95
103
  options[:headers][:date] = signature.timestamp
96
- options[:headers][:"x-mod-nonce"] = signature.nonce
104
+ options[:headers][:"x-mod-nonce"] ||= signature.nonce
105
+ end
106
+
107
+ private def add_idempotency_headers!(headers, method, options)
108
+ return if method == :get
109
+
110
+ idempotency_key = options.delete(:idempotency_key)
111
+ return unless idempotency_key
112
+
113
+ nonce = self.class.idempotency_nonce(idempotency_key)
114
+ headers[:"x-mod-nonce"] = nonce
115
+ headers[:"x-mod-retry"] = "true" if nonce && !nonce.empty?
116
+ end
117
+
118
+ private def merge_query_params(request, method, options)
119
+ return unless options
120
+ return unless method == :get
121
+
122
+ request.params.update(options.reject { |k, _| k == :idempotency_key })
97
123
  end
98
124
 
99
125
  def handle_request_error(error)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Modulr
4
- VERSION = "0.0.43"
4
+ VERSION = "0.0.44"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: modulr-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.43
4
+ version: 0.0.44
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aitor García Rey