fix: skip pay call if invoice already paid after finalize (#13924)
## Description When a customer downgrades from Enterprise to Business, they may retain unused Stripe credit balance. During an AI credits topup, Stripe::Invoice.finalize_invoice auto-applies that credit balance to the invoice. If the credit balance fully covers the invoice amount, Stripe marks it as paid immediately upon finalization. Calling Stripe::Invoice.pay on an already-paid invoice throws an error, breaking the topup flow. This fix retrieves the invoice status after finalization and skips the pay call if Stripe has already settled it via credits. ## Type of change Please delete options that are not relevant. - [ ] Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? Tested against Stripe test mode with the following scenarios: - Full credit balance payment: Customer has enough Stripe credit balance to cover the entire invoice. Invoice is marked paid after finalize_invoice — pay is correctly skipped. Credits are fulfilled successfully. - Partial credit balance payment: Customer has some Stripe credit balance but not enough to cover the full amount. Invoice remains open after finalization — pay is called and charges the remaining amount to the default payment method. Credits are fulfilled successfully. - Zero credit balance (normal payment): Customer has no Stripe credit balance. Invoice remains open after finalization — pay charges the full amount. Credits are fulfilled successfully. ## Checklist: - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my code - [ ] I have commented on my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] Any dependent changes have been merged and published in downstream modules
This commit is contained in:
committed by
GitHub
parent
44a7a13117
commit
04acc16609
@@ -73,8 +73,13 @@ class Enterprise::Billing::TopupCheckoutService
|
||||
description: description
|
||||
)
|
||||
|
||||
Stripe::Invoice.finalize_invoice(invoice.id, { auto_advance: false })
|
||||
Stripe::Invoice.pay(invoice.id)
|
||||
finalize_and_pay(invoice.id)
|
||||
end
|
||||
|
||||
def finalize_and_pay(invoice_id)
|
||||
Stripe::Invoice.finalize_invoice(invoice_id, { auto_advance: false })
|
||||
invoice = Stripe::Invoice.retrieve(invoice_id)
|
||||
Stripe::Invoice.pay(invoice_id) unless invoice.status == 'paid'
|
||||
end
|
||||
|
||||
def fulfill_credits(credits, topup_option)
|
||||
|
||||
Reference in New Issue
Block a user