diff --git a/app/controllers/spree/admin/payments_controller.rb b/app/controllers/spree/admin/payments_controller.rb index 0c17f8154a..a239652ed0 100644 --- a/app/controllers/spree/admin/payments_controller.rb +++ b/app/controllers/spree/admin/payments_controller.rb @@ -29,6 +29,8 @@ module Spree return end + authorize_stripe_sca_payment + if @order.completed? @payment.process! flash[:success] = flash_message_for(@payment, :successfully_created) @@ -93,7 +95,7 @@ module Spree available(:back_end). select{ |pm| pm.has_distributor? @order.distributor } - @payment_method = if @payment && @payment.payment_method + @payment_method = if @payment&.payment_method @payment.payment_method else @payment_methods.first @@ -124,6 +126,13 @@ module Spree def load_payment @payment = Payment.find(params[:id]) end + + def authorize_stripe_sca_payment + return unless @payment.payment_method.class == Spree::Gateway::StripeSCA + + @payment.authorize! + raise Spree::Core::GatewayError, I18n.t('authorization_failure') unless @payment.pending? + end end end end diff --git a/spec/controllers/spree/admin/payments_controller_spec.rb b/spec/controllers/spree/admin/payments_controller_spec.rb index 55b20d3484..115886ec7f 100644 --- a/spec/controllers/spree/admin/payments_controller_spec.rb +++ b/spec/controllers/spree/admin/payments_controller_spec.rb @@ -12,16 +12,104 @@ describe Spree::Admin::PaymentsController, type: :controller do context "#create" do let!(:payment_method) { create(:payment_method, distributors: [shop]) } - let!(:order) do - create(:order_with_totals_and_distribution, distributor: shop, state: "payment") - end - let(:params) { { amount: order.total, payment_method_id: payment_method.id } } - it "advances the order state" do - expect { - spree_post :create, payment: params, order_id: order.number - }.to change { order.reload.state }.from("payment").to("complete") + context "order is not complete" do + let!(:order) do + create(:order_with_totals_and_distribution, distributor: shop, state: "payment") + end + + it "advances the order state" do + expect { + spree_post :create, payment: params, order_id: order.number + }.to change { order.reload.state }.from("payment").to("complete") + end + end + + context "order is complete" do + let!(:order) do + create(:order_with_totals_and_distribution, distributor: shop, state: "complete", completed_at: Time.zone.now) + end + + context "with Check payment (payment.process! does nothing)" do + it "redirects to list of payments with success flash" do + spree_post :create, payment: params, order_id: order.number + + redirects_to_list_of_payments_with_success_flash + expect(order.reload.payments.last.state).to eq "checkout" + end + end + + context "with Stripe payment where payment.process! errors out" do + let!(:payment_method) { create(:stripe_payment_method, distributors: [shop]) } + before { allow_any_instance_of(Spree::Payment).to receive(:process!).and_raise(Spree::Core::GatewayError.new("Payment Gateway Error")) } + + it "redirects to new payment page with flash error" do + spree_post :create, payment: params, order_id: order.number + + redirects_to_new_payment_page_with_flash_error("Payment Gateway Error") + expect(order.reload.payments.last.state).to eq "checkout" + end + end + + context "with StripeSCA payment" do + let!(:payment_method) { create(:stripe_sca_payment_method, distributors: [shop]) } + + context "where payment.authorize! raises GatewayError" do + before { allow_any_instance_of(Spree::Payment).to receive(:authorize!).and_raise(Spree::Core::GatewayError.new("Stripe Authorization Failure")) } + + it "redirects to new payment page with flash error" do + spree_post :create, payment: params, order_id: order.number + + redirects_to_new_payment_page_with_flash_error("Stripe Authorization Failure") + expect(order.reload.payments.last.state).to eq "checkout" + end + end + + context "where payment.authorize! does not move payment to pending state" do + before do + allow_any_instance_of(Spree::Payment).to receive(:authorize!).and_return(true) + end + + it "redirects to new payment page with flash error" do + spree_post :create, payment: params, order_id: order.number + + redirects_to_new_payment_page_with_flash_error("Authorization Failure") + expect(order.reload.payments.last.state).to eq "checkout" + end + end + + context "where both payment.process! and payment.authorize! work" do + before do + allow_any_instance_of(Spree::Payment).to receive(:authorize!) do |payment| + payment.update_attribute :state, "pending" + end + allow_any_instance_of(Spree::Payment).to receive(:process!).and_return(true) + end + + it "redirects to list of payments with success flash" do + spree_post :create, payment: params, order_id: order.number + + redirects_to_list_of_payments_with_success_flash + expect(order.reload.payments.last.state).to eq "pending" + end + end + end + + def redirects_to_list_of_payments_with_success_flash + expect_redirect_to spree.admin_order_payments_url(order) + expect(flash[:success]).to eq "Payment has been successfully created!" + end + + def redirects_to_new_payment_page_with_flash_error(flash_error) + expect_redirect_to spree.new_admin_order_payment_url(order) + expect(flash[:error]).to eq flash_error + end + + def expect_redirect_to(path) + expect(response.status).to eq 302 + expect(response.location).to eq path + end end end