Skip to content

Commit

Permalink
PayPal: Add communication messages on known issue
Browse files Browse the repository at this point in the history
  • Loading branch information
raphaelm committed Dec 23, 2023
1 parent c58a1aa commit 7bc559a
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 14 deletions.
69 changes: 61 additions & 8 deletions src/pretix/plugins/paypal2/payment.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@
import logging
import urllib.parse
from collections import OrderedDict
from datetime import timedelta
from decimal import Decimal

from django import forms
from django.conf import settings
from django.contrib import messages
from django.core.cache import cache
from django.http import HttpRequest
from django.template.loader import get_template
from django.templatetags.static import static
Expand All @@ -38,6 +40,7 @@
from django.utils.timezone import now
from django.utils.translation import gettext as __, gettext_lazy as _
from django_countries import countries
from django_scopes import scopes_disabled
from i18nfield.strings import LazyI18nString
from paypalcheckoutsdk.orders import (
OrdersCaptureRequest, OrdersCreateRequest, OrdersGetRequest,
Expand Down Expand Up @@ -424,12 +427,25 @@ def build_kwargs():
kwargs[key] = request.resolver_match.kwargs[key]
return kwargs

@scopes_disabled()
def count_known_failures():
return OrderPayment.objects.filter(
provider="paypal", info__contains="RESOURCE_NOT_FOUND", created__gt=now() - timedelta(hours=2)
).count()

known_issue_failures = cache.get_or_set(
'paypal2_known_issue_failures',
count_known_failures(),
600
)

template = get_template('pretixplugins/paypal2/checkout_payment_form.html')
ctx = {
'request': request,
'event': self.event,
'settings': self.settings,
'method': self.method,
'known_issue': known_issue_failures > 1,
'xhr': eventreverse(self.event, 'plugins:paypal2:xhr', kwargs=build_kwargs())
}
return template.render(ctx)
Expand All @@ -445,7 +461,12 @@ def checkout_prepare(self, request, cart):
req = OrdersGetRequest(paypal_order_id)
response = self.client.execute(req)
except IOError as e:
messages.warning(request, _('We had trouble communicating with PayPal'))
if "RESOURCE_NOT_FOUND" in str(e):
messages.warning(request, _('Your payment has failed due to a known issue within PayPal. Please try '
'again, there is a high chance of the payment succeeding on a second '
'or third attempt. You can also try other payment methods, if available.'))
else:
messages.warning(request, _('We had trouble communicating with PayPal'))
logger.exception('PayPal OrdersGetRequest({}): {}'.format(paypal_order_id, str(e)))
return False
else:
Expand Down Expand Up @@ -566,7 +587,12 @@ def _create_paypal_order(self, request, payment=None, cart_total=None):
})
response = self.client.execute(paymentreq)
except IOError as e:
messages.error(request, _('We had trouble communicating with PayPal'))
if "RESOURCE_NOT_FOUND" in str(e):
messages.error(request, _('Your payment has failed due to a known issue within PayPal. Please try '
'again, there is a high chance of the payment succeeding on a second '
'or third attempt. You can also try other payment methods, if available.'))
else:
messages.error(request, _('We had trouble communicating with PayPal'))
logger.exception('PayPal OrdersCreateRequest: {}'.format(str(e)))
else:
if response.result.status not in ('CREATED', 'PAYER_ACTION_REQUIRED'):
Expand Down Expand Up @@ -615,6 +641,10 @@ def execute_payment(self, request: HttpRequest, payment: OrderPayment):
"order_id": paypal_oid,
}
})
if "RESOURCE_NOT_FOUND" in str(e):
raise PaymentException(_('Your payment has failed due to a known issue within PayPal. Please try '
'again, there is a high chance of the payment succeeding on a second '
'or third attempt. You can also try other payment methods, if available.'))
raise PaymentException(_('We had trouble communicating with PayPal'))
else:
pp_captured_order = response.result
Expand Down Expand Up @@ -673,7 +703,13 @@ def execute_payment(self, request: HttpRequest, payment: OrderPayment):
])
self.client.execute(patchreq)
except IOError as e:
messages.error(request, _('We had trouble communicating with PayPal'))
if "RESOURCE_NOT_FOUND" in str(e):
messages.error(request,
_('Your payment has failed due to a known issue within PayPal. Please try '
'again, there is a high chance of the payment succeeding on a second '
'or third attempt. You can also try other payment methods, if available.'))
else:
messages.error(request, _('We had trouble communicating with PayPal'))
payment.fail(info={
"error": {
"name": "IOError",
Expand Down Expand Up @@ -712,9 +748,14 @@ def execute_payment(self, request: HttpRequest, payment: OrderPayment):
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(pp_captured_order.id, str(e)))
raise PaymentException(
_('We were unable to process your payment. See below for details on how to proceed.')
)
if "RESOURCE_NOT_FOUND" in str(e):
raise PaymentException(
_('Your payment has failed due to a known issue within PayPal. Please try '
'again, there is a high chance of the payment succeeding on a second '
'or third attempt. You can also try other payment methods, if available.')
)
else:
raise PaymentException(_('We were unable to process your payment. See below for details on how to proceed.'))
else:
pp_captured_order = response.result

Expand Down Expand Up @@ -769,9 +810,13 @@ def payment_pending_render(self, request, payment) -> str:
retry = False
except (KeyError, IndexError):
pass

error = payment.info_data.get("error", {})
is_known_issue = error.get("name") == "RESOURCE_NOT_FOUND" or "RESOURCE_NOT_FOUND" in error.get("message")

template = get_template('pretixplugins/paypal2/pending.html')
ctx = {'request': request, 'event': self.event, 'settings': self.settings,
'retry': retry, 'order': payment.order}
'retry': retry, 'order': payment.order, 'is_known_issue': is_known_issue}
return template.render(ctx)

def matching_id(self, payment: OrderPayment):
Expand Down Expand Up @@ -932,7 +977,15 @@ def payment_prepare(self, request, payment):
req = OrdersGetRequest(paypal_order_id)
response = self.client.execute(req)
except IOError as e:
messages.warning(request, _('We had trouble communicating with PayPal'))
if "RESOURCE_NOT_FOUND" in str(e):
messages.warning(
request,
_('Your payment has failed due to a known issue within PayPal. Please try '
'again, there is a high chance of the payment succeeding on a second '
'or third attempt. You can also try other payment methods, if available.')
)
else:
messages.warning(request, _('We had trouble communicating with PayPal'))
logger.exception('PayPal OrdersGetRequest({}): {}'.format(paypal_order_id, str(e)))
return False
else:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@
{% endif %}
</p>

<input type="hidden" name="payment_paypal_{{ method }}_oid" value="" id="payment_paypal_{{ method }}_oid" />
<input type="hidden" name="payment_paypal_{{ method }}_payer" value="" id="payment_paypal_{{ method }}_payer" />
<input type="hidden" name="payment_paypal_{{ method }}_xhr" value="{{ xhr }}" id="payment_paypal_{{ method }}_xhr" />
{% if known_issue %}
<div class="alert alert-info">
{% blocktrans trimmed %}
There is currently a known issue with PayPal that causes some payments to fail. If your payment fails,
please just try again. You can also try with a different payment method, if you prefer.
{% endblocktrans %}
</div>
{% endif %}

<input type="hidden" name="payment_paypal_{{ method }}_oid" value="" id="payment_paypal_{{ method }}_oid"/>
<input type="hidden" name="payment_paypal_{{ method }}_payer" value="" id="payment_paypal_{{ method }}_payer"/>
<input type="hidden" name="payment_paypal_{{ method }}_xhr" value="{{ xhr }}" id="payment_paypal_{{ method }}_xhr"/>
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
{% load i18n %}

{% if retry %}
<p>{% blocktrans trimmed %}
Our attempt to execute your Payment via PayPal has failed. Please try again or contact us.
{% endblocktrans %}</p>
{% if is_known_issue %}
<div class="alert alert-info">{% blocktrans trimmed %}
Your payment has failed due to a known issue within PayPal. Please try again, there is a high chance of the
payment succeeding on a second or third attempt. You can also try other payment methods, if available.
{% endblocktrans %}</div>
{% else %}
<p>{% blocktrans trimmed %}
Our attempt to execute your payment via PayPal has failed. Please try again or contact us.
{% endblocktrans %}</p>
{% endif %}
{% else %}
<p>{% blocktrans trimmed %}
We're waiting for an answer from PayPal regarding your payment. Please contact us, if this
Expand Down

0 comments on commit 7bc559a

Please sign in to comment.