forked from CGM_Public/pretix_original
Fix #2165 -- Idempotency key errors from Stripe
This commit is contained in:
@@ -453,27 +453,25 @@ class StripeMethod(BasePaymentProvider):
|
|||||||
})
|
})
|
||||||
raise PaymentException(_('Stripe reported an error with your card: %s') % err['message'])
|
raise PaymentException(_('Stripe reported an error with your card: %s') % err['message'])
|
||||||
|
|
||||||
# This is not an error we normally expect, however some payment methods like iDEAL will redirect
|
|
||||||
# the user back to our confirmation page at the same time from two devices: the web browser the
|
|
||||||
# purchase is executed from and the online banking app the payment is authorized from.
|
|
||||||
# In this case we will just log the idempotency error but not expose it to the user and just
|
|
||||||
# forward them back to their order page. There is a good chance that by the time the user hits
|
|
||||||
# the order page, the other request has gone through and the payment is confirmed.
|
|
||||||
except stripe.error.IdempotencyError as e:
|
|
||||||
if e.json_body and 'error' in e.json_body:
|
|
||||||
err = e.json_body['error']
|
|
||||||
logger.exception('Stripe error: %s' % str(err))
|
|
||||||
else:
|
|
||||||
logger.exception('Stripe error: %s' % str(e))
|
|
||||||
return
|
|
||||||
|
|
||||||
except stripe.error.StripeError as e:
|
except stripe.error.StripeError as e:
|
||||||
if e.json_body and 'error' in e.json_body:
|
if e.json_body and 'error' in e.json_body:
|
||||||
err = e.json_body['error']
|
err = e.json_body['error']
|
||||||
logger.exception('Stripe error: %s' % str(err))
|
logger.exception('Stripe error: %s' % str(err))
|
||||||
|
|
||||||
|
if err.get('code') == 'idempotency_key_in_use':
|
||||||
|
# This is not an error we normally expect, however some payment methods like iDEAL will redirect
|
||||||
|
# the user back to our confirmation page at the same time from two devices: the web browser the
|
||||||
|
# purchase is executed from and the online banking app the payment is authorized from.
|
||||||
|
# In this case we will just log the idempotency error but not expose it to the user and just
|
||||||
|
# forward them back to their order page. There is a good chance that by the time the user hits
|
||||||
|
# the order page, the other request has gone through and the payment is confirmed.
|
||||||
|
# Usually however this should be prevented by SELECT FOR UPDATE calls!
|
||||||
|
return
|
||||||
|
|
||||||
else:
|
else:
|
||||||
err = {'message': str(e)}
|
err = {'message': str(e)}
|
||||||
logger.exception('Stripe error: %s' % str(e))
|
logger.exception('Stripe error: %s' % str(e))
|
||||||
|
|
||||||
payment.fail(info={
|
payment.fail(info={
|
||||||
'error': True,
|
'error': True,
|
||||||
'message': err['message'],
|
'message': err['message'],
|
||||||
@@ -615,20 +613,15 @@ class StripeMethod(BasePaymentProvider):
|
|||||||
try:
|
try:
|
||||||
source = self._create_source(request, payment)
|
source = self._create_source(request, payment)
|
||||||
|
|
||||||
except stripe.error.IdempotencyError as e:
|
|
||||||
# Same thing happening twice – we don't want to record a failure, as that might prevent the
|
|
||||||
# other thread from succeeding.
|
|
||||||
if e.json_body and 'error' in e.json_body:
|
|
||||||
err = e.json_body['error']
|
|
||||||
logger.exception('Stripe error: %s' % str(err))
|
|
||||||
else:
|
|
||||||
logger.exception('Stripe error: %s' % str(e))
|
|
||||||
return
|
|
||||||
|
|
||||||
except stripe.error.StripeError as e:
|
except stripe.error.StripeError as e:
|
||||||
if e.json_body and 'err' in e.json_body:
|
if e.json_body and 'err' in e.json_body:
|
||||||
err = e.json_body['error']
|
err = e.json_body['error']
|
||||||
logger.exception('Stripe error: %s' % str(err))
|
logger.exception('Stripe error: %s' % str(err))
|
||||||
|
|
||||||
|
if err.get('code') == 'idempotency_key_in_use':
|
||||||
|
# Same thing happening twice – we don't want to record a failure, as that might prevent the
|
||||||
|
# other thread from succeeding.
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
err = {'message': str(e)}
|
err = {'message': str(e)}
|
||||||
logger.exception('Stripe error: %s' % str(e))
|
logger.exception('Stripe error: %s' % str(e))
|
||||||
@@ -828,20 +821,15 @@ class StripeCC(StripeMethod):
|
|||||||
})
|
})
|
||||||
raise PaymentException(_('Stripe reported an error with your card: %s') % err['message'])
|
raise PaymentException(_('Stripe reported an error with your card: %s') % err['message'])
|
||||||
|
|
||||||
except stripe.error.IdempotencyError as e:
|
|
||||||
# Same thing happening twice – we don't want to record a failure, as that might prevent the
|
|
||||||
# other thread from succeeding.
|
|
||||||
if e.json_body and 'error' in e.json_body:
|
|
||||||
err = e.json_body['error']
|
|
||||||
logger.exception('Stripe error: %s' % str(err))
|
|
||||||
else:
|
|
||||||
logger.exception('Stripe error: %s' % str(e))
|
|
||||||
return
|
|
||||||
|
|
||||||
except stripe.error.StripeError as e:
|
except stripe.error.StripeError as e:
|
||||||
if e.json_body and 'error' in e.json_body:
|
if e.json_body and 'error' in e.json_body:
|
||||||
err = e.json_body['error']
|
err = e.json_body['error']
|
||||||
logger.exception('Stripe error: %s' % str(err))
|
logger.exception('Stripe error: %s' % str(err))
|
||||||
|
|
||||||
|
if err.get('code') == 'idempotency_key_in_use':
|
||||||
|
# Same thing happening twice – we don't want to record a failure, as that might prevent the
|
||||||
|
# other thread from succeeding.
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
err = {'message': str(e)}
|
err = {'message': str(e)}
|
||||||
logger.exception('Stripe error: %s' % str(e))
|
logger.exception('Stripe error: %s' % str(e))
|
||||||
@@ -1505,20 +1493,15 @@ class StripeWeChatPay(StripeMethod):
|
|||||||
try:
|
try:
|
||||||
source = self._create_source(request, payment)
|
source = self._create_source(request, payment)
|
||||||
|
|
||||||
except stripe.error.IdempotencyError as e:
|
|
||||||
# Same thing happening twice – we don't want to record a failure, as that might prevent the
|
|
||||||
# other thread from succeeding.
|
|
||||||
if e.json_body and 'error' in e.json_body:
|
|
||||||
err = e.json_body['error']
|
|
||||||
logger.exception('Stripe error: %s' % str(err))
|
|
||||||
else:
|
|
||||||
logger.exception('Stripe error: %s' % str(e))
|
|
||||||
return
|
|
||||||
|
|
||||||
except stripe.error.StripeError as e:
|
except stripe.error.StripeError as e:
|
||||||
if e.json_body and 'err' in e.json_body:
|
if e.json_body and 'err' in e.json_body:
|
||||||
err = e.json_body['error']
|
err = e.json_body['error']
|
||||||
logger.exception('Stripe error: %s' % str(err))
|
logger.exception('Stripe error: %s' % str(err))
|
||||||
|
|
||||||
|
if err.get('code') == 'idempotency_key_in_use':
|
||||||
|
# Same thing happening twice – we don't want to record a failure, as that might prevent the
|
||||||
|
# other thread from succeeding.
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
err = {'message': str(e)}
|
err = {'message': str(e)}
|
||||||
logger.exception('Stripe error: %s' % str(e))
|
logger.exception('Stripe error: %s' % str(e))
|
||||||
|
|||||||
Reference in New Issue
Block a user