Use native payment retrials for PayPal (fixes #33)

This commit is contained in:
Raphael Michel
2016-03-10 15:58:14 +01:00
parent cbc8ea44cc
commit bc0c171921
4 changed files with 51 additions and 77 deletions

View File

@@ -102,6 +102,7 @@ class Paypal(BasePaymentProvider):
} }
] ]
}) })
request.session['payment_paypal_order'] = None
return self._create_payment(request, payment) return self._create_payment(request, payment)
def _create_payment(self, request, payment): def _create_payment(self, request, payment):
@@ -238,3 +239,40 @@ class Paypal(BasePaymentProvider):
order = mark_order_refunded(order) order = mark_order_refunded(order)
order.payment_info = json.dumps(sale.to_dict()) order.payment_info = json.dumps(sale.to_dict())
order.save() order.save()
def order_can_retry(self, order):
return True
def retry_prepare(self, request, order):
self.init_api()
payment = paypalrestsdk.Payment({
'intent': 'sale',
'payer': {
"payment_method": "paypal",
},
"redirect_urls": {
"return_url": build_absolute_uri(request.event, 'plugins:paypal:return'),
"cancel_url": build_absolute_uri(request.event, 'plugins:paypal:abort'),
},
"transactions": [
{
"item_list": {
"items": [
{
"name": 'Order %s' % order.code,
"quantity": 1,
"price": str(order.total),
"currency": order.event.currency
}
]
},
"amount": {
"currency": request.event.currency,
"total": str(order.total)
},
"description": __('Event tickets for %s') % request.event.name
}
]
})
request.session['payment_paypal_order'] = order.pk
return self._create_payment(request, payment)

View File

@@ -4,9 +4,6 @@
<p>{% blocktrans trimmed %} <p>{% blocktrans trimmed %}
Our attempt to execute your Payment via PayPal has failed. Please try again or contact us. Our attempt to execute your Payment via PayPal has failed. Please try again or contact us.
{% endblocktrans %}</p> {% endblocktrans %}</p>
<p>
<a href="{% url "plugins:paypal:retry" order=order.code %}" class="btn btn-default">{% trans "Try again" %}</a>
</p>
{% else %} {% else %}
<p>{% blocktrans trimmed %} <p>{% blocktrans trimmed %}
We're waiting for an answer from PayPal regarding your payment. Please contact us, if this We're waiting for an answer from PayPal regarding your payment. Please contact us, if this

View File

@@ -1,11 +1,10 @@
from django.conf.urls import include, url from django.conf.urls import include, url
from .views import abort, retry, success from .views import abort, success
urlpatterns = [ urlpatterns = [
url(r'^(?:(?P<organizer>[^/]+)/)?(?P<event>[^/]+)/paypal/', include([ url(r'^(?:(?P<organizer>[^/]+)/)?(?P<event>[^/]+)/paypal/', include([
url(r'^abort/$', abort, name='abort'), url(r'^abort/$', abort, name='abort'),
url(r'^return/$', success, name='return'), url(r'^return/$', success, name='return'),
url(r'^retry/(?P<order>[^/]+)/', retry, name='retry')
])), ])),
] ]

View File

@@ -1,29 +1,33 @@
import logging import logging
import paypalrestsdk
from django.contrib import messages from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect from django.shortcuts import redirect
from django.utils.translation import ugettext as __, ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from pretix.base.models import Event, Order from pretix.base.models import Event, Order
from pretix.helpers.urls import build_absolute_uri
from pretix.multidomain.urlreverse import eventreverse from pretix.multidomain.urlreverse import eventreverse
from pretix.plugins.paypal.payment import Paypal from pretix.plugins.paypal.payment import Paypal
logger = logging.getLogger('pretix.plugins.paypal') logger = logging.getLogger('pretix.plugins.paypal')
@login_required def success(request, organizer=None, event=None):
def success(request):
pid = request.GET.get('paymentId') pid = request.GET.get('paymentId')
token = request.GET.get('token') token = request.GET.get('token')
payer = request.GET.get('PayerID') payer = request.GET.get('PayerID')
if pid == request.session['payment_paypal_id']: if pid == request.session.get('payment_paypal_id', None):
request.session['payment_paypal_token'] = token request.session['payment_paypal_token'] = token
request.session['payment_paypal_payer'] = payer request.session['payment_paypal_payer'] = payer
try: try:
event = Event.objects.get(id=request.session['payment_paypal_event']) event = Event.objects.get(id=request.session['payment_paypal_event'])
if request.session.get('payment_paypal_order'):
prov = Paypal(event)
order = Order.objects.get(pk=request.session.get('payment_paypal_order'))
resp = prov.payment_perform(request, order)
return redirect(resp or eventreverse(event, 'presale:event.order', kwargs={
'order': order.code,
'secret': order.secret
}) + '?paid=yes')
return redirect(eventreverse(event, 'presale:event.checkout', kwargs={'step': 'confirm'})) return redirect(eventreverse(event, 'presale:event.checkout', kwargs={'step': 'confirm'}))
except Event.DoesNotExist: except Event.DoesNotExist:
pass # TODO: Handle this pass # TODO: Handle this
@@ -31,74 +35,10 @@ def success(request):
pass # TODO: Handle this pass # TODO: Handle this
@login_required def abort(request, organizer=None, event=None):
def abort(request):
messages.error(request, _('It looks like you cancelled the PayPal payment')) messages.error(request, _('It looks like you cancelled the PayPal payment'))
try: try:
event = Event.objects.get(id=request.session['payment_paypal_event']) event = Event.objects.get(id=request.session['payment_paypal_event'])
return redirect(eventreverse(event, 'presale:event.checkout', kwargs={'step': 'payment'})) return redirect(eventreverse(event, 'presale:event.checkout', kwargs={'step': 'payment'}))
except Event.DoesNotExist: except Event.DoesNotExist:
pass # TODO: Handle this pass # TODO: Handle this
@login_required
def retry(request, order):
try:
order = Order.objects.get(
user=request.user,
code=order,
)
except Order.DoesNotExist:
return # TODO: Handle this
provider = Paypal(order.event)
provider.init_api()
if 'token' in request.GET:
if 'PayerID' in request.GET:
payment = paypalrestsdk.Payment.find(request.session.get('payment_paypal_id'))
provider._execute_payment(payment, request, order)
else:
messages.error(request, _('It looks like you cancelled the PayPal payment'))
else:
payment = paypalrestsdk.Payment({
'intent': 'sale',
'payer': {
"payment_method": "paypal",
},
"redirect_urls": {
"return_url": build_absolute_uri('plugins:paypal:retry', kwargs={
'order': order.code
}),
"cancel_url": build_absolute_uri('plugins:paypal:retry', kwargs={
'order': order.code
}),
},
"transactions": [
{
"item_list": {
"items": [
{
"name": 'Order %s' % order.code,
"quantity": 1,
"price": str(order.total),
"currency": order.event.currency
}
]
},
"amount": {
"currency": order.event.currency,
"total": str(order.total)
},
"description": __('Event tickets for %s') % order.event.name
}
]
})
resp = provider._create_payment(request, payment)
if resp:
return redirect(resp)
return redirect(eventreverse(order.event, 'presale:event.order', kwargs={
'order': order.code,
'secret': order.secret
}) + '?paid=yes')