diff --git a/app/models/spree/gateway/stripe_sca.rb b/app/models/spree/gateway/stripe_sca.rb index 8e77d3f258..e23a4ea479 100644 --- a/app/models/spree/gateway/stripe_sca.rb +++ b/app/models/spree/gateway/stripe_sca.rb @@ -129,8 +129,7 @@ module Spree payment = fetch_payment(creditcard, gateway_options) raise Stripe::StripeError, I18n.t(:no_pending_payments) unless payment&.response_code - payment_intent_response = Stripe::PaymentIntentValidator.new. - call(payment.response_code, stripe_account_id) + payment_intent_response = Stripe::PaymentIntentValidator.new.call(payment) raise_if_not_in_capture_state(payment_intent_response) diff --git a/app/services/process_payment_intent.rb b/app/services/process_payment_intent.rb index beb92e4869..e9456cfb0b 100644 --- a/app/services/process_payment_intent.rb +++ b/app/services/process_payment_intent.rb @@ -69,16 +69,6 @@ class ProcessPaymentIntent end def payment_intent_status - @payment_intent_status ||= Stripe::PaymentIntentValidator.new. - call(payment_intent, stripe_account_id). - status - end - - def stripe_account_id - StripeAccount.find_by(enterprise_id: preferred_enterprise_id).stripe_user_id - end - - def preferred_enterprise_id - payment.payment_method.preferred_enterprise_id + @payment_intent_status ||= Stripe::PaymentIntentValidator.new.call(payment).status end end diff --git a/lib/stripe/payment_intent_validator.rb b/lib/stripe/payment_intent_validator.rb index 879a49eac2..2deeb74584 100644 --- a/lib/stripe/payment_intent_validator.rb +++ b/lib/stripe/payment_intent_validator.rb @@ -3,9 +3,11 @@ # This class validates if a given payment intent ID is valid in Stripe module Stripe class PaymentIntentValidator - def call(payment_intent_id, stripe_account_id) - payment_intent_response = Stripe::PaymentIntent.retrieve(payment_intent_id, - stripe_account: stripe_account_id) + def call(payment) + payment_intent_response = Stripe::PaymentIntent.retrieve( + payment_intent_id(payment), + stripe_account: stripe_account_id(payment) + ) raise_if_last_payment_error_present(payment_intent_response) @@ -14,6 +16,16 @@ module Stripe private + def payment_intent_id(payment) + payment.response_code + end + + def stripe_account_id(payment) + enterprise_id = payment.payment_method&.preferred_enterprise_id + + StripeAccount.find_by(enterprise_id: enterprise_id)&.stripe_user_id + end + def raise_if_last_payment_error_present(payment_intent_response) return unless payment_intent_response.respond_to?(:last_payment_error) && payment_intent_response.last_payment_error.present? diff --git a/spec/controllers/spree/orders_controller_spec.rb b/spec/controllers/spree/orders_controller_spec.rb index 879d663342..909d7d3609 100644 --- a/spec/controllers/spree/orders_controller_spec.rb +++ b/spec/controllers/spree/orders_controller_spec.rb @@ -115,7 +115,7 @@ describe Spree::OrdersController, type: :controller do before do allow_any_instance_of(Stripe::PaymentIntentValidator) .to receive(:call) - .with(payment_intent, kind_of(String)) + .with(payment) .and_return(payment_intent_response) allow(Spree::Order).to receive(:find_by!) { order } @@ -161,7 +161,7 @@ describe Spree::OrdersController, type: :controller do before do allow_any_instance_of(Stripe::PaymentIntentValidator) .to receive(:call) - .with(payment_intent, kind_of(String)) + .with(payment) .and_raise(Stripe::StripeError, "error message") end diff --git a/spec/lib/stripe/payment_intent_validator_spec.rb b/spec/lib/stripe/payment_intent_validator_spec.rb index 81a730ab2a..c4ff925b08 100644 --- a/spec/lib/stripe/payment_intent_validator_spec.rb +++ b/spec/lib/stripe/payment_intent_validator_spec.rb @@ -7,13 +7,18 @@ module Stripe describe PaymentIntentValidator do describe "#call" do let(:validator) { Stripe::PaymentIntentValidator.new } + let(:payment) { build(:payment, response_code: payment_intent_id) } let(:payment_intent_id) { "pi_123" } let(:stripe_account_id) { "abc123" } + let(:stripe_account_mock) { double(stripe_user_id: stripe_account_id) } let(:payment_intent_response_mock) { { status: 200, body: payment_intent_response_body } } before do Stripe.api_key = "sk_test_12345" + allow(payment).to receive_message_chain(:payment_method, :preferred_enterprise_id) { 1 } + allow(StripeAccount).to receive(:find_by) { stripe_account_mock } + stub_request(:get, "https://api.stripe.com/v1/payment_intents/#{payment_intent_id}") .with(headers: { 'Stripe-Account' => stripe_account_id }) .to_return(payment_intent_response_mock) @@ -26,7 +31,7 @@ module Stripe it "returns payment intent id and does not raise" do expect { - result = validator.call(payment_intent_id, stripe_account_id) + result = validator.call(payment) expect(result).to eq payment_intent_response_body }.to_not raise_error Stripe::StripeError end @@ -39,7 +44,7 @@ module Stripe it "raises Stripe error with payment intent last_payment_error as message" do expect { - validator.call(payment_intent_id, stripe_account_id) + validator.call(payment) }.to raise_error Stripe::StripeError, "No money" end end diff --git a/spec/services/process_payment_intent_spec.rb b/spec/services/process_payment_intent_spec.rb index aa14085650..01424570af 100644 --- a/spec/services/process_payment_intent_spec.rb +++ b/spec/services/process_payment_intent_spec.rb @@ -52,8 +52,7 @@ describe ProcessPaymentIntent do context "where the stripe payment intent validation responds with errors" do before do allow(validator) - .to receive(:call).with(intent, anything).and_raise(Stripe::StripeError, - "error message") + .to receive(:call).with(payment).and_raise(Stripe::StripeError, "error message") end it "returns returns the error message" do @@ -77,7 +76,7 @@ describe ProcessPaymentIntent do before do allow(order).to receive(:deliver_order_confirmation_email) - allow(validator).to receive(:call).with(intent, anything).and_return(intent_response) + allow(validator).to receive(:call).with(payment).and_return(intent_response) end it "validates the intent" do @@ -143,7 +142,7 @@ describe ProcessPaymentIntent do before do payment.update_attribute(:state, "failed") - allow(validator).to receive(:call).with(intent, anything).and_return(intent) + allow(validator).to receive(:call).with(payment).and_return(intent) end it "does not return any error message" do @@ -166,7 +165,7 @@ describe ProcessPaymentIntent do before do allow(order).to receive(:process_payments!) { nil } - allow(validator).to receive(:call).with(intent, anything).and_return(intent_response) + allow(validator).to receive(:call).with(payment).and_return(intent_response) end it "returns a failed result" do