checkout_sdk 2.7.1 → 2.8.1

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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -0
  3. data/lib/checkout_sdk/api_client.rb +11 -6
  4. data/lib/checkout_sdk/checkout_utils.rb +77 -2
  5. data/lib/checkout_sdk/common/account_holder.rb +78 -1
  6. data/lib/checkout_sdk/common/account_holder_identification.rb +21 -0
  7. data/lib/checkout_sdk/common/common.rb +1 -0
  8. data/lib/checkout_sdk/common/customer_retry.rb +14 -2
  9. data/lib/checkout_sdk/common/residential_status_type.rb +11 -0
  10. data/lib/checkout_sdk/error.rb +28 -6
  11. data/lib/checkout_sdk/events/events_client.rb +1 -1
  12. data/lib/checkout_sdk/issuing/card_update_headers.rb +11 -12
  13. data/lib/checkout_sdk/issuing/issuing_client.rb +20 -11
  14. data/lib/checkout_sdk/oauth_sdk_credentials.rb +18 -11
  15. data/lib/checkout_sdk/payments/card_payout_item.rb +24 -0
  16. data/lib/checkout_sdk/payments/card_payout_processing.rb +39 -0
  17. data/lib/checkout_sdk/payments/destination/bank_account_destination.rb +29 -0
  18. data/lib/checkout_sdk/payments/destination/card_destination.rb +20 -0
  19. data/lib/checkout_sdk/payments/destination/destination.rb +5 -0
  20. data/lib/checkout_sdk/payments/destination/destination_type.rb +7 -0
  21. data/lib/checkout_sdk/payments/destination/id_destination.rb +16 -0
  22. data/lib/checkout_sdk/payments/destination/network_token_destination.rb +63 -0
  23. data/lib/checkout_sdk/payments/destination/token_destination.rb +15 -0
  24. data/lib/checkout_sdk/payments/downtime_retry_request.rb +14 -0
  25. data/lib/checkout_sdk/payments/dunning_retry_request.rb +22 -0
  26. data/lib/checkout_sdk/payments/hosted/hosted_payment_instruction.rb +9 -0
  27. data/lib/checkout_sdk/payments/hosted/hosted_payments_session.rb +42 -31
  28. data/lib/checkout_sdk/payments/instruction_remittance.rb +17 -0
  29. data/lib/checkout_sdk/payments/instruction_scheme.rb +5 -0
  30. data/lib/checkout_sdk/payments/links/payment_link.rb +50 -29
  31. data/lib/checkout_sdk/payments/payment_instruction.rb +48 -1
  32. data/lib/checkout_sdk/payments/payment_request.rb +1 -1
  33. data/lib/checkout_sdk/payments/payment_retry_request.rb +9 -7
  34. data/lib/checkout_sdk/payments/payment_segment.rb +11 -0
  35. data/lib/checkout_sdk/payments/payment_type.rb +4 -1
  36. data/lib/checkout_sdk/payments/payments.rb +10 -0
  37. data/lib/checkout_sdk/payments/payments_client.rb +10 -0
  38. data/lib/checkout_sdk/payments/payout_billing_descriptor.rb +10 -0
  39. data/lib/checkout_sdk/payments/payout_request.rb +59 -1
  40. data/lib/checkout_sdk/payments/sender/corporate_sender.rb +19 -0
  41. data/lib/checkout_sdk/payments/sender/government_sender.rb +21 -0
  42. data/lib/checkout_sdk/payments/sender/individual_sender.rb +46 -0
  43. data/lib/checkout_sdk/payments/sender/instrument_sender.rb +3 -0
  44. data/lib/checkout_sdk/payments/sender/sender.rb +16 -0
  45. data/lib/checkout_sdk/payments/sessions/payment_sessions_request.rb +55 -32
  46. data/lib/checkout_sdk/payments/setups/account_funding_transaction_identification.rb +10 -1
  47. data/lib/checkout_sdk/payments/setups/account_funding_transaction_identification_type.rb +5 -4
  48. data/lib/checkout_sdk/payments/setups/account_funding_transaction_recipient.rb +29 -1
  49. data/lib/checkout_sdk/payments/setups/account_funding_transaction_sender.rb +34 -1
  50. data/lib/checkout_sdk/payments/setups/bacs_payment_method.rb +70 -34
  51. data/lib/checkout_sdk/payments/setups/cash_app_payment_method.rb +3 -3
  52. data/lib/checkout_sdk/payments/setups/payment_setup_payment_type.rb +19 -0
  53. data/lib/checkout_sdk/payments/setups/payment_setups_client.rb +10 -0
  54. data/lib/checkout_sdk/payments/source/currency_account_source.rb +8 -0
  55. data/lib/checkout_sdk/payments/source/entity_source.rb +5 -0
  56. data/lib/checkout_sdk/payments/source/payout_source.rb +12 -1
  57. data/lib/checkout_sdk/payments/unreferenced_refund_request.rb +89 -0
  58. data/lib/checkout_sdk/version.rb +1 -1
  59. metadata +25 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ffa084c12fc5f4e0c765b41a3e4dd3e970ca006584c25623106e93dae1c6001
