Example #1
0
def route_and_process_donation(cd_donation_form, cd_user_form, stripe_token):
    """Routes the donation to the correct payment provider, then normalizes
    its response.

    Returns a dict with:
     - message: Any error messages that apply
     - status: The status of the payment for the database
     - payment_id: The ID of the payment
    """
    if cd_donation_form['payment_provider'] == 'paypal':
        response = process_paypal_payment(cd_donation_form)
        if response['result'] == 'created':
            response = {
                'message': None,
                'status': Donation.AWAITING_PAYMENT,
                'payment_id': response['payment_id'],
                'transaction_id': response['transaction_id'],
                'redirect': response['redirect'],
            }
        else:
            response = {
                'message': 'We had an error working with PayPal. Please try '
                'another payment method.',
                'status': Donation.UNKNOWN_ERROR,
                'payment_id': None,
                'redirect': None,
            }
    elif cd_donation_form['payment_provider'] == 'cc':
        response = process_stripe_payment(cd_donation_form, cd_user_form,
                                          stripe_token)
    else:
        response = None
    return response
Example #2
0
def route_and_process_payment(
    request,
    cd_donation_form,
    cd_user_form,
    payment_provider,
    frequency,
    stripe_redirect_url,
    payment_type,
):
    """Routes the donation to the correct payment provider, then normalizes
    its response.


    :param request: The WSGI request from Django
    :param cd_donation_form: The donation form with cleaned data
    :param cd_user_form: The user form with cleaned data
    :param payment_provider: The payment provider for the payment
    :param frequency: Whether monthly or one-time payment/donation
    :param stripe_redirect_url: Where to redirect a stripe payment after
    success
    :param payment_type: Whether it's a donation or payment

    Returns a dict with:
     - message: Any error messages that apply
     - status: The status of the payment for the database
     - payment_id: The ID of the payment
    """
    customer = None
    if payment_provider == PROVIDERS.PAYPAL:
        response = process_paypal_payment(cd_donation_form)
    elif payment_provider == PROVIDERS.CREDIT_CARD:
        stripe_token = request.POST.get("stripeToken")
        stripe_args = {"metadata": {"type": payment_type}}
        if frequency == FREQUENCIES.ONCE:
            stripe_args["card"] = stripe_token
        elif frequency == FREQUENCIES.MONTHLY:
            customer = create_stripe_customer(stripe_token,
                                              cd_user_form["email"])
            stripe_args["customer"] = customer.id
            stripe_args["metadata"].update({"recurring": True})
        else:
            raise NotImplementedError("Unknown frequency value: %s" %
                                      frequency)

        if cd_donation_form["reference"]:
            stripe_args["metadata"].update(
                {"reference": cd_donation_form["reference"]})

        # Calculate the amount in cents
        amount = int(float(cd_donation_form["amount"]) * 100)
        response = process_stripe_payment(amount, cd_user_form["email"],
                                          stripe_args, stripe_redirect_url)
    else:
        raise PaymentFailureException("Unknown/unhandled payment provider.")

    return response, customer
Example #3
0
def route_and_process_payment(request, cd_donation_form, cd_user_form,
                              payment_provider, frequency,
                              stripe_redirect_url, payment_type):
    """Routes the donation to the correct payment provider, then normalizes
    its response.


    :param request: The WSGI request from Django
    :param cd_donation_form: The donation form with cleaned data
    :param cd_user_form: The user form with cleaned data
    :param payment_provider: The payment provider for the payment
    :param frequency: Whether monthly or one-time payment/donation
    :param stripe_redirect_url: Where to redirect a stripe payment after
    success
    :param payment_type: Whether it's a donation or payment

    Returns a dict with:
     - message: Any error messages that apply
     - status: The status of the payment for the database
     - payment_id: The ID of the payment
    """
    customer = None
    if payment_provider == PROVIDERS.PAYPAL:
        response = process_paypal_payment(cd_donation_form)
    elif payment_provider == PROVIDERS.CREDIT_CARD:
        stripe_token = request.POST.get('stripeToken')
        stripe_args = {'metadata': {'type': payment_type}}
        if frequency == FREQUENCIES.ONCE:
            stripe_args['card'] = stripe_token
        elif frequency == FREQUENCIES.MONTHLY:
            customer = create_stripe_customer(stripe_token,
                                              cd_user_form['email'])
            stripe_args['customer'] = customer.id
            stripe_args['metadata'].update({'recurring': True})
        else:
            raise NotImplementedError("Unknown frequency value: %s" %
                                      frequency)

        if cd_donation_form['reference']:
            stripe_args['metadata'].update(
                {'reference': cd_donation_form['reference']})

        # Calculate the amount in cents
        amount = int(float(cd_donation_form['amount']) * 100)
        response = process_stripe_payment(
            amount, cd_user_form['email'], stripe_args, stripe_redirect_url)

    return response, customer
Example #4
0
def route_and_process_donation(cd_donation_form, cd_user_form, kwargs):
    """Routes the donation to the correct payment provider, then normalizes
    its response.

    Returns a dict with:
     - message: Any error messages that apply
     - status: The status of the payment for the database
     - payment_id: The ID of the payment
    """
    if cd_donation_form['payment_provider'] == PROVIDERS.PAYPAL:
        response = process_paypal_payment(cd_donation_form)
    elif cd_donation_form['payment_provider'] == PROVIDERS.CREDIT_CARD:
        # Calculate the amount in cents
        amount = int(float(cd_donation_form['amount']) * 100)
        response = process_stripe_payment(amount, cd_user_form['email'],
                                          kwargs)
    else:
        response = None
    return response
