def post(self, *args, **kwargs): to = self.request.POST.get('status', '') if self.order.status == 'n' and to == 'p': try: mark_order_paid(self.order, manual=True) except Quota.QuotaExceededException as e: messages.error(self.request, str(e)) else: messages.success(self.request, _('The order has been marked as paid.')) elif self.order.status == 'n' and to == 'c': order = self.order.clone() order.status = Order.STATUS_CANCELLED order.save() messages.success(self.request, _('The order has been cancelled.')) elif self.order.status == 'p' and to == 'n': order = self.order.clone() order.status = Order.STATUS_PENDING order.payment_manual = True order.save() messages.success(self.request, _('The order has been marked as not paid.')) elif self.order.status == 'p' and to == 'r': ret = self.payment_provider.order_control_refund_perform(self.request, self.order) if ret: return redirect(ret) return redirect(self.get_order_url())
def _execute_payment(self, payment, request, order): payment.execute({"payer_id": request.session.get("payment_paypal_payer")}) if payment.state == "pending": messages.warning( request, _("PayPal has not yet approved the payment. We will inform you as soon as the " "payment completed."), ) order = order.clone() order.payment_info = json.dumps(payment.to_dict()) order.save() return if payment.state != "approved": messages.error( request, _("We were unable to process your payment. See below for details on how to " "proceed.") ) logger.error("Invalid state: %s" % str(payment)) return try: mark_order_paid(order, "paypal", json.dumps(payment.to_dict())) except Quota.QuotaExceededException as e: messages.error(request, str(e)) return None
def test_paid_expired_available(self): self.order.status = Order.STATUS_EXPIRED self.order.expires = now() - timedelta(days=2) self.order.save() mark_order_paid(self.order) self.order = Order.objects.get(id=self.order.id) self.assertEqual(self.order.status, Order.STATUS_PAID)
def post(self, *args, **kwargs): to = self.request.POST.get('status', '') if self.order.status in (Order.STATUS_PENDING, Order.STATUS_EXPIRED) and to == 'p': try: mark_order_paid(self.order, manual=True, user=self.request.user) except Quota.QuotaExceededException as e: messages.error(self.request, str(e)) else: messages.success(self.request, _('The order has been marked as paid.')) elif self.order.status == Order.STATUS_PENDING and to == 'c': cancel_order(self.order, user=self.request.user) messages.success(self.request, _('The order has been cancelled.')) elif self.order.status == Order.STATUS_PAID and to == 'n': self.order.status = Order.STATUS_PENDING self.order.payment_manual = True self.order.save() self.order.log_action('pretix.event.order.unpaid', user=self.request.user) messages.success(self.request, _('The order has been marked as not paid.')) elif self.order.status == Order.STATUS_PENDING and to == 'e': self.order.status = Order.STATUS_EXPIRED self.order.save() self.order.log_action('pretix.event.order.expired', user=self.request.user) messages.success(self.request, _('The order has been marked as expired.')) elif self.order.status == Order.STATUS_PAID and to == 'r': ret = self.payment_provider.order_control_refund_perform(self.request, self.order) if ret: return redirect(ret) return redirect(self.get_order_url())
def test_paid_expired_unavailable_force(self): self.order.expires = now() - timedelta(days=2) self.order.save() self.quota.size = 0 self.quota.save() mark_order_paid(self.order, force=True) self.order = Order.objects.get(id=self.order.id) self.assertEqual(self.order.status, Order.STATUS_PAID)
def payment_perform(self, request, order) -> str: self._init_api() try: charge = stripe.Charge.create( amount=int(order.total * 100), currency=self.event.currency.lower(), source=request.session['payment_stripe_token'], metadata={ 'order': str(order.id), 'event': self.event.id, 'code': order.code }, # TODO: Is this sufficient? idempotency_key=str(self.event.id) + order.code + request.session['payment_stripe_token'] ) except stripe.error.CardError 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)) messages.error(request, _('Stripe reported an error with your card: %s' % err['message'])) logger.info('Stripe card error: %s' % str(err)) order.payment_info = json.dumps({ 'error': True, 'message': err['message'], }) order.save() 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)) messages.error(request, _('We had trouble communicating with Stripe. Please try again and get in touch ' 'with us if this problem persists.')) order.payment_info = json.dumps({ 'error': True, 'message': err['message'], }) order.save() else: if charge.status == 'succeeded' and charge.paid: try: mark_order_paid(order, 'stripe', str(charge)) except Quota.QuotaExceededException as e: messages.error(request, str(e)) except SendMailException: messages.warning(request, _('There was an error sending the confirmation mail.')) else: messages.warning(request, _('Stripe reported an error: %s' % charge.failure_message)) logger.info('Charge failed: %s' % str(charge)) order.payment_info = str(charge) order.save() del request.session['payment_stripe_token']
def test_paid_expired_available(self): self.event.settings.payment_term_last = ( now() + timedelta(days=2)).strftime('%Y-%m-%d') self.order.status = Order.STATUS_EXPIRED self.order.expires = now() - timedelta(days=2) self.order.save() mark_order_paid(self.order) self.order = Order.objects.get(id=self.order.id) self.assertEqual(self.order.status, Order.STATUS_PAID)
def webhook(request, *args, **kwargs): event_body = request.body.decode('utf-8').strip() event_json = json.loads(event_body) prov = Paypal(request.event) prov.init_api() # We do not check the signature, we just use it as a trigger to look the charge up. if event_json['resource_type'] not in ('sale', 'refund'): return HttpResponse("Not interested in this resource type", status=200) try: if event_json['resource_type'] == 'sale': sale = paypalrestsdk.Sale.find(event_json['resource']['id']) else: sale = paypalrestsdk.Sale.find(event_json['resource']['sale_id']) except: logger.exception('PayPal error on webhook. Event data: %s' % str(event_json)) return HttpResponse('Sale not found', status=500) orders = Order.objects.filter(event=request.event, payment_provider='paypal', payment_info__icontains=sale['id']) order = None for o in orders: payment_info = json.loads(o.payment_info) for res in payment_info['transactions'][0]['related_resources']: for k, v in res.items(): if k == 'sale' and v['id'] == sale['id']: order = o break if not order: return HttpResponse('Order not found', status=200) order.log_action('pretix.plugins.paypal.event', data=event_json) if order.status == Order.STATUS_PAID and sale['state'] in ('partially_refunded', 'refunded'): RequiredAction.objects.create( event=request.event, action_type='pretix.plugins.paypal.refund', data=json.dumps({ 'order': order.code, 'sale': sale['id'] }) ) elif order.status in (Order.STATUS_PENDING, Order.STATUS_EXPIRED) and sale['state'] == 'completed': try: mark_order_paid(order, user=None) except Quota.QuotaExceededException: if not RequiredAction.objects.filter(event=request.event, action_type='pretix.plugins.paypal.overpaid', data__icontains=order.code).exists(): RequiredAction.objects.create( event=request.event, action_type='pretix.plugins.paypal.overpaid', data=json.dumps({ 'order': order.code, 'payment': sale['parent_payment'] }) ) return HttpResponse(status=200)
def test_paid_expired_late_not_allowed(self): self.event.settings.payment_term_accept_late = False self.order.status = Order.STATUS_EXPIRED self.order.expires = now() - timedelta(days=2) self.order.save() with self.assertRaises(Quota.QuotaExceededException): mark_order_paid(self.order) self.order = Order.objects.get(id=self.order.id) self.assertEqual(self.order.status, Order.STATUS_EXPIRED)
def charge_webhook(event, event_json, charge_id): prov = StripeCC(event) prov._init_api() try: charge = stripe.Charge.retrieve(charge_id) except stripe.error.StripeError: logger.exception('Stripe error on webhook. Event data: %s' % str(event_json)) return HttpResponse('Charge not found', status=500) metadata = charge['metadata'] if 'event' not in metadata: return HttpResponse('Event not given in charge metadata', status=200) if int(metadata['event']) != event.pk: return HttpResponse('Not interested in this event', status=200) try: order = event.orders.get(id=metadata['order'], payment_provider__startswith='stripe') except Order.DoesNotExist: return HttpResponse('Order not found', status=200) if order.payment_provider != prov.identifier: prov = event.get_payment_providers()[order.payment_provider] prov._init_api() order.log_action('pretix.plugins.stripe.event', data=event_json) is_refund = charge['refunds']['total_count'] or charge['dispute'] if order.status == Order.STATUS_PAID and is_refund: RequiredAction.objects.create( event=event, action_type='pretix.plugins.stripe.refund', data=json.dumps({ 'order': order.code, 'charge': charge_id })) elif order.status in ( Order.STATUS_PENDING, Order.STATUS_EXPIRED ) and charge['status'] == 'succeeded' and not is_refund: try: mark_order_paid(order, user=None) except Quota.QuotaExceededException: if not RequiredAction.objects.filter( event=event, action_type='pretix.plugins.stripe.overpaid', data__icontains=order.code).exists(): RequiredAction.objects.create( event=event, action_type='pretix.plugins.stripe.overpaid', data=json.dumps({ 'order': order.code, 'charge': charge.id })) return HttpResponse(status=200)
def test_paid_expired_after_last_date(self): self.event.settings.payment_term_last = (now() - timedelta(days=2)).strftime('%Y-%m-%d') self.order.status = Order.STATUS_EXPIRED self.order.expires = now() - timedelta(days=2) self.order.save() with self.assertRaises(Quota.QuotaExceededException): mark_order_paid(self.order) self.order = Order.objects.get(id=self.order.id) self.assertEqual(self.order.status, Order.STATUS_EXPIRED)
def payment_perform(self, request, order) -> str: self._init_api() try: charge = stripe.Charge.create( amount=int(order.total * 100), currency=request.event.currency.lower(), source=request.session['payment_stripe_token'], metadata={ 'order': str(order.id), 'event': self.event.id, 'code': order.code }, # TODO: Is this sufficient? idempotency_key=str(self.event.id) + order.code + request.session['payment_stripe_token']) except stripe.error.CardError as e: err = e.json_body['error'] messages.error( request, _('Stripe reported an error with your card: %s' % err['message'])) logger.info('Stripe card error: %s' % str(err)) order.payment_info = json.dumps({ 'error': True, 'message': err['message'], }) order.save() except (stripe.error.InvalidRequestError, stripe.error.AuthenticationError, stripe.error.APIConnectionError, stripe.error.StripeError) as e: err = e.json_body['error'] messages.error( request, _('We had trouble communicating with Stripe. Please try again and get in touch ' 'with us if this problem persists.')) logger.error('Stripe error: %s' % str(err)) order.payment_info = json.dumps({ 'error': True, 'message': err['message'], }) order.save() else: if charge.status == 'succeeded' and charge.paid: try: mark_order_paid(order, 'stripe', str(charge)) except Quota.QuotaExceededException as e: messages.error(request, str(e)) else: messages.warning( request, _('Stripe reported an error: %s' % charge.failure_message)) logger.info('Charge failed: %s' % str(charge)) order.payment_info = str(charge) order.save() del request.session['payment_stripe_token']
def test_paid_expired_unavailable(self): self.order.expires = now() - timedelta(days=2) self.order.status = Order.STATUS_EXPIRED self.order.save() self.quota.size = 0 self.quota.save() with self.assertRaises(Quota.QuotaExceededException): mark_order_paid(self.order) self.order = Order.objects.get(id=self.order.id) self.assertIn(self.order.status, (Order.STATUS_PENDING, Order.STATUS_EXPIRED))
def test_paid_expired_unavailable_waiting_list_ignore(self): self.event.waitinglistentries.create(item=self.item1, email='*****@*****.**') self.order.expires = now() - timedelta(days=2) self.order.status = Order.STATUS_EXPIRED self.order.save() self.quota.size = 2 self.quota.save() mark_order_paid(self.order, count_waitinglist=False) self.order = Order.objects.get(id=self.order.id) self.assertEqual(self.order.status, Order.STATUS_PAID)
def test_paid_expired_unavailable_force(self): self.event.settings.payment_term_accept_late = True self.order.expires = now() - timedelta(days=2) self.order.status = Order.STATUS_EXPIRED self.order.save() self.quota.size = 0 self.quota.save() mark_order_paid(self.order, force=True) self.order = Order.objects.get(id=self.order.id) self.assertEqual(self.order.status, Order.STATUS_PAID)
def post(self, *args, **kwargs): to = self.request.POST.get('status', '') if self.order.status in (Order.STATUS_PENDING, Order.STATUS_EXPIRED) and to == 'p': if not self.mark_paid_form.is_valid(): return render(self.request, 'pretixcontrol/order/pay.html', { 'form': self.mark_paid_form, 'order': self.order, }) try: mark_order_paid(self.order, manual=True, user=self.request.user, count_waitinglist=False, force=self.mark_paid_form.cleaned_data.get( 'force', False)) except Quota.QuotaExceededException as e: messages.error(self.request, str(e)) except SendMailException: messages.warning( self.request, _('The order has been marked as paid, but we were unable to send a confirmation mail.' )) else: messages.success(self.request, _('The order has been marked as paid.')) elif self.order.cancel_allowed() and to == 'c': cancel_order(self.order, user=self.request.user, send_mail=self.request.POST.get("send_email") == "on") messages.success(self.request, _('The order has been canceled.')) elif self.order.status == Order.STATUS_PAID and to == 'n': self.order.status = Order.STATUS_PENDING self.order.payment_manual = True self.order.save() self.order.log_action('pretix.event.order.unpaid', user=self.request.user) messages.success(self.request, _('The order has been marked as not paid.')) elif self.order.status == Order.STATUS_PENDING and to == 'e': mark_order_expired(self.order, user=self.request.user) messages.success(self.request, _('The order has been marked as expired.')) elif self.order.status == Order.STATUS_PAID and to == 'r': if not self.payment_provider: messages.error( self.request, _('This order is not assigned to a known payment provider.' )) else: ret = self.payment_provider.order_control_refund_perform( self.request, self.order) if ret: return redirect(ret) return redirect(self.get_order_url())
def _execute_payment(self, payment, request, order): payment.replace([{ "op": "replace", "path": "/transactions/0/item_list", "value": { "items": [{ "name": __('Order {slug}-{code}').format( slug=self.event.slug.upper(), code=order.code), "quantity": 1, "price": str(order.total), "currency": order.event.currency }] } }, { "op": "replace", "path": "/transactions/0/description", "value": __('Order {order} for {event}').format(event=request.event.name, order=order.code) }]) payment.execute( {"payer_id": request.session.get('payment_paypal_payer')}) if payment.state == 'pending': messages.warning( request, _('PayPal has not yet approved the payment. We will inform you as soon as the ' 'payment completed.')) order.payment_info = json.dumps(payment.to_dict()) order.save() return if payment.state != 'approved': messages.error( request, _('We were unable to process your payment. See below for details on how to ' 'proceed.')) logger.error('Invalid state: %s' % str(payment)) return try: mark_order_paid(order, 'paypal', json.dumps(payment.to_dict())) except Quota.QuotaExceededException as e: messages.error(request, str(e)) except SendMailException: messages.warning( request, _('There was an error sending the confirmation mail.')) return None
def post(self, *args, **kwargs): if 'hbci_server' in self.request.POST: return self.process_hbci() if ('file' in self.request.FILES and 'csv' in self.request.FILES.get('file').name.lower()) \ or 'amount' in self.request.POST: # Process CSV return self.process_csv() if 'file' in self.request.FILES and 'txt' in self.request.FILES.get( 'file').name.lower(): return self.process_mt940() if 'confirm' in self.request.POST: orders = Order.objects.current.filter( event=self.request.event, code__in=self.request.POST.getlist('mark_paid')) some_failed = False for order in orders: try: mark_order_paid( order, provider='banktransfer', info=json.dumps({ 'reference': self.request.POST.get('reference_%s' % order.code), 'date': self.request.POST.get('date_%s' % order.code), 'payer': self.request.POST.get('payer_%s' % order.code), 'import': now().isoformat(), })) except Quota.QuotaExceededException: some_failed = True if some_failed: messages.warning( self.request, _('Not all of the selected orders could be marked as ' 'paid as some of them have expired and the selected ' 'items are sold out.')) else: messages.success( self.request, _('The selected orders have been marked as paid.')) # TODO: Display a list of them! return self.redirect_back() messages.error( self.request, _('We were unable to detect the file type of this import. Please ' 'contact support for help.')) return self.redirect_back()
def test_paid_expired_partial(self): self.order.expires = now() - timedelta(days=2) self.order.save() self.quota.size = 1 self.quota.save() try: mark_order_paid(self.order) self.assertFalse(True, "This should have raised an exception.") except Quota.QuotaExceededException: pass self.order = Order.objects.get(id=self.order.id) self.assertIn(self.order.status, (Order.STATUS_PENDING, Order.STATUS_EXPIRED))
def callback(request, *args, **kwargs): data = json.loads(request.body) logger.info("onepay cllback data {0}".format(request.body.decode('utf-8'))) onepay=ReferencedOnepayObject.objects.get(reference=data["orderId"]) if(data["status"]==1): mark_order_paid(onepay.order, 'onepay', data["transaction"]) else: onepay.order.status = Order.STATUS_CANCELED onepay.order.save() onepay.transaction=data['transaction'] onepay.save() return HttpResponse()
def test_paid_expired_unavailable(self): self.order.expires = now() - timedelta(days=2) self.order.save() self.quota.size = 0 self.quota.save() try: mark_order_paid(self.order) self.assertFalse(True, 'This should have raised an exception.') except Quota.QuotaExceededException: pass self.order = Order.objects.current.get(identity=self.order.identity) self.assertIn(self.order.status, (Order.STATUS_PENDING, Order.STATUS_EXPIRED))
def test_paid_expired_unavailable_waiting_list(self): self.event.settings.payment_term_accept_late = True self.event.waitinglistentries.create(item=self.item1, email='*****@*****.**') self.order.expires = now() - timedelta(days=2) self.order.status = Order.STATUS_EXPIRED self.order.save() self.quota.size = 2 self.quota.save() with self.assertRaises(Quota.QuotaExceededException): mark_order_paid(self.order) self.order = Order.objects.get(id=self.order.id) self.assertEqual(self.order.status, Order.STATUS_EXPIRED)
def payment_perform(self, request, order) -> str: info = {'payment_date': datetime.now().strftime('%Y%m%dT%H%M%S')} try: mark_order_paid(order, Cash.identifier, send_mail=False, info=json.dumps(info), user=request.user) except Exception as e: raise PaymentException(_('Cash payment error: {}').format(e)) return None
def test_paid_expired_unavailable(self): self.order.expires = now() - timedelta(days=2) self.order.save() self.quota.size = 0 self.quota.save() try: mark_order_paid(self.order) self.assertFalse(True, 'This should have raised an exception.') except Quota.QuotaExceededException: pass self.order = Order.objects.get(id=self.order.id) self.assertIn(self.order.status, (Order.STATUS_PENDING, Order.STATUS_EXPIRED))
def payment_perform(self, request, order) -> str: self._init_api() try: charge = stripe.Charge.create( amount=int(order.total * 100), currency=request.event.currency.lower(), source=request.session['payment_stripe_token'], metadata={ 'order': order.identity, 'event': self.event.identity, 'code': order.code }, # TODO: Is this sufficient? idempotency_key=self.event.identity + order.code + request.session['payment_stripe_token'] ) except stripe.error.CardError as e: err = e.json_body['error'] messages.error(request, _('Stripe reported an error with your card: %s' % err['message'])) logger.info('Stripe card error: %s' % str(err)) order = order.clone() order.payment_info = json.dumps({ 'error': True, 'message': err['message'], }) order.save() except stripe.error.InvalidRequestError or stripe.error.AuthenticationError or stripe.error.APIConnectionError \ or stripe.error.StripeError as e: err = e.json_body['error'] messages.error(request, _('We had trouble communicating with Stripe. Please try again and get in touch ' 'with us if this problem persists.')) logger.error('Stripe error: %s' % str(err)) order = order.clone() order.payment_info = json.dumps({ 'error': True, 'message': err['message'], }) order.save() else: if charge.status == 'succeeded' and charge.paid: try: mark_order_paid(order, 'stripe', str(charge)) messages.success(request, _('We successfully received your payment. Thank you!')) except Quota.QuotaExceededException as e: messages.error(request, str(e)) else: messages.warning(request, _('Stripe reported an error: %s' % charge.failure_message)) logger.info('Charge failed: %s' % str(charge)) order = order.clone() order.payment_info = str(charge) order.save() del request.session['payment_stripe_token']
def test_expiring_paid_invoice(event): o2 = Order.objects.create( code='FO2', event=event, email='*****@*****.**', status=Order.STATUS_PENDING, locale='en', datetime=now(), expires=now() - timedelta(days=10), total=12, payment_provider='banktransfer' ) generate_invoice(o2) expire_orders(None) o2 = Order.objects.get(id=o2.id) assert o2.status == Order.STATUS_EXPIRED assert o2.invoices.count() == 2 mark_order_paid(o2) assert o2.invoices.count() == 3 assert o2.invoices.last().is_cancellation is False
def _accept_ignore_amount(self, trans): if trans.order.status == Order.STATUS_PAID: return JsonResponse({ 'status': 'error', 'message': _('The order is already marked as paid.') }) elif trans.order.status == Order.STATUS_REFUNDED: return JsonResponse({ 'status': 'error', 'message': _('The order has already been refunded.') }) elif trans.order.status == Order.STATUS_CANCELED: return JsonResponse({ 'status': 'error', 'message': _('The order has already been canceled.') }) try: mark_order_paid(trans.order, provider='banktransfer', info=json.dumps({ 'reference': trans.reference, 'date': trans.date, 'payer': trans.payer, 'trans_id': trans.pk }), count_waitinglist=False) trans.state = BankTransaction.STATE_VALID trans.save() except Quota.QuotaExceededException as e: return JsonResponse({'status': 'error', 'message': str(e)}) except SendMailException: return JsonResponse({ 'status': 'error', 'message': _('Problem sending email.') }) else: trans.state = BankTransaction.STATE_VALID trans.save() return JsonResponse({'status': 'ok'})
def callback(request, *args, **kwargs): if request.GET.get('key'): key = request.GET.get('key') logger.info("woopay callback data {0}" + key) woopay = ReferencedWoopayObject.objects.filter(key=key).first() if woopay: if (woopay.order.status != Order.STATUS_PAID): mark_order_paid(woopay.order, 'woopay', key) return HttpResponse('{"data":1}') else: response = HttpResponse() response.status_code = 404 return response else: response = HttpResponse() response.status_code = 404 return response
def post(self, *args, **kwargs): to = self.request.POST.get('status', '') if self.order.status in (Order.STATUS_PENDING, Order.STATUS_EXPIRED) and to == 'p': try: mark_order_paid(self.order, manual=True, user=self.request.user, count_waitinglist=False) except Quota.QuotaExceededException as e: messages.error(self.request, str(e)) except SendMailException: messages.warning( self.request, _('The order has been marked as paid, but we were unable to send a confirmation mail.' )) else: messages.success(self.request, _('The order has been marked as paid.')) elif self.order.status == Order.STATUS_PENDING and to == 'c': cancel_order(self.order, user=self.request.user, send_mail=self.request.POST.get("send_email") == "on") messages.success(self.request, _('The order has been canceled.')) elif self.order.status == Order.STATUS_PAID and to == 'n': self.order.status = Order.STATUS_PENDING self.order.payment_manual = True self.order.save() self.order.log_action('pretix.event.order.unpaid', user=self.request.user) messages.success(self.request, _('The order has been marked as not paid.')) elif self.order.status == Order.STATUS_PENDING and to == 'e': self.order.status = Order.STATUS_EXPIRED self.order.save() self.order.log_action('pretix.event.order.expired', user=self.request.user) messages.success(self.request, _('The order has been marked as expired.')) elif self.order.status == Order.STATUS_PAID and to == 'r': ret = self.payment_provider.order_control_refund_perform( self.request, self.order) if ret: return redirect(ret) return redirect(self.get_order_url())
def webhook(request, *args, **kwargs): event_json = json.loads(request.body.decode('utf-8')) # We do not check for the event type as we are not interested in the event it self, # we just use it as a trigger to look the charge up to be absolutely sure. # Another reason for this is that stripe events are not authenticated, so they could # come from anywhere. if event_json['data']['object']['object'] == "charge": charge_id = event_json['data']['object']['id'] elif event_json['data']['object']['object'] == "dispute": charge_id = event_json['data']['object']['charge'] else: return HttpResponse("Not interested in this data type", status=200) prov = Stripe(request.event) prov._init_api() try: charge = stripe.Charge.retrieve(charge_id) except stripe.error.StripeError: logger.exception('Stripe error on webhook. Event data: %s' % str(event_json)) return HttpResponse('Charge not found', status=500) metadata = charge['metadata'] if 'event' not in metadata: return HttpResponse('Event not given in charge metadata', status=200) if int(metadata['event']) != request.event.pk: return HttpResponse('Not interested in this event', status=200) try: order = request.event.orders.get(id=metadata['order']) except Order.DoesNotExist: return HttpResponse('Order not found', status=200) order.log_action('pretix.plugins.stripe.event', data=event_json) is_refund = charge['refunds']['total_count'] or charge['dispute'] if order.status == Order.STATUS_PAID and is_refund: mark_order_refunded(order, user=None) elif order.status == Order.STATUS_PENDING and charge['status'] == 'succeeded' and not is_refund: mark_order_paid(order, user=None) return HttpResponse(status=200)
def process_result(request, order, prov): order.payment_info = json.dumps(dict(request.POST.items())) order.save() if order.status in (Order.STATUS_PENDING, Order.STATUS_EXPIRED ) and request.POST.get('paymentState') == 'SUCCESS': try: mark_order_paid(order, user=None, provider=prov.identifier) except Quota.QuotaExceededException: if not RequiredAction.objects.filter( event=request.event, action_type='pretix_wirecard.wirecard.overpaid', data__icontains=order.code).exists(): RequiredAction.objects.create( event=request.event, action_type='pretix_wirecard.wirecard.overpaid', data=json.dumps({ 'order': order.code, 'charge': request.POST.get('orderNumber') }))
def _accept_ignore_amount(self, trans): if trans.order.status == Order.STATUS_PAID: return JsonResponse({ 'status': 'error', 'message': _('The order is already marked as paid.') }) elif trans.order.status == Order.STATUS_REFUNDED: return JsonResponse({ 'status': 'error', 'message': _('The order has already been refunded.') }) elif trans.order.status == Order.STATUS_CANCELED: return JsonResponse({ 'status': 'error', 'message': _('The order has already been canceled.') }) try: mark_order_paid(trans.order, provider='banktransfer', info=json.dumps({ 'reference': trans.reference, 'date': trans.date, 'payer': trans.payer, 'trans_id': trans.pk })) trans.state = BankTransaction.STATE_VALID trans.save() except Quota.QuotaExceededException as e: return JsonResponse({ 'status': 'error', 'message': str(e) }) except SendMailException: return JsonResponse({ 'status': 'error', 'message': _('Problem sending email.') }) else: trans.state = BankTransaction.STATE_VALID trans.save() return JsonResponse({ 'status': 'ok' })
def _handle_transaction(event: Event, trans: BankTransaction, code: str): try: trans.order = event.orders.get(code=code) except Order.DoesNotExist: normalized_code = Order.normalize_code(code) try: trans.order = event.orders.get(code=normalized_code) except Order.DoesNotExist: trans.state = BankTransaction.STATE_NOMATCH trans.save() return if trans.order.status == Order.STATUS_PAID: trans.state = BankTransaction.STATE_DUPLICATE elif trans.order.status == Order.STATUS_REFUNDED: trans.state = BankTransaction.STATE_ERROR trans.message = ugettext_noop('The order has already been refunded.') elif trans.order.status == Order.STATUS_CANCELED: trans.state = BankTransaction.STATE_ERROR trans.message = ugettext_noop('The order has already been canceled.') elif trans.amount != trans.order.total: trans.state = BankTransaction.STATE_INVALID trans.message = ugettext_noop('The transaction amount is incorrect.') else: try: mark_order_paid(trans.order, provider='banktransfer', info=json.dumps({ 'reference': trans.reference, 'date': trans.date, 'payer': trans.payer, 'trans_id': trans.pk })) except Quota.QuotaExceededException as e: trans.state = BankTransaction.STATE_ERROR trans.message = str(e) except SendMailException: trans.state = BankTransaction.STATE_ERROR trans.message = ugettext_noop('Problem sending email.') else: trans.state = BankTransaction.STATE_VALID trans.save()
def mark_paid(self, request, **kwargs): order = self.get_object() if order.status in (Order.STATUS_PENDING, Order.STATUS_EXPIRED): try: mark_order_paid( order, manual=True, user=request.user if request.user.is_authenticated else None, api_token=(request.auth if isinstance(request.auth, TeamAPIToken) else None), ) except Quota.QuotaExceededException as e: return Response({'detail': str(e)}, status=status.HTTP_400_BAD_REQUEST) except SendMailException: pass return self.retrieve(request, [], **kwargs) return Response( {'detail': 'The order is not pending or expired.'}, status=status.HTTP_400_BAD_REQUEST )
def _execute_payment(self, payment, request, order): payment.execute({"payer_id": request.session.get('payment_paypal_payer')}) if payment.state == 'pending': messages.warning(request, _('PayPal has not yet approved the payment. We will inform you as soon as the ' 'payment completed.')) order.payment_info = json.dumps(payment.to_dict()) order.save() return if payment.state != 'approved': messages.error(request, _('We were unable to process your payment. See below for details on how to ' 'proceed.')) logger.error('Invalid state: %s' % str(payment)) return try: mark_order_paid(order, 'paypal', json.dumps(payment.to_dict())) except Quota.QuotaExceededException as e: messages.error(request, str(e)) return None
def payment_perform(self, request, order) -> str: self._init_api() result = braintree.Transaction.sale({ "amount": str(order.total), "payment_method_nonce": request.session['payment_braintree_nonce'], "options": { "submit_for_settlement": True } }) if result.is_success: try: mark_order_paid( order, self.identifier, json.dumps(self._serialize(result.transaction))) except Quota.QuotaExceededException as e: RequiredAction.objects.create( event=request.event, action_type='pretix_braintree.overpaid', data=json.dumps({ 'order': order.code, })) raise PaymentException(str(e)) except SendMailException: raise PaymentException( _('There was an error sending the confirmation mail.')) else: if result.transaction: order.payment_info = json.dumps( self._serialize(result.transaction)) else: order.payment_info = json.dumps({'error': result.message}) order.save() raise PaymentException( _('Your payment failed because Braintree reported the following error: %s' ) % str(result.message)) del request.session['payment_braintree_nonce']
def test_paid_expired_after_last_date_subevent_relative(self): self.event.has_subevents = True self.event.save() se1 = self.event.subevents.create(name="SE1", date_from=now() + timedelta(days=10)) se2 = self.event.subevents.create(name="SE2", date_from=now() + timedelta(days=1)) self.op1.subevent = se1 self.op1.save() self.op2.subevent = se2 self.op2.save() self.event.settings.set('payment_term_last', RelativeDateWrapper( RelativeDate(days_before=2, time=None, base_date_name='date_from') )) self.order.status = Order.STATUS_EXPIRED self.order.expires = now() - timedelta(days=2) self.order.save() with self.assertRaises(Quota.QuotaExceededException): mark_order_paid(self.order) self.order = Order.objects.get(id=self.order.id) self.assertEqual(self.order.status, Order.STATUS_EXPIRED) self.event.has_subevents = False self.event.save()
def post(self, *args, **kwargs): if 'hbci_server' in self.request.POST: return self.process_hbci() if ('file' in self.request.FILES and 'csv' in self.request.FILES.get('file').name.lower()) \ or 'amount' in self.request.POST: # Process CSV return self.process_csv() if 'file' in self.request.FILES and 'txt' in self.request.FILES.get('file').name.lower(): return self.process_mt940() if 'confirm' in self.request.POST: orders = Order.objects.current.filter(event=self.request.event, code__in=self.request.POST.getlist('mark_paid')) some_failed = False for order in orders: try: mark_order_paid(order, provider='banktransfer', info=json.dumps({ 'reference': self.request.POST.get('reference_%s' % order.code), 'date': self.request.POST.get('date_%s' % order.code), 'payer': self.request.POST.get('payer_%s' % order.code), 'import': now().isoformat(), })) except Quota.QuotaExceededException: some_failed = True if some_failed: messages.warning(self.request, _('Not all of the selected orders could be marked as ' 'paid as some of them have expired and the selected ' 'items are sold out.')) else: messages.success(self.request, _('The selected orders have been marked as paid.')) # TODO: Display a list of them! return self.redirect_back() messages.error(self.request, _('We were unable to detect the file type of this import. Please ' 'contact support for help.')) return self.redirect_back()
def test_paid_in_time(self): self.quota.size = 0 self.quota.save() mark_order_paid(self.order) self.order = Order.objects.get(id=self.order.id) self.assertEqual(self.order.status, Order.STATUS_PAID)
def _charge_source(self, request, source, order): try: charge = stripe.Charge.create( amount=self._get_amount(order), currency=self.event.currency.lower(), source=source, metadata={ 'order': str(order.id), 'event': self.event.id, 'code': order.code }, # TODO: Is this sufficient? idempotency_key=str(self.event.id) + order.code + source, **self.api_kwargs) except stripe.error.CardError 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)) logger.info('Stripe card error: %s' % str(err)) order.payment_info = json.dumps({ 'error': True, 'message': err['message'], }) order.save(update_fields=['payment_info']) raise PaymentException( _('Stripe reported an error with your card: %s') % err['message']) 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.')) else: ReferencedStripeObject.objects.get_or_create(order=order, reference=charge.id) if charge.status == 'succeeded' and charge.paid: try: mark_order_paid(order, self.identifier, str(charge)) except Quota.QuotaExceededException as e: RequiredAction.objects.create( event=self.event, action_type='pretix.plugins.stripe.overpaid', data=json.dumps({ 'order': order.code, 'charge': charge.id })) raise PaymentException(str(e)) except SendMailException: raise PaymentException( _('There was an error sending the confirmation mail.')) elif charge.status == 'pending': if request: messages.warning( request, _('Your payment is pending completion. We will inform you as soon as the ' 'payment completed.')) order.payment_info = str(charge) order.save(update_fields=['payment_info']) return else: logger.info('Charge failed: %s' % str(charge)) order.payment_info = str(charge) order.save(update_fields=['payment_info']) raise PaymentException( _('Stripe reported an error: %s') % charge.failure_message)
def payment_perform(self, request: HttpRequest, order: Order): mark_order_paid(order, 'free')
def test_paid_after_deadline_but_not_expired(self): self.order.expires = now() - timedelta(days=2) self.order.save() mark_order_paid(self.order) self.order = Order.objects.get(id=self.order.id) self.assertEqual(self.order.status, Order.STATUS_PAID)
def payment_perform(self, request: HttpRequest, order: Order): from pretix.base.services.orders import mark_order_paid mark_order_paid(order, 'free')
def payment_perform(self, request: HttpRequest, order: Order): from pretix.base.services.orders import mark_order_paid try: mark_order_paid(order, 'free', send_mail=False) except Quota.QuotaExceededException as e: raise PaymentException(str(e))
def test_paid_expired_available(self): self.order.expires = now() - timedelta(days=2) self.order.save() mark_order_paid(self.order) self.order = Order.objects.get(id=self.order.id) self.assertEqual(self.order.status, Order.STATUS_PAID)
def payment_perform(self, request: HttpRequest, order: Order): from pretix.base.services.orders import mark_order_paid try: mark_order_paid(order, 'free', send_mail=False) except Quota.QuotaExceededException as e: messages.error(request, str(e))