Check if internal payment can be voided

Add extra security, we don't want to void a credit payment that is not
completed, otherwise we would be refunding credit that was not used.
A credit payment should not be in a non completed state, but you never
know.
This commit is contained in:
Gaetan Craig-Riou
2026-02-27 15:07:58 +11:00
parent 85e0da8aeb
commit c67d47a773
3 changed files with 22 additions and 0 deletions

View File

@@ -146,6 +146,9 @@ module Spree
def internal_void!
return true if void?
# We should only void complete payment, otherwise we will be refunding credit that was
# not used in the first place.
return gateway_error(Spree.t(:internal_payment_not_voidable)) if state != "completed"
options = { customer_id: order.customer_id, payment_id: id, order_number: order.number }
response = payment_method.void(

View File

@@ -4196,6 +4196,7 @@ en:
items_cannot_be_shipped: "Items cannot be shipped"
gateway_config_unavailable: "Gateway config unavailable"
gateway_error: "Payment failed"
internal_payment_not_voidable: Payment not voidable
more: "More"
new_adjustment: "New adjustment"
new_tax_category: "New Tax Category"

View File

@@ -944,6 +944,13 @@ RSpec.describe Spree::Payment do
end
describe "internal_void!" do
let(:payment) do
payment = create(:payment, :completed)
payment.order = order
payment.payment_method = payment_method
payment
end
let(:order) { create(:order, customer:) }
let(:customer) { create(:customer) }
let(:payment_method) {
@@ -1018,6 +1025,17 @@ RSpec.describe Spree::Payment do
payment.internal_void!
end
end
context "when payment not voidable" do
it "raises an error" do
payment.update(state: "pending")
expect(payment_method).not_to receive(:void)
expect {
payment.internal_void!
}.to raise_error(Spree::Core::GatewayError, "Payment not voidable")
end
end
end
describe "applying transaction fees" do