Example #5
0
def route_and_process_donation(cd_donation_form, cd_user_form, stripe_token):
    """Routes the donation to the correct payment provider, then normalizes
    its response.

    Returns a dict with:
     - message: Any error messages that apply
     - status: The status of the payment for the database
     - payment_id: The ID of the payment
    """
    if cd_donation_form['payment_provider'] == 'paypal':
        response = process_paypal_payment(cd_donation_form)
        if response['result'] == 'created':
            response = {
                'message': None,
                'status': Donation.AWAITING_PAYMENT,
                'payment_id': response['payment_id'],
                'transaction_id': response['transaction_id'],
                'redirect': response['redirect'],
            }
        else:
            response = {
                'message': 'We had an error working with PayPal. Please try '
                           'another payment method.',
                'status': Donation.UNKNOWN_ERROR,
                'payment_id': None,
                'redirect': None,
            }
    elif cd_donation_form['payment_provider'] == 'cc':
        response = process_stripe_payment(
            cd_donation_form,
            cd_user_form,
            stripe_token
        )
    else:
        response = None
    return response
    def handle(self, *args, **options):
        super(Command, self).handle(*args, **options)

        m_donations = MonthlyDonation.objects.filter(
            enabled=True,
            monthly_donation_day=now().date().day,
            # This is a safety to account for timezones. We want to be very
            # careful that we don't double-bill people right when they sign up,
            # so this ensures that we don't bill anybody except when the
            # recurring donation is more than 15 days old.
            date_created__lt=now() - timedelta(days=15),
        ).order_by("-date_created")

        results = {"amount": 0, "users": []}
        for m_donation in m_donations:
            try:
                response = process_stripe_payment(
                    # Stripe rejects the charge if there are decimals;
                    # cast to int.
                    int(m_donation.monthly_donation_amount * 100),
                    m_donation.donor.email,
                    {
                        "customer": m_donation.stripe_customer_id,
                        "metadata": {
                            "recurring": True,
                            "type": PAYMENT_TYPES.DONATION,
                        },
                    },
                    reverse("donate_complete"),
                )
            except PaymentFailureException as e:
                m_donation.failure_count += 1
                m_donation.enabled = False
                m_donation.save()
                send_failed_subscription_email(m_donation)
                continue

            if response.get("status") == Donation.AWAITING_PAYMENT:
                # It worked. Create a donation in our system as well.
                results["amount"] += m_donation.monthly_donation_amount
                results["users"].append(" - %s %s (%s): $%s" % (
                    m_donation.donor.first_name,
                    m_donation.donor.last_name,
                    m_donation.donor.email,
                    m_donation.monthly_donation_amount,
                ))
                Donation.objects.create(
                    donor=m_donation.donor,
                    amount=m_donation.monthly_donation_amount,
                    payment_provider=m_donation.payment_provider,
                    status=response["status"],
                    payment_id=response["payment_id"],
                    # Only applies to PayPal
                    transaction_id=response.get("transaction_id"),
                    referrer="monthly_donation_%s" % m_donation.pk,
                )
                # Thank you email is triggered later when the stripe callback
                # is triggered.

        if results["users"]:
            email = emails["admin_donation_report"]
            body = email["body"] % (
                results["amount"],
                "\n".join(results["users"]),
            )
            send_mail(
                email["subject"] % results["amount"],
                body,
                email["from"],
                email["to"],
            )
    def handle(self, *args, **options):
        super(Command, self).handle(*args, **options)

        m_donations = MonthlyDonation.objects.filter(
            enabled=True,
            monthly_donation_day=now().date().day,
            # This is a safety to account for timezones. We want to be very
            # careful that we don't double-bill people right when they sign up,
            # so this ensures that we don't bill anybody except when the
            # recurring donation is more than 15 days old.
            date_created__lt=now() - timedelta(days=15),
        ).order_by('-date_created')

        results = {'amount': 0, 'users': []}
        for m_donation in m_donations:
            try:
                response = process_stripe_payment(
                    # Stripe rejects the charge if there are decimals;
                    # cast to int.
                    int(m_donation.monthly_donation_amount * 100),
                    m_donation.donor.email,
                    {'customer': m_donation.stripe_customer_id,
                     'metadata': {'recurring': True,
                                  'type': PAYMENT_TYPES.DONATION}},
                    reverse('donate_complete'),
                )
            except PaymentFailureException as e:
                m_donation.failure_count += 1
                if m_donation.failure_count == subscription_failure_threshold:
                    m_donation.enabled = False
                    send_failed_subscription_email(m_donation)

                email = emails['admin_bad_subscription']
                body = email['body'] % (m_donation.pk, e.message)
                send_mail(email['subject'], body, email['from'],
                          email['to'])
                m_donation.save()
                continue

            if response.get('status') == Donation.AWAITING_PAYMENT:
                # It worked. Create a donation in our system as well.
                results['amount'] += m_donation.monthly_donation_amount
                results['users'].append(' - %s %s (%s): $%s' % (
                    m_donation.donor.first_name,
                    m_donation.donor.last_name,
                    m_donation.donor.email,
                    m_donation.monthly_donation_amount,
                ))
                Donation.objects.create(
                    donor=m_donation.donor,
                    amount=m_donation.monthly_donation_amount,
                    payment_provider=m_donation.payment_provider,
                    status=response['status'],
                    payment_id=response['payment_id'],
                    # Only applies to PayPal
                    transaction_id=response.get('transaction_id'),
                    referrer='monthly_donation_%s' % m_donation.pk,
                )
                # Thank you email is triggered later when the stripe callback
                # is triggered.

        if results['users']:
            email = emails['admin_donation_report']
            body = email['body'] % (results['amount'],
                                    '\n'.join(results['users']))
            send_mail(email['subject'] % results['amount'], body,
                      email['from'], email['to'])