diff --git a/lib/checkout_sdk/payments/payments.rb b/lib/checkout_sdk/payments/payments.rb index f116554..6b7b907 100644 --- a/lib/checkout_sdk/payments/payments.rb +++ b/lib/checkout_sdk/payments/payments.rb @@ -219,6 +219,7 @@ require 'checkout_sdk/payments/setups/payment_setup_billing_descriptor' require 'checkout_sdk/payments/setups/payment_setup_presentment_details' require 'checkout_sdk/payments/setups/payment_setup_terminal' +require 'checkout_sdk/payments/setups/payment_setup_risk' require 'checkout_sdk/payments/setups/payment_setup_accommodation_address' require 'checkout_sdk/payments/setups/payment_setup_accommodation_guest' require 'checkout_sdk/payments/setups/payment_setup_accommodation_room' diff --git a/lib/checkout_sdk/payments/setups/pay_by_bank_payment_method.rb b/lib/checkout_sdk/payments/setups/pay_by_bank_payment_method.rb index 4fe6928..afaed0c 100644 --- a/lib/checkout_sdk/payments/setups/pay_by_bank_payment_method.rb +++ b/lib/checkout_sdk/payments/setups/pay_by_bank_payment_method.rb @@ -2,23 +2,47 @@ module CheckoutSdk module Payments - # Pay by Bank (Open Banking) payment method configuration on a Payment Setup. - # Maps swagger `PayByBank`. + # The Pay by Bank (Open Banking) payment method's details and configuration on a Payment Setup. + # Maps swagger `PayByBank`. Sent under the `payment_methods.paybybank` key (one lowercase word, + # not `pay_by_bank`; the API ignores `pay_by_bank` without an error). # - # @!attribute status - # @return [String] (response-only) Payment method status. - # @!attribute flags - # @return [Array(String)] (response-only) Diagnostic flags returned by the API. - # @!attribute bank_id - # @return [String] The identifier of the bank the customer has selected for the payment. - # @!attribute action - # @return [Hash] (response-only) The next available action for the payment method - # (`type`, `banks`). + # The Payment Setup request is a Hash, and a Hash request is sent as is, so do not nest an + # instance of this class in it directly: it would not be serialized. Pass a Hash with these keys, + # or convert an instance first: + # pay_by_bank = CheckoutSdk::Payments::PayByBankPaymentMethod.new + # pay_by_bank.bank_id = 'ob-natwest' + # request[:payment_methods] = { paybybank: CheckoutSdk::JsonSerializer.to_custom_hash(pay_by_bank) } + # Responses are read with dot access, for example response.payment_methods.paybybank.action.banks. class PayByBankPaymentMethod - attr_accessor :status, - :flags, - :bank_id, - :action + # The payment method status. + # [Optional] + # Read only. + # Enum: "unavailable" "action_required" "ready" "initialization_required" "invalid" + # @return [String] One of {PaymentSetupPaymentMethodStatus}. + attr_accessor :status + + # The list of error codes or indicators that highlight missing or invalid information. + # [Optional] + # Read only. + # @return [Array(String)] + attr_accessor :flags + + # The identifier of the bank the customer has selected for the payment. + # [Optional] + # @return [String] + attr_accessor :bank_id + + # The next available action for the payment method. + # [Optional] + # Read only. + # Keys: + # - `type` (String): The type of action. Enum: "select_bank". + # - `banks` (Array(Hash)): The list of banks available for the customer to select. Each item has + # `bank_id` (String, the unique identifier of the bank), `display_name` (String, the display + # name of the bank), `logo_url` (String, the URL of the bank's logo) and `available` + # (Boolean, whether the bank is currently available for selection). + # @return [Hash] + attr_accessor :action end end end diff --git a/lib/checkout_sdk/payments/setups/payment_setup_risk.rb b/lib/checkout_sdk/payments/setups/payment_setup_risk.rb new file mode 100644 index 0000000..51231b2 --- /dev/null +++ b/lib/checkout_sdk/payments/setups/payment_setup_risk.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module CheckoutSdk + module Payments + # Risk assessment settings for the Payment Setup. + # Maps the swagger `PaymentSetup.risk` object. Sent under the `risk` key. + # + # The Payment Setup request is a Hash, so pass { enabled: false } directly, or convert an + # instance first with CheckoutSdk::JsonSerializer.to_custom_hash(risk). + class PaymentSetupRisk + # Indicates whether a risk assessment should be performed. + # [Optional] + # Default: true + # @return [TrueClass, FalseClass] + attr_accessor :enabled + end + end +end diff --git a/lib/checkout_sdk/payments/setups/payment_setups_client.rb b/lib/checkout_sdk/payments/setups/payment_setups_client.rb index 1337004..aceb343 100644 --- a/lib/checkout_sdk/payments/setups/payment_setups_client.rb +++ b/lib/checkout_sdk/payments/setups/payment_setups_client.rb @@ -28,12 +28,19 @@ def initialize(api_client, configuration) # :industry {PaymentSetupIndustry} (containing :accommodation # {Array(PaymentSetupAccommodation)} and :airline {Array(PaymentSetupAirline)}). # A Hash request is sent as is, so every nested value must be a Hash too. To use one of the - # typed classes above (or {CashAppPaymentMethod}), convert it first with + # typed classes above (or {CashAppPaymentMethod}, {PayByBankPaymentMethod} or + # {PaymentSetupRisk}), convert it first with # CheckoutSdk::JsonSerializer.to_custom_hash(object); a typed object nested directly in the # Hash is not serialized and is sent as "#". # :payment_methods may include :cashapp (the key is the single lowercase word `cashapp`), a Hash # with the keys documented on {CashAppPaymentMethod}; you send :initialization ("disabled" or # "enabled") and :customer_profile_sharing (Boolean). + # :payment_methods may also include :paybybank (the key is the single lowercase word + # `paybybank`; the API ignores `pay_by_bank` without an error), a Hash with the keys documented + # on {PayByBankPaymentMethod}; you send :bank_id (the identifier of the bank the customer has + # selected for the payment). + # :risk {PaymentSetupRisk} - Risk assessment settings for the Payment Setup: :enabled + # (Boolean, whether a risk assessment should be performed, default true). # :customer may include: # - :id - The unique identifier of the customer. # - :country - The two-letter ISO country code of the customer for this payment @@ -58,7 +65,8 @@ def initialize(api_client, configuration) # customer's device, one of {PaymentSetupDeviceOs}). # @return [Hash] The Payment Setup (swagger `PaymentSetup`, 200). For Cash App Pay, read # payment_methods.cashapp.action.redirect_url, payment_methods.cashapp.reference and, once only, - # payment_methods.cashapp.customer_profile. + # payment_methods.cashapp.customer_profile. For Pay by Bank, read + # payment_methods.paybybank.action.banks. def create_payment_setup(payment_setups_request) api_client.invoke_post( build_path(PAYMENTS_PATH, SETUPS_PATH), @@ -81,12 +89,19 @@ def create_payment_setup(payment_setups_request) # :industry {PaymentSetupIndustry} (containing :accommodation # {Array(PaymentSetupAccommodation)} and :airline {Array(PaymentSetupAirline)}). # A Hash request is sent as is, so every nested value must be a Hash too. To use one of the - # typed classes above (or {CashAppPaymentMethod}), convert it first with + # typed classes above (or {CashAppPaymentMethod}, {PayByBankPaymentMethod} or + # {PaymentSetupRisk}), convert it first with # CheckoutSdk::JsonSerializer.to_custom_hash(object); a typed object nested directly in the # Hash is not serialized and is sent as "#". # :payment_methods may include :cashapp (the key is the single lowercase word `cashapp`), a Hash # with the keys documented on {CashAppPaymentMethod}; you send :initialization ("disabled" or # "enabled") and :customer_profile_sharing (Boolean). + # :payment_methods may also include :paybybank (the key is the single lowercase word + # `paybybank`; the API ignores `pay_by_bank` without an error), a Hash with the keys documented + # on {PayByBankPaymentMethod}; you send :bank_id (the identifier of the bank the customer has + # selected for the payment). + # :risk {PaymentSetupRisk} - Risk assessment settings for the Payment Setup: :enabled + # (Boolean, whether a risk assessment should be performed, default true). # :customer may include: # - :id - The unique identifier of the customer. # - :country - The two-letter ISO country code of the customer for this payment @@ -111,7 +126,8 @@ def create_payment_setup(payment_setups_request) # customer's device, one of {PaymentSetupDeviceOs}). # @return [Hash] The Payment Setup (swagger `PaymentSetup`, 200). For Cash App Pay, read # payment_methods.cashapp.action.redirect_url, payment_methods.cashapp.reference and, once only, - # payment_methods.cashapp.customer_profile. + # payment_methods.cashapp.customer_profile. For Pay by Bank, read + # payment_methods.paybybank.action.banks. def update_payment_setup(id, payment_setups_request) api_client.invoke_put( build_path(PAYMENTS_PATH, SETUPS_PATH, id), @@ -126,7 +142,8 @@ def update_payment_setup(id, payment_setups_request) # @param [String] id - The unique identifier of the Payment Setup to retrieve # @return [Hash] The Payment Setup (swagger `PaymentSetup`, 200). For Cash App Pay, read # payment_methods.cashapp.action.redirect_url, payment_methods.cashapp.reference and, once only, - # payment_methods.cashapp.customer_profile. + # payment_methods.cashapp.customer_profile. For Pay by Bank, read + # payment_methods.paybybank.action.banks. def get_payment_setup(id) api_client.invoke_get( build_path(PAYMENTS_PATH, SETUPS_PATH, id), @@ -143,7 +160,8 @@ def get_payment_setup(id) # payment with (for example, "tabby", "klarna", "card" or "cashapp") # @return [Hash] The Payment Setup (swagger `PaymentSetup`, 200). For Cash App Pay, read # payment_methods.cashapp.action.redirect_url, payment_methods.cashapp.reference and, once only, - # payment_methods.cashapp.customer_profile. + # payment_methods.cashapp.customer_profile. For Pay by Bank, read + # payment_methods.paybybank.action.banks. def confirm_payment_setup(id, payment_method_name) api_client.invoke_post( build_path(PAYMENTS_PATH, SETUPS_PATH, id, CONFIRM_PATH, payment_method_name), diff --git a/spec/checkout_sdk/payments/setups/setup_payment_methods_serialization_spec.rb b/spec/checkout_sdk/payments/setups/setup_payment_methods_serialization_spec.rb index 1a97e24..72126cd 100644 --- a/spec/checkout_sdk/payments/setups/setup_payment_methods_serialization_spec.rb +++ b/spec/checkout_sdk/payments/setups/setup_payment_methods_serialization_spec.rb @@ -70,6 +70,74 @@ expect(hash['flags']).to eq(%w[flag_a]) expect(hash['action']).to eq({ 'type' => 'select_bank', 'banks' => [{ 'bank_id' => 'ob-natwest' }] }) end + + it 'is sent under the literal paybybank key' do + pm = described_class.new + pm.bank_id = 'ob-natwest' + request = { payment_methods: { paybybank: CheckoutSdk::JsonSerializer.to_custom_hash(pm) } } + + json = CheckoutSdk::JsonSerializer.to_custom_hash(request).to_json + + expect(json).to include('"payment_methods":{"paybybank":{') + expect(json).not_to include('pay_by_bank') + expect(json).not_to include('payByBank') + expect(JSON.parse(json)['payment_methods']['paybybank']).to eq({ 'bank_id' => 'ob-natwest' }) + end + + it 'reads payment_methods.paybybank.action from the swagger example response' do + configuration = double('CheckoutConfiguration', + http_client: Faraday.new, + multipart_http_client: Faraday.new, + logger: Logger.new(nil)) + api_client = CheckoutSdk::ApiClient.new(configuration, 'https://api.sandbox.checkout.com') + body = { + 'id' => 'ps_2Un4WvKHNwAdrXDqTWOvGOgICcr', + 'payment_methods' => { + 'paybybank' => { + 'status' => 'action_required', + 'flags' => [], + 'bank_id' => 'ob-natwest', + 'action' => { + 'type' => 'select_bank', + 'banks' => [{ 'bank_id' => 'ob-natwest', 'display_name' => 'NatWest', + 'logo_url' => 'https://cdn.token.io/banks/natwest.png', 'available' => true }] + } + } + } + }.to_json + response = double('Response', status: 200, body: body, headers: { 'Content-Type' => 'application/json' }) + + pay_by_bank = api_client.send(:parse_response, response).payment_methods.paybybank + + expect(pay_by_bank.status).to eq('action_required') + expect(pay_by_bank.flags).to eq([]) + expect(pay_by_bank.bank_id).to eq('ob-natwest') + expect(pay_by_bank.action.type).to eq('select_bank') + bank = pay_by_bank.action.banks.first + expect(bank.bank_id).to eq('ob-natwest') + expect(bank.display_name).to eq('NatWest') + expect(bank.logo_url).to eq('https://cdn.token.io/banks/natwest.png') + expect(bank.available).to be(true) + end + end + + describe CheckoutSdk::Payments::PaymentSetupRisk do + it 'serializes enabled under the risk key, keeping false on the wire' do + risk = described_class.new + risk.enabled = false + request = { risk: CheckoutSdk::JsonSerializer.to_custom_hash(risk) } + + json = CheckoutSdk::JsonSerializer.to_custom_hash(request).to_json + + expect(json).to eq('{"risk":{"enabled":false}}') + end + + it 'round trips enabled true' do + risk = described_class.new + risk.enabled = true + + expect(CheckoutSdk::JsonSerializer.to_custom_hash(risk)).to eq({ 'enabled' => true }) + end end describe CheckoutSdk::Payments::StablecoinPaymentMethod do