diff --git a/app/jobs/subscription_confirm_job.rb b/app/jobs/subscription_confirm_job.rb index d7f4dcae8e..748257a340 100644 --- a/app/jobs/subscription_confirm_job.rb +++ b/app/jobs/subscription_confirm_job.rb @@ -57,10 +57,13 @@ class SubscriptionConfirmJob return true unless order.payment_required? setup_payment!(order) - return false if order.errors.present? + return false if order.errors.any? + + authorize_payment!(order) + return false if order.errors.any? order.process_payments! - return false if order.errors.present? + return false if order.errors.any? true end @@ -72,6 +75,12 @@ class SubscriptionConfirmJob OrderManagement::Subscriptions::StripePaymentSetup.new(order).call! end + def authorize_payment!(order) + return if order.subscription.payment_method.class != Spree::Gateway::StripeSCA + + OrderManagement::Subscriptions::StripeScaPaymentAuthorize.new(order).call! + end + def send_confirmation_email(order) order.update! record_success(order) diff --git a/app/services/checkout/stripe_redirect.rb b/app/services/checkout/stripe_redirect.rb index 40feebfde8..e7c40a4b9e 100644 --- a/app/services/checkout/stripe_redirect.rb +++ b/app/services/checkout/stripe_redirect.rb @@ -12,11 +12,8 @@ module Checkout def path return unless stripe_payment_method? - payment = @order.pending_payments.last - return unless payment&.checkout? - - payment.authorize! - raise unless payment.pending? + payment = OrderManagement::Subscriptions::StripeScaPaymentAuthorize.new(@order).call! + raise if @order.errors.any? field_with_url(payment) if url?(field_with_url(payment)) end diff --git a/engines/order_management/app/services/order_management/subscriptions/stripe_sca_payment_authorize.rb b/engines/order_management/app/services/order_management/subscriptions/stripe_sca_payment_authorize.rb new file mode 100644 index 0000000000..da8830ce70 --- /dev/null +++ b/engines/order_management/app/services/order_management/subscriptions/stripe_sca_payment_authorize.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module OrderManagement + module Subscriptions + class StripeScaPaymentAuthorize + def initialize(order) + @order = order + @payment = @order.pending_payments.last + end + + def call! + return unless @payment&.checkout? + + @payment.authorize! + + @order.errors.add(:base, I18n.t('authorization_failure')) unless @payment.pending? + + @payment + end + end + end +end diff --git a/engines/order_management/spec/services/order_management/subscriptions/stripe_sca_payment_authorize_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/stripe_sca_payment_authorize_spec.rb new file mode 100644 index 0000000000..17ece20be4 --- /dev/null +++ b/engines/order_management/spec/services/order_management/subscriptions/stripe_sca_payment_authorize_spec.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require 'spec_helper' + +module OrderManagement + module Subscriptions + describe StripeScaPaymentAuthorize do + let(:order) { create(:order) } + let(:payment_authorize) { + OrderManagement::Subscriptions::StripeScaPaymentAuthorize.new(order) + } + + describe "#call!" do + context "when no pending payments are present" do + before { allow(order).to receive(:pending_payments).once { [] } } + + it "does nothing" do + expect(payment_authorize.call!).to eq nil + end + end + + context "when a payment is present" do + let(:payment) { create(:payment, amount: 10) } + + before { allow(order).to receive(:pending_payments).once { [payment] } } + + context "in a state that is not checkout" do + before { payment.state = "processing" } + + it "does nothing" do + payment_authorize.call! + + expect(payment.state).to eq "processing" + expect(order.errors.size).to eq 0 + end + end + + context "in the checkout state" do + before { payment.state = "checkout" } + + context "and payment authorize moves the payment state to pending" do + before { expect(payment).to receive(:authorize!) { payment.state = "pending" } } + + it "does nothing" do + payment_authorize.call! + + expect(order.errors.size).to eq 0 + end + end + + context "and payment authorize does not move the payment state to pending" do + before { allow(payment).to receive(:authorize!) { payment.state = "failed" } } + + it "adds an error to the order indicating authorization failure" do + payment_authorize.call! + + expect(order.errors[:base].first).to eq "Authorization Failure" + end + end + end + end + end + end + end +end