From cc4ad998e16581fa20dc15f50c39ba0040962863 Mon Sep 17 00:00:00 2001 From: Mira Weller Date: Tue, 2 Dec 2025 12:57:20 +0100 Subject: [PATCH] refactor payment qr codes --- src/pretix/helpers/payment.py | 129 ++++++++++++++++++ src/pretix/plugins/banktransfer/payment.py | 58 ++------ .../pretixplugins/banktransfer/pending.html | 96 +------------ .../pretixpresale/event/payment_qr_codes.html | 44 ++++++ 4 files changed, 186 insertions(+), 141 deletions(-) create mode 100644 src/pretix/helpers/payment.py create mode 100644 src/pretix/presale/templates/pretixpresale/event/payment_qr_codes.html diff --git a/src/pretix/helpers/payment.py b/src/pretix/helpers/payment.py new file mode 100644 index 0000000000..6163d4f61f --- /dev/null +++ b/src/pretix/helpers/payment.py @@ -0,0 +1,129 @@ +import text_unidecode +from django.utils.http import urlencode +from django.utils.safestring import mark_safe +from django.utils.translation import gettext_lazy as _ + + +def dotdecimal(value): + return str(value).replace(",", ".") + + +def commadecimal(value): + return str(value).replace(".", ",") + + +def generate_payment_qr_codes( + event, + code, + amount, + bank_details_sepa_bic, + bank_details_sepa_name, + bank_details_sepa_iban +): + out = [] + qr_data = swiss_qrbill( + event, + code, + amount, + bank_details_sepa_bic, + bank_details_sepa_name, + bank_details_sepa_iban + ) + if qr_data: + out.append({ + "id": "qrbill", + "label": "QR-bill", + "html_prefix": mark_safe(''), + "qr_data": qr_data, + "css_class": "banktransfer-swiss-cross-overlay", + }) + + if event.currency == 'EUR' and bank_details_sepa_iban: + out.append({ + "id": "girocode", + "label": "EPC-QR", + "qr_data": "\n".join(text_unidecode.unidecode(str(d or '')) for d in [ + "BCD", # Service Tag: ‘BCD’ + "002", # Version: V2 + "2", # Character set: ISO 8859-1 + "SCT", # Identification code: ‘SCT‘ + bank_details_sepa_bic, # AT-23 BIC of the Beneficiary Bank + bank_details_sepa_name, # AT-21 Name of the Beneficiary + bank_details_sepa_iban, # AT-20 Account number of the Beneficiary + f"{event.currency}{dotdecimal(amount)}", # AT-04 Amount of the Credit Transfer in Euro + "", # AT-44 Purpose of the Credit Transfer + "", # AT-05 Remittance Information (Structured) + code, # AT-05 Remittance Information (Unstructured) + "", # Beneficiary to originator information + "", + ]), + }) + + qr_data = f"bank://singlepaymentsepa?" + urlencode({ + "name": bank_details_sepa_name, + "iban":bank_details_sepa_iban, + "bic": bank_details_sepa_bic, + "amount": commadecimal(amount), + "reason": code, + "currency": event.currency, + }) + out.append({ + "id": "bezahlcode", + "label": "BezahlCode", + "qr_data": mark_safe(qr_data), + "link": qr_data, + "link_aria_label": _("Open BezahlCode in your banking app to start the payment process."), + }) + return out + +def swiss_qrbill( + event, + code, + amount, + bank_details_sepa_bic, + bank_details_sepa_name, + bank_details_sepa_iban +): + if not bank_details_sepa_iban or not bank_details_sepa_iban[:2] in ('CH', 'LI'): + return + if event.currency not in ('EUR', 'CHF'): + return + if not event.settings.invoice_address_from or not event.settings.invoice_address_from_country: + return + + data_fields = [ + 'SPC', + '0200', + '1', + bank_details_sepa_iban, + 'K', + bank_details_sepa_name[:70], + event.settings.invoice_address_from.replace('\n', ', ')[:70], + (event.settings.invoice_address_from_zipcode + ' ' + event.settings.invoice_address_from_city)[:70], + '', + '', + str(event.settings.invoice_address_from_country), + '', # rfu + '', # rfu + '', # rfu + '', # rfu + '', # rfu + '', # rfu + '', # rfu + str(amount), + event.currency, + '', # debtor address + '', # debtor address + '', # debtor address + '', # debtor address + '', # debtor address + '', # debtor address + '', # debtor address + 'NON', + '', # structured reference + code, + 'EPD', + ] + + data_fields = [text_unidecode.unidecode(d or '') for d in data_fields] + return '\r\n'.join(data_fields) diff --git a/src/pretix/plugins/banktransfer/payment.py b/src/pretix/plugins/banktransfer/payment.py index 380c31a12d..c53aaa339a 100644 --- a/src/pretix/plugins/banktransfer/payment.py +++ b/src/pretix/plugins/banktransfer/payment.py @@ -46,12 +46,12 @@ from i18nfield.forms import I18nTextInput from i18nfield.strings import LazyI18nString from localflavor.generic.forms import BICFormField, IBANFormField from localflavor.generic.validators import IBANValidator -from text_unidecode import unidecode from pretix.base.forms import I18nMarkdownTextarea from pretix.base.models import InvoiceAddress, Order, OrderPayment, OrderRefund from pretix.base.payment import BasePaymentProvider from pretix.base.templatetags.money import money_filter +from pretix.helpers.payment import generate_payment_qr_codes from pretix.plugins.banktransfer.templatetags.ibanformat import ibanformat from pretix.presale.views.cart import cart_session @@ -313,51 +313,6 @@ class BankTransfer(BasePaymentProvider): t += str(self.settings.get('bank_details', as_type=LazyI18nString)) return t - def swiss_qrbill(self, payment): - if not self.settings.get('bank_details_sepa_iban') or not self.settings.get('bank_details_sepa_iban')[:2] in ('CH', 'LI'): - return - if self.event.currency not in ('EUR', 'CHF'): - return - if not self.event.settings.invoice_address_from or not self.event.settings.invoice_address_from_country: - return - - data_fields = [ - 'SPC', - '0200', - '1', - self.settings.get('bank_details_sepa_iban'), - 'K', - self.settings.get('bank_details_sepa_name')[:70], - self.event.settings.invoice_address_from.replace('\n', ', ')[:70], - (self.event.settings.invoice_address_from_zipcode + ' ' + self.event.settings.invoice_address_from_city)[:70], - '', - '', - str(self.event.settings.invoice_address_from_country), - '', # rfu - '', # rfu - '', # rfu - '', # rfu - '', # rfu - '', # rfu - '', # rfu - str(payment.amount), - self.event.currency, - '', # debtor address - '', # debtor address - '', # debtor address - '', # debtor address - '', # debtor address - '', # debtor address - '', # debtor address - 'NON', - '', # structured reference - self._code(payment.order), - 'EPD', - ] - - data_fields = [unidecode(d or '') for d in data_fields] - return '\r\n'.join(data_fields) - def payment_pending_render(self, request: HttpRequest, payment: OrderPayment): template = get_template('pretixplugins/banktransfer/pending.html') ctx = { @@ -367,13 +322,18 @@ class BankTransfer(BasePaymentProvider): 'amount': payment.amount, 'payment_info': payment.info_data, 'settings': self.settings, - 'swiss_qrbill': self.swiss_qrbill(payment), - 'eu_barcodes': self.event.currency == 'EUR', + 'payment_qr_codes': generate_payment_qr_codes( + event=self.event, + code=self._code(payment.order), + amount=payment.amount, + bank_details_sepa_bic=self.settings.get('bank_details_sepa_bic'), + bank_details_sepa_name=self.settings.get('bank_details_sepa_name'), + bank_details_sepa_iban=self.settings.get('bank_details_sepa_iban'), + ) if self.settings.bank_details_type == "sepa" else None, 'pending_description': self.settings.get('pending_description', as_type=LazyI18nString), 'details': self.settings.get('bank_details', as_type=LazyI18nString), 'has_invoices': payment.order.invoices.exists(), } - ctx['any_barcodes'] = ctx['swiss_qrbill'] or ctx['eu_barcodes'] return template.render(ctx, request=request) def payment_control_render(self, request: HttpRequest, payment: OrderPayment) -> str: diff --git a/src/pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/pending.html b/src/pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/pending.html index 028d90bac2..5d25bad1b1 100644 --- a/src/pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/pending.html +++ b/src/pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/pending.html @@ -1,7 +1,6 @@ {% load i18n %} {% load l10n %} {% load commadecimal %} -{% load static %} {% load dotdecimal %} {% load ibanformat %} {% load money %} @@ -17,7 +16,7 @@ {% endblocktrans %}

-
+
{% trans "Reference code (important):" %}
{{ code }}
{% trans "Amount:" %}
{{ amount|money:event.currency }}
@@ -36,94 +35,7 @@ {% trans "We will send you an email as soon as we received your payment." %}

- {% if settings.bank_details_type == "sepa" and any_barcodes %} - + {% if payment_qr_codes %} + {% include "pretixpresale/event/payment_qr_codes.html" %} {% endif %} -
-{% if swiss_qrbill %} - -{% endif %} +
\ No newline at end of file diff --git a/src/pretix/presale/templates/pretixpresale/event/payment_qr_codes.html b/src/pretix/presale/templates/pretixpresale/event/payment_qr_codes.html new file mode 100644 index 0000000000..9c1500f082 --- /dev/null +++ b/src/pretix/presale/templates/pretixpresale/event/payment_qr_codes.html @@ -0,0 +1,44 @@ +{% load i18n %} +{% load static %} + +{% if payment_qr_codes %} + + {% for code_info in payment_qr_codes %} + {% if code_info.id == "qrbill" %} + + {% endif %} + {% endfor %} +{% endif %} \ No newline at end of file