示例#1
0
def process_stripe_callback(request):
    """Always return 200 message or else the webhook will try again ~200 times
    and then send us an email.
    """
    if request.method == 'POST':
        # Stripe hits us with a callback, and their security model is for us
        # to use the ID from that to hit their API. It's analogous to when you
        # get a random call and you call them back to make sure it's legit.
        event_id = simplejson.loads(request.body)['id']
        # Now use the API to call back.
        stripe.api_key = settings.STRIPE_SECRET_KEY
        event = simplejson.loads(str(stripe.Event.retrieve(event_id)))
        logger.info('Stripe callback triggered. See webhook documentation for details.')
        if event['type'].startswith('charge') and \
                        event['livemode'] != settings.PAYMENT_TESTING_MODE:
            charge = event['data']['object']
            try:
                d = Donation.objects.get(payment_id=charge['id'])
            except Donation.DoesNotExist:
                d = None

            # See: https://stripe.com/docs/api#event_types
            if event['type'].endswith('succeeded'):
                d.clearing_date = datetime.utcfromtimestamp(
                    charge['created']).replace(tzinfo=utc)
                d.status = 4
                from alert.donate.views import send_thank_you_email
                send_thank_you_email(d)
            elif event['type'].endswith('failed'):
                if not d:
                    return HttpResponse('<h1>200: No matching object in the '
                                        'database. No action needed.</h1>')
                d.clearing_date = datetime.utcfromtimestamp(
                    charge['created']).replace(tzinfo=utc)
                d.status = 1
            elif event['type'].endswith('refunded'):
                d.clearing_date = datetime.utcfromtimestamp(
                    charge['created']).replace(tzinfo=utc)
                d.status = 7
            elif event['type'].endswith('captured'):
                d.clearing_date = datetime.utcfromtimestamp(
                    charge['created']).replace(tzinfo=utc)
                d.status = 8
            elif event['type'].endswith('dispute.created'):
                logger.critical("Somebody has created a dispute in "
                                "Stripe: %s" % charge['id'])
            elif event['type'].endswith('dispute.updated'):
                logger.critical("The Stripe dispute on charge %s has been "
                                "updated." % charge['id'])
            elif event['type'].endswith('dispute.closed'):
                logger.critical("The Stripe dispute on charge %s has been "
                                "closed." % charge['id'])
            d.save()
        return HttpResponse('<h1>200: OK</h1>')
    else:
        return HttpResponseNotAllowed(
            permitted_methods={'POST'},
            content='<h1>405: This is a callback endpoint for a payment '
                    'provider. Only POST methods are allowed.</h1>'
        )
示例#2
0
def process_paypal_callback(request):
    """Process the GET request that PayPal uses.

    After a transaction is completed, PayPal sends the user back to a page on our site. This could be our "Thanks" page,
    but since that page is seen by all the payment providers, instead this is an intermediate page, where we grab the
    correct things from the URL, process the item, and then shuttle the user off to the normal "Thanks" page.

    The other providers do this via a POST rather than a GET, so that's why this one is a bit of an oddball.
    """
    access_token = get_paypal_access_token()
    d = Donation.objects.get(transaction_id=request.GET['token'])
    r = requests.post(
        '%s/v1/payments/payment/%s/execute/' % (settings.PAYPAL_ENDPOINT, d.payment_id),
        headers={
            'Content-Type': 'application/json',
            'Authorization': 'Bearer %s' % access_token
        },
        data=simplejson.dumps({'payer_id': request.GET['PayerID']}),
    )
    if r.status_code == 200:
        d.clearing_date = now()
        d.status = 2
        d.save()
        from alert.donate.views import send_thank_you_email
        send_thank_you_email(d)
    else:
        logger.critical("Unable to execute PayPal transaction. Status code %s with data: %s" %
                        (r.status_code, r.content))
        d.status = 1
        d.save()
    # Finally, show them the thank you page
    return HttpResponseRedirect('/donate/paypal/complete/')
示例#3
0
def process_dwolla_callback(request):
    if request.method == 'POST':
        data = simplejson.loads(request.body)
        logger.info('Data from Dwolla callback is: %s' % data)
        if check_dwolla_signature(
                data['Signature'],
                '%s&%0.2f' % (data['CheckoutId'], data['Amount'])):
            d = Donation.objects.get(payment_id=data['CheckoutId'])
            if data['Status'].lower() == 'completed':
                d.amount = data['Amount']
                d.transaction_id = data['TransactionId']
                d.clearing_date = parser.parse(data['ClearingDate'])
                d.status = 2
                from alert.donate.views import send_thank_you_email
                send_thank_you_email(d)
            elif data['Status'].lower() == 'failed':
                d.status = 1
            d.save()
            return HttpResponse('<h1>200: OK</h1>')
        else:
            logger.warn('Dwolla signature check failed.')
            return HttpResponseForbidden(
                '<h1>403: Did not pass signature check.</h1>'
            )
    else:
        return HttpResponseNotAllowed(
            permitted_methods={'POST'},
            content='<h1>405: This is a callback endpoint for a payment '
                    'provider. Only POST methods are allowed.</h1>'
        )
