示例#1
0
def retry(request, order):
    try:
        order = Order.objects.current.get(
            user=request.user,
            code=order,
        )
    except Order.DoesNotExist:
        return  # TODO: Handle this

    provider = Paypal(order.event)
    provider.init_api()

    if 'token' in request.GET:
        if 'PayerID' in request.GET:
            payment = paypalrestsdk.Payment.find(request.session.get('payment_paypal_id'))
            provider._execute_payment(payment, request, order)
        else:
            messages.error(request, _('It looks like you cancelled the PayPal payment'))
    else:
        payment = paypalrestsdk.Payment({
            'intent': 'sale',
            'payer': {
                "payment_method": "paypal",
            },
            "redirect_urls": {
                "return_url": build_absolute_uri('plugins:paypal:retry', kwargs={
                    'order': order.code
                }),
                "cancel_url": build_absolute_uri('plugins:paypal:retry', kwargs={
                    'order': order.code
                }),
            },
            "transactions": [
                {
                    "item_list": {
                        "items": [
                            {
                                "name": 'Order %s' % order.code,
                                "quantity": 1,
                                "price": str(order.total),
                                "currency": order.event.currency
                            }
                        ]
                    },
                    "amount": {
                        "currency": order.event.currency,
                        "total": str(order.total)
                    },
                    "description": __('Event tickets for %s') % order.event.name
                }
            ]
        })
        resp = provider._create_payment(request, payment)
        if resp:
            return redirect(resp)

    return redirect(eventreverse(order.event, 'presale:event.order', kwargs={
        'order': order.code,
        'secret': order.secret
    }) + '?paid=yes')
示例#2
0
def oauth_return(request, *args, **kwargs):
    if 'payment_paypal_oauth_event' not in request.session:
        messages.error(request, _('An error occurred during connecting with PayPal, please try again.'))
        return redirect(reverse('control:index'))

    event = get_object_or_404(Event, pk=request.session['payment_paypal_oauth_event'])

    prov = Paypal(event)
    prov.init_api()

    try:
        tokeninfo = Tokeninfo.create(request.GET.get('code'))
        userinfo = Tokeninfo.create_with_refresh_token(tokeninfo['refresh_token']).userinfo()
    except:
        logger.exception('Failed to obtain OAuth token')
        messages.error(request, _('An error occurred during connecting with PayPal, please try again.'))
    else:
        messages.success(request,
                         _('Your PayPal account is now connected to pretix. You can change the settings in '
                           'detail below.'))

        event.settings.payment_paypal_connect_refresh_token = tokeninfo['refresh_token']
        event.settings.payment_paypal_connect_user_id = userinfo.email

    return redirect(reverse('control:event.settings.payment.provider', kwargs={
        'organizer': event.organizer.slug,
        'event': event.slug,
        'provider': 'paypal'
    }))
示例#3
0
文件: views.py 项目: tydonk/pretix
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)
示例#4
0
文件: views.py 项目: akuks/pretix
def retry(request, order):
    try:
        order = Order.objects.current.get(user=request.user, code=order)
    except Order.DoesNotExist:
        return  # TODO: Handle this

    provider = Paypal(order.event)
    provider.init_api()

    if "token" in request.GET:
        if "PayerID" in request.GET:
            payment = paypalrestsdk.Payment.find(request.session.get("payment_paypal_id"))
            provider._execute_payment(payment, request, order)
        else:
            messages.error(request, _("It looks like you cancelled the PayPal payment"))
    else:
        payment = paypalrestsdk.Payment(
            {
                "intent": "sale",
                "payer": {"payment_method": "paypal"},
                "redirect_urls": {
                    "return_url": build_absolute_uri("plugins:paypal:retry", kwargs={"order": order.code}),
                    "cancel_url": build_absolute_uri("plugins:paypal:retry", kwargs={"order": order.code}),
                },
                "transactions": [
                    {
                        "item_list": {
                            "items": [
                                {
                                    "name": "Order %s" % order.code,
                                    "quantity": 1,
                                    "price": str(order.total),
                                    "currency": order.event.currency,
                                }
                            ]
                        },
                        "amount": {"currency": order.event.currency, "total": str(order.total)},
                        "description": __("Event tickets for %s") % order.event.name,
                    }
                ],
            }
        )
        resp = provider._create_payment(request, payment)
        if resp:
            return redirect(resp)

    return redirect(
        "presale:event.order", event=order.event.slug, organizer=order.event.organizer.slug, order=order.code
    )
