diff --git a/app/decorators/models/spree/refund_decorator.rb b/app/decorators/models/spree/refund_decorator.rb new file mode 100644 index 00000000..1351837b --- /dev/null +++ b/app/decorators/models/spree/refund_decorator.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +module Spree + module RefundDecorator + attr_reader :response + + Spree::Refund.prepend(self) + end +end diff --git a/app/models/spree/payment_method/stripe_credit_card.rb b/app/models/spree/payment_method/stripe_credit_card.rb index eadc346b..b6887131 100644 --- a/app/models/spree/payment_method/stripe_credit_card.rb +++ b/app/models/spree/payment_method/stripe_credit_card.rb @@ -81,6 +81,21 @@ def void(response_code, _creditcard, _transaction_options) gateway.void(response_code, {}) end + def payment_intents_refund_reason + Spree::RefundReason.where(name: Spree::Payment::Cancellation::DEFAULT_REASON).first_or_create + end + + def try_void(payment) + if v3_intents? && payment.completed? + payment.refunds.create!( + amount: payment.credit_allowed, + reason: payment_intents_refund_reason + ).response + else + payment.void_transaction! + end + end + def cancel(response_code) gateway.void(response_code, {}) end diff --git a/spec/features/stripe_checkout_spec.rb b/spec/features/stripe_checkout_spec.rb index a3adaedb..dd1adbf0 100644 --- a/spec/features/stripe_checkout_spec.rb +++ b/spec/features/stripe_checkout_spec.rb @@ -400,8 +400,9 @@ click_button "Place Order" expect(page).to have_content("Your order has been processed successfully") - # Capture in backend Spree::Order.complete.each do |order| + # Capture in backend + visit spree.admin_path expect(page).to have_selector("#listing_orders tbody tr", count: 2) @@ -413,6 +414,21 @@ expect(page).to have_content "Payment Updated" expect(find("table#payments")).to have_content "Completed" + + # Order cancel, after capture + click_link "Cart" + + within "#sidebar" do + expect(page).to have_content "Completed" + end + + find('input[value="Cancel"]').click + + expect(page).to have_content "Order canceled" + + within "#sidebar" do + expect(page).to have_content "Canceled" + end end end end diff --git a/spec/models/spree/payment_method/stripe_credit_card_spec.rb b/spec/models/spree/payment_method/stripe_credit_card_spec.rb index 250b9165..95cc4962 100644 --- a/spec/models/spree/payment_method/stripe_credit_card_spec.rb +++ b/spec/models/spree/payment_method/stripe_credit_card_spec.rb @@ -22,7 +22,8 @@ let(:payment) { double('Spree::Payment', source: source, - order: order + order: order, + amount: order.total ) } @@ -241,4 +242,46 @@ expect(gateway).to receive(:capture).with(9855, '12345', anything).and_return(success_response) end end + + describe '#try_void' do + let(:payment) { create :payment, amount: order.total } + + shared_examples 'voids the payment transaction' do + it 'voids the payment transaction' do + expect(payment).to receive(:void_transaction!) + + subject.try_void(payment) + end + end + + context 'when using Payment Intents' do + before { subject.preferred_v3_intents = true } + + context 'when the payment is completed' do + before do + allow(payment).to receive(:completed?) { true } + end + + it 'creates a refund' do + expect { subject.try_void(payment) }.to change { Spree::Refund.count }.by(1) + end + end + + context 'when the payment is not completed' do + it_behaves_like 'voids the payment transaction' + end + end + + context 'when not using Payment Intents' do + before { subject.preferred_v3_intents = false } + + context 'when the payment is completed' do + it_behaves_like 'voids the payment transaction' + end + + context 'when the payment is not completed' do + it_behaves_like 'voids the payment transaction' + end + end + end end