details: https://code.tryton.org/tryton/commit/5993be1ee56f
branch: default
user: Cédric Krier <[email protected]>
date: Thu Mar 26 16:23:55 2026 +0100
description:
Always convert JSON payload to stripe Event and replace dict methods by
StripeObject methods
Since Stripe 15.0.0 the StripeObject no longer inherits from dict. This
means
that we can no more manage payload as simple JSON but we must convert
it to stripe.Event.
And we must replace dict method by their StripeObject equivalent.
Closes #14714
diffstat:
modules/account_payment_stripe/payment.py
| 16 +++++-----
modules/account_payment_stripe/routes.py
| 12 +++++--
modules/account_payment_stripe/tests/scenario_account_payment_stripe_dispute.rst
| 12 +++---
3 files changed, 22 insertions(+), 18 deletions(-)
diffs (140 lines):
diff -r 3788376a2789 -r 5993be1ee56f modules/account_payment_stripe/payment.py
--- a/modules/account_payment_stripe/payment.py Fri Mar 06 12:17:27 2026 +0100
+++ b/modules/account_payment_stripe/payment.py Thu Mar 26 16:23:55 2026 +0100
@@ -1073,16 +1073,16 @@
account.save()
Transaction().commit()
- def webhook(self, payload):
+ def webhook(self, event):
"""This method handles stripe webhook callbacks
The return values are:
- - None if the method could not handle payload['type']
- - True if the payload has been handled
+ - None if the method could not handle event.type
+ - True if the event has been handled
- False if the webhook should be retried by Stripe
"""
- data = payload['data']
- type_ = payload['type']
+ data = event.data
+ type_ = event.type
if type_ == 'charge.succeeded':
return self.webhook_charge_succeeded(data)
if type_ == 'charge.captured':
@@ -1126,7 +1126,7 @@
('stripe_charge_id', '=', charge['id']),
])
if not payments:
- payment_intent_id = charge.get('payment_intent')
+ payment_intent_id = getattr(charge, 'payment_intent', None)
if payment_intent_id:
found = Payment.search([
('stripe_payment_intent_id', '=', payment_intent_id),
@@ -1181,7 +1181,7 @@
if not refunds:
logger.error("charge.refund.updated: No refund '%s'", rf['id'])
for refund in refunds:
- refund.stripe_error_code = rf.get('failure_reason')
+ refund.stripe_error_code = getattr(rf, 'failure_reason', None)
if rf['status'] == 'pending':
Refund.process([refund])
elif rf['status'] == 'succeeded':
@@ -1202,7 +1202,7 @@
('stripe_charge_id', '=', charge['id']),
])
if not payments:
- payment_intent_id = charge.get('payment_intent')
+ payment_intent_id = getattr(charge, 'payment_intent', None)
if payment_intent_id:
found = Payment.search([
('stripe_payment_intent_id', '=', payment_intent_id),
diff -r 3788376a2789 -r 5993be1ee56f modules/account_payment_stripe/routes.py
--- a/modules/account_payment_stripe/routes.py Fri Mar 06 12:17:27 2026 +0100
+++ b/modules/account_payment_stripe/routes.py Thu Mar 26 16:23:55 2026 +0100
@@ -91,7 +91,7 @@
if account.webhook_signing_secret:
sig_header = request.headers['STRIPE_SIGNATURE']
try:
- stripe.Webhook.construct_event(
+ event = stripe.Webhook.construct_event(
request_body, sig_header, account.webhook_signing_secret)
except ValueError: # Invalid payload
abort(HTTPStatus.BAD_REQUEST)
@@ -99,11 +99,15 @@
abort(HTTPStatus.BAD_REQUEST)
else:
logger.warn("Stripe signature ignored")
+ try:
+ event = stripe.Event.construct_from(
+ json.loads(request_body), account.secret_key)
+ except ValueError:
+ abort(HTTPStatus.BAD_REQUEST)
- payload = json.loads(request_body)
- result = account.webhook(payload)
+ result = account.webhook(event)
if result is None:
- logger.info("No callback for payload type '%s'", payload['type'])
+ logger.info("No callback for event type '%s'", event['type'])
elif not result:
return Response(status=HTTPStatus.NOT_FOUND)
return Response(status=HTTPStatus.NO_CONTENT)
diff -r 3788376a2789 -r 5993be1ee56f
modules/account_payment_stripe/tests/scenario_account_payment_stripe_dispute.rst
---
a/modules/account_payment_stripe/tests/scenario_account_payment_stripe_dispute.rst
Fri Mar 06 12:17:27 2026 +0100
+++
b/modules/account_payment_stripe/tests/scenario_account_payment_stripe_dispute.rst
Thu Mar 26 16:23:55 2026 +0100
@@ -108,7 +108,7 @@
Simulate charge.dispute.created event::
- >>> StripeAccount.webhook([stripe_account], {
+ >>> StripeAccount.webhook([stripe_account], stripe.Event.construct_from({
... 'type': 'charge.dispute.created',
... 'data': {
... 'object': {
@@ -120,7 +120,7 @@
... 'status': 'needs_response',
... },
... },
- ... }, {})
+ ... }, stripe_account.secret_key), {})
[True]
>>> payment.reload()
>>> payment.state
@@ -132,7 +132,7 @@
Simulate charge.dispute.closed event::
- >>> StripeAccount.webhook([stripe_account], {
+ >>> StripeAccount.webhook([stripe_account], stripe.Event.construct_from({
... 'type': 'charge.dispute.closed',
... 'data': {
... 'object': {
@@ -144,7 +144,7 @@
... 'status': 'lost',
... },
... },
- ... }, {})
+ ... }, stripe_account.secret_key), {})
[True]
>>> payment.reload()
>>> payment.state
@@ -202,7 +202,7 @@
Simulate charge.dispute.closed event::
- >>> StripeAccount.webhook([stripe_account], {
+ >>> StripeAccount.webhook([stripe_account], stripe.Event.construct_from({
... 'type': 'charge.dispute.closed',
... 'data': {
... 'object': {
@@ -214,7 +214,7 @@
... 'status': 'lost',
... },
... },
- ... }, {})
+ ... }, stripe_account.secret_key), {})
[True]
>>> payment.reload()
>>> payment.state