diff --git a/doc/development/api/payment_2.0.rst b/doc/development/api/payment_2.0.rst index 2acbfd78f..ab5fcc882 100644 --- a/doc/development/api/payment_2.0.rst +++ b/doc/development/api/payment_2.0.rst @@ -69,6 +69,8 @@ Payment processing ``BasePaymentProvider.payment_pending_render(request, payment)`` method that is passed an ``OrderPayment`` object instead of an ``Order``. +* The method ``BasePaymentProvider.payment_form_render`` now receives a new ``total`` parameter. + * The method ``BasePaymentProvider.payment_perform`` has been removed and replaced by a new method ``BasePaymentProvider.execute_payment(request, payment)`` that is passed an ``OrderPayment`` object instead of an ``Order``. diff --git a/src/pretix/base/payment.py b/src/pretix/base/payment.py index 122169944..4c8024859 100644 --- a/src/pretix/base/payment.py +++ b/src/pretix/base/payment.py @@ -373,7 +373,7 @@ class BasePaymentProvider: return timing and pricing - def payment_form_render(self, request: HttpRequest) -> str: + def payment_form_render(self, request: HttpRequest, total: Decimal) -> str: """ When the user selects this provider as their preferred payment method, they will be shown the HTML you return from this method. diff --git a/src/pretix/plugins/stripe/__init__.py b/src/pretix/plugins/stripe/__init__.py index 215ac2853..4022c3e56 100644 --- a/src/pretix/plugins/stripe/__init__.py +++ b/src/pretix/plugins/stripe/__init__.py @@ -17,7 +17,7 @@ class StripeApp(AppConfig): "via Stripe") def ready(self): - from . import signals # NOQA + from . import signals, tasks # NOQA @cached_property def compatibility_errors(self): diff --git a/src/pretix/plugins/stripe/management/__init__.py b/src/pretix/plugins/stripe/management/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/pretix/plugins/stripe/management/commands/__init__.py b/src/pretix/plugins/stripe/management/commands/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/pretix/plugins/stripe/management/commands/stripe_connect_fill_countries.py b/src/pretix/plugins/stripe/management/commands/stripe_connect_fill_countries.py new file mode 100644 index 000000000..ed104a372 --- /dev/null +++ b/src/pretix/plugins/stripe/management/commands/stripe_connect_fill_countries.py @@ -0,0 +1,29 @@ +import stripe +from django.core.management.base import BaseCommand + +from pretix.base.models import Event +from pretix.base.settings import GlobalSettingsObject + + +class Command(BaseCommand): + help = "Detect country for Stripe Connect accounts connected with pretix 2.0 (required for payment request buttons)" + + def handle(self, *args, **options): + cache = {} + gs = GlobalSettingsObject() + api_key = gs.settings.payment_stripe_connect_secret_key or gs.settings.payment_stripe_connect_test_secret_key + if not api_key: + self.stderr.write(self.style.ERROR("Stripe Connect is not set up!")) + return + + for e in Event.objects.filter(plugins__icontains="pretix.plugins.stripe"): + uid = e.settings.payment_stripe_connect_user_id + if uid and not e.settings.payment_stripe_merchant_country: + if uid in cache: + e.settings.payment_stripe_merchant_country = cache[uid] + else: + account = stripe.Account.retrieve( + uid, + api_key=api_key + ) + e.settings.payment_stripe_merchant_country = cache[uid] = account.get('country') diff --git a/src/pretix/plugins/stripe/migrations/0003_registeredapplepaydomain.py b/src/pretix/plugins/stripe/migrations/0003_registeredapplepaydomain.py new file mode 100644 index 000000000..c64fc0109 --- /dev/null +++ b/src/pretix/plugins/stripe/migrations/0003_registeredapplepaydomain.py @@ -0,0 +1,21 @@ +# Generated by Django 2.1 on 2018-08-12 14:51 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('stripe', '0002_referencedstripeobject_payment'), + ] + + operations = [ + migrations.CreateModel( + name='RegisteredApplePayDomain', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('domain', models.CharField(max_length=190)), + ('account', models.CharField(max_length=190)), + ], + ), + ] diff --git a/src/pretix/plugins/stripe/models.py b/src/pretix/plugins/stripe/models.py index 9ebdc32d6..fea980b4f 100644 --- a/src/pretix/plugins/stripe/models.py +++ b/src/pretix/plugins/stripe/models.py @@ -5,3 +5,8 @@ class ReferencedStripeObject(models.Model): reference = models.CharField(max_length=190, db_index=True, unique=True) order = models.ForeignKey('pretixbase.Order', on_delete=models.CASCADE) payment = models.ForeignKey('pretixbase.OrderPayment', null=True, blank=True, on_delete=models.CASCADE) + + +class RegisteredApplePayDomain(models.Model): + domain = models.CharField(max_length=190) + account = models.CharField(max_length=190) diff --git a/src/pretix/plugins/stripe/payment.py b/src/pretix/plugins/stripe/payment.py index 487766175..4d4ac001f 100644 --- a/src/pretix/plugins/stripe/payment.py +++ b/src/pretix/plugins/stripe/payment.py @@ -15,6 +15,7 @@ from django.urls import reverse from django.utils.crypto import get_random_string from django.utils.http import urlquote from django.utils.translation import pgettext, ugettext, ugettext_lazy as _ +from django_countries import countries from pretix import __version__ from pretix.base.decimal import round_decimal @@ -25,7 +26,12 @@ from pretix.base.settings import SettingsSandbox from pretix.helpers.urls import build_absolute_uri as build_global_uri from pretix.multidomain.urlreverse import build_absolute_uri from pretix.plugins.stripe.forms import StripeKeyValidator -from pretix.plugins.stripe.models import ReferencedStripeObject +from pretix.plugins.stripe.models import ( + ReferencedStripeObject, RegisteredApplePayDomain, +) +from pretix.plugins.stripe.tasks import ( + get_stripe_account_key, stripe_verify_domain, +) logger = logging.getLogger('pretix.plugins.stripe') @@ -109,6 +115,9 @@ class StripeSettingsHolder(BasePaymentProvider): else: return {} else: + allcountries = list(countries) + allcountries.insert(0, ('', _('Select country'))) + fields = [ ('publishable_key', forms.CharField( @@ -128,6 +137,13 @@ class StripeSettingsHolder(BasePaymentProvider): StripeKeyValidator(['sk_', 'rk_']), ), )), + ('merchant_country', + forms.ChoiceField( + choices=allcountries, + label=_('Merchant country'), + help_text=_('The country in which your Stripe-account is registred in. Usually, this is your ' + 'country of residence.'), + )), ] d = OrderedDict( fields + [ @@ -235,9 +251,12 @@ class StripeMethod(BasePaymentProvider): places = settings.CURRENCY_PLACES.get(self.event.currency, 2) return round_decimal(float(cents) / (10 ** places), self.event.currency) - def _get_amount(self, payment): + def _decimal_to_int(self, amount): places = settings.CURRENCY_PLACES.get(self.event.currency, 2) - return int(payment.amount * 10 ** places) + return int(amount * 10 ** places) + + def _get_amount(self, payment): + return self._decimal_to_int(payment.amount) @property def api_kwargs(self): @@ -510,7 +529,11 @@ class StripeCC(StripeMethod): public_name = _('Credit card') method = 'cc' - def payment_form_render(self, request) -> str: + def payment_form_render(self, request, total) -> str: + account = get_stripe_account_key(self) + if not RegisteredApplePayDomain.objects.filter(account=account, domain=request.host).exists(): + stripe_verify_domain.apply_async(args=(self.event.pk, request.host)) + ui = self.settings.get('ui', default='pretix') if ui == 'checkout': template = get_template('pretixplugins/stripe/checkout_payment_form_stripe_checkout.html') @@ -519,6 +542,7 @@ class StripeCC(StripeMethod): ctx = { 'request': request, 'event': self.event, + 'total': self._decimal_to_int(total), 'settings': self.settings, } return template.render(ctx) diff --git a/src/pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.css b/src/pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.css new file mode 100644 index 000000000..fd6b62960 --- /dev/null +++ b/src/pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.css @@ -0,0 +1,45 @@ +.sep { +} + +.sepText { + width: 75px; + background: #FFFFFF; + margin: -15px 0 0 -38px; + padding: 5px 0; + position: absolute; + top: 50%; + text-align: center; +} + +.hr { + width:2px; + height:100px; + background-color: #DDDDDD; + position:inherit; + top:0px; + left:50%; + z-index:10; +} + +@media only screen and (max-width: 999px) { + .hr { + width: 100%; + height: 2px; + left: 0px; + margin: 15px 0 15px 0; + } + .sepText { + left: 50%; + } +} + +@media only screen and (min-width: 999px) { + .row.equal { + display: flex; + flex-wrap: wrap; + } +} + +.vcenter { + margin: auto; +} diff --git a/src/pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js b/src/pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js index cbd479ae5..70dfb7d05 100644 --- a/src/pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js +++ b/src/pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js @@ -5,6 +5,8 @@ var pretixstripe = { stripe: null, elements: null, card: null, + paymentRequest: null, + paymentRequestButton: null, 'cc_request': function () { waitingDialog.show(gettext("Contacting Stripe …")); @@ -37,8 +39,47 @@ var pretixstripe = { url: 'https://js.stripe.com/v3/', dataType: 'script', success: function () { - pretixstripe.stripe = Stripe($.trim($("#stripe_pubkey").html())); + if ($.trim($("#stripe_connectedAccountId").html())) { + pretixstripe.stripe = Stripe($.trim($("#stripe_pubkey").html()), { + stripeAccount: $.trim($("#stripe_connectedAccountId").html()) + }); + } else { + pretixstripe.stripe = Stripe($.trim($("#stripe_pubkey").html())); + } pretixstripe.elements = pretixstripe.stripe.elements(); + if ($.trim($("#stripe_merchantcountry").html()) !== "") { + try { + pretixstripe.paymentRequest = pretixstripe.stripe.paymentRequest({ + country: $("#stripe_merchantcountry").html(), + currency: $("#stripe_currency").val().toLowerCase(), + total: { + label: gettext('Total'), + amount: parseInt($("#stripe_total").val()) + }, + displayItems: [], + requestPayerName: false, + requestPayerEmail: false, + requestPayerPhone: false, + requestShipping: false, + }); + + pretixstripe.paymentRequest.on('token', function (ev) { + ev.complete('success'); + + var $form = $("#stripe_token").closest("form"); + // Insert the token into the form so it gets submitted to the server + $("#stripe_token").val(ev.token.id); + $("#stripe_card_brand").val(ev.token.card.brand); + $("#stripe_card_last4").val(ev.token.card.last4); + // and submit + $form.get(0).submit(); + }); + } catch { + pretixstripe.paymentRequest = null; + } + } else { + pretixstripe.paymentRequest = null; + } if ($("#stripe-card").length) { pretixstripe.card = pretixstripe.elements.create('card', { 'style': { @@ -63,6 +104,27 @@ var pretixstripe = { }); pretixstripe.card.mount("#stripe-card"); } + if ($("#stripe-payment-request-button").length && pretixstripe.paymentRequest != null) { + pretixstripe.paymentRequestButton = pretixstripe.elements.create('paymentRequestButton', { + paymentRequest: pretixstripe.paymentRequest, + }); + + pretixstripe.paymentRequest.canMakePayment().then(function(result) { + if (result) { + pretixstripe.paymentRequestButton.mount('#stripe-payment-request-button'); + $('#stripe-payment-request-button').parent().hide(); + $('#stripe-payment-request-button').parent().next("div").hide(); + $('#stripe-payment-request-button').parent().removeClass("hidden"); + $('#stripe-payment-request-button').parent().next("div").removeClass("hidden"); + $('#stripe-payment-request-button').parent().show(500); + $('#stripe-payment-request-button').parent().next("div").show(500); + } else { + $('#stripe-payment-request-button').hide(); + $('#stripe-card').parent().removeClass("col-md-5").addClass("col-md-12"); + document.getElementById('stripe-payment-request-button').style.display = 'none'; + } + }); + } $('.stripe-container').closest("form").find(".btn-primary").prop("disabled", false); } } @@ -144,7 +206,7 @@ $(function () { pretixstripe.show_checkout(); } else { $("#stripe-current-card").slideUp(); - $("#stripe-card").slideDown(); + $("#stripe-elements").slideDown(); } e.preventDefault(); return false; @@ -152,7 +214,7 @@ $(function () { ); if ($("#stripe-current-card").length) { - $("#stripe-card").hide(); + $("#stripe-elements").hide(); } $('.stripe-container').closest("form").submit( diff --git a/src/pretix/plugins/stripe/tasks.py b/src/pretix/plugins/stripe/tasks.py new file mode 100644 index 000000000..92894cca0 --- /dev/null +++ b/src/pretix/plugins/stripe/tasks.py @@ -0,0 +1,51 @@ +import logging +from urllib.parse import urlsplit + +import stripe +from django.conf import settings + +from pretix.base.models import Event +from pretix.celery_app import app +from pretix.multidomain.urlreverse import get_domain +from pretix.plugins.stripe.models import RegisteredApplePayDomain + +logger = logging.getLogger(__name__) + + +def get_domain_for_event(event): + domain = get_domain(event.organizer) + if not domain: + siteurlsplit = urlsplit(settings.SITE_URL) + return siteurlsplit.hostname + return domain + + +def get_stripe_account_key(prov): + if prov.settings.connect_user_id: + return prov.settings.connect_user_id + else: + return prov.settings.publishable_key + + +@app.task(max_retries=5, default_retry_delay=1) +def stripe_verify_domain(event_id, domain): + from pretix.plugins.stripe.payment import StripeCC + event = Event.objects.get(pk=event_id) + prov = StripeCC(event) + account = get_stripe_account_key(prov) + + if RegisteredApplePayDomain.objects.filter(account=account, domain=domain).exists(): + return + + try: + stripe.ApplePayDomain.create( + domain_name=domain, + **prov.api_kwargs + ) + except stripe.error.StripeError: + logger.exception('Could not verify domain with Stripe') + else: + RegisteredApplePayDomain.objects.create( + domain=domain, + account=account + ) diff --git a/src/pretix/plugins/stripe/templates/pretixplugins/stripe/apple-developer-merchantid-domain-association b/src/pretix/plugins/stripe/templates/pretixplugins/stripe/apple-developer-merchantid-domain-association new file mode 100644 index 000000000..41a146474 --- /dev/null +++ b/src/pretix/plugins/stripe/templates/pretixplugins/stripe/apple-developer-merchantid-domain-association @@ -0,0 +1 @@ +7B227073704964223A2239373943394538343346343131343044463144313834343232393232313734313034353044314339464446394437384337313531303944334643463542433731222C2276657273696F6E223A312C22637265617465644F6E223A313437313435343137313137362C227369676E6174757265223A2233303830303630393261383634383836663730643031303730326130383033303830303230313031333130663330306430363039363038363438303136353033303430323031303530303330383030363039326138363438383666373064303130373031303030306130383033303832303365363330383230333862613030333032303130323032303836383630663639396439636361373066333030613036303832613836343863653364303430333032333037613331326533303263303630333535303430333063323534313730373036633635323034313730373036633639363336313734363936663665323034393665373436353637373236313734363936663665323034333431323032643230343733333331323633303234303630333535303430623063316434313730373036633635323034333635373237343639363636393633363137343639366636653230343137353734363836663732363937343739333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303165313730643331333633303336333033333331333833313336333433303561313730643332333133303336333033323331333833313336333433303561333036323331323833303236303630333535303430333063316636353633363332643733366437303264363237323666366236353732326437333639363736653566353534333334326435333431346534343432346635383331313433303132303630333535303430623063306236393466353332303533373937333734363536643733333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353333303539333031333036303732613836343863653364303230313036303832613836343863653364303330313037303334323030303438323330666461626333396366373565323032633530643939623435313265363337653261393031646436636233653062316364346235323637393866386366346562646538316132356138633231653463333364646365386532613936633266366166613139333033343563346538376134343236636539353162313239356133383230323131333038323032306433303435303630383262303630313035303530373031303130343339333033373330333530363038326230363031303530353037333030313836323936383734373437303361326632663666363337333730326536313730373036633635326536333666366432663666363337333730333033343264363137303730366336353631363936333631333333303332333031643036303335353164306530343136303431343032323433303062396165656564343633313937613461363561323939653432373138323163343533303063303630333535316431333031303166663034303233303030333031663036303335353164323330343138333031363830313432336632343963343466393365346566323765366334663632383663336661326262666432653462333038323031316430363033353531643230303438323031313433303832303131303330383230313063303630393261383634383836663736333634303530313330383166653330383163333036303832623036303130353035303730323032333038316236306338316233353236353663363936313665363336353230366636653230373436383639373332303633363537323734363936363639363336313734363532303632373932303631366537393230373036313732373437393230363137333733373536643635373332303631363336333635373037343631366536333635323036663636323037343638363532303734363836353665323036313730373036633639363336313632366336353230373337343631366536343631373236343230373436353732366437333230363136653634323036333666366536343639373436393666366537333230366636363230373537333635326332303633363537323734363936363639363336313734363532303730366636633639363337393230363136653634323036333635373237343639363636393633363137343639366636653230373037323631363337343639363336353230373337343631373436353664363536653734373332653330333630363038326230363031303530353037303230313136326136383734373437303361326632663737373737373265363137303730366336353265363336663664326636333635373237343639363636393633363137343635363137353734363836663732363937343739326633303334303630333535316431663034326433303262333032396130323761303235383632333638373437343730336132663266363337323663326536313730373036633635326536333666366432663631373037303663363536313639363336313333326536333732366333303065303630333535316430663031303166663034303430333032303738303330306630363039326138363438383666373633363430363164303430323035303033303061303630383261383634386365336430343033303230333439303033303436303232313030646131633633616538626535663634663865313165383635363933376239623639633437326265393365616333323333613136373933366534613864356538333032323130306264356166626638363966336330636132373462326664646534663731373135396362336264373139396232636130666634303964653635396138326232346433303832303265653330383230323735613030333032303130323032303834393664326662663361393864613937333030613036303832613836343863653364303430333032333036373331316233303139303630333535303430333063313234313730373036633635323035323666366637343230343334313230326432303437333333313236333032343036303335353034306230633164343137303730366336353230343336353732373436393636363936333631373436393666366532303431373537343638366637323639373437393331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533333031653137306433313334333033353330333633323333333433363333333035613137306433323339333033353330333633323333333433363333333035613330376133313265333032633036303335353034303330633235343137303730366336353230343137303730366336393633363137343639366636653230343936653734363536373732363137343639366636653230343334313230326432303437333333313236333032343036303335353034306230633164343137303730366336353230343336353732373436393636363936333631373436393666366532303431373537343638366637323639373437393331313333303131303630333535303430613063306134313730373036633635323034393665363332653331306233303039303630333535303430363133303235353533333035393330313330363037326138363438636533643032303130363038326138363438636533643033303130373033343230303034663031373131383431396437363438356435316135653235383130373736653838306132656664653762616534646530386466633462393365313333353664353636356233356165323264303937373630643232346537626261303866643736313763653838636237366262363637306265633865383239383466663534343561333831663733303831663433303436303630383262303630313035303530373031303130343361333033383330333630363038326230363031303530353037333030313836326136383734373437303361326632663666363337333730326536313730373036633635326536333666366432663666363337333730333033343264363137303730366336353732366636663734363336313637333333303164303630333535316430653034313630343134323366323439633434663933653465663237653663346636323836633366613262626664326534623330306630363033353531643133303130316666303430353330303330313031666633303166303630333535316432333034313833303136383031346262623064656131353833333838396161343861393964656265626465626166646163623234616233303337303630333535316431663034333033303265333032636130326161303238383632363638373437343730336132663266363337323663326536313730373036633635326536333666366432663631373037303663363537323666366637343633363136373333326536333732366333303065303630333535316430663031303166663034303430333032303130363330313030363061326138363438383666373633363430363032306530343032303530303330306130363038326138363438636533643034303330323033363730303330363430323330336163663732383335313136393962313836666233356333353663613632626666343137656464393066373534646132386562656631396338313565343262373839663839386637396235393966393864353431306438663964653963326665303233303332326464353434323162306133303537373663356466333338336239303637666431373763326332313664393634666336373236393832313236663534663837613764316239396362396230393839323136313036393930663039393231643030303033313832303136303330383230313563303230313031333038313836333037613331326533303263303630333535303430333063323534313730373036633635323034313730373036633639363336313734363936663665323034393665373436353637373236313734363936663665323034333431323032643230343733333331323633303234303630333535303430623063316434313730373036633635323034333635373237343639363636393633363137343639366636653230343137353734363836663732363937343739333131333330313130363033353530343061306330613431373037303663363532303439366536333265333130623330303930363033353530343036313330323535353330323038363836306636393964396363613730663330306430363039363038363438303136353033303430323031303530306130363933303138303630393261383634383836663730643031303930333331306230363039326138363438383666373064303130373031333031633036303932613836343838366637306430313039303533313066313730643331333633303338333133373331333733313336333133313561333032663036303932613836343838366637306430313039303433313232303432303733343832623432653665366332323264616536643963303961346336663332316534656136653666326661626631356430376562333338643264613435646233303061303630383261383634386365336430343033303230343438333034363032323130306564333264376438616131623536623036626164623162396639396264643063653662363931316530623032393232633934333362663564326130656135353830323231303066393433353637663030323361643061343561373236663238376636303062656334666566373335383832383935633733313531383337336163383934383137303030303030303030303030227D \ No newline at end of file diff --git a/src/pretix/plugins/stripe/templates/pretixplugins/stripe/checkout_payment_form.html b/src/pretix/plugins/stripe/templates/pretixplugins/stripe/checkout_payment_form.html index f196af3af..768c1411b 100644 --- a/src/pretix/plugins/stripe/templates/pretixplugins/stripe/checkout_payment_form.html +++ b/src/pretix/plugins/stripe/templates/pretixplugins/stripe/checkout_payment_form.html @@ -30,20 +30,39 @@ {% endif %} -
- - +
+ + +
+
+ + +
+
+

{% blocktrans trimmed %} Your payment will be processed by Stripe, Inc. Your credit card data will be transmitted directly to Stripe and never touches our servers. {% endblocktrans %} + +

- diff --git a/src/pretix/plugins/stripe/templates/pretixplugins/stripe/presale_head.html b/src/pretix/plugins/stripe/templates/pretixplugins/stripe/presale_head.html index 07430fef0..0e67d2ceb 100644 --- a/src/pretix/plugins/stripe/templates/pretixplugins/stripe/presale_head.html +++ b/src/pretix/plugins/stripe/templates/pretixplugins/stripe/presale_head.html @@ -5,9 +5,15 @@ {% compress js %} {% endcompress %} +{% compress css %} + +{% endcompress %} {% if settings.endpoint == "test" and settings.publishable_test_key %} {% else %} {% endif %} - +{% if settings.connect_user_id %} + +{% endif %} + diff --git a/src/pretix/plugins/stripe/urls.py b/src/pretix/plugins/stripe/urls.py index 4766e3bda..2dfac9f0d 100644 --- a/src/pretix/plugins/stripe/urls.py +++ b/src/pretix/plugins/stripe/urls.py @@ -3,7 +3,8 @@ from django.conf.urls import include, url from pretix.multidomain import event_url from .views import ( - ReturnView, oauth_disconnect, oauth_return, redirect_view, webhook, + ReturnView, applepay_association, oauth_disconnect, oauth_return, + redirect_view, webhook, ) event_patterns = [ @@ -19,4 +20,5 @@ urlpatterns = [ oauth_disconnect, name='oauth.disconnect'), url(r'^_stripe/webhook/$', webhook, name='webhook'), url(r'^_stripe/oauth_return/$', oauth_return, name='oauth.return'), + url(r'^.well-known/apple-developer-merchantid-domain-association$', applepay_association, name='applepay.association'), ] diff --git a/src/pretix/plugins/stripe/views.py b/src/pretix/plugins/stripe/views.py index 3f354ac1e..e346ba67b 100644 --- a/src/pretix/plugins/stripe/views.py +++ b/src/pretix/plugins/stripe/views.py @@ -26,6 +26,9 @@ from pretix.control.permissions import event_permission_required from pretix.multidomain.urlreverse import eventreverse from pretix.plugins.stripe.models import ReferencedStripeObject from pretix.plugins.stripe.payment import StripeCC +from pretix.plugins.stripe.tasks import ( + get_domain_for_event, stripe_verify_domain, +) logger = logging.getLogger('pretix.plugins.stripe') @@ -111,6 +114,7 @@ def oauth_return(request, *args, **kwargs): # event.settings.payment_stripe_connect_access_token = data['access_token'] we don't need it, right? event.settings.payment_stripe_connect_refresh_token = data['refresh_token'] event.settings.payment_stripe_connect_user_id = data['stripe_user_id'] + event.settings.payment_stripe_merchant_country = account.get('country') if account.get('business_name') or account.get('display_name') or account.get('email'): event.settings.payment_stripe_connect_user_name = ( account.get('business_name') or account.get('display_name') or account.get('email') @@ -125,6 +129,8 @@ def oauth_return(request, *args, **kwargs): event.settings.payment_stripe__enabled = True del request.session['payment_stripe_oauth_enable'] + stripe_verify_domain.apply_async(args=(event.pk, get_domain_for_event(event))) + return redirect(reverse('control:event.settings.payment.provider', kwargs={ 'organizer': event.organizer.slug, 'event': event.slug, @@ -340,6 +346,13 @@ def oauth_disconnect(request, **kwargs): })) +@xframe_options_exempt +def applepay_association(request, *args, **kwargs): + r = render(request, 'pretixplugins/stripe/apple-developer-merchantid-domain-association') + r._csp_ignore = True + return r + + class StripeOrderView: def dispatch(self, request, *args, **kwargs): try: diff --git a/src/pretix/presale/checkoutflow.py b/src/pretix/presale/checkoutflow.py index 2a78acf9e..433ce3b15 100644 --- a/src/pretix/presale/checkoutflow.py +++ b/src/pretix/presale/checkoutflow.py @@ -440,11 +440,15 @@ class PaymentStep(QuestionsViewMixin, CartMixin, TemplateFlowStep): if not provider.is_enabled or not self._is_allowed(provider, self.request): continue fee = provider.calculate_fee(self._total_order_value) + try: + form = provider.payment_form_render(self.request, self._total_order_value + fee) + except TypeError: + form = provider.payment_form_render(self.request) providers.append({ 'provider': provider, 'fee': fee, 'total': self._total_order_value + fee, - 'form': provider.payment_form_render(self.request) + 'form': form }) return providers diff --git a/src/pretix/presale/views/order.py b/src/pretix/presale/views/order.py index dbfd8a26f..347bee7c4 100644 --- a/src/pretix/presale/views/order.py +++ b/src/pretix/presale/views/order.py @@ -199,7 +199,10 @@ class OrderPaymentStart(EventViewMixin, OrderDetailMixin, TemplateView): @cached_property def form(self): - return self.payment.payment_provider.payment_form_render(self.request) + try: + return self.payment.payment_provider.payment_form_render(self.request, self.payment.amount) + except TypeError: + return self.payment.payment_provider.payment_form_render(self.request) @cached_property def payment(self): @@ -384,13 +387,17 @@ class OrderPayChangeMethod(EventViewMixin, OrderDetailMixin, TemplateView): continue current_fee = sum(f.value for f in self.open_fees) or Decimal('0.00') fee = provider.calculate_fee(pending_sum - current_fee) + try: + form = provider.payment_form_render(self.request, abs(pending_sum + fee - current_fee)) + except TypeError: + form = provider.payment_form_render(self.request) providers.append({ 'provider': provider, 'fee': fee, 'fee_diff': fee - current_fee, 'fee_diff_abs': abs(fee - current_fee), 'total': abs(pending_sum + fee - current_fee), - 'form': provider.payment_form_render(self.request) + 'form': form }) return providers