checkout_sdk 2.8.0 → 2.8.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 26bd6c4871771d8d22c647b6724c577af0434c881b9af1433959cb1e4fdf98c8
4
- data.tar.gz: b18c0c03cef39d44080aadbf798f76910c87fc84506ecb4d6dfcb9b6c67a5d76
3
+ metadata.gz: ddcb702f44152460535a2f068b532e473f5076ab558231ab49087fa89b85bc5e
4
+ data.tar.gz: 44453c69fdf11cb1e35e18d22aade6e0fdfc7bed1eeab8db230179e9439fb3f7
5
5
  SHA512:
6
- metadata.gz: abbd929efceca48389c89b804075ee1c49a18a2a99532e03445ce061221a69c07545dbd1271cbb209435ca60da1209ad3c30c585d35b15a1db1d29832023fee8
7
- data.tar.gz: 2bb659ec58fa5022fd17278f9d4467ab9f18b8ca47f657240c2d8da0b76724bc13d136ab865d68d90d01b81791e2a32fb886258eaa3d9edc34f3f90b5a7fcf38
6
+ metadata.gz: 5fc31731ba185059c64e43c7c54025fb7e61ec53df0317d6b8115cf10e131da37e187eaafa74ba0f93569ed3e8ef2ca4ac1b36a4ac5044d26f392ab8d9c4034f
7
+ data.tar.gz: 7318c1c93ad5979a27514c98c486985776648c19aa71544d07b026f8eb812ac1dbecd2c53531796b45f41c581785328fbda42b7c836443da4c0770d792455207
data/README.md CHANGED
@@ -151,6 +151,11 @@ All the API responses that do not fall in the 2** status codes will cause a `Che
151
151
  exception
152
152
  encapsulates the `http_metadata` and a map of `error_details`, if available.
153
153
 
154
+ Identifiers passed to client methods (for example a payment id) are sent as single, percent-encoded path
155
+ segments: pass them unencoded. A `CheckoutSdk::CheckoutArgumentException` is raised before any request is sent
156
+ when an identifier is `nil`, empty, `.` or `..`, cannot be converted to valid UTF-8, or contains `/`, `\` or an
157
+ ASCII control character (U+0000 to U+001F, U+007F).
158
+
154
159
  ## Custom Http Client
155
160
 
156
161
  Ruby SDK supports your own configuration for `http client` using `Faraday::Connection` object, you can pass
@@ -172,6 +177,10 @@ api = CheckoutSdk.builder
172
177
  .build
173
178
  ```
174
179
 
180
+ If your connection uses the `raise_error` middleware, configure it as the default client does:
181
+ `conn.response :raise_error, include_request: false` (the option needs Faraday 2.7.11 or later;
182
+ the SDK leaves the request data out of the errors it raises in any case).
183
+
175
184
  You don't need to specify the URL for Faraday constructor the SDK grabs the belong URI from `CheckoutSdk::Environment`
176
185
  however if you want to
177
186
  use specific URI's without a proxy you can create the `Environment` object as follows.
@@ -52,10 +52,12 @@ module CheckoutSdk
52
52
  json_body = CheckoutSdk::JsonSerializer.to_custom_hash(body).to_json
53
53
 
54
54
  begin
55
- @log.info "#{method}: /#{path}"
55
+ @log.info "#{method}: /#{CheckoutUtils.loggable_path(path)}"
56
56
  response = @client.run_request(method, path, json_body, headers)
57
57
  rescue Faraday::ClientError => e
58
- raise CheckoutApiException, e.response
58
+ raise CheckoutApiException.new(e.response), cause: nil
59
+ rescue Faraday::Error => e
60
+ raise CheckoutUtils.without_request_data(e), cause: nil
59
61
  end
60
62
 
61
63
  parse_response(response)
@@ -140,10 +142,12 @@ module CheckoutSdk
140
142
  form = build_multipart_request(file_request, file)
141
143
 
142
144
  begin
143
- @log.info "post: /#{path}"
145
+ @log.info "post: /#{CheckoutUtils.loggable_path(path)}"
144
146
  response = @multipart_client.run_request(:post, path, form, headers)
145
147
  rescue Faraday::ClientError => e
146
- raise CheckoutApiException, e.response
148
+ raise CheckoutApiException.new(e.response), cause: nil
149
+ rescue Faraday::Error => e
150
+ raise CheckoutUtils.without_request_data(e), cause: nil
147
151
  end
