From 2db1e6b59637c24d0be85b81bac9e5ef3bca95a0 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Tue, 20 Mar 2018 12:27:17 +0100 Subject: [PATCH] Stripe: Open payment gateways in new window when shown in widget --- src/pretix/plugins/stripe/payment.py | 16 ++++++++-- .../pretixplugins/stripe/redirect.html | 32 +++++++++++++++++++ src/pretix/plugins/stripe/urls.py | 3 +- src/pretix/plugins/stripe/views.py | 20 ++++++++++-- 4 files changed, 66 insertions(+), 5 deletions(-) create mode 100644 src/pretix/plugins/stripe/templates/pretixplugins/stripe/redirect.html diff --git a/src/pretix/plugins/stripe/payment.py b/src/pretix/plugins/stripe/payment.py index 046daff19d..6db96e3290 100644 --- a/src/pretix/plugins/stripe/payment.py +++ b/src/pretix/plugins/stripe/payment.py @@ -1,12 +1,14 @@ import hashlib import json import logging +import urllib.parse from collections import OrderedDict import stripe from django import forms from django.conf import settings from django.contrib import messages +from django.core import signing from django.template.loader import get_template from django.utils.translation import ugettext, ugettext_lazy as _ @@ -371,7 +373,17 @@ class StripeMethod(BasePaymentProvider): order.payment_info = str(source) order.save(update_fields=['payment_info']) request.session['payment_stripe_order_secret'] = order.secret - return source.redirect.url + return self.redirect(request, source.redirect.url) + + def redirect(self, request, url): + if request.session.get('iframe_session', False): + signer = signing.Signer(salt='safe-redirect') + return ( + build_absolute_uri(request.event, 'plugins:stripe:redirect') + '?url=' + + urllib.parse.quote(signer.sign(url)) + ) + else: + return str(url) class StripeCC(StripeMethod): @@ -436,7 +448,7 @@ class StripeCC(StripeMethod): if source.status == "pending": order.payment_info = str(source) order.save(update_fields=['payment_info']) - return source.redirect.url + return self.redirect(request, source.redirect.url) except stripe.error.StripeError as e: if e.json_body: err = e.json_body['error'] diff --git a/src/pretix/plugins/stripe/templates/pretixplugins/stripe/redirect.html b/src/pretix/plugins/stripe/templates/pretixplugins/stripe/redirect.html new file mode 100644 index 0000000000..01c9d1ae9d --- /dev/null +++ b/src/pretix/plugins/stripe/templates/pretixplugins/stripe/redirect.html @@ -0,0 +1,32 @@ +{% load compress %} +{% load i18n %} +{% load staticfiles %} + + + + {{ settings.PRETIX_INSTANCE_NAME }} + {% compress css %} + + {% endcompress %} + {% compress js %} + + {% endcompress %} + + +
+

{% trans "The payment process has started in a new window." %}

+ +

+ {% trans "The window to enter your payment data was not opened or was closed?" %} +

+

+ + {% trans "Click here in order to open the window." %} + +

+ +
+ + diff --git a/src/pretix/plugins/stripe/urls.py b/src/pretix/plugins/stripe/urls.py index 0e6502d867..7e56626b5a 100644 --- a/src/pretix/plugins/stripe/urls.py +++ b/src/pretix/plugins/stripe/urls.py @@ -2,11 +2,12 @@ from django.conf.urls import include, url from pretix.multidomain import event_url -from .views import ReturnView, refund, webhook +from .views import ReturnView, redirect_view, refund, webhook event_patterns = [ url(r'^stripe/', include([ event_url(r'^webhook/$', webhook, name='webhook', require_live=False), + url(r'^redirect/$', redirect_view, name='redirect'), url(r'^return/(?P[^/]+)/(?P[^/]+)/$', ReturnView.as_view(), name='return'), ])), ] diff --git a/src/pretix/plugins/stripe/views.py b/src/pretix/plugins/stripe/views.py index 5a673041ee..294b395bee 100644 --- a/src/pretix/plugins/stripe/views.py +++ b/src/pretix/plugins/stripe/views.py @@ -4,9 +4,10 @@ import logging import stripe from django.contrib import messages +from django.core import signing from django.db import transaction -from django.http import Http404, HttpResponse -from django.shortcuts import get_object_or_404, redirect +from django.http import Http404, HttpResponse, HttpResponseBadRequest +from django.shortcuts import get_object_or_404, redirect, render from django.urls import reverse from django.utils.decorators import method_decorator from django.utils.functional import cached_property @@ -28,6 +29,21 @@ from pretix.plugins.stripe.payment import StripeCC logger = logging.getLogger('pretix.plugins.stripe') +@xframe_options_exempt +def redirect_view(request, *args, **kwargs): + signer = signing.Signer(salt='safe-redirect') + try: + url = signer.unsign(request.GET.get('url', '')) + except signing.BadSignature: + return HttpResponseBadRequest('Invalid parameter') + + r = render(request, 'pretixplugins/paypal/redirect.html', { + 'url': url, + }) + r._csp_ignore = True + return r + + @csrf_exempt @require_POST def webhook(request, *args, **kwargs):