示例#5
0
def webhook(request, *args, **kwargs):
    event_body = request.body.decode('utf-8').strip()
    event_json = json.loads(event_body)

    # 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)

    if event_json['resource_type'] == 'sale':
        saleid = event_json['resource']['id']
    else:
        saleid = event_json['resource']['sale_id']

    try:
        refs = [saleid]
        if event_json['resource'].get('parent_payment'):
            refs.append(event_json['resource'].get('parent_payment'))

        rso = ReferencedPayPalObject.objects.select_related(
            'order', 'order__event').get(reference__in=refs)
        event = rso.order.event
    except ReferencedPayPalObject.DoesNotExist:
        rso = None
        if hasattr(request, 'event'):
            event = request.event
        else:
            return HttpResponse("Unable to detect event", status=200)

    prov = Paypal(event)
    prov.init_api()

    try:
        sale = paypalrestsdk.Sale.find(saleid)
    except:
        logger.exception('PayPal error on webhook. Event data: %s' %
                         str(event_json))
        return HttpResponse('Sale not found', status=500)

    if rso and rso.payment:
        payment = rso.payment
    else:
        payments = OrderPayment.objects.filter(order__event=event,
                                               provider='paypal',
                                               info__icontains=sale['id'])
        payment = None
        for p in payments:
            payment_info = p.info_data
            for res in payment_info['transactions'][0]['related_resources']:
                for k, v in res.items():
                    if k == 'sale' and v['id'] == sale['id']:
                        payment = p
                        break

    if not payment:
        return HttpResponse('Payment not found', status=200)

    payment.order.log_action('pretix.plugins.paypal.event', data=event_json)

    if payment.state == OrderPayment.PAYMENT_STATE_CONFIRMED and sale[
            'state'] in ('partially_refunded', 'refunded'):
        if event_json['resource_type'] == 'refund':
            try:
                refund = paypalrestsdk.Refund.find(
                    event_json['resource']['id'])
            except:
                logger.exception('PayPal error on webhook. Event data: %s' %
                                 str(event_json))
                return HttpResponse('Refund not found', status=500)

            known_refunds = {
                r.info_data.get('id'): r
                for r in payment.refunds.all()
            }
            if refund['id'] not in known_refunds:
                payment.create_external_refund(
                    amount=abs(Decimal(refund['amount']['total'])),
                    info=json.dumps(refund.to_dict(
                    ) if not isinstance(refund, dict) else refund))
            elif known_refunds.get(refund['id']).state in (
                    OrderRefund.REFUND_STATE_CREATED, OrderRefund.
                    REFUND_STATE_TRANSIT) and refund['state'] == 'completed':
                known_refunds.get(refund['id']).done()

            if 'total_refunded_amount' in refund:
                known_sum = payment.refunds.filter(
                    state__in=(OrderRefund.REFUND_STATE_DONE,
                               OrderRefund.REFUND_STATE_TRANSIT,
                               OrderRefund.REFUND_STATE_CREATED,
                               OrderRefund.REFUND_SOURCE_EXTERNAL)).aggregate(
                                   s=Sum('amount'))['s'] or Decimal('0.00')
                total_refunded_amount = Decimal(
                    refund['total_refunded_amount']['value'])
                if known_sum < total_refunded_amount:
                    payment.create_external_refund(
                        amount=total_refunded_amount - known_sum)
        elif sale['state'] == 'refunded':
            known_sum = payment.refunds.filter(
                state__in=(OrderRefund.REFUND_STATE_DONE,
                           OrderRefund.REFUND_STATE_TRANSIT,
                           OrderRefund.REFUND_STATE_CREATED,
                           OrderRefund.REFUND_SOURCE_EXTERNAL)).aggregate(
                               s=Sum('amount'))['s'] or Decimal('0.00')

            if known_sum < payment.amount:
                payment.create_external_refund(amount=payment.amount -
                                               known_sum)
    elif payment.state in (OrderPayment.PAYMENT_STATE_PENDING,
                           OrderPayment.PAYMENT_STATE_CREATED,
                           OrderPayment.PAYMENT_STATE_CANCELED,
                           OrderPayment.PAYMENT_STATE_FAILED
                           ) and sale['state'] == 'completed':
        try:
            payment.confirm()
        except Quota.QuotaExceededException:
            pass

    return HttpResponse(status=200)
