Пример #1
0
 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)
Пример #2
0
    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)
Пример #3
0
    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)
Пример #4
0
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
Пример #5
0
 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']
Пример #6
0
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')
Пример #7
0
    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
Пример #8
0
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')
Пример #9
0
 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
Пример #10
0
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)
Пример #11
0
    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
Пример #12
0
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
Пример #13
0
 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)
Пример #14
0
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
Пример #15
0
    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
            )
Пример #16
0
 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)
Пример #17
0
    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)
Пример #18
0
 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
Пример #19
0
 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)
Пример #20
0
 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']
Пример #21
0
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
Пример #22
0
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
Пример #23
0
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)
Пример #24
0
 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
         )
Пример #25
0
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')
Пример #26
0
 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
         )
Пример #27
0
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))
Пример #28
0
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)
Пример #29
0
    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']
Пример #30
0
    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)
Пример #31
0
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
Пример #32
0
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
Пример #33
0
 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)
Пример #34
0
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
Пример #35
0
 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())
Пример #36
0
    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'))
Пример #37
0
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
Пример #38
0
    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
Пример #39
0
 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
Пример #40
0
 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']
Пример #41
0
    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())
Пример #42
0
    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)
Пример #43
0
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')
Пример #44
0
    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())
Пример #45
0
 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
Пример #46
0
 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))
Пример #47
0
 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
Пример #48
0
 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())
Пример #49
0
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')
Пример #50
0
 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
Пример #51
0
 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())
Пример #52
0
 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']
Пример #53
0
 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
         )
Пример #54
0
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
Пример #55
0
 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))
Пример #56
0
    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
        )
Пример #57
0
 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')
     )
Пример #58
0
def get_picture(event, picture):
    return urljoin(build_absolute_uri(event, 'presale:event.index'), get_thumbnail(picture.name, '60x60^').thumb.url)
Пример #59
0
    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)