diff --git a/lib/checkout_sdk/common/customer_retry.rb b/lib/checkout_sdk/common/customer_retry.rb index ef5f253..d1a4270 100644 --- a/lib/checkout_sdk/common/customer_retry.rb +++ b/lib/checkout_sdk/common/customer_retry.rb @@ -1,11 +1,23 @@ # frozen_string_literal: true module CheckoutSdk - module Accounts + module Common + # Configures the parameters for customer retries. A customer retry is a payment attempt + # performed by the customer on the checkout page, used by hosted payments, payment links + # and payment sessions. + # # @!attribute max_attempts - # @return [Integer] + # @return [Integer] [Optional] The maximum number of customer retry attempts, excluding the + # initial payment attempt. Minimum 0, maximum 5. Default 5. + # Required when used in a payment sessions request. class CustomerRetry attr_accessor :max_attempts end end + + module Accounts + # @deprecated Please use {CheckoutSdk::Common::CustomerRetry} instead. This alias will be + # removed in the next major version. + CustomerRetry = CheckoutSdk::Common::CustomerRetry + end end diff --git a/lib/checkout_sdk/payments/downtime_retry_request.rb b/lib/checkout_sdk/payments/downtime_retry_request.rb new file mode 100644 index 0000000..1735c1a --- /dev/null +++ b/lib/checkout_sdk/payments/downtime_retry_request.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module CheckoutSdk + module Payments + # Configuration of Downtime retries. + # + # @!attribute enabled + # @return [TrueClass, FalseClass] [Required] Indicates if Checkout.com retries the payment when it's declined + # due to issuer or acquirer downtime. + class DowntimeRetryRequest + attr_accessor :enabled + end + end +end diff --git a/lib/checkout_sdk/payments/dunning_retry_request.rb b/lib/checkout_sdk/payments/dunning_retry_request.rb new file mode 100644 index 0000000..1be7456 --- /dev/null +++ b/lib/checkout_sdk/payments/dunning_retry_request.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module CheckoutSdk + module Payments + # Configuration of Dunning retries. + # + # @!attribute enabled + # @return [TrueClass, FalseClass] [Required] Indicates if Checkout.com retries the payment when it's declined + # with a supported decline code. + # @!attribute max_attempts + # @return [Integer] [Optional] The maximum number of authorization retry attempts, excluding the initial + # authorization. Minimum 1, maximum 15. Default 6. + # @!attribute end_after_days + # @return [Integer] [Optional] The maximum number of days between the initial request and the final retry + # attempt. Minimum 1, maximum 60. Default 30. + class DunningRetryRequest + attr_accessor :enabled, + :max_attempts, + :end_after_days + end + end +end diff --git a/lib/checkout_sdk/payments/hosted/hosted_payments_session.rb b/lib/checkout_sdk/payments/hosted/hosted_payments_session.rb index f319295..abbc61b 100644 --- a/lib/checkout_sdk/payments/hosted/hosted_payments_session.rb +++ b/lib/checkout_sdk/payments/hosted/hosted_payments_session.rb @@ -49,7 +49,8 @@ module Payments # @!attribute risk # @return [RiskRequest] # @!attribute customer_retry - # @return [PaymentRetryRequest] + # @return [CheckoutSdk::Common::CustomerRetry] [Optional] Configures the parameters for customer retries + # performed by the customer on the checkout page. # @!attribute sender # @return [CheckoutSdk::Payments::Sender] # @!attribute metadata diff --git a/lib/checkout_sdk/payments/links/payment_link.rb b/lib/checkout_sdk/payments/links/payment_link.rb index 3679a28..ed4bb50 100644 --- a/lib/checkout_sdk/payments/links/payment_link.rb +++ b/lib/checkout_sdk/payments/links/payment_link.rb @@ -49,7 +49,8 @@ module Payments # @!attribute risk # @return [RiskRequest] # @!attribute customer_retry - # @return [CheckoutSdk::Common::CustomerRetry] + # @return [CheckoutSdk::Common::CustomerRetry] [Optional] Configures the parameters for customer retries + # performed by the customer on the checkout page. # @!attribute sender # @return [CheckoutSdk::Payments::Sender] # @!attribute return_url diff --git a/lib/checkout_sdk/payments/payment_request.rb b/lib/checkout_sdk/payments/payment_request.rb index 9ce278b..b3a9a77 100644 --- a/lib/checkout_sdk/payments/payment_request.rb +++ b/lib/checkout_sdk/payments/payment_request.rb @@ -62,7 +62,7 @@ module Payments # @!attribute items # @return [Array(Product)] # @!attribute retry - # @return [PaymentRetryRequest] + # @return [PaymentRetryRequest] [Optional] Configuration of asynchronous retries. # @!attribute metadata # @return [Hash{String => Object}] # @!attribute instruction diff --git a/lib/checkout_sdk/payments/payment_retry_request.rb b/lib/checkout_sdk/payments/payment_retry_request.rb index b8fb06e..eb6ac59 100644 --- a/lib/checkout_sdk/payments/payment_retry_request.rb +++ b/lib/checkout_sdk/payments/payment_retry_request.rb @@ -2,15 +2,33 @@ module CheckoutSdk module Payments + # Configuration of asynchronous retries (POST /payments). + # # @!attribute enabled - # @return [TrueClass, FalseClass] + # @return [TrueClass, FalseClass] [Required] Indicates whether asynchronous retries are enabled for the payment. + # @!attribute dunning + # @return [DunningRetryRequest] [Optional] Configuration of asynchronous Dunning retries. + # @!attribute downtime + # @return [DowntimeRetryRequest] [Optional] Configuration of asynchronous Downtime retries. # @!attribute max_attempts # @return [Integer] + # @deprecated Please use {DunningRetryRequest#max_attempts} via {#dunning} instead. This attribute + # will be removed in the next major version. # @!attribute end_after_days # @return [Integer] + # @deprecated Please use {DunningRetryRequest#end_after_days} via {#dunning} instead. This attribute + # will be removed in the next major version. + # @!attribute end_after_day + # @return [Integer] + # @deprecated Misspelled attribute that serialized as "end_after_day", which the API does not accept. + # Please use {DunningRetryRequest#end_after_days} via {#dunning} instead. This attribute will be + # removed in the next major version. class PaymentRetryRequest attr_accessor :enabled, + :dunning, + :downtime, :max_attempts, + :end_after_days, :end_after_day end end diff --git a/lib/checkout_sdk/payments/payments.rb b/lib/checkout_sdk/payments/payments.rb index 6b7b907..021c41c 100644 --- a/lib/checkout_sdk/payments/payments.rb +++ b/lib/checkout_sdk/payments/payments.rb @@ -42,6 +42,9 @@ require 'checkout_sdk/payments/exemption' require 'checkout_sdk/payments/three_ds_flow_type' require 'checkout_sdk/payments/void_request' +require 'checkout_sdk/payments/dunning_retry_request' +require 'checkout_sdk/payments/downtime_retry_request' +require 'checkout_sdk/payments/payment_retry_request' require 'checkout_sdk/payments/payment_request' require 'checkout_sdk/payments/processing_settings' require 'checkout_sdk/payments/processing_data' diff --git a/lib/checkout_sdk/payments/sessions/payment_sessions_request.rb b/lib/checkout_sdk/payments/sessions/payment_sessions_request.rb index fa1ac45..449f1f4 100644 --- a/lib/checkout_sdk/payments/sessions/payment_sessions_request.rb +++ b/lib/checkout_sdk/payments/sessions/payment_sessions_request.rb @@ -42,6 +42,13 @@ module Payments # @return [RiskRequest] # @!attribute retry # @return [PaymentRetryRequest] + # @deprecated Not part of the payment sessions specification. Please use {#customer_retry} instead. + # This attribute will be removed in the next major version. + # @!attribute customer_retry + # @return [CheckoutSdk::Common::CustomerRetry] [Optional] Configures the parameters for customer retries + # performed by the customer on the checkout page. max_attempts is the maximum number of customer retry + # attempts, excluding the initial payment attempt (minimum 0, maximum 5, default 5); it is required + # when customer_retry is set. # @!attribute display_name # @return [String] # @!attribute success_url @@ -90,6 +97,7 @@ class PaymentSessionsRequest :amount_allocations, :risk, :retry, + :customer_retry, :display_name, :success_url, :failure_url, diff --git a/spec/checkout_sdk/payments/hosted/hosted_payments_integration_spec.rb b/spec/checkout_sdk/payments/hosted/hosted_payments_integration_spec.rb index 7cd6ff5..33052d5 100644 --- a/spec/checkout_sdk/payments/hosted/hosted_payments_integration_spec.rb +++ b/spec/checkout_sdk/payments/hosted/hosted_payments_integration_spec.rb @@ -78,7 +78,7 @@ def create_hosted_payments_request billing_descriptor.name = "The Jewelry Shop" billing_descriptor.reference = "ORD-123A" - customer_retry = CheckoutSdk::Payments::PaymentRetryRequest.new + customer_retry = CheckoutSdk::Common::CustomerRetry.new customer_retry.max_attempts = 2 sender = CheckoutSdk::Payments::InstrumentSender.new diff --git a/spec/checkout_sdk/payments/retry_request_serialization_spec.rb b/spec/checkout_sdk/payments/retry_request_serialization_spec.rb new file mode 100644 index 0000000..581504e --- /dev/null +++ b/spec/checkout_sdk/payments/retry_request_serialization_spec.rb @@ -0,0 +1,91 @@ +# frozen_string_literal: true + +def retry_to_json_hash(obj) + JSON.parse(CheckoutSdk::JsonSerializer.to_custom_hash(obj).to_json) +end + +def build_full_retry_request + dunning = CheckoutSdk::Payments::DunningRetryRequest.new + dunning.enabled = true + dunning.max_attempts = 6 + dunning.end_after_days = 30 + downtime = CheckoutSdk::Payments::DowntimeRetryRequest.new + downtime.enabled = false + request = CheckoutSdk::Payments::PaymentRetryRequest.new + request.enabled = true + request.dunning = dunning + request.downtime = downtime + request +end + +RSpec.describe CheckoutSdk::Payments::PaymentRetryRequest do + it 'serializes all properties to the expected JSON' do + expected = JSON.parse('{"enabled":true,"dunning":{"enabled":true,"max_attempts":6,"end_after_days":30},' \ + '"downtime":{"enabled":false}}') + expect(retry_to_json_hash(build_full_retry_request)).to eq(expected) + end + + it 'serializes enabled false' do + request = described_class.new + request.enabled = false + expect(retry_to_json_hash(request)).to eq(JSON.parse('{"enabled":false}')) + end + + it 'serializes deprecated max_attempts and end_after_days with the spec names' do + request = described_class.new + request.enabled = true + request.max_attempts = 3 + request.end_after_days = 10 + expect(retry_to_json_hash(request)).to eq(JSON.parse('{"enabled":true,"max_attempts":3,"end_after_days":10}')) + end + + it 'keeps the deprecated end_after_day accessor, serialized under its own key' do + request = described_class.new + request.end_after_day = 7 + expect(request.end_after_day).to eq(7) + expect(retry_to_json_hash(request)).to eq(JSON.parse('{"end_after_day":7}')) + end +end + +RSpec.describe CheckoutSdk::Payments::DunningRetryRequest do + it 'serializes all properties with enabled false' do + request = described_class.new + request.enabled = false + request.max_attempts = 15 + request.end_after_days = 60 + expect(retry_to_json_hash(request)).to eq(JSON.parse('{"enabled":false,"max_attempts":15,"end_after_days":60}')) + end +end + +RSpec.describe CheckoutSdk::Payments::DowntimeRetryRequest do + it 'serializes enabled false' do + request = described_class.new + request.enabled = false + expect(retry_to_json_hash(request)).to eq(JSON.parse('{"enabled":false}')) + end +end + +RSpec.describe CheckoutSdk::Common::CustomerRetry do + it 'serializes the swagger example' do + expect(retry_to_json_hash(described_class.new.tap { |c| c.max_attempts = 2 })) + .to eq(JSON.parse('{"max_attempts":2}')) + end + + it 'serializes max_attempts 0' do + expect(retry_to_json_hash(described_class.new.tap { |c| c.max_attempts = 0 })) + .to eq(JSON.parse('{"max_attempts":0}')) + end + + it 'keeps the deprecated Accounts alias pointing to the same class' do + expect(CheckoutSdk::Accounts::CustomerRetry).to equal(described_class) + end + + it 'is used by hosted payments, payment links and payment sessions' do + [CheckoutSdk::Payments::HostedPaymentsSession, CheckoutSdk::Payments::PaymentLink, + CheckoutSdk::Payments::PaymentSessionsRequest].each do |klass| + request = klass.new + request.customer_retry = described_class.new.tap { |c| c.max_attempts = 2 } + expect(retry_to_json_hash(request)['customer_retry']).to eq(JSON.parse('{"max_attempts":2}')) + end + end +end