示例#6
0
def webhook(request, *args, **kwargs):
    event_body = request.body.decode('utf-8').strip()
    event_json = json.loads(event_body)

    # 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)

    if event_json['resource_type'] == 'sale':
        saleid = event_json['resource']['id']
    else:
        saleid = event_json['resource']['sale_id']

    try:
        refs = [saleid]
        if event_json['resource'].get('parent_payment'):
            refs.append(event_json['resource'].get('parent_payment'))

        rso = ReferencedPayPalObject.objects.select_related('order', 'order__event').get(
            reference__in=refs
        )
        event = rso.order.event
    except ReferencedPayPalObject.DoesNotExist:
        rso = None
        if hasattr(request, 'event'):
            event = request.event
        else:
            return HttpResponse("Unable to detect event", status=200)

    prov = Paypal(event)
    prov.init_api()

    try:
        sale = paypalrestsdk.Sale.find(saleid)
    except:
        logger.exception('PayPal error on webhook. Event data: %s' % str(event_json))
        return HttpResponse('Sale not found', status=500)

    if rso and rso.payment:
        payment = rso.payment
    else:
        payments = OrderPayment.objects.filter(order__event=event, provider='paypal',
                                               info__icontains=sale['id'])
        payment = None
        for p in payments:
            payment_info = p.info_data
            for res in payment_info['transactions'][0]['related_resources']:
                for k, v in res.items():
                    if k == 'sale' and v['id'] == sale['id']:
                        payment = p
                        break

    if not payment:
        return HttpResponse('Payment not found', status=200)

    payment.order.log_action('pretix.plugins.paypal.event', data=event_json)

    if payment.state == OrderPayment.PAYMENT_STATE_CONFIRMED and sale['state'] in ('partially_refunded', 'refunded'):
        if event_json['resource_type'] == 'refund':
            try:
                refund = paypalrestsdk.Refund.find(event_json['resource']['id'])
            except:
                logger.exception('PayPal error on webhook. Event data: %s' % str(event_json))
                return HttpResponse('Refund not found', status=500)

            known_refunds = {r.info_data.get('id'): r for r in payment.refunds.all()}
            if refund['id'] not in known_refunds:
                payment.create_external_refund(
                    amount=abs(Decimal(refund['amount']['total'])),
                    info=json.dumps(refund.to_dict() if not isinstance(refund, dict) else refund)
                )
            elif known_refunds.get(refund['id']).state in (
                    OrderRefund.REFUND_STATE_CREATED, OrderRefund.REFUND_STATE_TRANSIT) and refund['state'] == 'completed':
                known_refunds.get(refund['id']).done()

            if 'total_refunded_amount' in refund:
                known_sum = payment.refunds.filter(
                    state__in=(OrderRefund.REFUND_STATE_DONE, OrderRefund.REFUND_STATE_TRANSIT,
                               OrderRefund.REFUND_STATE_CREATED, OrderRefund.REFUND_SOURCE_EXTERNAL)
                ).aggregate(s=Sum('amount'))['s'] or Decimal('0.00')
                total_refunded_amount = Decimal(refund['total_refunded_amount']['value'])
                if known_sum < total_refunded_amount:
                    payment.create_external_refund(
                        amount=total_refunded_amount - known_sum
                    )
        elif sale['state'] == 'refunded':
            known_sum = payment.refunds.filter(
                state__in=(OrderRefund.REFUND_STATE_DONE, OrderRefund.REFUND_STATE_TRANSIT,
                           OrderRefund.REFUND_STATE_CREATED, OrderRefund.REFUND_SOURCE_EXTERNAL)
            ).aggregate(s=Sum('amount'))['s'] or Decimal('0.00')

            if known_sum < payment.amount:
                payment.create_external_refund(
                    amount=payment.amount - known_sum
                )
    elif payment.state in (OrderPayment.PAYMENT_STATE_PENDING, OrderPayment.PAYMENT_STATE_CREATED) and sale['state'] == 'completed':
        try:
            payment.confirm()
        except Quota.QuotaExceededException:
            pass

    return HttpResponse(status=200)