mirror of
https://github.com/pretix/pretix.git
synced 2026-08-24 13:02:00 +00:00
Stripe: Optional support for Stripe checkout
This commit is contained in:
@@ -155,10 +155,11 @@ class SecurityMiddleware:
|
|||||||
resp['X-XSS-Protection'] = '1'
|
resp['X-XSS-Protection'] = '1'
|
||||||
h = {
|
h = {
|
||||||
'default-src': "{static}",
|
'default-src': "{static}",
|
||||||
'script-src': '{static} https://js.stripe.com',
|
'script-src': '{static} https://checkout.stripe.com https://js.stripe.com',
|
||||||
'object-src': "'none'",
|
'object-src': "'none'",
|
||||||
'frame-src': '{static} https://js.stripe.com',
|
'frame-src': '{static} https://checkout.stripe.com https://js.stripe.com',
|
||||||
'style-src': "{static}",
|
'style-src': "{static}",
|
||||||
|
'connect-src': "{dynamic} https://checkout.stripe.com",
|
||||||
'img-src': "{static} data: https://*.stripe.com",
|
'img-src': "{static} data: https://*.stripe.com",
|
||||||
# form-action is not only used to match on form actions, but also on URLs
|
# form-action is not only used to match on form actions, but also on URLs
|
||||||
# form-ations redirect to. In the context of e.g. payment providers or
|
# form-ations redirect to. In the context of e.g. payment providers or
|
||||||
|
|||||||
@@ -32,6 +32,14 @@ class Stripe(BasePaymentProvider):
|
|||||||
('publishable_key',
|
('publishable_key',
|
||||||
forms.CharField(
|
forms.CharField(
|
||||||
label=_('Publishable key'),
|
label=_('Publishable key'),
|
||||||
|
)),
|
||||||
|
('ui',
|
||||||
|
forms.ChoiceField(
|
||||||
|
label=_('User interface'),
|
||||||
|
choices=(
|
||||||
|
('pretix', _('Simple (pretix design)')),
|
||||||
|
('checkout', _('Stripe Checkout')),
|
||||||
|
)
|
||||||
))
|
))
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@@ -60,7 +68,11 @@ class Stripe(BasePaymentProvider):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def payment_form_render(self, request) -> str:
|
def payment_form_render(self, request) -> str:
|
||||||
template = get_template('pretixplugins/stripe/checkout_payment_form.html')
|
ui = self.settings.get('ui', default='pretix')
|
||||||
|
if ui == 'checkout':
|
||||||
|
template = get_template('pretixplugins/stripe/checkout_payment_form_stripe_checkout.html')
|
||||||
|
else:
|
||||||
|
template = get_template('pretixplugins/stripe/checkout_payment_form.html')
|
||||||
ctx = {'request': request, 'event': self.event, 'settings': self.settings}
|
ctx = {'request': request, 'event': self.event, 'settings': self.settings}
|
||||||
return template.render(ctx)
|
return template.render(ctx)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
/*global $, stripe_pubkey, stripe_loadingmessage, gettext */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var Stripe = null;
|
||||||
|
var pretixstripe = {
|
||||||
|
'load': function () {
|
||||||
|
$.ajax(
|
||||||
|
{
|
||||||
|
url: 'https://checkout.stripe.com/checkout.js',
|
||||||
|
dataType: 'script',
|
||||||
|
success: function () {
|
||||||
|
pretixstripe.handler = StripeCheckout.configure({
|
||||||
|
key: $.trim($("#stripe_pubkey").html()),
|
||||||
|
locale: 'auto',
|
||||||
|
token: function(token) {
|
||||||
|
var $form = $("#stripe-checkout").parents("form");
|
||||||
|
$("#stripe_token").val(token.id);
|
||||||
|
$("#stripe_card_brand").val(token.card.brand);
|
||||||
|
$("#stripe_card_last4").val(token.card.last4);
|
||||||
|
$form.get(0).submit();
|
||||||
|
},
|
||||||
|
shippingAddress: false,
|
||||||
|
allowRememberMe: false,
|
||||||
|
billingAddress: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
handler: null
|
||||||
|
};
|
||||||
|
$(function () {
|
||||||
|
if (!$("#stripe-checkout").length) { // Not on the checkout page
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($("input[name=payment][value=stripe]").is(':checked') || $(".payment-redo-form").length) {
|
||||||
|
pretixstripe.load();
|
||||||
|
} else {
|
||||||
|
$("input[name=payment]").change(function() {
|
||||||
|
if ($(this).val() == 'stripe') {
|
||||||
|
pretixstripe.load();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$(".checkout-button-row .btn-primary").click(
|
||||||
|
function (e) {
|
||||||
|
if (($("input[name=payment][value=stripe]").prop('checked') || $("input[name=payment]").length === 0)
|
||||||
|
&& $("#stripe_token").val() == "") {
|
||||||
|
var amount = Math.round(
|
||||||
|
parseFloat(
|
||||||
|
$("#stripe-checkout").parents("[data-total]").attr("data-total").replace(",", ".")
|
||||||
|
) * 100
|
||||||
|
);
|
||||||
|
pretixstripe.handler.open({
|
||||||
|
name: $("#organizer_name").val(),
|
||||||
|
description: $("#event_name").val(),
|
||||||
|
currency: $("#stripe_currency").val(),
|
||||||
|
email: $("#stripe_email").val(),
|
||||||
|
amount: amount,
|
||||||
|
});
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$(window).on('popstate', function () {
|
||||||
|
if (pretixstripe.handler) {
|
||||||
|
pretixstripe.handler.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
<div class="form-horizontal" id="stripe-checkout">
|
||||||
|
<noscript>
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
{% trans "For a credit card payment, please turn on JavaScript." %}
|
||||||
|
</div>
|
||||||
|
</noscript>
|
||||||
|
<p>
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
Please continue below to start the credit card payment.
|
||||||
|
{% endblocktrans %}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<em>{% 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 %}</em>
|
||||||
|
</p>
|
||||||
|
<input type="hidden" name="stripe_token" value="" id="stripe_token" />
|
||||||
|
<input type="hidden" name="stripe_card_last4" value="" id="stripe_card_last4" />
|
||||||
|
<input type="hidden" name="stripe_card_brand" value="" id="stripe_card_brand" />
|
||||||
|
<input type="hidden" id="organizer_name" value="{{ event.organizer.name }}" />
|
||||||
|
<input type="hidden" id="event_name" value="{{ event.name }}" />
|
||||||
|
<input type="hidden" id="stripe_currency" value="{{ event.currency }}" />
|
||||||
|
<input type="hidden" id="event_name" value="{{ event.name }}" />
|
||||||
|
<input type="hidden" id="stripe_email" value="{{ request.session.email }}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
@@ -2,8 +2,14 @@
|
|||||||
{% load compress %}
|
{% load compress %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% compress js %}
|
{% if settings.ui == "checkout" %}
|
||||||
<script type="text/javascript" src="{% static "pretixplugins/stripe/pretix-stripe.js" %}"></script>
|
{% compress js %}
|
||||||
{% endcompress %}
|
<script type="text/javascript" src="{% static "pretixplugins/stripe/pretix-stripe-checkout.js" %}"></script>
|
||||||
|
{% endcompress %}
|
||||||
|
{% else %}
|
||||||
|
{% compress js %}
|
||||||
|
<script type="text/javascript" src="{% static "pretixplugins/stripe/pretix-stripe.js" %}"></script>
|
||||||
|
{% endcompress %}
|
||||||
|
{% endif %}
|
||||||
<script type="text/plain" id="stripe_pubkey">{{ settings.publishable_key }}</script>
|
<script type="text/plain" id="stripe_pubkey">{{ settings.publishable_key }}</script>
|
||||||
|
|
||||||
|
|||||||
@@ -234,6 +234,7 @@ class PaymentStep(QuestionsViewMixin, CartMixin, TemplateFlowStep):
|
|||||||
providers.append({
|
providers.append({
|
||||||
'provider': provider,
|
'provider': provider,
|
||||||
'fee': fee,
|
'fee': fee,
|
||||||
|
'total': self._total_order_value + fee,
|
||||||
'form': provider.payment_form_render(self.request)
|
'form': provider.payment_form_render(self.request)
|
||||||
})
|
})
|
||||||
return providers
|
return providers
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<div class="panel-group" id="payment_accordion">
|
<div class="panel-group" id="payment_accordion">
|
||||||
{% for p in providers %}
|
{% for p in providers %}
|
||||||
<div class="panel panel-default">
|
<div class="panel panel-default" data-total="{{ p.total|floatformat:2 }}">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<h4 class="panel-title">
|
<h4 class="panel-title">
|
||||||
<label class="radio">
|
<label class="radio">
|
||||||
|
|||||||
Reference in New Issue
Block a user