summaryrefslogtreecommitdiff
path: root/addons/payment_stripe
diff options
context:
space:
mode:
authorDamien Bouvy <dbo@odoo.com>2019-12-31 09:18:54 +0000
committerDamien Bouvy <dbo@odoo.com>2019-12-31 09:19:34 +0000
commit525d363b560ca5b3671850163ecd0ec9e6c8a290 (patch)
treea2ee911a06efe9d0298a61264333eb6e39be364d /addons/payment_stripe
parentaca2b7191936f0b72a3a24aea1568b7d32c27a16 (diff)
[FIX] payment_stripe: better error handling
In some cases, Stripe will return the result of a transaction with a faulty HTTP Status (e.g. 4XX statuses) - not because the request was malformed, but because the payment failed. It is a bit unfortunate that Stripe would not differentiate between payment status and request validity, but that's the state of things. This commit ensures that such a response will be logged correctly, by making the call to `raise_for_status` conditionnal on the response object's status code and internal structure, forwarding the response's json to the validation flow if the status is in the 4XX range and a `code` key is found in the response, as described in https://stripe.com/docs/error-codes While testing this fix, it became apparent that some error message processing in the frontend was not correctly handled as well - instead of purely rejecting the promise, a failed payment should still send its payload to the backend, to allow the server to put the transaction in the correct state according to the response.
Diffstat (limited to 'addons/payment_stripe')
-rw-r--r--addons/payment_stripe/models/payment.py31
1 files changed, 15 insertions, 16 deletions
diff --git a/addons/payment_stripe/models/payment.py b/addons/payment_stripe/models/payment.py
index 39a8a67493e..f7aeeb770a1 100644
--- a/addons/payment_stripe/models/payment.py
+++ b/addons/payment_stripe/models/payment.py
@@ -61,17 +61,19 @@ class PaymentAcquirerStripe(models.Model):
'Stripe-Version': '2019-05-16', # SetupIntent need a specific version
}
resp = requests.request(method, url, data=data, headers=headers)
- try:
- resp.raise_for_status()
- except HTTPError:
- _logger.error("Here are some more information for the "
- "following HTTP error on %s:\n"
- "Request data:\n%s\n"
- "Response body:\n%s",
- url, pprint.pformat(data), resp.text)
- stripe_error = resp.json().get('error', {}).get('message', '')
- error_msg = " " + (_("Stripe gave us the following info about the problem: '%s'") % stripe_error)
- raise ValidationError(error_msg)
+ # Stripe can send 4XX errors for payment failure (not badly-formed requests)
+ # check if error `code` is present in 4XX response and raise only if not
+ # cfr https://stripe.com/docs/error-codes
+ # these can be made customer-facing, as they usually indicate a problem with the payment
+ # (e.g. insufficient funds, expired card, etc.)
+ if not resp.ok and not (400 <= resp.status_code < 500 and resp.json().get('error', {}).get('code')):
+ try:
+ resp.raise_for_status()
+ except HTTPError:
+ _logger.error(resp.text)
+ stripe_error = resp.json().get('error', {}).get('message', '')
+ error_msg = " " + (_("Stripe gave us the following info about the problem: '%s'") % stripe_error)
+ raise ValidationError(error_msg)
return resp.json()
def _create_stripe_session(self, kwargs):
@@ -276,11 +278,8 @@ class PaymentTransactionStripe(models.Model):
self._set_transaction_pending()
return True
else:
- error = tree.get('failure_message')
- _logger.warning(error)
- vals.update({'state_message': error})
- self.write(vals)
- self._set_transaction_cancel()
+ error = tree.get("failure_message") or tree.get('error', {}).get('message')
+ self._set_transaction_error(error)
return False
def _stripe_form_get_invalid_parameters(self, data):