示例#1
0
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 LockTimeoutException:
            return HttpResponse("Lock timeout, please try again.", status=503)
        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)
示例#2
0
def paymentintent_webhook(event, event_json, paymentintent_id, rso):
    prov = StripeCC(event)
    prov._init_api()

    try:
        paymentintent = stripe.PaymentIntent.retrieve(paymentintent_id, **prov.api_kwargs)
    except stripe.error.StripeError:
        logger.exception('Stripe error on webhook. Event data: %s' % str(event_json))
        return HttpResponse('Charge not found', status=500)

    for charge in paymentintent.charges.data:
        ReferencedStripeObject.objects.get_or_create(
            reference=charge.id,
            defaults={'order': rso.payment.order, 'payment': rso.payment}
        )

    return HttpResponse(status=200)
示例#3
0
def source_webhook(event, event_json, source_id):
    prov = StripeCC(event)
    prov._init_api()
    try:
        src = stripe.Source.retrieve(source_id, **prov.api_kwargs)
    except stripe.error.StripeError:
        logger.exception('Stripe error on webhook. Event data: %s' %
                         str(event_json))
        return HttpResponse('Charge not found', status=500)

    metadata = src['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)

    with transaction.atomic():
        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)
        go = (event_json['type'] == 'source.chargeable'
              and order.status == Order.STATUS_PENDING
              and src.status == 'chargeable')
        if go:
            try:
                prov._charge_source(None, source_id, order)
            except PaymentException:
                logger.exception('Webhook error')

    return HttpResponse(status=200)
