def order_prepare(self, request, order): self.init_api() payment = paypalrestsdk.Payment({ 'intent': 'sale', 'payer': { "payment_method": "paypal", }, "redirect_urls": { "return_url": build_absolute_uri(request.event, 'plugins:paypal:return'), "cancel_url": build_absolute_uri(request.event, 'plugins:paypal:abort'), }, "transactions": [ { "item_list": { "items": [ { "name": 'Order %s' % order.code, "quantity": 1, "price": str(order.total), "currency": order.event.currency } ] }, "amount": { "currency": request.event.currency, "total": str(order.total) }, "description": __('Event tickets for %s') % request.event.name } ] }) request.session['payment_paypal_order'] = order.pk return self._create_payment(request, payment)
def payment_prepare(self, request, payment_obj): self.init_api() if request.event.settings.payment_paypal_connect_user_id: userinfo = Tokeninfo.create_with_refresh_token(request.event.settings.payment_paypal_connect_refresh_token).userinfo() request.event.settings.payment_paypal_connect_user_id = userinfo.email payee = { "email": request.event.settings.payment_paypal_connect_user_id, # If PayPal ever offers a good way to get the MerchantID via the Identifity API, # we should use it instead of the merchant's eMail-address # "merchant_id": request.event.settings.payment_paypal_connect_user_id, } else: payee = {} payment = paypalrestsdk.Payment({ 'intent': 'sale', 'payer': { "payment_method": "paypal", }, "redirect_urls": { "return_url": build_absolute_uri(request.event, 'plugins:paypal:return'), "cancel_url": build_absolute_uri(request.event, 'plugins:paypal:abort'), }, "transactions": [ { "item_list": { "items": [ { "name": __('Order {slug}-{code}').format(slug=self.event.slug.upper(), code=payment_obj.order.code), "quantity": 1, "price": self.format_price(payment_obj.amount), "currency": payment_obj.order.event.currency } ] }, "amount": { "currency": request.event.currency, "total": self.format_price(payment_obj.amount) }, "description": __('Order {order} for {event}').format( event=request.event.name, order=payment_obj.order.code ), "payee": payee } ] }) request.session['payment_paypal_order'] = payment_obj.order.pk request.session['payment_paypal_payment'] = payment_obj.pk return self._create_payment(request, payment)
def checkout_prepare(self, request, cart): self.init_api() kwargs = {} if request.resolver_match and 'cart_namespace' in request.resolver_match.kwargs: kwargs['cart_namespace'] = request.resolver_match.kwargs['cart_namespace'] if request.event.settings.payment_paypal_connect_user_id: userinfo = Tokeninfo.create_with_refresh_token(request.event.settings.payment_paypal_connect_refresh_token).userinfo() request.event.settings.payment_paypal_connect_user_id = userinfo.email payee = { "email": request.event.settings.payment_paypal_connect_user_id, # If PayPal ever offers a good way to get the MerchantID via the Identifity API, # we should use it instead of the merchant's eMail-address # "merchant_id": request.event.settings.payment_paypal_connect_user_id, } else: payee = {} payment = paypalrestsdk.Payment({ 'intent': 'sale', 'payer': { "payment_method": "paypal", }, "redirect_urls": { "return_url": build_absolute_uri(request.event, 'plugins:paypal:return', kwargs=kwargs), "cancel_url": build_absolute_uri(request.event, 'plugins:paypal:abort', kwargs=kwargs), }, "transactions": [ { "item_list": { "items": [ { "name": __('Order for %s') % str(request.event), "quantity": 1, "price": self.format_price(cart['total']), "currency": request.event.currency } ] }, "amount": { "currency": request.event.currency, "total": self.format_price(cart['total']) }, "description": __('Event tickets for {event}').format(event=request.event.name), "payee": payee } ] }) request.session['payment_paypal_order'] = None return self._create_payment(request, payment)
def get_ical(events): cal = vobject.iCalendar() cal.add('prodid').value = '-//pretix//{}//'.format(settings.PRETIX_INSTANCE_NAME.replace(" ", "_")) creation_time = datetime.datetime.now(pytz.utc) for ev in events: event = ev if isinstance(ev, Event) else ev.event tz = pytz.timezone(event.settings.timezone) if isinstance(ev, Event): url = build_absolute_uri(event, 'presale:event.index') else: url = build_absolute_uri(event, 'presale:event.index', { 'subevent': ev.pk }) vevent = cal.add('vevent') vevent.add('summary').value = str(ev.name) vevent.add('dtstamp').value = creation_time if ev.location: vevent.add('location').value = str(ev.location) vevent.add('uid').value = 'pretix-{}-{}-{}@{}'.format( event.organizer.slug, event.slug, ev.pk if not isinstance(ev, Event) else '0', urlparse(url).netloc ) if event.settings.show_times: vevent.add('dtstart').value = ev.date_from.astimezone(tz) else: vevent.add('dtstart').value = ev.date_from.astimezone(tz).date() if event.settings.show_date_to and ev.date_to: if event.settings.show_times: vevent.add('dtend').value = ev.date_to.astimezone(tz) else: vevent.add('dtend').value = ev.date_to.astimezone(tz).date() descr = [] descr.append(_('Tickets: {url}').format(url=url)) if ev.date_admission: descr.append(str(_('Admission: {datetime}')).format( datetime=date_format(ev.date_admission.astimezone(tz), 'SHORT_DATETIME_FORMAT') )) descr.append(_('Organizer: {organizer}').format(organizer=event.organizer.name)) vevent.add('description').value = '\n'.join(descr) return cal
def _create_source(self, request, payment): try: source = stripe.Source.create( type='bancontact', 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_bancontact_account') or ugettext('unknown name') }, bancontact={ 'statement_descriptor': ugettext('{event}-{code}').format( event=self.event.slug.upper(), code=payment.order.code )[: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 finally: if 'payment_stripe_bancontact_account' in request.session: del request.session['payment_stripe_bancontact_account']
def send_expiry_warnings(sender, **kwargs): eventcache = {} today = now().replace(hour=0, minute=0, second=0) for o in Order.objects.filter(expires__gte=today, expiry_reminder_sent=False, status=Order.STATUS_PENDING).select_related('event'): settings = eventcache.get(o.event.pk, None) if settings is None: settings = o.event.settings eventcache[o.event.pk] = settings days = settings.get('mail_days_order_expire_warning', as_type=int) if days and (o.expires - today).days <= days: o.expiry_reminder_sent = True o.save() try: mail( o.email, _('Your order is about to expire: %(code)s') % {'code': o.code}, settings.mail_text_order_expire_warning, { 'event': o.event.name, 'url': build_absolute_uri(o.event, 'presale:event.order', kwargs={ 'order': o.code, 'secret': o.secret }), 'expire_date': date_format(o.expires, 'SHORT_DATE_FORMAT') }, o.event, locale=o.locale ) except SendMailException: logger.exception('Reminder email could not be sent') else: o.log_action('pretix.event.order.expire_warning_sent')
def render(self, context): from pretix.multidomain.urlreverse import eventreverse kwargs = { smart_text(k, 'ascii'): v.resolve(context) for k, v in self.kwargs.items() } view_name = self.view_name.resolve(context) event = self.event.resolve(context) url = '' try: if self.absolute: url = build_absolute_uri(event, view_name, kwargs=kwargs) else: url = eventreverse(event, view_name, kwargs=kwargs) except NoReverseMatch: if self.asvar is None: raise if self.asvar: context[self.asvar] = url return '' else: if context.autoescape: url = conditional_escape(url) return url
def notify_incomplete_payment(o: Order): with language(o.locale): tz = pytz.timezone(o.event.settings.get('timezone', settings.TIME_ZONE)) try: invoice_name = o.invoice_address.name invoice_company = o.invoice_address.company except InvoiceAddress.DoesNotExist: invoice_name = "" invoice_company = "" email_template = o.event.settings.mail_text_order_expire_warning email_context = { 'event': o.event.name, 'url': build_absolute_uri(o.event, 'presale:event.order.open', kwargs={ 'order': o.code, 'secret': o.secret, 'hash': o.email_confirm_hash() }), 'expire_date': date_format(o.expires.astimezone(tz), 'SHORT_DATE_FORMAT'), 'invoice_name': invoice_name, 'invoice_company': invoice_company, } email_subject = ugettext('Your order received an incomplete payment: %(code)s') % {'code': o.code} try: o.send_mail( email_subject, email_template, email_context, 'pretix.event.order.email.expire_warning_sent' ) except SendMailException: logger.exception('Reminder email could not be sent')
def _create_source(self, request, payment): source = stripe.Source.create( type='sofort', amount=self._get_amount(payment), currency=self.event.currency.lower(), metadata={ 'order': str(payment.order.id), 'event': self.event.id, 'code': payment.order.code }, sofort={ 'country': request.session.get('payment_stripe_sofort_bank_country'), 'statement_descriptor': ugettext('{event}-{code}').format( event=self.event.slug.upper(), code=payment.order.code )[: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 mail(email: str, subject: str, template: str, context: Dict[str, Any]=None, event: Event=None, locale: str=None, order: Order=None): """ Sends out an email to a user. The mail will be sent synchronously or asynchronously depending on the installation. :param email: The email address of the recipient :param subject: The email subject. Should be localized to the recipients's locale or a lazy object that will be localized by being casted to a string. :param template: The filename of a template to be used. It will be rendered with the locale given in the locale argument and the context given in the next argument. Alternatively, you can pass a LazyI18nString and ``context`` will be used as the argument to a Python ``.format()`` call on the template. :param context: The context for rendering the template (see ``template`` parameter) :param event: The event this email is related to (optional). If set, this will be used to determine the sender, a possible prefix for the subject and the SMTP server that should be used to send this email. :param order: The order this email is related to (optional). If set, this will be used to include a link to the order below the email. :param locale: The locale to be used while evaluating the subject and the template :return: ``False`` on obvious, immediate failures, ``True`` otherwise. ``True`` does not necessarily mean that the email has been sent, just that it has been queued by the email backend. """ with language(locale): if isinstance(template, LazyI18nString): body = str(template) if context: body = body.format_map(TolerantDict(context)) else: tpl = get_template(template) body = tpl.render(context) sender = event.settings.get('mail_from') if event else settings.MAIL_FROM subject = str(subject) if event: prefix = event.settings.get('mail_prefix') if prefix: subject = "[%s] %s" % (prefix, subject) body += "\r\n\r\n----\r\n" body += _( "You are receiving this email because you placed an order for {event}." ).format(event=event.name) if order: body += "\r\n" body += _( "You can view your order details at the following URL:\r\n{orderurl}." ).format(event=event.name, orderurl=build_absolute_uri(order.event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret })) body += "\r\n" return mail_send([email], subject, body, sender, event.id if event else None)
def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) ctx['order'] = self.order can_download = all([r for rr, r in allow_ticket_download.send(self.request.event, order=self.order)]) if self.request.event.settings.ticket_download_date: ctx['ticket_download_date'] = self.order.ticket_download_date ctx['can_download'] = can_download and self.order.ticket_download_available ctx['download_buttons'] = self.download_buttons ctx['cart'] = self.get_cart( answers=True, downloads=ctx['can_download'], queryset=self.order.positions.select_related('tax_rule'), order=self.order ) ctx['can_download_multi'] = any([b['multi'] for b in self.download_buttons]) and ( self.request.event.settings.ticket_download_nonadm or [p.item.admission for p in ctx['cart']['positions']].count(True) > 1 ) ctx['invoices'] = list(self.order.invoices.all()) can_generate_invoice = ( self.request.event.settings.get('invoice_generate') in ('user', 'True') or ( self.request.event.settings.get('invoice_generate') == 'paid' and self.order.status == Order.STATUS_PAID ) ) ctx['can_generate_invoice'] = invoice_qualified(self.order) and can_generate_invoice ctx['url'] = build_absolute_uri( self.request.event, 'presale:event.order', kwargs={ 'order': self.order.code, 'secret': self.order.secret } ) if self.order.status == Order.STATUS_PENDING: ctx['pending_sum'] = self.order.pending_sum lp = self.order.payments.last() ctx['can_pay'] = False for provider in self.request.event.get_payment_providers().values(): if provider.is_enabled and provider.order_change_allowed(self.order): ctx['can_pay'] = True break if lp and lp.state not in (OrderPayment.PAYMENT_STATE_CONFIRMED, OrderPayment.PAYMENT_STATE_REFUNDED): ctx['last_payment'] = self.order.payments.last() pp = lp.payment_provider ctx['last_payment_info'] = pp.payment_pending_render(self.request, ctx['last_payment']) if lp.state == OrderPayment.PAYMENT_STATE_PENDING and not pp.abort_pending_allowed: ctx['can_pay'] = False ctx['can_pay'] = ctx['can_pay'] and self.order._can_be_paid() is True elif self.order.status == Order.STATUS_PAID: ctx['can_pay'] = False return ctx
def mark_order_paid(order: Order, provider: str=None, info: str=None, date: datetime=None, manual: bool=None, force: bool=False, send_mail: bool=True, user: User=None) -> Order: """ Marks an order as paid. This sets the payment provider, info and date and returns the order object. :param provider: The payment provider that marked this as paid :type provider: str :param info: The information to store in order.payment_info :type info: str :param date: The date the payment was received (if you pass ``None``, the current time will be used). :type date: datetime :param force: Whether this payment should be marked as paid even if no remaining quota is available (default: ``False``). :type force: boolean :param send_mail: Whether an email should be sent to the user about this event (default: ``True``). :type send_mail: boolean :param user: The user that performed the change :raises Quota.QuotaExceededException: if the quota is exceeded and ``force`` is ``False`` """ with order.event.lock(): can_be_paid = order._can_be_paid() if not force and can_be_paid is not True: raise Quota.QuotaExceededException(can_be_paid) order.payment_provider = provider or order.payment_provider order.payment_info = info or order.payment_info order.payment_date = date or now() if manual is not None: order.payment_manual = manual order.status = Order.STATUS_PAID order.save() order.log_action('pretix.event.order.paid', { 'provider': provider, 'info': info, 'date': date, 'manual': manual, 'force': force }, user=user) order_paid.send(order.event, order=order) if send_mail: with language(order.locale): mail( order.email, _('Payment received for your order: %(code)s') % {'code': order.code}, order.event.settings.mail_text_order_paid, { 'event': order.event.name, 'url': build_absolute_uri(order.event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret }), 'downloads': order.event.settings.get('ticket_download', as_type=bool) }, order.event, locale=order.locale ) return order
def redirect(self, request, url): if request.session.get('iframe_session', False): signer = signing.Signer(salt='safe-redirect') return ( build_absolute_uri(request.event, 'plugins:stripe:redirect') + '?url=' + urllib.parse.quote(signer.sign(url)) ) else: return str(url)
def _perform_order(event: str, payment_provider: str, position_ids: List[str], email: str, locale: str, address: int): event = Event.objects.get(id=event) responses = register_payment_providers.send(event) pprov = None for rec, response in responses: provider = response(event) if provider.identifier == payment_provider: pprov = provider if not pprov: raise OrderError(error_messages['internal']) dt = now() with event.lock(): positions = list(CartPosition.objects.filter( id__in=position_ids).select_related('item', 'variation')) if len(position_ids) != len(positions): raise OrderError(error_messages['internal']) _check_positions(event, dt, positions) order = _create_order(event, email, positions, dt, pprov, locale=locale) if address is not None: try: addr = InvoiceAddress.objects.get( pk=address ) if addr.order is not None: addr.pk = None addr.order = order addr.save() except InvoiceAddress.DoesNotExist: pass if event.settings.get('invoice_generate') == 'True': generate_invoice(order) with language(order.locale): mail( order.email, _('Your order: %(code)s') % {'code': order.code}, event.settings.mail_text_order_placed, { 'total': LazyNumber(order.total), 'currency': event.currency, 'date': LazyDate(order.expires), 'event': event.name, 'url': build_absolute_uri(event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret }), 'paymentinfo': str(pprov.order_pending_mail_render(order)) }, event, locale=order.locale ) return order.id
def send_voucher(self, quota_cache=None, user=None, auth=None): availability = ( self.variation.check_quotas(count_waitinglist=False, subevent=self.subevent, _cache=quota_cache) if self.variation else self.item.check_quotas(count_waitinglist=False, subevent=self.subevent, _cache=quota_cache) ) if availability[1] is None or availability[1] < 1: raise WaitingListException(_('This product is currently not available.')) if self.voucher: raise WaitingListException(_('A voucher has already been sent to this person.')) if '@' not in self.email: raise WaitingListException(_('This entry is anonymized and can no longer be used.')) with transaction.atomic(): v = Voucher.objects.create( event=self.event, max_usages=1, valid_until=now() + timedelta(hours=self.event.settings.waiting_list_hours), item=self.item, variation=self.variation, tag='waiting-list', comment=_('Automatically created from waiting list entry for {email}').format( email=self.email ), block_quota=True, subevent=self.subevent, ) v.log_action('pretix.voucher.added.waitinglist', { 'item': self.item.pk, 'variation': self.variation.pk if self.variation else None, 'tag': 'waiting-list', 'block_quota': True, 'valid_until': v.valid_until.isoformat(), 'max_usages': 1, 'email': self.email, 'waitinglistentry': self.pk, 'subevent': self.subevent.pk if self.subevent else None, }, user=user, auth=auth) self.log_action('pretix.waitinglist.voucher', user=user, auth=auth) self.voucher = v self.save() with language(self.locale): mail( self.email, _('You have been selected from the waitinglist for {event}').format(event=str(self.event)), self.event.settings.mail_text_waiting_list, { 'event': self.event.name, 'url': build_absolute_uri(self.event, 'presale:event.redeem') + '?voucher=' + self.voucher.code, 'code': self.voucher.code, 'product': str(self.item) + (' - ' + str(self.variation) if self.variation else ''), 'hours': self.event.settings.waiting_list_hours, }, self.event, locale=self.locale )
def checkout_prepare(self, request, cart): self.init_api() items = [] for cp in cart['positions']: items.append({ "name": str(cp.item.name), "description": str(cp.variation) if cp.variation else "", "quantity": cp.count, "price": str(cp.price), "currency": request.event.currency }) if cart['payment_fee']: items.append({ "name": __('Payment method fee'), "description": "", "quantity": 1, "currency": request.event.currency, "price": str(cart['payment_fee']) }) payment = paypalrestsdk.Payment({ 'intent': 'sale', 'payer': { "payment_method": "paypal", }, "redirect_urls": { "return_url": build_absolute_uri(request.event, 'plugins:paypal:return'), "cancel_url": build_absolute_uri(request.event, 'plugins:paypal:abort'), }, "transactions": [ { "item_list": { "items": items }, "amount": { "currency": request.event.currency, "total": str(cart['total']) }, "description": __('Event tickets for %s') % request.event.name } ] }) request.session['payment_paypal_order'] = None return self._create_payment(request, payment)
def social_image(self): from pretix.multidomain.urlreverse import build_absolute_uri img = None logo_file = self.settings.get('logo_image', as_type=str, default='')[7:] og_file = self.settings.get('og_image', as_type=str, default='')[7:] if og_file: img = get_thumbnail(og_file, '1200').thumb.url elif logo_file: img = get_thumbnail(logo_file, '5000x120').thumb.url if img: return urljoin(build_absolute_uri(self, 'presale:event.index'), img)
def _get_payment_body(self, payment): b = { 'amount': { 'currency': self.event.currency, 'value': str(payment.amount), }, 'description': 'Order {}-{}'.format(self.event.slug.upper(), payment.full_id), 'redirectUrl': build_absolute_uri( self.event, 'plugins:pretix_mollie:return', kwargs={ 'order': payment.order.code, 'payment': payment.pk, 'hash': hashlib.sha1( payment.order.secret.lower().encode()).hexdigest(), }), 'webhookUrl': build_absolute_uri(self.event, 'plugins:pretix_mollie:webhook', kwargs={'payment': payment.pk}), 'locale': self.get_locale(payment.order.locale), 'method': self.method, 'metadata': { 'organizer': self.event.organizer.slug, 'event': self.event.slug, 'order': payment.order.code, 'payment': payment.local_id, } } if self.settings.connect_client_id and self.settings.access_token: b['profileId'] = self.settings.connect_profile b['testmode'] = self.settings.endpoint == 'test' or self.event.testmode return b
def order_prepare(self, request, order): self.init_api() payment = paypalrestsdk.Payment({ 'intent': 'sale', 'payer': { "payment_method": "paypal", }, "redirect_urls": { "return_url": build_absolute_uri(request.event, 'plugins:paypal:return'), "cancel_url": build_absolute_uri(request.event, 'plugins:paypal:abort'), }, "transactions": [{ "item_list": { "items": [{ "name": __('Order {slug}-{code}').format( slug=self.event.slug.upper(), code=order.code), "quantity": 1, "price": str(order.total), "currency": order.event.currency }] }, "amount": { "currency": request.event.currency, "total": str(order.total) }, "description": __('Order {order} for {event}').format( event=request.event.name, order=order.code) }] }) request.session['payment_paypal_order'] = order.pk return self._create_payment(request, payment)
def __init__(self, *args, **kwargs): self.organizer = kwargs.pop('organizer') self.locales = kwargs.get('locales') self.has_subevents = kwargs.pop('has_subevents') kwargs.pop('user') super().__init__(*args, **kwargs) self.initial['timezone'] = get_current_timezone_name() self.fields['locale'].choices = [(a, b) for a, b in settings.LANGUAGES if a in self.locales] self.fields['location'].widget.attrs['rows'] = '3' self.fields['slug'].widget.prefix = build_absolute_uri(self.organizer, 'presale:organizer.index') if self.has_subevents: del self.fields['presale_start'] del self.fields['presale_end']
def _cancel_order(order, user=None, send_mail: bool = True): """ Mark this order as canceled :param order: The order to change :param user: The user that performed the change """ if isinstance(order, int): order = Order.objects.get(pk=order) if isinstance(user, int): user = User.objects.get(pk=user) with order.event.lock(): if order.status != Order.STATUS_PENDING: raise OrderError(_('You cannot cancel this order.')) order.status = Order.STATUS_CANCELED order.save() order.log_action('pretix.event.order.canceled', user=user) i = order.invoices.filter(is_cancellation=False).last() if i: generate_cancellation(i) for position in order.positions.all(): if position.voucher: Voucher.objects.filter(pk=position.voucher.pk).update( redeemed=F('redeemed') - 1) if send_mail: email_template = order.event.settings.mail_text_order_canceled email_context = { 'event': order.event.name, 'code': order.code, 'url': build_absolute_uri(order.event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret }) } email_subject = _('Order canceled: %(code)s') % {'code': order.code} with language(order.locale): try: order.send_mail(email_subject, email_template, email_context, 'pretix.event.order.email.order_canceled', user) except SendMailException: logger.exception('Order canceled email could not be sent') return order.pk
def _perform_order(event: str, payment_provider: str, position_ids: List[str], email: str, locale: str): event = Event.objects.get(id=event) responses = register_payment_providers.send(event) pprov = None for receiver, response in responses: provider = response(event) if provider.identifier == payment_provider: pprov = provider if not pprov: raise OrderError(error_messages['internal']) dt = now() with event.lock(): positions = list( CartPosition.objects.filter(id__in=position_ids).select_related( 'item', 'variation')) if len(position_ids) != len(positions): raise OrderError(error_messages['internal']) _check_positions(event, dt, positions) order = _create_order(event, email, positions, dt, pprov, locale=locale) mail(order.email, _('Your order: %(code)s') % {'code': order.code}, event.settings.mail_text_order_placed, { 'total': LazyNumber(order.total), 'currency': event.currency, 'date': LazyDate(order.expires), 'event': event.name, 'url': build_absolute_uri(event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret }), 'paymentinfo': str(pprov.order_pending_mail_render(order)) }, event, locale=order.locale) return order.id
def send_mails(event: int, user: int, subject: dict, message: dict, orders: list) -> None: failures = [] event = Event.objects.get(pk=event) user = User.objects.get(pk=user) if user else None orders = Order.objects.filter(pk__in=orders) subject = LazyI18nString(subject) message = LazyI18nString(message) tz = pytz.timezone(event.settings.timezone) for o in orders: try: invoice_name = o.invoice_address.name invoice_company = o.invoice_address.company except InvoiceAddress.DoesNotExist: invoice_name = "" invoice_company = "" try: with language(o.locale): email_context = { 'event': o.event, 'code': o.code, 'date': date_format(o.datetime.astimezone(tz), 'SHORT_DATETIME_FORMAT'), 'expire_date': date_format(o.expires, 'SHORT_DATE_FORMAT'), 'url': build_absolute_uri(event, 'presale:event.order', kwargs={ 'order': o.code, 'secret': o.secret }), 'invoice_name': invoice_name, 'invoice_company': invoice_company, } mail( o.email, subject, message, email_context, event, locale=o.locale, order=o ) o.log_action( 'pretix.plugins.sendmail.order.email.sent', user=user, data={ 'subject': subject.localize(o.locale).format_map(email_context), 'message': message.localize(o.locale).format_map(email_context), 'recipient': o.email } ) except SendMailException: failures.append(o.email)
def _notify_user(self): with language(self.order.locale): mail( self.order.email, _('Your order has been changed: %(code)s') % {'code': self.order.code}, self.order.event.settings.mail_text_order_changed, { 'event': self.order.event.name, 'url': build_absolute_uri(self.order.event, 'presale:event.order', kwargs={ 'order': self.order.code, 'secret': self.order.secret }), }, self.order.event, locale=self.order.locale )
def send_expiry_warnings(sender, **kwargs): eventcache = {} today = now().replace(hour=0, minute=0, second=0) for o in Order.objects.filter( expires__gte=today, expiry_reminder_sent=False, status=Order.STATUS_PENDING).select_related('event'): eventsettings = eventcache.get(o.event.pk, None) if eventsettings is None: eventsettings = o.event.settings eventcache[o.event.pk] = eventsettings days = eventsettings.get('mail_days_order_expire_warning', as_type=int) tz = pytz.timezone(eventsettings.get('timezone', settings.TIME_ZONE)) if days and (o.expires - today).days <= days: o.expiry_reminder_sent = True o.save() try: invoice_name = o.invoice_address.name invoice_company = o.invoice_address.company except InvoiceAddress.DoesNotExist: invoice_name = "" invoice_company = "" email_template = eventsettings.mail_text_order_expire_warning email_context = { 'event': o.event.name, 'url': build_absolute_uri(o.event, 'presale:event.order', kwargs={ 'order': o.code, 'secret': o.secret }), 'expire_date': date_format(o.expires.astimezone(tz), 'SHORT_DATE_FORMAT'), 'invoice_name': invoice_name, 'invoice_company': invoice_company, } email_subject = _('Your order is about to expire: %(code)s') % { 'code': o.code } try: o.send_mail(email_subject, email_template, email_context, 'pretix.event.order.email.expire_warning_sent') except SendMailException: logger.exception('Reminder email could not be sent')
def _notify_user(self): with language(self.order.locale): mail( self.order.email, _('Your order has been changed: %(code)s') % {'code': self.order.code}, self.order.event.settings.mail_text_order_changed, { 'event': self.order.event.name, 'url': build_absolute_uri(self.order.event, 'presale:event.order', kwargs={ 'order': self.order.code, 'secret': self.order.secret }), }, self.order.event, locale=self.order.locale )
def success(request, *args, **kwargs): # @see https://tech.dibspayment.com/D2/Hosted/Output_parameters/Return_pages parameters = request.POST if request.method == 'POST' else request.GET order_id = parameters.get('orderid') order = DIBS.get_order(order_id) urlkwargs = {'order': order.code, 'secret': order.secret} if 'cart_namespace' in kwargs: urlkwargs['cart_namespace'] = kwargs['cart_namespace'] return redirect( build_absolute_uri(request.event, 'presale:event.order', kwargs=urlkwargs))
def redirect_view(request, *args, **kwargs): info = DIBS.get_payment_info(request) template = 'pretix_paymentdibs/redirect.html' ctx = info.copy() ctx.update({ 'callback_url': build_absolute_uri(request.event, 'plugins:pretix_paymentdibs:webhook', kwargs={ 'payment': info['payment_id'], }), 'accept_url': build_absolute_uri(request.event, 'plugins:pretix_paymentdibs:return', kwargs={ 'order': info['order_code'], 'payment': info['payment_id'], 'hash': hashlib.sha1(info['order_secret'].lower().encode()).hexdigest(), 'action': 'success' }), 'cancel_url': build_absolute_uri(request.event, 'plugins:pretix_paymentdibs:return', kwargs={ 'order': info['order_code'], 'payment': info['payment_id'], 'hash': hashlib.sha1(info['order_secret'].lower().encode()).hexdigest(), 'action': 'cancel' }), }) return render(request, template, ctx)
def payment_perform(self, request, order) -> str: self._init_api() if request.session['payment_stripe_token'].startswith('src_'): try: src = stripe.Source.retrieve(request.session['payment_stripe_token']) if src.type == 'card' and src.card and src.card.three_d_secure == 'required': request.session['payment_stripe_order_secret'] = order.secret source = stripe.Source.create( type='three_d_secure', amount=int(order.total * 100), currency=self.event.currency.lower(), three_d_secure={ 'card': src.id }, metadata={ 'order': str(order.id), 'event': self.event.id, 'code': order.code }, redirect={ 'return_url': build_absolute_uri(self.event, 'plugins:stripe:return', kwargs={ 'order': order.code, 'hash': hashlib.sha1(order.secret.lower().encode()).hexdigest(), }) }, ) if source.status == "pending": order.payment_info = str(source) order.save(update_fields=['payment_info']) return source.redirect.url except stripe.error.StripeError as e: if 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)) order.payment_info = json.dumps({ 'error': True, 'message': err['message'], }) order.save(update_fields=['payment_info']) raise PaymentException(_('We had trouble communicating with Stripe. Please try again and get in touch ' 'with us if this problem persists.')) try: self._charge_source(request, request.session['payment_stripe_token'], order) finally: del request.session['payment_stripe_token']
def checkout_prepare(self, request, cart): self.init_api() kwargs = {} if request.resolver_match and 'cart_namespace' in request.resolver_match.kwargs: kwargs['cart_namespace'] = request.resolver_match.kwargs['cart_namespace'] payment = paypalrestsdk.Payment({ 'intent': 'sale', 'payer': { "payment_method": "paypal", }, "redirect_urls": { "return_url": build_absolute_uri(request.event, 'plugins:paypal:return', kwargs=kwargs), "cancel_url": build_absolute_uri(request.event, 'plugins:paypal:abort', kwargs=kwargs), }, "transactions": [ { "item_list": { "items": [ { "name": __('Order for %s') % str(request.event), "quantity": 1, "price": self.format_price(cart['total']), "currency": request.event.currency } ] }, "amount": { "currency": request.event.currency, "total": self.format_price(cart['total']) }, "description": __('Event tickets for {event}').format(event=request.event.name) } ] }) request.session['payment_paypal_order'] = None return self._create_payment(request, payment)
def _perform_order(event: str, payment_provider: str, position_ids: List[str], email: str, locale: str, address: int, meta_info: dict=None): event = Event.objects.get(id=event) responses = register_payment_providers.send(event) pprov = None for rec, response in responses: provider = response(event) if provider.identifier == payment_provider: pprov = provider if not pprov: raise OrderError(error_messages['internal']) with event.lock() as now_dt: positions = list(CartPosition.objects.filter( id__in=position_ids).select_related('item', 'variation')) if len(position_ids) != len(positions): raise OrderError(error_messages['internal']) _check_positions(event, now_dt, positions) order = _create_order(event, email, positions, now_dt, pprov, locale=locale, address=address, meta_info=meta_info) if event.settings.get('invoice_generate') == 'True' and invoice_qualified(order): if not order.invoices.exists(): generate_invoice(order) with language(order.locale): if order.total == Decimal('0.00'): mailtext = event.settings.mail_text_order_free else: mailtext = event.settings.mail_text_order_placed mail( order.email, _('Your order: %(code)s') % {'code': order.code}, mailtext, { 'total': LazyNumber(order.total), 'currency': event.currency, 'date': LazyDate(order.expires), 'event': event.name, 'url': build_absolute_uri(event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret }), 'paymentinfo': str(pprov.order_pending_mail_render(order)) }, event, locale=order.locale ) return order.id
def _perform_order(event: str, payment_provider: str, position_ids: List[str], email: str, locale: str, address: int): event = Event.objects.get(id=event) responses = register_payment_providers.send(event) pprov = None for rec, response in responses: provider = response(event) if provider.identifier == payment_provider: pprov = provider if not pprov: raise OrderError(error_messages['internal']) with event.lock() as now_dt: positions = list(CartPosition.objects.filter( id__in=position_ids).select_related('item', 'variation')) if len(position_ids) != len(positions): raise OrderError(error_messages['internal']) _check_positions(event, now_dt, positions) order = _create_order(event, email, positions, now_dt, pprov, locale=locale, address=address) if event.settings.get('invoice_generate') == 'True' and invoice_qualified(order): if not order.invoices.exists(): generate_invoice(order) with language(order.locale): if order.total == Decimal('0.00'): mailtext = event.settings.mail_text_order_free else: mailtext = event.settings.mail_text_order_placed mail( order.email, _('Your order: %(code)s') % {'code': order.code}, mailtext, { 'total': LazyNumber(order.total), 'currency': event.currency, 'date': LazyDate(order.expires), 'event': event.name, 'url': build_absolute_uri(event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret }), 'paymentinfo': str(pprov.order_pending_mail_render(order)) }, event, locale=order.locale ) return order.id
def form_valid(self, form): tz = pytz.timezone(self.request.event.settings.timezone) order = Order.objects.get( event=self.request.event, code=self.kwargs['code'].upper() ) self.preview_output = {} try: invoice_name = order.invoice_address.name invoice_company = order.invoice_address.company except InvoiceAddress.DoesNotExist: invoice_name = "" invoice_company = "" with language(order.locale): email_context = { 'event': order.event, 'code': order.code, 'date': date_format(order.datetime.astimezone(tz), 'SHORT_DATETIME_FORMAT'), 'expire_date': date_format(order.expires, 'SHORT_DATE_FORMAT'), 'url': build_absolute_uri(order.event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret }), 'invoice_name': invoice_name, 'invoice_company': invoice_company, } email_template = LazyI18nString(form.cleaned_data['message']) email_content = render_mail(email_template, email_context)[0] if self.request.POST.get('action') == 'preview': self.preview_output = [] self.preview_output.append( _('Subject: {subject}').format(subject=form.cleaned_data['subject'])) self.preview_output.append(email_content) return self.get(self.request, *self.args, **self.kwargs) else: try: order.send_mail( form.cleaned_data['subject'], email_template, email_context, 'pretix.event.order.email.custom_sent', self.request.user ) messages.success(self.request, _('Your message has been queued and will be sent to {}.'.format(order.email))) except SendMailException: messages.error( self.request, _('Failed to send mail to the following user: {}'.format(order.email)) ) return super(OrderSendMail, self).form_valid(form)
def mark_order_paid(order: Order, provider: str=None, info: str=None, date: datetime=None, manual: bool=None, force: bool=False): """ Marks an order as paid. This clones the order object, sets the payment provider, info and date and returns the cloned order object. :param provider: The payment provider that marked this as paid :type provider: str :param info: The information to store in order.payment_info :type info: str :param date: The date the payment was received (if you pass ``None``, the current time will be used). :type date: datetime :param force: Whether this payment should be marked as paid even if no remaining quota is available (default: ``False``). :type force: boolean :raises Quota.QuotaExceededException: if the quota is exceeded and ``force`` is ``False`` """ with order.event.lock(): can_be_paid = order._can_be_paid() if not force and can_be_paid is not True: raise Quota.QuotaExceededException(can_be_paid) order = order.clone() order.payment_provider = provider or order.payment_provider order.payment_info = info or order.payment_info order.payment_date = date or now() if manual is not None: order.payment_manual = manual order.status = Order.STATUS_PAID order.save() order_paid.send(order.event, order=order) mail( order.email, _('Payment received for your order: %(code)s') % {'code': order.code}, 'pretixpresale/email/order_paid.txt', { 'order': order, 'event': order.event, 'url': build_absolute_uri(order.event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret }), 'downloads': order.event.settings.get('ticket_download', as_type=bool) }, order.event, locale=order.locale ) return order
def post(self, *args, **kwargs): with language(self.order.locale): mail( self.order.email, _('Your order: %(code)s') % {'code': self.order.code}, self.order.event.settings.mail_text_resend_link, { 'event': self.order.event.name, 'url': build_absolute_uri(self.order.event, 'presale:event.order', kwargs={ 'order': self.order.code, 'secret': self.order.secret }), }, self.order.event, locale=self.order.locale ) messages.success(self.request, _('The email has been queued to be sent.')) self.order.log_action('pretix.event.order.resend', user=self.request.user) return redirect(self.get_order_url())
def post(self, request, *args, **kwargs): if not self.link_form.is_valid(): messages.error(self.request, _('We had difficulties processing your input.')) return self.get(request, *args, **kwargs) user = self.link_form.cleaned_data.get('email') if settings.HAS_REDIS: from django_redis import get_redis_connection rc = get_redis_connection("redis") if rc.exists('pretix_resend_{}'.format(user)): messages.error(request, _('We already sent you an email in the last 24 hours.')) return redirect(eventreverse(self.request.event, 'presale:event.resend_link')) else: rc.setex('pretix_resend_{}'.format(user), 3600 * 24, '1') orders = self.request.event.orders.filter(email__iexact=user) order_context = [] for order in orders: url = build_absolute_uri( self.request.event, 'presale:event.order', kwargs={'order': order.code, 'secret': order.secret} ) order_context.append(' - {} - {}'.format(order, url)) if not orders: user = INVALID_ADDRESS subject = _('Your orders for {}'.format(self.request.event)) template = self.request.event.settings.mail_text_resend_all_links context = { 'orders': '\n'.join(order_context), 'event': self.request.event, } try: mail(user, subject, template, context, event=self.request.event, locale=self.request.LANGUAGE_CODE) except SendMailException: logger = logging.getLogger('pretix.presale.user') logger.exception('A mail resending order links to {} could not be sent.'.format(user)) messages.error(self.request, _('We have trouble sending emails right now, please check back later.')) return self.get(request, *args, **kwargs) messages.success(self.request, _('If there were any orders by this user, they will receive an email with their order codes.')) return redirect(eventreverse(self.request.event, 'presale:event.index'))
def _perform_order(event: str, payment_provider: str, position_ids: list, email: str, locale: str): event = Event.objects.current.get(identity=event) responses = register_payment_providers.send(event) pprov = None for receiver, response in responses: provider = response(event) if provider.identifier == payment_provider: pprov = provider if not pprov: raise OrderError(error_messages['internal']) dt = now() with event.lock(): positions = list( CartPosition.objects.current.filter( identity__in=position_ids).select_related('item', 'variation')) if len(position_ids) != len(positions): raise OrderError(error_messages['internal']) _check_positions(event, dt, positions) order = _create_order(event, email, positions, dt, pprov, locale=locale) mail(order.email, _('Your order: %(code)s') % {'code': order.code}, 'pretixpresale/email/order_placed.txt', { 'order': order, 'event': event, 'url': build_absolute_uri(event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret }), 'payment': pprov.order_pending_mail_render(order) }, event, locale=order.locale) return order.identity
def _get_sample_context(self, base_parameters): placeholders = {'organizer': self.organizer.name} if 'url' in base_parameters: placeholders['url'] = build_absolute_uri( self.organizer, 'presale:organizer.customer.activate' ) + '?token=' + get_random_string(30) if 'customer' in base_parameters: placeholders['name'] = pgettext_lazy('person_name_sample', 'John Doe') name_scheme = PERSON_NAME_SCHEMES[ self.organizer.settings.name_scheme] for f, l, w in name_scheme['fields']: if f == 'full_name': continue placeholders['name_%s' % f] = name_scheme['sample'][f] return placeholders
def _create_source(self, request, order): source = stripe.Source.create( type='alipay', amount=int(order.total * 100), currency=self.event.currency.lower(), metadata={ 'order': str(order.id), 'event': self.event.id, 'code': order.code }, redirect={ 'return_url': build_absolute_uri(self.event, 'plugins:stripe:return', kwargs={ 'order': order.code, 'hash': hashlib.sha1(order.secret.lower().encode()).hexdigest(), }) }, ) return source
def _create_source(self, request, payment): try: source = stripe.Source.create( type='giropay', 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_giropay_account') or ugettext('unknown name') }, giropay={ 'statement_descriptor': '{event}-{code} {eventname}'.format( event=self.event.slug.upper(), code=payment.order.code, eventname=str(self.event.name))[: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 finally: if 'payment_stripe_giropay_account' in request.session: del request.session['payment_stripe_giropay_account']
def post(self, *args, **kwargs): with language(self.order.locale): try: try: invoice_name = self.order.invoice_address.name invoice_company = self.order.invoice_address.company except InvoiceAddress.DoesNotExist: invoice_name = "" invoice_company = "" email_template = self.order.event.settings.mail_text_resend_link email_context = { 'event': self.order.event.name, 'url': build_absolute_uri(self.order.event, 'presale:event.order', kwargs={ 'order': self.order.code, 'secret': self.order.secret }), 'invoice_name': invoice_name, 'invoice_company': invoice_company, } email_subject = _('Your order: %(code)s') % { 'code': self.order.code } self.order.send_mail(email_subject, email_template, email_context, 'pretix.event.order.email.resend', user=self.request.user) except SendMailException: messages.error( self.request, _('There was an error sending the mail. Please try again later.' )) return redirect(self.get_order_url()) messages.success(self.request, _('The email has been queued to be sent.')) return redirect(self.get_order_url())
def form_valid(self, form): if not self.formset.is_valid(): messages.error(self.request, _('Your input was invalid')) return self.get(self.request, *self.args, **self.kwargs) try: self.create_cart(form.instance, form.cleaned_data['expires']) except CartError as e: messages.error(self.request, str(e)) return super().get(self.request, *self.args, **self.kwargs) else: url = build_absolute_uri(self.request.event, 'plugins:pretix_cartshare:redeem', kwargs={'id': form.instance.cart_id}) messages.success( self.request, _('The cart has been saved. You can now share the following URL: ' '{url}').format(url=url)) return super().form_valid(form)
def send_download_reminders(sender, **kwargs): today = now().replace(hour=0, minute=0, second=0, microsecond=0) for e in Event.objects.filter(date_from__gte=today): days = e.settings.get('mail_days_download_reminder', as_type=int) if days is None: continue reminder_date = (e.date_from - timedelta(days=days)).replace( hour=0, minute=0, second=0, microsecond=0) if now() < reminder_date: continue for o in e.orders.filter(status=Order.STATUS_PAID, download_reminder_sent=False): if not all([r for rr, r in allow_ticket_download.send(e, order=o)]): continue o.download_reminder_sent = True o.save() email_template = e.settings.mail_text_download_reminder email_context = { 'event': o.event.name, 'url': build_absolute_uri(o.event, 'presale:event.order', kwargs={ 'order': o.code, 'secret': o.secret }), } email_subject = _( 'Your ticket is ready for download: %(code)s') % { 'code': o.code } try: o.send_mail(email_subject, email_template, email_context, 'pretix.event.order.email.expire_warning_sent') except SendMailException: logger.exception('Reminder email could not be sent')
def form_valid(self, form): if form.cleaned_data['email'] != self.initial_email: new_email = form.cleaned_data['email'] form.cleaned_data[ 'email'] = form.instance.email = self.initial_email ctx = form.instance.get_email_context() ctx['url'] = build_absolute_uri( self.request.organizer, 'presale:organizer.customer.change.confirm' ) + '?token=' + dumps( { 'customer': form.instance.pk, 'email': new_email }, salt='pretix.presale.views.customer.ChangeInformationView') mail( new_email, _('Confirm email address for your account at {organizer}' ).format(organizer=self.request.organizer.name), self.request.organizer.settings. mail_text_customer_email_change, ctx, locale=form.instance.locale, customer=form.instance, organizer=self.request.organizer, ) messages.success( self.request, _('Your changes have been saved. We\'ve sent you an email with a link to update your ' 'email address. The email address of your account will be changed as soon as you ' 'click that link.')) else: messages.success(self.request, _('Your changes have been saved.')) with transaction.atomic(): form.save() d = dict(form.cleaned_data) del d['email'] self.request.customer.log_action('pretix.customer.changed', d) update_customer_session_auth_hash(self.request, form.instance) return HttpResponseRedirect(self.get_success_url())
def _create_source(self, request, payment): source = stripe.Source.create( type='alipay', amount=self._get_amount(payment), currency=self.event.currency.lower(), metadata={ 'order': str(payment.order.id), 'event': self.event.id, 'code': payment.order.code }, 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 _create_payment(self, request, payment): if payment.create(): if payment.state not in ('created', 'approved', 'pending'): messages.error(request, _('We had trouble communicating with PayPal')) logger.error('Invalid payment state: ' + str(payment)) return request.session['payment_paypal_id'] = payment.id for link in payment.links: if link.method == "REDIRECT" and link.rel == "approval_url": if request.session.get('iframe_session', False): signer = signing.Signer(salt='safe-redirect') return ( build_absolute_uri(request.event, 'plugins:paypal:redirect') + '?url=' + urllib.parse.quote(signer.sign(link.href)) ) else: return str(link.href) else: messages.error(request, _('We had trouble communicating with PayPal')) logger.error('Error on creating payment: ' + str(payment.error))
def _create_source(self, request, payment): source = stripe.Source.create( type='alipay', amount=self._get_amount(payment), currency=self.event.currency.lower(), metadata={ 'order': str(payment.order.id), 'event': self.event.id, 'code': payment.order.code }, 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 form_valid(self, form): customer = form.customer customer.log_action('pretix.customer.password.resetrequested', {}) ctx = customer.get_email_context() token = TokenGenerator().make_token(customer) ctx['url'] = build_absolute_uri(self.request.organizer, 'presale:organizer.customer.recoverpw') + '?id=' + customer.identifier + '&token=' + token mail( customer.email, _('Set a new password for your account at {organizer}').format(organizer=self.request.organizer.name), self.request.organizer.settings.mail_text_customer_reset, ctx, locale=customer.locale, customer=customer, organizer=self.request.organizer, ) messages.success( self.request, _('We\'ve sent you an email with further instructions on resetting your password.') ) return HttpResponseRedirect(self.get_success_url())
def send_expiry_warnings(sender, **kwargs): eventcache = {} today = now().replace(hour=0, minute=0, second=0) for o in Order.objects.filter( expires__gte=today, expiry_reminder_sent=False, status=Order.STATUS_PENDING).select_related('event'): settings = eventcache.get(o.event.pk, None) if settings is None: settings = o.event.settings eventcache[o.event.pk] = settings days = settings.get('mail_days_order_expire_warning', as_type=int) if days and (o.expires - today).days <= days: o.expiry_reminder_sent = True o.save() try: mail(o.email, _('Your order is about to expire: %(code)s') % {'code': o.code}, settings.mail_text_order_expire_warning, { 'event': o.event.name, 'url': build_absolute_uri(o.event, 'presale:event.order', kwargs={ 'order': o.code, 'secret': o.secret }), 'expire_date': date_format(o.expires, 'SHORT_DATE_FORMAT') }, o.event, locale=o.locale) except SendMailException: logger.exception('Reminder email could not be sent') else: o.log_action('pretix.event.order.expire_warning_sent')
def _serialize_events(self, ebd): events = [] for e in ebd: ev = e['event'] if isinstance(ev, SubEvent): event = ev.event else: event = ev tz = pytz.timezone(e['timezone']) events.append({ 'name': str(ev.name), 'time': date_format(ev.date_from.astimezone(tz), 'TIME_FORMAT') if e.get('time') and event.settings.show_times else None, 'continued': e['continued'], 'date_range': ev.get_date_range_display() + ( " " + date_format(ev.date_from.astimezone(tz), "TIME_FORMAT") if event.settings.show_times else "" ), 'availability': self._get_availability(ev, event), 'event_url': build_absolute_uri(event, 'presale:event.index'), 'subevent': ev.pk if isinstance(ev, SubEvent) else None, }) return events
def post(self, *args, **kwargs): with language(self.order.locale): mail(self.order.email, _('Your order: %(code)s') % {'code': self.order.code}, self.order.event.settings.mail_text_resend_link, { 'event': self.order.event.name, 'url': build_absolute_uri(self.order.event, 'presale:event.order', kwargs={ 'order': self.order.code, 'secret': self.order.secret }), }, self.order.event, locale=self.order.locale) messages.success(self.request, _('The email has been queued to be sent.')) self.order.log_action('pretix.event.order.resend', user=self.request.user) return redirect(self.get_order_url())
def _create_source(self, request, order): try: source = stripe.Source.create( type='bancontact', amount=int(order.total * 100), currency=self.event.currency.lower(), metadata={ 'order': str(order.id), 'event': self.event.id, 'code': order.code }, owner={ 'name': request.session.get('payment_stripe_bancontact_account') or ugettext('unknown name') }, bancontact={ 'statement_descriptor': ugettext('{event}-{code}').format( event=self.event.slug.upper(), code=order.code)[:35] }, redirect={ 'return_url': build_absolute_uri( self.event, 'plugins:stripe:return', kwargs={ 'order': order.code, 'hash': hashlib.sha1( order.secret.lower().encode()).hexdigest(), }) }, ) return source finally: if 'payment_stripe_bancontact_account' in request.session: del request.session['payment_stripe_bancontact_account']
def _notify_user(self): with language(self.order.locale): try: invoice_name = self.order.invoice_address.name invoice_company = self.order.invoice_address.company except InvoiceAddress.DoesNotExist: invoice_name = "" invoice_company = "" mail( self.order.email, _('Your order has been changed: %(code)s') % {'code': self.order.code}, self.order.event.settings.mail_text_order_changed, { 'event': self.order.event.name, 'url': build_absolute_uri(self.order.event, 'presale:event.order', kwargs={ 'order': self.order.code, 'secret': self.order.secret }), 'invoice_name': invoice_name, 'invoice_company': invoice_company, }, self.order.event, locale=self.order.locale )
def _perform_order(event: str, payment_provider: str, position_ids: list, email: str, locale: str): event = Event.objects.current.get(identity=event) responses = register_payment_providers.send(event) pprov = None for receiver, response in responses: provider = response(event) if provider.identifier == payment_provider: pprov = provider if not pprov: raise OrderError(error_messages['internal']) dt = now() with event.lock(): positions = list(CartPosition.objects.current.filter( identity__in=position_ids).select_related('item', 'variation')) if len(position_ids) != len(positions): raise OrderError(error_messages['internal']) _check_positions(event, dt, positions) order = _create_order(event, email, positions, dt, pprov, locale=locale) mail( order.email, _('Your order: %(code)s') % {'code': order.code}, 'pretixpresale/email/order_placed.txt', { 'order': order, 'event': event, 'url': build_absolute_uri(event, 'presale:event.order', kwargs={ 'order': order.code, 'secret': order.secret }), 'payment': pprov.order_pending_mail_render(order) }, event, locale=order.locale ) return order.identity
def _create_payment(self, request, payment): try: if payment.create(): if payment.state not in ('created', 'approved', 'pending'): messages.error(request, _('We had trouble communicating with PayPal')) logger.error('Invalid payment state: ' + str(payment)) return request.session['payment_paypal_id'] = payment.id for link in payment.links: if link.method == "REDIRECT" and link.rel == "approval_url": if request.session.get('iframe_session', False): signer = signing.Signer(salt='safe-redirect') return ( build_absolute_uri(request.event, 'plugins:paypal:redirect') + '?url=' + urllib.parse.quote(signer.sign(link.href)) ) else: return str(link.href) else: messages.error(request, _('We had trouble communicating with PayPal')) logger.error('Error on creating payment: ' + str(payment.error)) except Exception as e: messages.error(request, _('We had trouble communicating with PayPal')) logger.exception('Error on creating payment: ' + str(e))
def form_valid(self, form): qs = Order.objects.filter(event=self.request.event) statusq = Q(status__in=form.cleaned_data['sendto']) if 'overdue' in form.cleaned_data['sendto']: statusq |= Q(status=Order.STATUS_PENDING, expires__lt=now()) orders = qs.filter(statusq) orders = orders.filter(all_positions__item_id__in=[i.pk for i in form.cleaned_data.get('items')], all_positions__canceled=False) if form.cleaned_data.get('subevent'): orders = orders.filter(all_positions__subevent__in=(form.cleaned_data.get('subevent'),), all_positions__canceled=False) orders = orders.distinct() self.output = {} if not orders: messages.error(self.request, _('There are no orders matching this selection.')) return self.get(self.request, *self.args, **self.kwargs) if self.request.POST.get("action") == "preview": for l in self.request.event.settings.locales: with language(l): context_dict = { 'code': 'ORDER1234', 'event': self.request.event.name, 'date': date_format(now(), 'SHORT_DATE_FORMAT'), 'expire_date': date_format(now() + timedelta(days=7), 'SHORT_DATE_FORMAT'), 'url': build_absolute_uri(self.request.event, 'presale:event.order.open', kwargs={ 'order': 'ORDER1234', 'secret': 'longrandomsecretabcdef123456', 'hash': 'abcdef', }), 'invoice_name': _('John Doe'), 'invoice_company': _('Sample Company LLC') } subject = form.cleaned_data['subject'].localize(l) preview_subject = subject.format_map(context_dict) message = form.cleaned_data['message'].localize(l) preview_text = markdown_compile_email(message.format_map(context_dict)) self.output[l] = { 'subject': _('Subject: {subject}').format(subject=preview_subject), 'html': preview_text, } return self.get(self.request, *self.args, **self.kwargs) send_mails.apply_async( kwargs={ 'recipients': form.cleaned_data['recipients'], 'event': self.request.event.pk, 'user': self.request.user.pk, 'subject': form.cleaned_data['subject'].data, 'message': form.cleaned_data['message'].data, 'orders': [o.pk for o in orders], 'items': [i.pk for i in form.cleaned_data.get('items')] } ) self.request.event.log_action('pretix.plugins.sendmail.sent', user=self.request.user, data=dict(form.cleaned_data)) messages.success(self.request, _('Your message has been queued and will be sent to the contact addresses of %d ' 'orders in the next minutes.') % len(orders)) return redirect( 'plugins:sendmail:send', event=self.request.event.slug, organizer=self.request.event.organizer.slug )
def settings_content_render(self, request): return "<div class='alert alert-info'>%s<br /><code>%s</code></div>" % ( _('Please configure a <a href="https://dashboard.stripe.com/account/webhooks">Stripe Webhook</a> to ' 'the following endpoint in order to automatically cancel orders when charges are refunded externally.'), build_absolute_uri(self.event, 'plugins:stripe:webhook') )
def get_picture(event, picture): return urljoin(build_absolute_uri(event, 'presale:event.index'), get_thumbnail(picture.name, '60x60^').thumb.url)
def _get_event_list(self, request, **kwargs): data = {} o = getattr(request, 'event', request.organizer) list_type = self.request.GET.get("style", o.settings.event_list_type) data['list_type'] = list_type cache_key = ':'.join([ 'widget.py', 'eventlist', request.organizer.slug, request.event.slug if hasattr(request, 'event') else '-', list_type, request.GET.get("year") or "-", request.GET.get("month") or "-", request.GET.get("old") or "-", get_language(), ]) cached_data = cache.get(cache_key) if cached_data: return self.response(cached_data) if list_type == "calendar": self._set_month_year() _, ndays = calendar.monthrange(self.year, self.month) data['date'] = date(self.year, self.month, 1) if hasattr(self.request, 'event'): tz = pytz.timezone(self.request.event.settings.timezone) else: tz = pytz.UTC before = datetime(self.year, self.month, 1, 0, 0, 0, tzinfo=tz) - timedelta(days=1) after = datetime(self.year, self.month, ndays, 0, 0, 0, tzinfo=tz) + timedelta(days=1) ebd = defaultdict(list) if hasattr(self.request, 'event'): add_subevents_for_days( self.request.event.subevents_annotated('web'), before, after, ebd, set(), self.request.event, kwargs.get('cart_namespace') ) else: timezones = set() add_events_for_days(self.request, Event.annotated(self.request.organizer.events, 'web'), before, after, ebd, timezones) add_subevents_for_days(filter_qs_by_attr(SubEvent.annotated(SubEvent.objects.filter( event__organizer=self.request.organizer, event__is_public=True, event__live=True, ).prefetch_related( 'event___settings_objects', 'event__organizer___settings_objects' )), self.request), before, after, ebd, timezones) data['weeks'] = weeks_for_template(ebd, self.year, self.month) for w in data['weeks']: for d in w: if not d: continue d['events'] = self._serialize_events(d['events'] or []) else: if hasattr(self.request, 'event'): evs = self.request.event.subevents_sorted( self.request.event.subevents_annotated(self.request.sales_channel) ) tz = pytz.timezone(request.event.settings.timezone) data['events'] = [ { 'name': str(ev.name), 'date_range': ev.get_date_range_display(tz) + ( (" " + ev.get_time_from_display(tz)) if ev.event.settings.show_times else "" ), 'availability': self._get_availability(ev, ev.event), 'event_url': build_absolute_uri(ev.event, 'presale:event.index'), 'subevent': ev.pk, } for ev in evs ] else: data['events'] = [] qs = self._get_event_queryset() for event in qs: tz = pytz.timezone(event.cache.get_or_set('timezone', lambda: event.settings.timezone)) if event.has_subevents: dr = daterange( event.min_from.astimezone(tz), (event.max_fromto or event.max_to or event.max_from).astimezone(tz) ) avail = {'color': 'none', 'text': ugettext('Event series')} else: dr = event.get_date_range_display(tz) + ( " " + event.get_time_from_display(tz) if event.settings.show_times else "" ) avail = self._get_availability(event, event) data['events'].append({ 'name': str(event.name), 'date_range': dr, 'availability': avail, 'event_url': build_absolute_uri(event, 'presale:event.index'), }) cache.set(cache_key, data, 30) # These pages are cached for a really short duration – this should make them pretty accurate, while still # providing some protection against burst traffic. return self.response(data)