diff --git a/src/pretix/base/orderimport.py b/src/pretix/base/orderimport.py
index 1b49ab382..8ba6a4709 100644
--- a/src/pretix/base/orderimport.py
+++ b/src/pretix/base/orderimport.py
@@ -18,8 +18,9 @@ from i18nfield.strings import LazyI18nString
from pretix.base.channels import get_all_sales_channels
from pretix.base.forms.questions import guess_country
from pretix.base.models import (
- ItemVariation, OrderPosition, QuestionAnswer, QuestionOption, Seat,
- Question)
+ ItemVariation, OrderPosition, Question, QuestionAnswer, QuestionOption,
+ Seat,
+)
from pretix.base.services.pricing import get_price
from pretix.base.settings import (
COUNTRIES_WITH_STATE_IN_ADDRESS, PERSON_NAME_SCHEMES,
diff --git a/src/pretix/plugins/stripe/payment.py b/src/pretix/plugins/stripe/payment.py
index c29db066a..7acc296be 100644
--- a/src/pretix/plugins/stripe/payment.py
+++ b/src/pretix/plugins/stripe/payment.py
@@ -15,7 +15,6 @@ from django.db import transaction
from django.http import HttpRequest
from django.template.loader import get_template
from django.urls import reverse
-from django.utils.crypto import get_random_string
from django.utils.safestring import mark_safe
from django.utils.timezone import now
from django.utils.translation import gettext, gettext_lazy as _, pgettext
@@ -52,17 +51,10 @@ class StripeSettingsHolder(BasePaymentProvider):
self.settings = SettingsSandbox('payment', 'stripe', event)
def get_connect_url(self, request):
- request.session['payment_stripe_oauth_event'] = request.event.pk
- if 'payment_stripe_oauth_token' not in request.session:
- request.session['payment_stripe_oauth_token'] = get_random_string(32)
- return (
- "https://connect.stripe.com/oauth/authorize?response_type=code&client_id={}&state={}"
- "&scope=read_write&redirect_uri={}"
- ).format(
- self.settings.connect_client_id,
- request.session['payment_stripe_oauth_token'],
- urllib.parse.quote(build_global_uri('plugins:stripe:oauth.return')),
- )
+ return reverse('plugins:stripe:oauth.connect', kwargs={
+ 'organizer': self.event.organizer.slug,
+ 'event': self.event.slug,
+ })
def settings_content_render(self, request):
if self.settings.connect_client_id and not self.settings.secret_key:
diff --git a/src/pretix/plugins/stripe/signals.py b/src/pretix/plugins/stripe/signals.py
index ddccc9205..f07527b71 100644
--- a/src/pretix/plugins/stripe/signals.py
+++ b/src/pretix/plugins/stripe/signals.py
@@ -38,15 +38,19 @@ def html_head_presale(sender, request=None, **kwargs):
provider = StripeSettingsHolder(sender)
url = resolve(request.path_info)
+
+ if provider.settings.connect_client_id:
+ pubkey = provider.settings.connect_publishable_key
+ if (provider.settings.get('endpoint', 'live') == 'test' or sender.testmode):
+ pubkey = provider.settings.connect_test_publishable_key
+ else:
+ pubkey = provider.settings.publishable_key
+
if provider.settings.get('_enabled', as_type=bool) and ("checkout" in url.url_name or "order.pay" in url.url_name):
template = get_template('pretixplugins/stripe/presale_head.html')
ctx = {
'event': sender,
- 'settings': provider.settings,
- 'testmode': (
- (provider.settings.get('endpoint', 'live') == 'test' or sender.testmode)
- and provider.settings.publishable_test_key
- )
+ 'pubkey': pubkey,
}
return template.render(ctx)
else:
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 6aa35780d..a4c514677 100644
--- a/src/pretix/plugins/stripe/templates/pretixplugins/stripe/presale_head.html
+++ b/src/pretix/plugins/stripe/templates/pretixplugins/stripe/presale_head.html
@@ -8,12 +8,8 @@
{% compress css %}
{% endcompress %}
-{% if testmode %}
-
-{% 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 82af46c18..908d1d055 100644
--- a/src/pretix/plugins/stripe/urls.py
+++ b/src/pretix/plugins/stripe/urls.py
@@ -4,8 +4,8 @@ from pretix.multidomain import event_url
from .views import (
OrganizerSettingsFormView, ReturnView, ScaReturnView, ScaView,
- applepay_association, oauth_disconnect, oauth_return, redirect_view,
- webhook,
+ applepay_association, oauth_connect, oauth_disconnect, oauth_return,
+ redirect_view, webhook,
)
event_patterns = [
@@ -29,6 +29,8 @@ organizer_patterns = [
urlpatterns = [
url(r'^control/event/(?P[^/]+)/(?P[^/]+)/stripe/disconnect/',
oauth_disconnect, name='oauth.disconnect'),
+ url(r'^control/event/(?P[^/]+)/(?P[^/]+)/stripe/connect/',
+ oauth_connect, name='oauth.connect'),
url(r'^control/organizer/(?P[^/]+)/stripeconnect/',
OrganizerSettingsFormView.as_view(), name='settings.connect'),
url(r'^_stripe/webhook/$', webhook, name='webhook'),
diff --git a/src/pretix/plugins/stripe/views.py b/src/pretix/plugins/stripe/views.py
index 61d9162cf..e3e41510a 100644
--- a/src/pretix/plugins/stripe/views.py
+++ b/src/pretix/plugins/stripe/views.py
@@ -2,7 +2,6 @@ import hashlib
import json
import logging
-import requests
import stripe
from django.contrib import messages
from django.core import signing
@@ -29,6 +28,7 @@ from pretix.control.permissions import (
)
from pretix.control.views.event import DecoupleMixin
from pretix.control.views.organizer import OrganizerDetailViewMixin
+from pretix.helpers.urls import build_absolute_uri as build_global_uri
from pretix.multidomain.urlreverse import eventreverse
from pretix.plugins.stripe.forms import OrganizerStripeSettingsForm
from pretix.plugins.stripe.models import ReferencedStripeObject
@@ -57,87 +57,30 @@ def redirect_view(request, *args, **kwargs):
@scopes_disabled()
def oauth_return(request, *args, **kwargs):
- if 'payment_stripe_oauth_event' not in request.session:
+ if 'payment_stripe_oauth_event' not in request.session or 'payment_stripe_oauth_account' not in request.session:
messages.error(request, _('An error occurred during connecting with Stripe, please try again.'))
return redirect(reverse('control:index'))
event = get_object_or_404(Event, pk=request.session['payment_stripe_oauth_event'])
- if request.GET.get('state') != request.session['payment_stripe_oauth_token']:
- messages.error(request, _('An error occurred during connecting with Stripe, please try again.'))
- return redirect(reverse('control:event.settings.payment.provider', kwargs={
- 'organizer': event.organizer.slug,
- 'event': event.slug,
- 'provider': 'stripe_settings'
- }))
-
gs = GlobalSettingsObject()
- testdata = {}
+ stripe.api_key = gs.settings.payment_stripe_connect_secret_key or gs.settings.payment_stripe_connect_test_secret_key
try:
- resp = requests.post('https://connect.stripe.com/oauth/token', data={
- 'grant_type': 'authorization_code',
- 'client_secret': (
- gs.settings.payment_stripe_connect_secret_key or gs.settings.payment_stripe_connect_test_secret_key
- ),
- 'code': request.GET.get('code')
- })
- data = resp.json()
-
- if 'error' not in data:
- account = stripe.Account.retrieve(
- data['stripe_user_id'],
- api_key=gs.settings.payment_stripe_connect_secret_key or gs.settings.payment_stripe_connect_test_secret_key
- )
+ account = stripe.Account.retrieve(request.session['payment_stripe_oauth_account'])
except:
logger.exception('Failed to obtain OAuth token')
messages.error(request, _('An error occurred during connecting with Stripe, please try again.'))
else:
- if 'error' not in data and data['livemode']:
- try:
- testresp = requests.post('https://connect.stripe.com/oauth/token', data={
- 'grant_type': 'refresh_token',
- 'client_secret': gs.settings.payment_stripe_connect_test_secret_key,
- 'refresh_token': data['refresh_token']
- })
- testdata = testresp.json()
- except:
- logger.exception('Failed to obtain OAuth token')
- messages.error(request, _('An error occurred during connecting with Stripe, please try again.'))
- return redirect(reverse('control:event.settings.payment.provider', kwargs={
- 'organizer': event.organizer.slug,
- 'event': event.slug,
- 'provider': 'stripe_settings'
- }))
+ event.settings.payment_stripe_connect_user_id = account.id
+ event.settings.payment_stripe_connect_user_name = (
+ account.get('business_profile', {}).get('name') or account.get('email')
+ )
+ if request.session.get('payment_stripe_oauth_enable', False):
+ event.settings.payment_stripe__enabled = True
+ del request.session['payment_stripe_oauth_enable']
- if 'error' in data:
- messages.error(request, _('Stripe returned an error: {}').format(data['error_description']))
- elif data['livemode'] and 'error' in testdata:
- messages.error(request, _('Stripe returned an error: {}').format(testdata['error_description']))
- else:
- messages.success(request,
- _('Your Stripe account is now connected to pretix. You can change the settings in '
- 'detail below.'))
- event.settings.payment_stripe_publishable_key = data['stripe_publishable_key']
- # 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')
- )
-
- if data['livemode']:
- event.settings.payment_stripe_publishable_test_key = testdata['stripe_publishable_key']
- else:
- event.settings.payment_stripe_publishable_test_key = event.settings.payment_stripe_publishable_key
-
- if request.session.get('payment_stripe_oauth_enable', False):
- 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)))
+ 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,
@@ -409,6 +352,41 @@ def oauth_disconnect(request, **kwargs):
}))
+@event_permission_required('can_change_event_settings')
+def oauth_connect(request, **kwargs):
+ gs = GlobalSettingsObject()
+ stripe.api_key = gs.settings.payment_stripe_connect_secret_key or gs.settings.payment_stripe_connect_test_secret_key
+
+ request.session['payment_stripe_oauth_event'] = request.event.pk
+ try:
+ account = stripe.Account.create(
+ type='standard',
+ metadata={
+ 'organizer': request.organizer.slug,
+ }
+ )
+ request.session['payment_stripe_oauth_account'] = account.stripe_id
+ account_link = stripe.AccountLink.create(
+ account=account.stripe_id,
+ return_url=build_global_uri('plugins:stripe:oauth.return'),
+ refresh_url=build_global_uri('plugins:stripe:oauth.connect', kwargs={
+ 'organizer': request.organizer.slug,
+ 'event': request.event.slug,
+ }),
+ type='account_onboarding',
+ )
+ except:
+ logger.exception('Failed to obtain account link')
+ messages.error(request, _('An error occurred during connecting with Stripe, please try again.'))
+ return redirect(reverse('control:event.settings.payment.provider', kwargs={
+ 'organizer': request.event.organizer.slug,
+ 'event': request.event.slug,
+ 'provider': 'stripe_settings'
+ }))
+
+ return redirect(account_link.url)
+
+
@xframe_options_exempt
def applepay_association(request, *args, **kwargs):
r = render(request, 'pretixplugins/stripe/apple-developer-merchantid-domain-association')