示例#4
0
文件: views.py 项目: ryardley/pretix
def source_webhook(event, event_json, source_id, rso):
    prov = StripeCC(event)
    prov._init_api()
    try:
        src = stripe.Source.retrieve(source_id, **prov.api_kwargs)
    except stripe.error.StripeError:
        logger.exception('Stripe error on webhook. Event data: %s' % str(event_json))
        return HttpResponse('Charge not found', status=500)

    metadata = src['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)

    with transaction.atomic():
        if rso and rso.payment:
            order = rso.payment.order
            payment = rso.payment
        elif rso:
            order = rso.order
            payment = None
        else:
            try:
                order = event.orders.get(id=metadata['order'])
            except Order.DoesNotExist:
                return HttpResponse('Order not found', status=200)
            payment = None

        if not payment:
            payment = order.payments.filter(
                info__icontains=src['id'],
                provider__startswith='stripe',
                amount=prov._amount_to_decimal(src['amount']) if src['amount'] is not None else order.total,
            ).last()
        if not payment:
            payment = order.payments.create(
                state=OrderPayment.PAYMENT_STATE_CREATED,
                provider=SOURCE_TYPES.get(src['type'], 'stripe'),
                amount=prov._amount_to_decimal(src['amount']) if src['amount'] is not None else order.total,
                info=str(src),
            )

        if payment.provider != prov.identifier:
            prov = payment.payment_provider
            prov._init_api()

        order.log_action('pretix.plugins.stripe.event', data=event_json)
        go = (event_json['type'] == 'source.chargeable' and
              payment.state in (OrderPayment.PAYMENT_STATE_PENDING, OrderPayment.PAYMENT_STATE_CREATED) and
              src.status == 'chargeable')
        if go:
            try:
                prov._charge_source(None, source_id, payment)
            except PaymentException:
                logger.exception('Webhook error')

        elif src.status == 'failed':
            payment.info = str(src)
            payment.state = OrderPayment.PAYMENT_STATE_FAILED
            payment.order.log_action('pretix.event.order.payment.failed', {
                'local_id': payment.local_id,
                'provider': payment.provider,
                'info': str(src)
            })
            payment.save()

    return HttpResponse(status=200)
示例#5
0
文件: views.py 项目: ryardley/pretix
def charge_webhook(event, event_json, charge_id, rso):
    prov = StripeCC(event)
    prov._init_api()
    try:
        charge = stripe.Charge.retrieve(charge_id, expand=['dispute'], **prov.api_kwargs)
    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)

    if rso and rso.payment:
        order = rso.payment.order
        payment = rso.payment
    elif rso:
        order = rso.order
        payment = None
    else:
        try:
            order = event.orders.get(id=metadata['order'])
        except Order.DoesNotExist:
            return HttpResponse('Order not found', status=200)
        payment = None

    if not payment:
        payment = order.payments.filter(
            info__icontains=charge['id'],
            provider__startswith='stripe',
            amount=prov._amount_to_decimal(charge['amount']),
        ).last()
    if not payment:
        payment = order.payments.create(
            state=OrderPayment.PAYMENT_STATE_CREATED,
            provider=SOURCE_TYPES.get(charge['source'].get('type', charge['source'].get('object', 'card')), 'stripe'),
            amount=prov._amount_to_decimal(charge['amount']),
            info=str(charge),
        )

    if payment.provider != prov.identifier:
        prov = payment.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 is_refund:
        known_refunds = [r.info_data.get('id') for r in payment.refunds.all()]
        migrated_refund_amounts = [r.amount for r in payment.refunds.all() if not r.info_data.get('id')]
        for r in charge['refunds']['data']:
            a = prov._amount_to_decimal(r['amount'])
            if r['status'] in ('failed', 'canceled'):
                continue

            if a in migrated_refund_amounts:
                migrated_refund_amounts.remove(a)
                continue

            if r['id'] not in known_refunds:
                payment.create_external_refund(
                    amount=a,
                    info=str(r)
                )
        if charge['dispute']:
            if charge['dispute']['status'] != 'won' and charge['dispute']['id'] not in known_refunds:
                a = prov._amount_to_decimal(charge['dispute']['amount'])
                if a in migrated_refund_amounts:
                    migrated_refund_amounts.remove(a)
                else:
                    payment.create_external_refund(
                        amount=a,
                        info=str(charge['dispute'])
                    )
    elif charge['status'] == 'succeeded' and payment.state in (OrderPayment.PAYMENT_STATE_PENDING,
                                                               OrderPayment.PAYMENT_STATE_CREATED,
                                                               OrderPayment.PAYMENT_STATE_CANCELED,
                                                               OrderPayment.PAYMENT_STATE_FAILED):
        try:
            payment.confirm()
        except LockTimeoutException:
            return HttpResponse("Lock timeout, please try again.", status=503)
        except Quota.QuotaExceededException:
            pass
    elif charge['status'] == 'failed' and payment.state in (OrderPayment.PAYMENT_STATE_PENDING, OrderPayment.PAYMENT_STATE_CREATED):
            payment.info = str(charge)
            payment.state = OrderPayment.PAYMENT_STATE_FAILED
            payment.save()
            payment.order.log_action('pretix.event.order.payment.failed', {
                'local_id': payment.local_id,
                'provider': payment.provider,
                'info': str(charge)
            })

    return HttpResponse(status=200)
