Add more Stripe Payment Methods, simplify forms (#1571)

* Add more Stripe Payment Methods, simplify forms

* Revert accidential commit of boxoffice control renderer...

* Use existing QR-Code encoding in presale
This commit is contained in:
Martin Gross
2020-02-05 09:50:29 +01:00
committed by GitHub
parent 6e88054af7
commit b3e3d427cb
8 changed files with 295 additions and 36 deletions

View File

@@ -28,7 +28,7 @@ from pretix.base.payment import BasePaymentProvider, PaymentException
from pretix.base.services.mail import SendMailException
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.multidomain.urlreverse import build_absolute_uri, eventreverse
from pretix.plugins.stripe.forms import StripeKeyValidator
from pretix.plugins.stripe.models import (
ReferencedStripeObject, RegisteredApplePayDomain,
@@ -200,6 +200,34 @@ class StripeSettingsHolder(BasePaymentProvider):
),
required=False,
)),
('method_eps',
forms.BooleanField(
label=_('EPS'),
disabled=self.event.currency != 'EUR',
help_text=_('Needs to be enabled in your Stripe account first.'),
required=False,
)),
('method_multibanco',
forms.BooleanField(
label=_('Multibanco'),
disabled=self.event.currency != 'EUR',
help_text=_('Needs to be enabled in your Stripe account first.'),
required=False,
)),
('method_przelewy24',
forms.BooleanField(
label=_('Przelewy24'),
disabled=self.event.currency not in ['EUR', 'PLN'],
help_text=_('Needs to be enabled in your Stripe account first.'),
required=False,
)),
('method_wechatpay',
forms.BooleanField(
label=_('WeChat Pay'),
disabled=self.event.currency not in ['AUD', 'CAD', 'EUR', 'GBP', 'HKD', 'JPY', 'SGD', 'USD'],
help_text=_('Needs to be enabled in your Stripe account first.'),
required=False,
)),
] + list(super().settings_form_fields.items())
)
d.move_to_end('_enabled', last=False)
@@ -603,7 +631,7 @@ class StripeCC(StripeMethod):
if not RegisteredApplePayDomain.objects.filter(account=account, domain=request.host).exists():
stripe_verify_domain.apply_async(args=(self.event.pk, request.host))
template = get_template('pretixplugins/stripe/checkout_payment_form.html')
template = get_template('pretixplugins/stripe/checkout_payment_form_cc.html')
ctx = {
'request': request,
'event': self.event,
@@ -843,7 +871,7 @@ class StripeGiropay(StripeMethod):
method = 'giropay'
def payment_form_render(self, request) -> str:
template = get_template('pretixplugins/stripe/checkout_payment_form_giropay.html')
template = get_template('pretixplugins/stripe/checkout_payment_form_simple.html')
ctx = {
'request': request,
'event': self.event,
@@ -872,9 +900,7 @@ class StripeGiropay(StripeMethod):
owner={
'name': request.session.get('payment_stripe_giropay_account') or ugettext('unknown name')
},
giropay={
'statement_descriptor': self.statement_descriptor(payment, 35),
},
statement_descriptor=self.statement_descriptor(payment, 35),
redirect={
'return_url': build_absolute_uri(self.event, 'plugins:stripe:return', kwargs={
'order': payment.order.code,
@@ -909,7 +935,7 @@ class StripeIdeal(StripeMethod):
method = 'ideal'
def payment_form_render(self, request) -> str:
template = get_template('pretixplugins/stripe/checkout_payment_form_simple.html')
template = get_template('pretixplugins/stripe/checkout_payment_form_simple_noform.html')
ctx = {
'request': request,
'event': self.event,
@@ -927,9 +953,7 @@ class StripeIdeal(StripeMethod):
'event': self.event.id,
'code': payment.order.code
},
ideal={
'statement_descriptor': self.statement_descriptor(payment)
},
statement_descriptor=self.statement_descriptor(payment),
redirect={
'return_url': build_absolute_uri(self.event, 'plugins:stripe:return', kwargs={
'order': payment.order.code,
@@ -955,7 +979,7 @@ class StripeAlipay(StripeMethod):
method = 'alipay'
def payment_form_render(self, request) -> str:
template = get_template('pretixplugins/stripe/checkout_payment_form_simple.html')
template = get_template('pretixplugins/stripe/checkout_payment_form_simple_noform.html')
ctx = {
'request': request,
'event': self.event,
@@ -998,7 +1022,7 @@ class StripeBancontact(StripeMethod):
method = 'bancontact'
def payment_form_render(self, request) -> str:
template = get_template('pretixplugins/stripe/checkout_payment_form_bancontact.html')
template = get_template('pretixplugins/stripe/checkout_payment_form_simple.html')
ctx = {
'request': request,
'event': self.event,
@@ -1027,9 +1051,7 @@ class StripeBancontact(StripeMethod):
owner={
'name': request.session.get('payment_stripe_bancontact_account') or ugettext('unknown name')
},
bancontact={
'statement_descriptor': self.statement_descriptor(payment, 35)
},
statement_descriptor=self.statement_descriptor(payment, 35),
redirect={
'return_url': build_absolute_uri(self.event, 'plugins:stripe:return', kwargs={
'order': payment.order.code,
@@ -1064,7 +1086,7 @@ class StripeSofort(StripeMethod):
method = 'sofort'
def payment_form_render(self, request) -> str:
template = get_template('pretixplugins/stripe/checkout_payment_form_sofort.html')
template = get_template('pretixplugins/stripe/checkout_payment_form_simple.html')
ctx = {
'request': request,
'event': self.event,
@@ -1095,9 +1117,9 @@ class StripeSofort(StripeMethod):
'event': self.event.id,
'code': payment.order.code
},
statement_descriptor=self.statement_descriptor(payment, 35),
sofort={
'country': request.session.get('payment_stripe_sofort_bank_country'),
'statement_descriptor': self.statement_descriptor(payment, 35)
},
redirect={
'return_url': build_absolute_uri(self.event, 'plugins:stripe:return', kwargs={
@@ -1124,3 +1146,244 @@ class StripeSofort(StripeMethod):
def payment_can_retry(self, payment):
return payment.state != OrderPayment.PAYMENT_STATE_PENDING and self._is_still_available(order=payment.order)
class StripeEPS(StripeMethod):
identifier = 'stripe_eps'
verbose_name = _('EPS via Stripe')
public_name = _('EPS')
method = 'eps'
def payment_form_render(self, request) -> str:
template = get_template('pretixplugins/stripe/checkout_payment_form_simple.html')
ctx = {
'request': request,
'event': self.event,
'settings': self.settings,
'form': self.payment_form(request)
}
return template.render(ctx)
@property
def payment_form_fields(self):
return OrderedDict([
('account', forms.CharField(label=_('Account holder'))),
])
def _create_source(self, request, payment):
try:
source = stripe.Source.create(
type='eps',
amount=self._get_amount(payment),
currency=self.event.currency.lower(),
metadata={
'order': str(payment.order.id),
'event': self.event.id,
'code': payment.order.code
},
owner={
'name': request.session.get('payment_stripe_eps_account') or ugettext('unknown name')
},
statement_descriptor=self.statement_descriptor(payment),
redirect={
'return_url': build_absolute_uri(self.event, 'plugins:stripe:return', kwargs={
'order': payment.order.code,
'payment': payment.pk,
'hash': hashlib.sha1(payment.order.secret.lower().encode()).hexdigest(),
})
},
**self.api_kwargs
)
return source
finally:
if 'payment_stripe_eps_account' in request.session:
del request.session['payment_stripe_eps_account']
def payment_is_valid_session(self, request):
return (
request.session.get('payment_stripe_eps_account', '') != ''
)
def checkout_prepare(self, request, cart):
form = self.payment_form(request)
if form.is_valid():
request.session['payment_stripe_eps_account'] = form.cleaned_data['account']
return True
return False
class StripeMultibanco(StripeMethod):
identifier = 'stripe_multibanco'
verbose_name = _('Multibanco via Stripe')
public_name = _('Multibanco')
method = 'multibanco'
def payment_form_render(self, request) -> str:
template = get_template('pretixplugins/stripe/checkout_payment_form_simple_noform.html')
ctx = {
'request': request,
'event': self.event,
'settings': self.settings,
'form': self.payment_form(request)
}
return template.render(ctx)
def _create_source(self, request, payment):
source = stripe.Source.create(
type='multibanco',
amount=self._get_amount(payment),
currency=self.event.currency.lower(),
metadata={
'order': str(payment.order.id),
'event': self.event.id,
'code': payment.order.code
},
owner={
'email': payment.order.email
},
redirect={
'return_url': build_absolute_uri(self.event, 'plugins:stripe:return', kwargs={
'order': payment.order.code,
'payment': payment.pk,
'hash': hashlib.sha1(payment.order.secret.lower().encode()).hexdigest(),
})
},
**self.api_kwargs
)
return source
def payment_is_valid_session(self, request):
return True
def checkout_prepare(self, request, cart):
return True
class StripePrzelewy24(StripeMethod):
identifier = 'stripe_przelewy24'
verbose_name = _('Przelewy24 via Stripe')
public_name = _('Przelewy24')
method = 'przelewy24'
def payment_form_render(self, request) -> str:
template = get_template('pretixplugins/stripe/checkout_payment_form_simple_noform.html')
ctx = {
'request': request,
'event': self.event,
'settings': self.settings,
'form': self.payment_form(request)
}
return template.render(ctx)
def _create_source(self, request, payment):
source = stripe.Source.create(
type='p24',
amount=self._get_amount(payment),
currency=self.event.currency.lower(),
metadata={
'order': str(payment.order.id),
'event': self.event.id,
'code': payment.order.code
},
owner={
'email': payment.order.email
},
statement_descriptor=self.statement_descriptor(payment, 35),
redirect={
'return_url': build_absolute_uri(self.event, 'plugins:stripe:return', kwargs={
'order': payment.order.code,
'payment': payment.pk,
'hash': hashlib.sha1(payment.order.secret.lower().encode()).hexdigest(),
})
},
**self.api_kwargs
)
return source
def payment_is_valid_session(self, request):
return True
def checkout_prepare(self, request, cart):
return True
class StripeWeChatPay(StripeMethod):
identifier = 'stripe_wechatpay'
verbose_name = _('WeChat Pay via Stripe')
public_name = _('WeChat Pay')
method = 'wechatpay'
def payment_form_render(self, request) -> str:
template = get_template('pretixplugins/stripe/checkout_payment_form_simple_noform.html')
ctx = {
'request': request,
'event': self.event,
'settings': self.settings,
'form': self.payment_form(request)
}
return template.render(ctx)
def _create_source(self, request, payment):
source = stripe.Source.create(
type='wechat',
amount=self._get_amount(payment),
currency=self.event.currency.lower(),
metadata={
'order': str(payment.order.id),
'event': self.event.id,
'code': payment.order.code
},
statement_descriptor=self.statement_descriptor(payment, 32),
redirect={
'return_url': build_absolute_uri(self.event, 'plugins:stripe:return', kwargs={
'order': payment.order.code,
'payment': payment.pk,
'hash': hashlib.sha1(payment.order.secret.lower().encode()).hexdigest(),
})
},
**self.api_kwargs
)
return source
def payment_is_valid_session(self, request):
return True
def checkout_prepare(self, request, cart):
return True
def execute_payment(self, request: HttpRequest, payment: OrderPayment):
self._init_api()
try:
source = self._create_source(request, payment)
except stripe.error.StripeError as e:
if e.json_body and 'err' in e.json_body:
err = e.json_body['error']
logger.exception('Stripe error: %s' % str(err))
else:
err = {'message': str(e)}
logger.exception('Stripe error: %s' % str(e))
payment.info_data = {
'error': True,
'message': err['message'],
}
payment.state = OrderPayment.PAYMENT_STATE_FAILED
payment.save()
payment.order.log_action('pretix.event.order.payment.failed', {
'local_id': payment.local_id,
'provider': payment.provider,
'message': err['message']
})
raise PaymentException(_('We had trouble communicating with Stripe. Please try again and get in touch '
'with us if this problem persists.'))
ReferencedStripeObject.objects.get_or_create(
reference=source.id,
defaults={'order': payment.order, 'payment': payment}
)
payment.info = str(source)
payment.save()
return eventreverse(request.event, 'presale:event.order', kwargs={
'order': payment.order.code,
'secret': payment.order.secret
})