4
- data.tar.gz: 8b69b0fff53b0eb662383c47f36af073aad85adca12d6d7edb46db9323859eb9
3
+ metadata.gz: 9849ed54d294ed9bea5fdb04bb5378fb55b942a2adb0ffe0653cb5c628cc0882
4
+ data.tar.gz: 7bd35374ce13e3feb72eb37a16930316ab6a01ce2cc10c49245f3e5a2daf6229
5
5
  SHA512:
6
- metadata.gz: c4d4935f79a0e91ce703cae0dbdf02e6445065525e501cba3401adf956de27d7ea399e75d52b230e7c3de5279e5e2d5936fff9fcc77f556b19aae6b80c7de801
7
- data.tar.gz: a209f2204ed7275f7e9b880dc4fe0c55758eefbd3687d8c83eed8596c3c69f701f4aadd0193c5d79e4da241756eeb19eaf21f88feefc1f49de076df41d8c3b2d
6
+ metadata.gz: b6f8c31a1c66aecb8b8fad6345a2b693f133b8bee59376920445caa7779db02a3f18882170318870c5f86fb728d898a4baffc32a0b71159d8b1fa4e17087c144
7
+ data.tar.gz: 6bdaf1a3c38c96bcafe0f52135ff77edda7a51d66946df1bc7d4b4d8e9e5729bf85f017e0a3a755567466e9132b4464428b7861ee58e56040fbf74294bc97598
data/README.md CHANGED
@@ -172,6 +172,10 @@ api = CheckoutSdk.builder
172
172
  .build
