Summary
A successful Stripe payment against Payment Request can complete on Stripe, create a completed Integration Request, and still leave the ERPNext Payment Request in status Requested.
No Payment Entry is created automatically, even though the payment is already captured successfully by Stripe.
The underlying problem is that the Stripe integration calls:
frappe.get_doc(reference_doctype, reference_docname).run_method("on_payment_authorized", status)
but ERPNext's Payment Request doctype does not implement on_payment_authorized().
As a result, the payment can succeed externally while the ERPNext document is not finalized internally.
Affected components
ERPNext file:
erpnext/accounts/doctype/payment_request/payment_request.py
Interaction initiated from:
payments/payment_gateways/doctype/stripe_settings/stripe_settings.py
Environment
Please replace this section with your exact output from:
erpnext 16.9.1 version-16 (99a81db)
frappe 16.11.0 version-16 (694a53f)
payments 0.0.1 develop (3cebd94)
print_designer 1.6.7 develop (9d62227)
swiss_accounting_software 0.0.6 main (5388f1c)
Observed in our environment with:
- ERPNext
Payment Request
- Stripe via official
payments app
- Stripe test mode
- Payment Request against Sales Invoice
Steps to reproduce
- Configure Stripe with the official
payments app.
- Create a
Payment Request against a Sales Invoice.
- Open the generated payment URL and complete the Stripe payment successfully.
- Check Stripe and ERPNext afterwards.
Actual behavior
Observed result:
- Stripe charge succeeds
- Stripe sends receipt
Integration Request is marked Completed
Payment Request remains Requested
- no automatic
Payment Entry is created
- the underlying invoice remains effectively unpaid on the ERPNext side
In our case, the Integration Request looked correct:
- Service:
Stripe
- Status:
Completed
- No explicit error in the integration request itself
However, the ERPNext Payment Request did not transition to Paid.
Expected behavior
When Stripe payment succeeds for a Payment Request, ERPNext should:
- finalize the
Payment Request
- create / submit the corresponding
Payment Entry
- update
Payment Request.status to Paid
- reduce / clear the outstanding amount appropriately
- update the linked reference document state as expected
Root cause
The Stripe integration calls:
frappe.get_doc(
self.data.reference_doctype,
self.data.reference_docname
).run_method("on_payment_authorized", self.flags.status_changed_to)
For a Stripe payment against Payment Request, the reference document is:
reference_doctype = "Payment Request"
reference_docname = <payment request id>
But ERPNext's PaymentRequest class does not define:
def on_payment_authorized(self, payment_status=None):
...
We verified this directly in bench console:
doc = frappe.get_doc("Payment Request", "ACC-PRQ-2026-00002")
hasattr(doc, "on_payment_authorized")
# False
At the same time, PaymentRequest already contains the correct business logic that should be used on successful payment:
set_as_paid()
create_payment_entry()
So the finalization logic exists, but the callback expected by the payment gateway integration does not.
Proposed fix
Add an on_payment_authorized() handler to PaymentRequest that bridges successful payment authorization to the existing ERPNext logic.
Suggested implementation:
def on_payment_authorized(self, payment_status=None):
if payment_status == "Completed":
if self.status != "Paid":
return self.set_as_paid()
elif payment_status in ("Failed", "Cancelled"):
self.set_failed()
There is also a related improvement opportunity because set_failed() is currently a no-op in our observed code:
def set_failed(self):
pass
A minimal improvement would be:
def set_failed(self):
self.db_set("status", "Failed")
Why this matters
This is a serious accounting / operational bug.
The external payment succeeds, but ERPNext does not complete the internal accounting flow automatically. This creates a mismatch between:
- payment provider state
- integration request state
- ERPNext accounting state
In practice, this means users can receive money successfully in Stripe while the ERPNext Payment Request remains open.
Local verification
We verified locally that adding:
def on_payment_authorized(self, payment_status=None):
if payment_status == "Completed":
if self.status != "Paid":
return self.set_as_paid()
elif payment_status in ("Failed", "Cancelled"):
self.set_failed()
to erpnext/accounts/doctype/payment_request/payment_request.py
caused the previously failing Stripe completion flow to mark the Payment Request as paid successfully.
Additional context
This issue is triggered by the Stripe flow in the payments app, but the missing callback is on ERPNext's Payment Request doctype itself. Because of that, this issue likely needs coordination between erpnext and payments.
Summary
A successful Stripe payment against
Payment Requestcan complete on Stripe, create a completedIntegration Request, and still leave the ERPNextPayment Requestin statusRequested.No
Payment Entryis created automatically, even though the payment is already captured successfully by Stripe.The underlying problem is that the Stripe integration calls:
but ERPNext's
Payment Requestdoctype does not implementon_payment_authorized().As a result, the payment can succeed externally while the ERPNext document is not finalized internally.
Affected components
ERPNext file:
erpnext/accounts/doctype/payment_request/payment_request.pyInteraction initiated from:
payments/payment_gateways/doctype/stripe_settings/stripe_settings.pyEnvironment
Please replace this section with your exact output from:
erpnext 16.9.1 version-16 (99a81db)
frappe 16.11.0 version-16 (694a53f)
payments 0.0.1 develop (3cebd94)
print_designer 1.6.7 develop (9d62227)
swiss_accounting_software 0.0.6 main (5388f1c)
Observed in our environment with:
Payment RequestpaymentsappSteps to reproduce
paymentsapp.Payment Requestagainst aSales Invoice.Actual behavior
Observed result:
Integration Requestis markedCompletedPayment RequestremainsRequestedPayment Entryis createdIn our case, the
Integration Requestlooked correct:StripeCompletedHowever, the ERPNext
Payment Requestdid not transition toPaid.Expected behavior
When Stripe payment succeeds for a
Payment Request, ERPNext should:Payment RequestPayment EntryPayment Request.statustoPaidRoot cause
The Stripe integration calls:
For a Stripe payment against
Payment Request, the reference document is:reference_doctype = "Payment Request"reference_docname = <payment request id>But ERPNext's
PaymentRequestclass does not define:We verified this directly in bench console:
At the same time,
PaymentRequestalready contains the correct business logic that should be used on successful payment:set_as_paid()create_payment_entry()So the finalization logic exists, but the callback expected by the payment gateway integration does not.
Proposed fix
Add an
on_payment_authorized()handler toPaymentRequestthat bridges successful payment authorization to the existing ERPNext logic.Suggested implementation:
There is also a related improvement opportunity because
set_failed()is currently a no-op in our observed code:A minimal improvement would be:
Why this matters
This is a serious accounting / operational bug.
The external payment succeeds, but ERPNext does not complete the internal accounting flow automatically. This creates a mismatch between:
In practice, this means users can receive money successfully in Stripe while the ERPNext
Payment Requestremains open.Local verification
We verified locally that adding:
to
erpnext/accounts/doctype/payment_request/payment_request.pycaused the previously failing Stripe completion flow to mark the Payment Request as paid successfully.
Additional context
This issue is triggered by the Stripe flow in the
paymentsapp, but the missing callback is on ERPNext'sPayment Requestdoctype itself. Because of that, this issue likely needs coordination betweenerpnextandpayments.