示例#4
0
def process_dwolla_callback(request):
    if request.method == 'POST':
        data = simplejson.loads(request.body)
        logger.info('data is: %s' % data)
        if check_dwolla_signature(
                data['Signature'],
                '%s&%0.2f' % (data['CheckoutId'], data['Amount'])):
            d = Donation.objects.get(payment_id=data['CheckoutId'])
            if data['Status'].lower() == 'completed':
                d.amount = data['Amount']
                d.transaction_id = data['TransactionId']
                d.clearing_date = parser.parse(data['ClearingDate'] + ' UTC')
                d.status = 2
                from alert.donate.views import send_thank_you_email
                send_thank_you_email(d)
            elif data['Status'].lower() == 'failed':
                d.status = 1
            d.save()
            return HttpResponse('<h1>200: OK</h1>')
        else:
            logger.warn('Dwolla signature check failed.')
            return HttpResponseForbidden(
                '<h1>403: Did not pass signature check.</h1>')
    else:
        return HttpResponseNotAllowed(
            '<h1>405: This is a callback endpoint for a payment provider. Only POST methods '
            'are allowed.</h1>')
示例#5
0
def process_stripe_callback(request):
    if request.method == 'POST':
        # Stripe hits us with a callback, and their security model is for us
        # to use the ID from that to hit their API. It's analogous to when you
        # get a random call and you call them back to make sure it's legit.
        event_id = simplejson.loads(request.body)['id']
        # Now use the API to call back.
        stripe.api_key = settings.STRIPE_SECRET_KEY
        event = simplejson.loads(str(stripe.Event.retrieve(event_id)))
        logger.info(
            'Stripe callback triggered. See webhook documentation for details.'
        )
        if event['type'].startswith('charge') and \
                        event['livemode'] != settings.PAYMENT_TESTING_MODE:  # Livemode is opposite of testing mode
            charge = event['data']['object']
            d = get_object_or_404(Donation, payment_id=charge['id'])
            # See: https://stripe.com/docs/api#event_types
            if event['type'].endswith('succeeded'):
                d.clearing_date = datetime.utcfromtimestamp(
                    charge['created']).replace(tzinfo=utc)
                d.status = 4
                from alert.donate.views import send_thank_you_email
                send_thank_you_email(d)
            elif event['type'].endswith('failed'):
                d.clearing_date = datetime.utcfromtimestamp(
                    charge['created']).replace(tzinfo=utc)
                d.status = 1
            elif event['type'].endswith('refunded'):
                d.clearing_date = datetime.utcfromtimestamp(
                    charge['created']).replace(tzinfo=utc)
                d.status = 7
            elif event['type'].endswith('captured'):
                d.clearing_date = datetime.utcfromtimestamp(
                    charge['created']).replace(tzinfo=utc)
                d.status = 8
            elif event['type'].endswith('dispute.created'):
                logger.critical(
                    "Somebody has created a dispute in Stripe: %s" %
                    charge['id'])
            elif event['type'].endswith('dispute.updated'):
                logger.critical(
                    "The Stripe dispute on charge %s has been updated." %
                    charge['id'])
            elif event['type'].endswith('dispute.closed'):
                logger.critical(
                    "The Stripe dispute on charge %s has been closed." %
                    charge['id'])
            d.save()
        return HttpResponse('<h1>200: OK</h1>')
    else:
        return HttpResponseNotAllowed(
            '<h1>405: This is a callback endpoint for a payment provider. Only '
            'POST methods are allowed.</h1>')
示例#6
0
def process_stripe_callback(request):
    """Always return 200 message or else the webhook will try again ~200 times
    and then send us an email.
    """
    if request.method == "POST":
        # Stripe hits us with a callback, and their security model is for us
        # to use the ID from that to hit their API. It's analogous to when you
        # get a random call and you call them back to make sure it's legit.
        event_id = simplejson.loads(request.body)["id"]
        # Now use the API to call back.
        stripe.api_key = settings.STRIPE_SECRET_KEY
        event = simplejson.loads(str(stripe.Event.retrieve(event_id)))
        logger.info("Stripe callback triggered. See webhook documentation for details.")
        if event["type"].startswith("charge") and event["livemode"] != settings.PAYMENT_TESTING_MODE:
            charge = event["data"]["object"]
            try:
                d = Donation.objects.get(payment_id=charge["id"])
            except Donation.DoesNotExist:
                d = None

            # See: https://stripe.com/docs/api#event_types
            if event["type"].endswith("succeeded"):
                d.clearing_date = datetime.utcfromtimestamp(charge["created"]).replace(tzinfo=utc)
                d.status = 4
                from alert.donate.views import send_thank_you_email

                send_thank_you_email(d)
            elif event["type"].endswith("failed"):
                if not d:
                    return HttpResponse("<h1>200: No matching object in the " "database. No action needed.</h1>")
                d.clearing_date = datetime.utcfromtimestamp(charge["created"]).replace(tzinfo=utc)
                d.status = 1
            elif event["type"].endswith("refunded"):
                d.clearing_date = datetime.utcfromtimestamp(charge["created"]).replace(tzinfo=utc)
                d.status = 7
            elif event["type"].endswith("captured"):
                d.clearing_date = datetime.utcfromtimestamp(charge["created"]).replace(tzinfo=utc)
                d.status = 8
            elif event["type"].endswith("dispute.created"):
                logger.critical("Somebody has created a dispute in " "Stripe: %s" % charge["id"])
            elif event["type"].endswith("dispute.updated"):
                logger.critical("The Stripe dispute on charge %s has been " "updated." % charge["id"])
            elif event["type"].endswith("dispute.closed"):
                logger.critical("The Stripe dispute on charge %s has been " "closed." % charge["id"])
            d.save()
        return HttpResponse("<h1>200: OK</h1>")
    else:
        return HttpResponseNotAllowed(
            permitted_methods={"POST"},
            content="<h1>405: This is a callback endpoint for a payment "
            "provider. Only POST methods are allowed.</h1>",
        )