173
173
  ```
174
174
 
175
+ If your connection uses the `raise_error` middleware, configure it as the default client does:
176
+ `conn.response :raise_error, include_request: false` (the option needs Faraday 2.7.11 or later;
177
+ the SDK leaves the request data out of the errors it raises in any case).
178
+
175
179
  You don't need to specify the URL for Faraday constructor the SDK grabs the belong URI from `CheckoutSdk::Environment`
176
180
  however if you want to
177
181
  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)
@@ -68,8 +70,9 @@ module CheckoutSdk
68
70
 
69
71
  # Attribute name to HTTP header name, for every typed headers container the SDK supports.
70
72
  #
71
- # The header names are case sensitive in the spec: return-encrypted-cvv is lower case where a
72
- # naive conversion would produce Return-Encrypted-Cvv.
73
+ # The header names are emitted with an exact spelling: return-encrypted-cvv (sent by the
74
+ # deprecated CardUpdateHeaders) is lower case where a naive conversion would produce
75
+ # Return-Encrypted-Cvv.
73
76
  #
74
77
  # The values are Strings, not Symbols, and that is load bearing. Faraday::Utils::Headers
75
78
  # preserves a String key verbatim but rewrites a Symbol key as
@@ -139,10 +142,12 @@ module CheckoutSdk
139
142
  form = build_multipart_request(file_request, file)
140
143
 
141
144
  begin
142
- @log.info "post: /#{path}"
145
+ @log.info "post: /#{CheckoutUtils.loggable_path(path)}"
143
146
  response = @multipart_client.run_request(:post, path, form, headers)
144
147
  rescue Faraday::ClientError => e
145
- 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
146
151
  end
147
152
 
148
153
  parse_response(response)
@@ -21,11 +21,86 @@ 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
+ # Returns a copy of the Faraday error, of the same class and with the same backtrace and wrapped
56
+ # exception, that keeps only the response status, headers and body and whose message names the
57
+ # method and URL without the query string. Errors without a response are returned unchanged.
58
+ #
59
+ # @param [Faraday::Error] error
60
+ # @return [Faraday::Error]
61
+ def self.without_request_data(error)
62
+ return error if error.response.nil?
63
+
64
+ metadata = map_to_http_metadata(error.response)
65
+ rebuilt = error.exception(response_error_message(metadata.status_code, error.response))
66
+ rebuilt.instance_variable_set(:@response,
67
+ { status: metadata.status_code, headers: metadata.headers, body: metadata.body })
68
+ rebuilt
69
+ end
70
+
71
+ def self.response_error_message(status, response)
72
+ message = "the server responded with status #{status}"
73
+ request = response.is_a?(Hash) ? response[:request] : nil
74
+ return message unless request.is_a?(Hash) && request[:url]
75
+
76
+ "#{message} for #{request[:method].to_s.upcase} #{loggable_path(request[:url].to_s)}"
77
+ end
78
+ private_class_method :response_error_message
79
+
80
+ def self.json_object(text)
81
+ parsed = JSON.parse(text)
82
+ parsed.is_a?(Hash) ? parsed : nil
83
+ rescue JSON::ParserError
84
+ nil
85
+ end
86
+ private_class_method :json_object
87
+
88
+ # Escapes control characters and Unicode line and paragraph separators in UTF-8 text.
89
+ def self.escape_control_characters(text)
90
+ text.gsub(/[[:cntrl:]\p{Zl}\p{Zp}]/) { |char| char.dump[1..-2] }
91
+ end
92
+ private_class_method :escape_control_characters
93
+
94
+ def self.utf8_text(text)
95
+ text.to_s.dup.force_encoding(Encoding::UTF_8).scrub
96
+ end
97
+ private_class_method :utf8_text
98
+
24
99
  # @return [Faraday::Connection]
25
100
  def self.build_multipart_client
26
101
  Faraday.new do |f|
27
102
  f.request :multipart
28
- f.response :raise_error
103
+ f.response :raise_error, include_request: false
29
104
  end
30
105
  end
31
106
 
@@ -33,7 +108,7 @@ module CheckoutSdk
33
108
  def self.build_default_client
34
109
  Faraday.new do |f|
35
110
  f.response :follow_redirects
36
- f.response :raise_error
111
+ f.response :raise_error, include_request: false
37
112
  end
38
113
  end
39
114
  end
@@ -2,37 +2,114 @@
2
2
 
3
3
  module CheckoutSdk
4
4
  module Common
5
+ # The account holder of a payment source, an instrument, or a payout or unreferenced refund destination.
6
+ # This class is shared by many positions; the per-position notes below cover the card payout, bank payout
7
+ # and unreferenced refund destinations. Each position only accepts the keys its schema declares, so leave
8
+ # the other properties unset.
9
+ # - Card payout card and network_token destinations: type, first_name, middle_name, last_name,
10
+ # billing_address, phone, identification, email, date_of_birth, country_of_birth.
11
+ # - Card payout id and token destinations: type, first_name, middle_name, last_name, company_name.
12
+ # - Bank payout bank_account destination: type, first_name, last_name, company_name, tax_id,
13
+ # date_of_birth, country_of_birth, residential_status, billing_address, phone, identification.
14
+ # - Unreferenced refund destinations: as the card payout card and network_token destinations.
15
+ #
5
16
  # @!attribute type
17
+ # The type of account holder.
18
+ # [Required] for payout and unreferenced refund destinations (when the account holder is sent)
19
+ # Enum: "individual" "corporate" "government"
6
20
  # @return [String] {AccountHolderType}
7
21
  # @!attribute full_name
22
+ # The account holder's full name.
23
+ # [Optional]
24
+ # @deprecated Not in the request schema of any account holder. Still returned in the PayPal payment
25
+ # details source account_holder.
26
+ # Retained for backwards compatibility and will be removed in the next major version. There is no
27
+ # replacement.
8
28
  # @return [String]
9
29
  # @!attribute first_name
30
+ # The account holder's legal first name. The combination of first_name, middle_name and last_name
31
+ # should exceed 3 letters in length for card payouts. A single character or all non-alphabetic
32
+ # characters return a field validation error.
33
+ # [Required] for individual account holders in card payouts, bank payouts and the unreferenced refund
34
+ # card and network_token destinations; [Optional] for the unreferenced refund id and token
35
+ # destinations. In the card payout id and token destinations it is not required if the first name is
36
+ # already stored with the token or instrument.
37
+ # max 50 characters (card payouts and unreferenced refunds)
10
38
  # @return [String]
11
39
  # @!attribute middle_name
40
+ # The account holder's middle name.
41
+ # [Optional] Card payouts and unreferenced refunds only.
42
+ # max 50 characters
12
43
  # @return [String]
13
44
  # @!attribute last_name
45
+ # The account holder's legal last name. The combination of first_name, middle_name and last_name
46
+ # should exceed 3 letters in length for card payouts. A single character or all non-alphabetic
47
+ # characters return a field validation error.
48
+ # [Required] for individual account holders in card payouts, bank payouts and the unreferenced refund
49
+ # card and network_token destinations; [Optional] for the unreferenced refund id and token
50
+ # destinations. In the card payout id and token destinations it is not required if the last name is
51
+ # already stored with the token or instrument.
52
+ # max 50 characters (card payouts and unreferenced refunds)
14
53
  # @return [String]
15
54
  # @!attribute email
55
+ # The account holder's email address.
56
+ # [Optional] Card payout card and network_token destinations and unreferenced refunds only.
57
+ # max 255 characters
16
58
  # @return [String]
17
59
  # @!attribute gender
60
+ # The account holder's gender.
61
+ # [Optional]
62
+ # @deprecated Not in the request schema of any account holder. Still returned in the Klarna payment
63
+ # details source account_holder.
64
+ # Retained for backwards compatibility and will be removed in the next major version. There is no
65
+ # replacement.
18
66
  # @return [String]
19
67
  # @!attribute company_name
68
+ # The legal name of the corporate or government account holder. A single character or all
69
+ # non-alphabetic characters return a field validation error.
70
+ # [Required] for corporate and government payout and unreferenced refund destinations
71
+ # max 50 characters (card payouts and unreferenced refunds)
20
72
  # @return [String]
21
73
  # @!attribute tax_id
74
+ # The legal account holder's tax number or reference.
75
+ # [Optional] Bank payouts only.
22
76
  # @return [String]
23
77
  # @!attribute date_of_birth
78
+ # The account holder's date of birth, in the format YYYY-MM-DD. Individual account holders only.
79
+ # [Optional]
80
+ # 10 characters (card payouts and unreferenced refunds)
24
81
  # @return [String]
25
82
  # @!attribute country_of_birth
26
- # @return [Country]
83
+ # The account holder's country of birth, as a two-letter ISO country code. Individual account holders
84
+ # only.
85
+ # [Optional]
86
+ # 2 characters
87
+ # @return [String] {Country}
27
88
  # @!attribute residential_status
89
+ # The account holder's residential status.
90
+ # [Optional] Bank payouts only.
91
+ # Enum: "resident" "non_resident"
28
92
  # @return [String] {ResidentialStatusType}
29
93
  # @!attribute billing_address
94
+ # The account holder's billing address. For card payouts and unreferenced refunds, it is required if
95
+ # your company is incorporated in the United States.
96
+ # [Required] for individual bank payout destinations, [Optional] otherwise
30
97
  # @return [Address]
31
98
  # @!attribute phone
99
+ # The account holder's phone number.
100
+ # [Optional] Not part of the card payout id and token destinations, nor of the corporate and
101
+ # government bank payout destinations.
32
102
  # @return [Phone]
33
103
  # @!attribute identification
104
+ # The account holder's identification. Providing identification details for the payout recipient
105
+ # increases the likelihood of a successful payout.
106
+ # [Optional] Not part of the card payout id and token destinations, nor of the corporate and
107
+ # government bank payout destinations.
34
108
  # @return [AccountHolderIdentification]
35
109
  # @!attribute account_name_inquiry
110
+ # Whether the ANI (account name inquiry) check should be performed with the scheme (Visa or
111
+ # Mastercard). Payment sources only.
112
+ # [Optional] Not declared by the payout or unreferenced refund destination schemas.
36
113
  # @return [Boolean]
37
114
  class AccountHolder
38
115
  attr_accessor :type,
@@ -2,13 +2,34 @@
2
2
 
3
3
  module CheckoutSdk
4
4
  module Common
5
+ # The identification of an account holder or a sender. Shared by the card payout, bank payout,
6
+ # unreferenced refund and regular payment positions.
7
+ #
5
8
  # @!attribute type
9
+ # The type of identification.
10
+ # [Required] for card payout and unreferenced refund account holders and card payout senders,
11
+ # [Optional] for bank payout and regular payment senders and bank payout account holders
12
+ # Enum: "passport" "driving_license" "national_id" "company_registration" "tax_id" (card payouts and
13
+ # unreferenced refunds); "passport" "driving_licence" "national_id" (bank payout and regular payment
14
+ # senders)
6
15
  # @return [String] {AccountHolderIdentificationType}
7
16
  # @!attribute number
17
+ # The identification number.
18
+ # [Required] for card payout and unreferenced refund account holders and card payout senders,
19
+ # [Optional] for bank payout and regular payment senders and bank payout account holders
20
+ # max 25 characters (card payout and unreferenced refund account holders)
8
21
  # @return [String]
9
22
  # @!attribute issuing_country
23
+ # If applicable, the country that issued the identification, as a two-letter ISO country code.
24
+ # Providing it increases the likelihood of a successful identity verification.
25
+ # [Optional]
26
+ # 2 characters (card payouts and unreferenced refunds)
10
27
  # @return [String] {Country}
11
28
  # @!attribute date_of_expiry
29
+ # If applicable, the expiration date of the identification, in the format YYYY-MM-DD.
30
+ # Card payouts and unreferenced refunds only.
31
+ # [Optional]
32
+ # 10 characters
12
33
  # @return [String]
13
34
  class AccountHolderIdentification
14
35
  attr_accessor :type,
@@ -9,6 +9,7 @@ require 'checkout_sdk/common/account_holder'
9
9
  require 'checkout_sdk/common/country'
10
10
  require 'checkout_sdk/common/account_holder_identification_type'
11
11
  require 'checkout_sdk/common/account_holder_type'
12
+ require 'checkout_sdk/common/residential_status_type'
12
13
  require 'checkout_sdk/common/instrument_type'
13
14
  require 'checkout_sdk/common/bank_details'
14
15
  require 'checkout_sdk/common/payment_source_type'
@@ -1,11 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CheckoutSdk
4
- module Accounts
4
+ module Common
5
+ # Configures the parameters for customer retries. A customer retry is a payment attempt
6
+ # performed by the customer on the checkout page, used by hosted payments, payment links
7
+ # and payment sessions.
8
+ #
5
9
  # @!attribute max_attempts
6
- # @return [Integer]
10
+ # @return [Integer] [Optional] The maximum number of customer retry attempts, excluding the
11
+ # initial payment attempt. Minimum 0, maximum 5. Default 5.
12
+ # Required when used in a payment sessions request.
7
13
  class CustomerRetry
8
14
  attr_accessor :max_attempts
9
15
  end
10
16
  end
17
+
18
+ module Accounts
19
+ # @deprecated Please use {CheckoutSdk::Common::CustomerRetry} instead. This alias will be
20
+ # removed in the next major version.
21
+ CustomerRetry = CheckoutSdk::Common::CustomerRetry
22
+ end
11
23
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CheckoutSdk
4
+ module Common
5
+ # The account holder's residential status (bank payout and refund destination account holders).
6
+ module ResidentialStatusType
7
+ RESIDENT = 'resident'
8
+ NON_RESIDENT = 'non_resident'
9
+ end
10
+ end
11
+ end
@@ -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
 
@@ -4,26 +4,25 @@ module CheckoutSdk
4
4
  module Issuing
5
5
  # The optional HTTP headers accepted when updating a card's details.
6
6
  #
7
+ # @deprecated The API no longer documents these headers; use the method without headers. Will
8
+ # be removed in the next major version. Headers that are set are still sent unchanged.
9
+ #
7
10
  # Modelled as its own class rather than added to {CheckoutSdk::Common::Headers} because these
8
11
  # two headers belong to one endpoint, and Common::Headers is shared by every client.
9
12
  #
10
13
  # @!attribute return_encrypted_cvv
11
- # Set to "true" to retrieve the card's encrypted credentials in the response. Requires an
12
- # RSA public key in the Encryption-Key header, otherwise the API answers 422 with error code
13
- # encryption_key_required.
14
- #
15
- # A String rather than a boolean: the value is emitted verbatim as an HTTP header, and "true"
16
- # is what the spec shows.
14
+ # @deprecated The API no longer documents these headers; use the method without headers.
15
+ # Will be removed in the next major version.
16
+ # No longer documented by the API. Still sent unchanged as the return-encrypted-cvv HTTP
17
+ # header when set.
17
18
  # [Optional]
18
- # Maps to HTTP header return-encrypted-cvv.
19
- # Example: "true"
20
19
  # @return [String]
21
20
  # @!attribute encryption_key
22
- # The RSA public key used to encrypt returned credentials. Required when
23
- # return_encrypted_cvv is set. Provide the public key with the BEGIN PUBLIC KEY and END
24
- # PUBLIC KEY headers and any newline characters removed, encoded as Base64.
21
+ # @deprecated The API no longer documents these headers; use the method without headers.
22
+ # Will be removed in the next major version.
23
+ # No longer documented by the API. Still sent unchanged as the Encryption-Key HTTP header
24
+ # when set.
25
25
  # [Optional]
26
- # Maps to HTTP header Encryption-Key.
27
26
  # @return [String]
28
27
  class CardUpdateHeaders
29
28
  attr_accessor :return_encrypted_cvv, :encryption_key
@@ -90,13 +90,13 @@ module CheckoutSdk
90
90
  #
91
91
  # @param [String] card_id
92
92
  # @param [Hash, UpdateCardRequest] update_card_request
93
- # @param [CardUpdateHeaders, nil] headers the optional return-encrypted-cvv and
94
- # Encryption-Key HTTP headers. Setting return_encrypted_cvv without encryption_key returns
95
- # a 422 with error code encryption_key_required.
96
- # @return [OpenStruct] the update response, carrying encrypted_cvv when requested. For a
97
- # virtual card the response may also carry is_single_use (boolean, default false),
98
- # specifying whether the card is set to expire after a single use. Physical cards never
99
- # send it.
93
+ # @param [CardUpdateHeaders, nil] headers deprecated. The API no longer documents these
94
+ # headers; use the method without headers. Will be removed in the next major version.
95
+ # When set, the return-encrypted-cvv and Encryption-Key headers are still sent unchanged.
96
+ # @return [OpenStruct] the update-card-response: the updated card details and _links. The
97
+ # type field discriminates the variant; a virtual card response also carries
98
+ # is_single_use (boolean, default false), whether the card expires after a single use.
99
+ # Physical card responses never carry it.
100
100
  def update_card(card_id, update_card_request, headers = nil)
101
101
  api_client.invoke_patch(
102
102
  build_path(ISSUING, CARDS, card_id),
@@ -134,15 +134,24 @@ module CheckoutSdk
134
134
  api_client.invoke_get(build_path(ISSUING, CARDS, card_id, CREDENTIALS), sdk_authorization, query)
135
135
  end
136
136
 
137
+ # Revoke a card. POST /issuing/cards/{cardId}/revoke. The request body is optional; when
138
+ # omitted an empty JSON object is sent.
137
139
  # @param [String] card_id
138
- # @param [Hash] revoke_request
139
- def revoke_card(card_id, revoke_request)
140
+ # @param [Hash, nil] revoke_request optional, may carry reason (expired, reported_lost,
141
+ # reported_stolen)
142
+ # @return [OpenStruct] the revoke-card-response, carrying _links with self and controls.
143
+ def revoke_card(card_id, revoke_request = nil)
140
144
  api_client.invoke_post(build_path(ISSUING, CARDS, card_id, REVOKE), sdk_authorization, revoke_request)
141
145
  end
142
146
 
147
+ # Suspend a card. POST /issuing/cards/{cardId}/suspend. The request body is optional; when
148
+ # omitted an empty JSON object is sent.
143
149
  # @param [String] card_id
144
- # @param [Hash] suspend_request
145
- def suspend_card(card_id, suspend_request)
150
+ # @param [Hash, nil] suspend_request optional, may carry reason (suspected_lost,
151
+ # suspected_stolen)
152
+ # @return [OpenStruct] the suspend-card-response, carrying _links with self, activate,
153
+ # revoke and controls.
154
+ def suspend_card(card_id, suspend_request = nil)
146
155
  api_client.invoke_post(build_path(ISSUING, CARDS, card_id, SUSPEND), sdk_authorization, suspend_request)
147
156
  end
148
157
 
@@ -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
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CheckoutSdk
4
+ module Payments
5
+ # A line item of a card payout.
6
+ #
7
+ # @!attribute type
8
+ # The item type. For example, physical or digital.
9
+ # This field is used to provide item level metadata where applicable.
10
+ # [Optional]
11
+ # Enum: "digital" "physical"
12
+ # @return [String] {ProductItemType}
13
+ # @!attribute sub_type
14
+ # The digital item type.
15
+ # If type is set to digital, this field is required.
16
+ # [Optional]
17
+ # Enum: "blockchain" "cbdc" "cryptocurrency" "nft" "stablecoin"
18
+ # @return [String] {ProductSubType}
19
+ class CardPayoutItem
20
+ attr_accessor :type,
21
+ :sub_type
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CheckoutSdk
4
+ module Payments
5
+ # Information related to the processing of a card payout.
6
+ #
7
+ # @!attribute affiliate_id
8
+ # The unique identifier for Visa-registered ramp providers.
9
+ # Must only contain alphanumeric characters.
10
+ # If you're a Visa-registered ramp provider operating with affiliates, this field is required.
11
+ # [Optional]
12
+ # ^[a-zA-Z0-9]{1,15}$
13
+ # max 15 characters
14
+ # @return [String]
15
+ # @!attribute affiliate_url
16
+ # The affiliate URL.
17
+ # If you're a Visa-registered ramp provider operating with affiliates, this field is required.
18
+ # [Optional]
19
+ # @return [String]
20
+ # @!attribute processing_speed
21
+ # The speed at which the payout is processed.
22
+ # Only applicable for unreferenced refunds.
23
+ # [Optional]
24
+ # Enum: "fast"
25
+ # @return [String]
26
+ # @!attribute purchase_country
27
+ # The two-letter ISO country code of the purchase country.
28
+ # If you're a Visa-registered ramp provider operating with affiliates, this field is required.
29
+ # [Optional]
30
+ # max 2 characters
31
+ # @return [String] {CheckoutSdk::Common::Country}
32
+ class CardPayoutProcessing
33
+ attr_accessor :affiliate_id,
34
+ :affiliate_url,
35
+ :processing_speed,
36
+ :purchase_country
37
+ end
38
+ end
39
+ end