Compare commits

...

1 Commits

Author SHA1 Message Date
Raphael Michel
951e498089 Use Stripe's new connect onboardning 2020-10-14 18:42:34 +02:00
6 changed files with 69 additions and 96 deletions

View File

@@ -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,

View File

@@ -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:

View File

@@ -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:

View File

@@ -8,12 +8,8 @@
{% compress css %}
<link type="text/css" rel="stylesheet" href="{% static "pretixplugins/stripe/pretix-stripe.css" %}">
{% endcompress %}
{% if testmode %}
<script type="text/plain" id="stripe_pubkey">{{ settings.publishable_test_key }}</script>
{% else %}
<script type="text/plain" id="stripe_pubkey">{{ settings.publishable_key }}</script>
{% endif %}
<script type="text/plain" id="stripe_pubkey">{{ pubkey }}</script>
{% if settings.connect_user_id %}
<script type="text/plain" id="stripe_connectedAccountId">{{ settings.connect_user_id }}</script>
{% endif %}
<script type="text/plain" id="stripe_merchantcountry">{{ settings.merchant_country|default:"" }}</script>
<script type="text/plain" id="stripe_merchantcountry">{{ settings.merchant_country|default:"" }}</script>

View File

@@ -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<organizer>[^/]+)/(?P<event>[^/]+)/stripe/disconnect/',
oauth_disconnect, name='oauth.disconnect'),
url(r'^control/event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/stripe/connect/',
oauth_connect, name='oauth.connect'),
url(r'^control/organizer/(?P<organizer>[^/]+)/stripeconnect/',
OrganizerSettingsFormView.as_view(), name='settings.connect'),
url(r'^_stripe/webhook/$', webhook, name='webhook'),

View File

@@ -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')