示例#6
0
def source_webhook(event, event_json, source_id, rso):
    prov = StripeCC(event)
    prov._init_api()
    try:
        src = stripe.Source.retrieve(source_id, **prov.api_kwargs)
    except stripe.error.StripeError:
        logger.exception('Stripe error on webhook. Event data: %s' % str(event_json))
        return HttpResponse('Charge not found', status=500)

    metadata = src['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)

    with transaction.atomic():
        if rso and rso.payment:
            order = rso.payment.order
            payment = rso.payment
        elif rso:
            order = rso.order
            payment = None
        else:
            try:
                order = event.orders.get(id=metadata['order'])
            except Order.DoesNotExist:
                return HttpResponse('Order not found', status=200)
            payment = None

        if not payment:
            payment = order.payments.filter(
                info__icontains=src['id'],
                provider__startswith='stripe',
                amount=prov._amount_to_decimal(src['amount']) if src['amount'] is not None else order.total,
            ).last()
        if not payment:
            payment = order.payments.create(
                state=OrderPayment.PAYMENT_STATE_CREATED,
                provider=SOURCE_TYPES.get(src['type'], 'stripe'),
                amount=prov._amount_to_decimal(src['amount']) if src['amount'] is not None else order.total,
                info=str(src),
            )

        if payment.provider != prov.identifier:
            prov = payment.payment_provider
            prov._init_api()

        order.log_action('pretix.plugins.stripe.event', data=event_json)
        go = (event_json['type'] == 'source.chargeable' and
              payment.state in (OrderPayment.PAYMENT_STATE_PENDING, OrderPayment.PAYMENT_STATE_CREATED) and
              src.status == 'chargeable')
        if go:
            try:
                prov._charge_source(None, source_id, payment)
            except PaymentException:
                logger.exception('Webhook error')

        elif src.status == 'failed':
            payment.info = str(src)
            payment.state = OrderPayment.PAYMENT_STATE_FAILED
            payment.order.log_action('pretix.event.order.payment.failed', {
                'local_id': payment.local_id,
                'provider': payment.provider,
                'info': str(src)
            })
            payment.save()
        elif src.status == 'canceled' and payment.state in (Order.STATUS_PENDING, OrderPayment.PAYMENT_STATE_CREATED):
            payment.info = str(src)
            payment.state = OrderPayment.PAYMENT_STATE_CANCELED
            payment.save()

    return HttpResponse(status=200)
示例#7
0
def charge_webhook(event, event_json, charge_id, rso):
    prov = StripeCC(event)
    prov._init_api()
    try:
        charge = stripe.Charge.retrieve(charge_id, expand=['dispute'], **prov.api_kwargs)
    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)

    if rso and rso.payment:
        order = rso.payment.order
        payment = rso.payment
    elif rso:
        order = rso.order
        payment = None
    else:
        try:
            order = event.orders.get(id=metadata['order'])
        except Order.DoesNotExist:
            return HttpResponse('Order not found', status=200)
        payment = None

    if not payment:
        payment = order.payments.filter(
            info__icontains=charge['id'],
            provider__startswith='stripe',
            amount=prov._amount_to_decimal(charge['amount']),
        ).last()
    if not payment:
        payment = order.payments.create(
            state=OrderPayment.PAYMENT_STATE_CREATED,
            provider=SOURCE_TYPES.get(charge['source'].get('type', charge['source'].get('object', 'card')), 'stripe'),
            amount=prov._amount_to_decimal(charge['amount']),
            info=str(charge),
        )

    if payment.provider != prov.identifier:
        prov = payment.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 is_refund:
        known_refunds = [r.info_data.get('id') for r in payment.refunds.all()]
        migrated_refund_amounts = [r.amount for r in payment.refunds.all() if not r.info_data.get('id')]
        for r in charge['refunds']['data']:
            a = prov._amount_to_decimal(r['amount'])
            if r['status'] in ('failed', 'canceled'):
                continue

            if a in migrated_refund_amounts:
                migrated_refund_amounts.remove(a)
                continue

            if r['id'] not in known_refunds:
                payment.create_external_refund(
                    amount=a,
                    info=str(r)
                )
        if charge['dispute']:
            if charge['dispute']['status'] != 'won' and charge['dispute']['id'] not in known_refunds:
                a = prov._amount_to_decimal(charge['dispute']['amount'])
                if a in migrated_refund_amounts:
                    migrated_refund_amounts.remove(a)
                else:
                    payment.create_external_refund(
                        amount=a,
                        info=str(charge['dispute'])
                    )
    elif charge['status'] == 'succeeded' and payment.state in (OrderPayment.PAYMENT_STATE_PENDING,
                                                               OrderPayment.PAYMENT_STATE_CREATED,
                                                               OrderPayment.PAYMENT_STATE_CANCELED,
                                                               OrderPayment.PAYMENT_STATE_FAILED):
        try:
            payment.confirm()
        except LockTimeoutException:
            return HttpResponse("Lock timeout, please try again.", status=503)
        except Quota.QuotaExceededException:
            pass
    elif charge['status'] == 'failed' and payment.state in (OrderPayment.PAYMENT_STATE_PENDING, OrderPayment.PAYMENT_STATE_CREATED):
        payment.info = str(charge)
        payment.state = OrderPayment.PAYMENT_STATE_FAILED
        payment.save()
        payment.order.log_action('pretix.event.order.payment.failed', {
            'local_id': payment.local_id,
            'provider': payment.provider,
            'info': str(charge)
        })

    return HttpResponse(status=200)