def process_stripe_callback(request):
    if request.method == 'POST':
        # Stripe hits us with a callback, and their security model is for us
        # to use the ID from that to hit their API. It's analogous to when you
        # get a random call and you call them back to make sure it's legit.
        event_id = simplejson.loads(request.body)['id']
        # Now use the API to call back.
        stripe.api_key = settings.STRIPE_SECRET_KEY
        event = simplejson.loads(str(stripe.Event.retrieve(event_id)))
        logger.info('Stripe callback triggered. See webhook documentation for details.')
        if event['type'].startswith('charge') and \
                        event['livemode'] != settings.PAYMENT_TESTING_MODE:  # Livemode is opposite of testing mode
            charge = event['data']['object']
            d = get_object_or_404(Donation, payment_id=charge['id'])
            # See: https://stripe.com/docs/api#event_types
            if event['type'].endswith('succeeded'):
                d.clearing_date = datetime.utcfromtimestamp(charge['created']).replace(tzinfo=utc)
                d.status = 4
                from alert.donate.views import send_thank_you_email
                send_thank_you_email(d)
            elif event['type'].endswith('failed'):
                d.clearing_date = datetime.utcfromtimestamp(charge['created']).replace(tzinfo=utc)
                d.status = 1
            elif event['type'].endswith('refunded'):
                d.clearing_date = datetime.utcfromtimestamp(charge['created']).replace(tzinfo=utc)
                d.status = 7
            elif event['type'].endswith('captured'):
                d.clearing_date = datetime.utcfromtimestamp(charge['created']).replace(tzinfo=utc)
                d.status = 8
            elif event['type'].endswith('dispute.created'):
                logger.critical("Somebody has created a dispute in Stripe: %s" % charge['id'])
            elif event['type'].endswith('dispute.updated'):
                logger.critical("The Stripe dispute on charge %s has been updated." % charge['id'])
            elif event['type'].endswith('dispute.closed'):
                logger.critical("The Stripe dispute on charge %s has been closed." % charge['id'])
            d.save()
        return HttpResponse('<h1>200: OK</h1>')
    else:
        return HttpResponseNotAllowed(
            permitted_methods={'POST'},
            content='<h1>405: This is a callback endpoint for a payment '
                    'provider. Only POST methods are allowed.</h1>'
        )
示例#8
0
def process_paypal_callback(request):
    """Process the GET request that PayPal uses.

    After a transaction is completed, PayPal sends the user back to a page on
    our site. This could be our "Thanks" page, but since that page is seen by
    all the payment providers, instead this is an intermediate page, where we
    grab the correct things from the URL, process the item, and then shuttle
    the user off to the normal "Thanks" page.

    The other providers do this via a POST rather than a GET, so that's why
    this one is a bit of an oddball.
    """
    access_token = get_paypal_access_token()
    d = Donation.objects.get(transaction_id=request.GET['token'])
    r = requests.post(
        '%s/v1/payments/payment/%s/execute/' % (
            settings.PAYPAL_ENDPOINT,
            d.payment_id
        ),
        headers={
            'Content-Type': 'application/json',
            'Authorization': 'Bearer %s' % access_token
        },
        data=simplejson.dumps({'payer_id': request.GET['PayerID']}),
    )
    if r.status_code == 200:
        d.clearing_date = now()
        # Technically, this should be d.status = 2 (Completed, awaiting
        # processing) and we should await a webhook to tell us that the
        # processing completed successfully (4). Alas, PayPal is so terrible
        # that I can't figure that out, so we just assume that if it gets
        # completed (2), it'll get processed (4).
        d.status = 4
        d.save()
        from alert.donate.views import send_thank_you_email
        send_thank_you_email(d)
    else:
        logger.critical("Unable to execute PayPal transaction. Status code %s "
                        "with data: %s" % (r.status_code, r.content))
        d.status = 1
        d.save()
    # Finally, show them the thank you page
    return HttpResponseRedirect('/donate/paypal/complete/')