148
152
 
149
153
  parse_response(response)
@@ -5,8 +5,9 @@ module CheckoutSdk
5
5
  # Bacs Direct Debit client.
6
6
  class BacsClient < Client
7
7
  APMS = 'apms'
8
- BACS_NOTIFICATIONS = 'bacs/notifications'
9
- private_constant :APMS, :BACS_NOTIFICATIONS
8
+ BACS = 'bacs'
9
+ NOTIFICATIONS = 'notifications'
10
+ private_constant :APMS, :BACS, :NOTIFICATIONS
10
11
 
11
12
  # @param [ApiClient] api_client
12
13
  # @param [CheckoutConfiguration] configuration
@@ -20,7 +21,7 @@ module CheckoutSdk
20
21
  # @param [Hash, BacsNotificationRequest] bacs_notification_request
21
22
  # @return [Hash] the BacsNotificationResponse, carrying event_id.
22
23
  def send_notification(bacs_notification_request)
23
- api_client.invoke_post(build_path(APMS, BACS_NOTIFICATIONS),
24
+ api_client.invoke_post(build_path(APMS, BACS, NOTIFICATIONS),
24
25
  sdk_authorization,
25
26
  bacs_notification_request)
26
27
  end
@@ -5,10 +5,11 @@ module CheckoutSdk
5
5
  module Apm
6
6
  class SepaClient < Client
7
7
  APMS = 'apms'
8
- SEPA_MANDATES = 'sepa/mandates'
8
+ SEPA = 'sepa'
9
+ MANDATES = 'mandates'
9
10
  PPRO = 'ppro'
10
11
  CANCEL = 'cancel'
11
- private_constant :APMS, :SEPA_MANDATES, :PPRO, :CANCEL
12
+ private_constant :APMS, :SEPA, :MANDATES, :PPRO, :CANCEL
12
13
 
13
14
  # @param [ApiClient] api_client
14
15
  # @param [CheckoutConfiguration] configuration
@@ -18,22 +19,22 @@ module CheckoutSdk
18
19
 
19
20
  # @param mandate_id [String]
20
21
  def get_mandate(mandate_id)
21
- api_client.invoke_get(build_path(SEPA_MANDATES, mandate_id), sdk_authorization)
22
+ api_client.invoke_get(build_path(SEPA, MANDATES, mandate_id), sdk_authorization)
22
23
  end
23
24
 
24
25
  # @param mandate_id [String]
25
26
  def cancel_mandate(mandate_id)
26
- api_client.invoke_post(build_path(SEPA_MANDATES, mandate_id, CANCEL), sdk_authorization)
27
+ api_client.invoke_post(build_path(SEPA, MANDATES, mandate_id, CANCEL), sdk_authorization)
27
28
  end
28
29
 
29
30
  # @param mandate_id [String]
30
31
  def get_mandate_via_ppro(mandate_id)
31
- api_client.invoke_get(build_path(APMS, PPRO, SEPA_MANDATES, mandate_id), sdk_authorization)
32
+ api_client.invoke_get(build_path(APMS, PPRO, SEPA, MANDATES, mandate_id), sdk_authorization)
32
33
  end
33
34
 
34
35
  # @param mandate_id [String]
35
36
  def cancel_mandate_via_ppro(mandate_id)
36
- api_client.invoke_post(build_path(APMS, PPRO, SEPA_MANDATES, mandate_id, CANCEL), sdk_authorization)
37
+ api_client.invoke_post(build_path(APMS, PPRO, SEPA, MANDATES, mandate_id, CANCEL), sdk_authorization)
37
38
  end
38
39
  end
39
40
  end
@@ -39,9 +39,8 @@ module CheckoutSdk
39
39
  # @param [String] currency_account_id the ID of the sub-account to retrieve top-up
40
40
  # instructions for
41
41
  # @return [Hash] the top-up instructions response
42
- # @raise [CheckoutArgumentException] if either path parameter is nil, empty or blank. Both
43
- # segments are interpolated straight into the request path, so a blank value would build a
44
- # malformed URL and be rejected by the API rather than by the SDK.
42
+ # @raise [CheckoutArgumentException] if either path parameter is nil, empty or blank, or is not
43
+ # a valid path segment (see Client#build_path).
45
44
  def retrieve_top_up_instructions(entity_id, currency_account_id)
46
45
  raise CheckoutArgumentException, 'entity_id cannot be blank' if entity_id.to_s.strip.empty?
47
46
  raise CheckoutArgumentException, 'currency_account_id cannot be blank' if currency_account_id.to_s.strip.empty?
@@ -21,11 +21,130 @@ module CheckoutSdk
21
21
  http_metadata
22
22
  end
23
23
 
24
+ MAX_MESSAGE_DETAILS_LENGTH = 256
25
+ private_constant :MAX_MESSAGE_DETAILS_LENGTH
26
+
27
+ # Returns the request path in a form safe for a single log line: the query string is left out
28
+ # and control characters are escaped.
29
+ #
30
+ # @param [String, nil] path
31
+ # @return [String]
32
+ def self.loggable_path(path)
33
+ escape_control_characters(utf8_text(path).split('?', 2).first.to_s)
34
+ end
35
+
36
+ # Builds an exception message from a prefix and a response body. A JSON object body adds its
37
+ # "key: value" pairs as details; any other non-empty body is added as is only when
38
+ # include_text_body is true. Details are shortened and their control characters escaped.
39
+ #
40
+ # @param [String] prefix
41
+ # @param [String, nil] body
42
+ # @param [Boolean] include_text_body
43
+ # @return [String]
44
+ def self.error_message(prefix, body, include_text_body: false)
45
+ text = utf8_text(body).strip
46
+ parsed = json_object(text)
47
+ details = parsed&.map { |key, value| "#{key}: #{value}" }&.join(', ')
48
+ details = text if details.nil? && include_text_body
49
+ return prefix if details.nil? || details.empty?
50
+
51
+ details = "#{details[0, MAX_MESSAGE_DETAILS_LENGTH]}..." if details.length > MAX_MESSAGE_DETAILS_LENGTH
52
+ "#{prefix} Details: #{escape_control_characters(details)}."
53
+ end
54
+
55
+ INVALID_PATH_SEGMENTS = ['', '.', '..'].freeze
56
+ FORBIDDEN_PATH_SEGMENT_BYTES = %r{[/\\\x00-\x1F\x7F]}n.freeze
57
+ INVALID_PATH_SEGMENT_MESSAGE = "Invalid path segment: it must be valid text, not nil, empty, '.' or '..', " \
58
+ "and must not contain '/', '\\' or ASCII control characters"
59
+ private_constant :INVALID_PATH_SEGMENTS, :FORBIDDEN_PATH_SEGMENT_BYTES, :INVALID_PATH_SEGMENT_MESSAGE
60
+
61
+ # Encodes a value as one RFC 3986 path segment. The value is converted to UTF-8 and every byte
62
+ # outside the unreserved set (A-Z, a-z, 0-9, "-", ".", "_", "~") is percent-encoded, so the value
63
+ # always stays a single segment of the request path. The checks run on the converted text.
64
+ #
65
+ # @param [String, Symbol, Integer] value
66
+ # @return [String]
67
+ # @raise [CheckoutArgumentException] when the value is nil, empty, "." or "..", cannot be converted
68
+ # to valid UTF-8, contains "/", "\" or an ASCII control character (U+0000 to U+001F, U+007F), or
69
+ # its to_s does not return a String
70
+ def self.encode_path_segment(value)
71
+ text = value.nil? ? '' : value.to_s
72
+ raise CheckoutArgumentException, INVALID_PATH_SEGMENT_MESSAGE unless text.is_a?(String)
73
+
74
+ bytes = to_valid_utf8(text)&.b
75
+ if bytes.nil? || FORBIDDEN_PATH_SEGMENT_BYTES.match?(bytes)
76
+ raise CheckoutArgumentException, INVALID_PATH_SEGMENT_MESSAGE
77
+ end
78
+
79
+ encoded = bytes.gsub(/[^A-Za-z0-9\-._~]/n) { |byte| format('%%%02X', byte.ord) }
80
+ .force_encoding(Encoding::UTF_8)
81
+ raise CheckoutArgumentException, INVALID_PATH_SEGMENT_MESSAGE if INVALID_PATH_SEGMENTS.include?(encoded)
82
+
83
+ encoded
84
+ end
85
+
86
+ # Returns a copy of the Faraday error, of the same class and with the same backtrace and wrapped
87
+ # exception, that keeps only the response status, headers and body and whose message names the
88
+ # method and URL without the query string. Errors without a response are returned unchanged.
89
+ #
90
+ # @param [Faraday::Error] error
91
+ # @return [Faraday::Error]
92
+ def self.without_request_data(error)
93
+ return error if error.response.nil?
94
+
95
+ metadata = map_to_http_metadata(error.response)
96
+ rebuilt = error.exception(response_error_message(metadata.status_code, error.response))
97
+ rebuilt.instance_variable_set(:@response,
98
+ { status: metadata.status_code, headers: metadata.headers, body: metadata.body })
99
+ rebuilt
100
+ end
101
+
102
+ def self.response_error_message(status, response)
103
+ message = "the server responded with status #{status}"
104
+ request = response.is_a?(Hash) ? response[:request] : nil
105
+ return message unless request.is_a?(Hash) && request[:url]
106
+
107
+ "#{message} for #{request[:method].to_s.upcase} #{loggable_path(request[:url].to_s)}"
108
+ end
109
+ private_class_method :response_error_message
110
+
111
+ def self.json_object(text)
112
+ parsed = JSON.parse(text)
113
+ parsed.is_a?(Hash) ? parsed : nil
114
+ rescue JSON::ParserError
115
+ nil
116
+ end
117
+ private_class_method :json_object
118
+
119
+ # Escapes control characters and Unicode line and paragraph separators in UTF-8 text.
120
+ def self.escape_control_characters(text)
121
+ text.gsub(/[[:cntrl:]\p{Zl}\p{Zp}]/) { |char| char.dump[1..-2] }
122
+ end
123
+ private_class_method :escape_control_characters
124
+
125
+ # Converts text to UTF-8, transcoding from its own encoding. Returns nil when the text cannot be
126
+ # converted or the result is not valid UTF-8.
127
+ def self.to_valid_utf8(text)
128
+ converted = text.encode(Encoding::UTF_8)
129
+ converted.valid_encoding? ? converted : nil
130
+ rescue EncodingError
131
+ nil
132
+ end
133
+ private_class_method :to_valid_utf8
134
+
135
+ # Lenient form of to_valid_utf8 for log and message text: bytes that cannot be converted are read
136
+ # as UTF-8 and invalid sequences are replaced.
137
+ def self.utf8_text(text)
138
+ text = text.to_s
139
+ (to_valid_utf8(text) || text.dup.force_encoding(Encoding::UTF_8)).scrub
140
+ end
141
+ private_class_method :utf8_text
142
+
24
143
  # @return [Faraday::Connection]
25
144
  def self.build_multipart_client
26
145
  Faraday.new do |f|
27
146
  f.request :multipart
28
- f.response :raise_error
147
+ f.response :raise_error, include_request: false
29
148
  end
30
149
  end
31
150
 
@@ -33,7 +152,7 @@ module CheckoutSdk
33
152
  def self.build_default_client
34
153
  Faraday.new do |f|
35
154
  f.response :follow_redirects
36
- f.response :raise_error
155
+ f.response :raise_error, include_request: false
37
156
  end
38
157
  end
39
158
  end
@@ -23,9 +23,15 @@ module CheckoutSdk
23
23
  @configuration = configuration
24
24
  end
25
25
 
26
- # @param [Array] args
26
+ # Joins the arguments into a request path. Each argument is one path segment and is
27
+ # percent-encoded, so it never adds segments, a query or a fragment.
28
+ #
29
+ # @param [Array<String, Symbol, Integer>] args
30
+ # @return [String]
31
+ # @raise [CheckoutArgumentException] when an argument is not a valid path segment (see
32
+ # CheckoutUtils.encode_path_segment)
27
33
  def build_path(*args)
28
- args.join('/')
34
+ args.map { |segment| CheckoutUtils.encode_path_segment(segment) }.join('/')
29
35
  end
30
36
 
31
37
  # @return [TrueClass, FalseClass]
@@ -6,6 +6,16 @@ module CheckoutSdk
6
6
  class CheckoutArgumentException < CheckoutException; end
7
7
 
8
8
  class CheckoutAuthorizationException < CheckoutException
9
+ # @return [CheckoutSdk::HttpMetadata, nil] response status, headers and body when raised for an OAuth token response
10
+ attr_reader :http_metadata
11
+
12
+ # @param [String, nil] message
13
+ # @param [CheckoutSdk::HttpMetadata, nil] http_metadata
14
+ def initialize(message = nil, http_metadata = nil)
15
+ @http_metadata = http_metadata
16
+ super(message)
17
+ end
18
+
9
19
  def self.invalid_authorization(authorization_type)
10
20
  new("Operation requires #{authorization_type} authorization type.")
11
21
  end
@@ -13,6 +23,22 @@ module CheckoutSdk
13
23
  def self.invalid_key(key_type)
14
24
  new("#{key_type} is required for this operation.")
15
25
  end
26
+
27
+ # Builds the error for an unsuccessful OAuth token response from the response data only.
28
+ #
29
+ # @param [CheckoutSdk::HttpMetadata] http_metadata
30
+ # @return [CheckoutSdk::CheckoutAuthorizationException]
31
+ def self.token_request_failed(http_metadata)
32
+ prefix = "The OAuth token response status code (#{http_metadata.status_code}) does not indicate success."
33
+ new(CheckoutUtils.error_message(prefix, http_metadata.body, include_text_body: true), http_metadata)
34
+ end
35
+
36
+ # Builds the error for an OAuth token request that failed without a response.
37
+ #
38
+ # @return [CheckoutSdk::CheckoutAuthorizationException]
39
+ def self.token_request_without_response
40
+ new('The OAuth token request failed without a response.')
41
+ end
16
42
  end
17
43
 
18
44
  class CheckoutApiException < CheckoutException
@@ -35,12 +61,8 @@ module CheckoutSdk
35
61
  end
36
62
 
37
63
  def build_error_message
38
- message = "The API response status code (#{http_metadata.status_code}) does not indicate success."
39
- if @error_details && !@error_details.to_h.empty?
40
- details = @error_details.to_h.map { |key, value| "#{key}: #{value}" }.join(', ')
41
- message += " Details: #{details}."
42
- end
43
- message
64
+ prefix = "The API response status code (#{http_metadata.status_code}) does not indicate success."
65
+ CheckoutUtils.error_message(prefix, http_metadata.body)
44
66
  end
45
67
  end
46
68
  end
@@ -20,7 +20,7 @@ module CheckoutSdk
20
20
 
21
21
  # @param [String,nil] version
22
22
  def retrieve_all_event_types(version = nil)
23
- query = "version=#{version}" unless version.nil?
23
+ query = URI.encode_www_form(version: version) unless version.nil?
24
24
  api_client.invoke_get(EVENT_TYPES, sdk_authorization, query)
25
25
  end
26
26
 
@@ -3,8 +3,9 @@
3
3
  module CheckoutSdk
4
4
  module Instruments
5
5
  class InstrumentsClient < BaseInstrumentsClient
6
- VALIDATION = 'validation/bank-accounts'
7
- private_constant :VALIDATION
6
+ VALIDATION = 'validation'
7
+ BANK_ACCOUNTS = 'bank-accounts'
8
+ private_constant :VALIDATION, :BANK_ACCOUNTS
8
9
 
9
10
  # @param [ApiClient] api_client
10
11
  # @param [CheckoutConfiguration] configuration
@@ -29,7 +30,7 @@ module CheckoutSdk
29
30
  # @param [String] currency {CheckoutSdk::Common::Currency}
30
31
  # @param [Hash, BankAccountFieldQuery] bank_account_field_query
31
32
  def get_bank_account_field_formatting(country, currency, bank_account_field_query)
32
- api_client.invoke_get(build_path(VALIDATION, country, currency),
33
+ api_client.invoke_get(build_path(VALIDATION, BANK_ACCOUNTS, country, currency),
33
34
  sdk_authorization(CheckoutSdk::AuthorizationType::OAUTH),
34
35
  bank_account_field_query)
35
36
  end
@@ -65,17 +65,7 @@ module CheckoutSdk
65
65
  scope: @scopes.join(' ')
66
66
  }
67
67
 
68
- headers = { 'Content-Type': 'application/x-www-form-urlencoded' }
69
- body = URI.encode_www_form data
70
-
71
- begin
72
- @log.info "post: #{authorization_uri}"
73
- response = @oauth_http_client.run_request(:post, @authorization_uri, body, headers)
74
- rescue Faraday::ClientError => e
75
- raise CheckoutAuthorizationException, e.response
76
- rescue Faraday::ConnectionFailed => e
77
- raise CheckoutArgumentException, e.wrapped_exception
78
- end
68
+ response = request_access_token(URI.encode_www_form(data))
79
69
 
80
70
  if !response.body.nil? && response.body != ''
81
71
  oauth_response = JSON.parse(response.body, object_class: OpenStruct)
@@ -90,6 +80,23 @@ module CheckoutSdk
90
80
 
91
81
  private
92
82
 
83
+ # @param [String] body
84
+ # @return [Faraday::Response]
85
+ def request_access_token(body)
86
+ headers = { 'Content-Type': 'application/x-www-form-urlencoded' }
87
+ @log.info "post: #{CheckoutUtils.loggable_path(authorization_uri)}"
88
+ @oauth_http_client.run_request(:post, @authorization_uri, body, headers)
89
+ rescue Faraday::ClientError => e
90
+ raise CheckoutAuthorizationException.token_request_without_response if e.response.nil?
91
+
92
+ raise CheckoutAuthorizationException.token_request_failed(CheckoutUtils.map_to_http_metadata(e.response)),
93
+ cause: nil
94
+ rescue Faraday::ConnectionFailed => e
95
+ raise CheckoutArgumentException, e.wrapped_exception
96
+ rescue Faraday::Error => e
97
+ raise CheckoutUtils.without_request_data(e), cause: nil
98
+ end
99
+
93
100
  # @param [String] client_id
94
101
  # @param [String] client_secret
95
102
  # @param [Environment] environment
@@ -248,6 +248,8 @@ module CheckoutSdk
248
248
  # :schemes (supported card scheme names; Google Pay never lists cartes_bancaires) and card
249
249
  # details :last4, :bin, :scheme (Strings) and :expires_on (date-time); instrument returns the
250
250
  # read-only :type (String) and :action (:type, "set_instrument").
251
+ # @raise [CheckoutArgumentException] when id or payment_method_name is not a valid path segment
252
+ # (see Client#build_path)
251
253
  def confirm_payment_setup(id, payment_method_name)
252
254
  api_client.invoke_post(
253
255
  build_path(PAYMENTS_PATH, SETUPS_PATH, id, CONFIRM_PATH, payment_method_name),
@@ -5,9 +5,11 @@ module CheckoutSdk
5
5
  # @deprecated Risk endpoints are no longer supported officially, This module will be removed in a
6
6
  # future release.
7
7
  class RiskClient < Client
8
- PRE_AUTHENTICATION = 'risk/assessments/pre-authentication'
9
- PRE_CAPTURE = 'risk/assessments/pre-capture'
10
- private_constant :PRE_AUTHENTICATION, :PRE_CAPTURE
8
+ RISK = 'risk'
9
+ ASSESSMENTS = 'assessments'
10
+ PRE_AUTHENTICATION = 'pre-authentication'
11
+ PRE_CAPTURE = 'pre-capture'
12
+ private_constant :RISK, :ASSESSMENTS, :PRE_AUTHENTICATION, :PRE_CAPTURE
11
13
 
12
14
  # @param [ApiClient] api_client
13
15
  # @param [CheckoutConfiguration] configuration
@@ -17,12 +19,14 @@ module CheckoutSdk
17
19
 
18
20
  # @param [Hash, PreAuthenticationAssessment] pre_authentication_request
19
21
  def pre_authentication_scan(pre_authentication_request)
20
- api_client.invoke_post(PRE_AUTHENTICATION, sdk_authorization, pre_authentication_request)
22
+ api_client.invoke_post(build_path(RISK, ASSESSMENTS, PRE_AUTHENTICATION),
23
+ sdk_authorization,
24
+ pre_authentication_request)
21
25
  end
22
26
 
23
27
  # @param [Hash, PreCaptureAssessment] pre_capture_request
24
28
  def pre_capture_scan(pre_capture_request)
25
- api_client.invoke_post(PRE_CAPTURE, sdk_authorization, pre_capture_request)
29
+ api_client.invoke_post(build_path(RISK, ASSESSMENTS, PRE_CAPTURE), sdk_authorization, pre_capture_request)
26
30
  end
27
31
  end
28
32
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CheckoutSdk
4
- VERSION = '2.8.0'
4
+ VERSION = '2.8.2'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: checkout_sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.0
4
+ version: 2.8.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Checkout
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-11-02 00:00:00.000000000 Z
11
+ date: 2026-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0.60'
69
+ - !ruby/object:Gem::Dependency
70
+ name: csv
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: faraday
71
85
  requirement: !ruby/object:Gem::Requirement