PPv2: Improve error handling (#2899)

This commit is contained in:
Raphael Michel
2022-11-14 16:55:30 +01:00
committed by GitHub
parent a628f605a6
commit 5b8228bea0
2 changed files with 35 additions and 6 deletions

View File

@@ -43,6 +43,7 @@ from paypalcheckoutsdk.orders import (
OrdersPatchRequest,
)
from paypalcheckoutsdk.payments import CapturesRefundRequest, RefundsGetRequest
from paypalhttp import HttpError
from pretix import settings
from pretix.base.decimal import round_decimal
@@ -659,10 +660,34 @@ class PaypalMethod(BasePaymentProvider):
try:
capturereq = OrdersCaptureRequest(pp_captured_order.id)
response = self.client.execute(capturereq)
except IOError as e:
messages.error(request, _('We had trouble communicating with PayPal'))
except HttpError as e:
text = _('We were unable to process your payment. See below for details on how to proceed.')
try:
error = json.loads(e.message)
except ValueError:
error = {"message": str(e.message)}
try:
if error["details"][0]["issue"] == "ORDER_ALREADY_CAPTURED":
# ignore, do nothing, write nothing, just redirect user to order page, this is likely
# a race condition
logger.info('PayPal ORDER_ALREADY_CAPTURED, ignoring')
return
elif error["details"][0]["issue"] == "INSTRUMENT_DECLINED":
# Use PayPal's rejection message
text = error["details"][0]["description"]
except (KeyError, IndexError):
pass
payment.fail(info={**pp_captured_order.dict(), "error": error}, log_data=error)
logger.exception('PayPal OrdersCaptureRequest: {}'.format(str(e)))
return
raise PaymentException(text)
except IOError as e:
payment.fail(info={**pp_captured_order.dict(), "error": {"message": str(e)}}, log_data={"error": str(e)})
logger.exception('PayPal OrdersCaptureRequest: {}'.format(str(e)))
raise PaymentException(
_('We were unable to process your payment. See below for details on how to proceed.')
)
else:
pp_captured_order = response.result
@@ -685,7 +710,7 @@ class PaypalMethod(BasePaymentProvider):
if pp_captured_order.status != 'COMPLETED':
payment.fail(info=pp_captured_order.dict())
logger.error('Invalid state: %s' % str(pp_captured_order))
logger.error('Invalid state: %s' % repr(pp_captured_order.dict()))
raise PaymentException(
_('We were unable to process your payment. See below for details on how to proceed.')
)
@@ -704,7 +729,8 @@ class PaypalMethod(BasePaymentProvider):
except SendMailException:
messages.warning(request, _('There was an error sending the confirmation mail.'))
finally:
del request.session['payment_paypal_oid']
if 'payment_paypal_oid' in request.session:
del request.session['payment_paypal_oid']
def payment_pending_render(self, request, payment) -> str:
retry = True

View File

@@ -179,7 +179,10 @@ class PayView(PaypalOrderView, TemplateView):
return r
def post(self, request, *args, **kwargs):
self.payment.payment_provider.execute_payment(request, self.payment)
try:
self.payment.payment_provider.execute_payment(request, self.payment)
except PaymentException as e:
messages.error(request, str(e))
return self._redirect_to_order()
def get_context_data(self, **kwargs):