Skip to main content

Zebra is a library that makes using Stripe with Django even easier.

Quagga is a fork of the original Django Zebra library. See the note on compatibility below.

https://github.com/bennylope/django-quagga/raw/master/quagga.jpg

It’s made of:

  • zebra, the core library, with forms, webhook handlers, abstract models, mixins, signals, and templatetags that cover most stripe implementations.

  • marty, an example app for how to integrate zebra, that also serves as its test suite.

Pull requests are quite welcome!

Note (2016): this fork is maintained solely to maintain compatability between existing functionality and current versions of Django.

Usage

Installation

  1. pip install django-quagga

  2. Edit your settings.py:

    INSTALLED_APPS += ("zebra",)
    STRIPE_SECRET = "YOUR-SECRET-API-KEY"
    STRIPE_PUBLISHABLE = "YOUR-PUBLISHABLE-API-KEY"
    # Set any optional settings (below)
  3. (optional) ./manage.py migrate if you have ZEBRA_ENABLE_APP = True

  4. (optional) Add in the webhook urls:

    urlpatterns += [
        url(r'zebra/', include('zebra.urls',  namespace="zebra",  app_name='zebra')),
    ]
  5. Enjoy easy billing.

Optional Settings

  • ZEBRA_ENABLE_APP

    Defaults to False. Enables Customer, Plan, and Subscription django models, as a part of zebra.

  • ZEBRA_CUSTOMER_MODEL

    The app+model string for the model that implements the StripeCustomerMixin. ie “myapp.MyCustomer”. If ZEBRA_ENABLE_APP is true, defaults to “zebra.Customer”.

  • ZEBRA_AUTO_CREATE_STRIPE_CUSTOMERS

    Defaults to True. Automatically creates a stripe customer object on stripe_customer access, if one doesn’t exist.

Webhooks

Zebra handles all the webhooks that stripe sends back and calls a set of signals that you can plug your app into. To use the webhooks:

Note: The initial Stripe webhook system is being deprecated. See below for a description of Zebra’s support for the new system.

Zebra provides:

  • zebra_webhook_recurring_payment_failed

  • zebra_webhook_invoice_ready

  • zebra_webhook_recurring_payment_succeeded

  • zebra_webhook_subscription_trial_ending

  • zebra_webhook_subscription_final_payment_attempt_failed

All of the webhooks provide the same arguments:

  • customer - if ZEBRA_CUSTOMER_MODEL is set, returns an instance that matches the stripe_customer_id, or None. If ZEBRA_CUSTOMER_MODEL is not set, returns None.

  • full_json - the full json response, parsed with simplejson.

So, for example, to update the customer’s new billing date after a successful payment, you could:

(assuming you’ve set ZEBRA_CUSTOMER_MODEL or are using ZEBRA_ENABLE_APP):

from zebra.signals import zebra_webhook_recurring_payment_succeeded

def update_last_invoice_date(sender, **kwargs):
    customer = kwargs.pop("customer", None)
    full_json = kwargs.pop("full_json", None)
    customer.billing_date = full_json.date
    customer.save()

zebra_webhook_recurring_payment_succeeded.connect(update_last_invoice_date)

Webhooks Update

Stripe recently updated their webhook implementation (see https://stripe.com/blog/webhooks). Zebra includes an implementation of the new system.

Zebra provides:

  • zebra_webhook_charge_succeeded

  • zebra_webhook_charge_failed

  • zebra_webhook_charge_refunded

  • zebra_webhook_charge_disputed

  • zebra_webhook_customer_created

  • zebra_webhook_customer_updated

  • zebra_webhook_customer_deleted

  • zebra_webhook_customer_subscription_created

  • zebra_webhook_customer_subscription_updated

  • zebra_webhook_customer_subscription_deleted

  • zebra_webhook_customer_subscription_trial_will_end

  • zebra_webhook_customer_discount_created

  • zebra_webhook_customer_discount_updated

  • zebra_webhook_customer_discount_deleted

  • zebra_webhook_invoice_created

  • zebra_webhook_invoice_updated

  • zebra_webhook_invoice_payment_succeeded

  • zebra_webhook_invoice_payment_failed

  • zebra_webhook_invoiceitem_created

  • zebra_webhook_invoiceitem_updated

  • zebra_webhook_invoiceitem_deleted

  • zebra_webhook_plan_created

  • zebra_webhook_plan_updated

  • zebra_webhook_plan_deleted

  • zebra_webhook_coupon_created

  • zebra_webhook_coupon_updated

  • zebra_webhook_coupon_deleted

  • zebra_webhook_transfer_created

  • zebra_webhook_transfer_failed

  • zebra_webhook_ping

Zebra also provides an easy map of all the signals as zebra.signals.WEBHOOK_MAP, which maps events (charge_succeeded) to the Zebra signal (zebra_webhook_charge_succeeded). To assign a handler to all the signals that zebra sends, for example, loop over the items in the map:

for event_key, webhook_signal in WEBHOOK_MAP.items():
    webhook_signal.connect(webhook_logger)

Forms

The StripePaymentForm sets up a form with fields like [the official stripe example](https://gist.github.com/1204718#file_stripe_tutorial_page.html).

In particular, the form is stripped of the name attribute for any of the credit card fields, to prevent accidental submission. Media is also provided to set up stripe.js (it assumes you have jQuery).

Use it in a view like so:

if request.method == 'POST':
    zebra_form = StripePaymentForm(request.POST)
    if zebra_form.is_valid():
        my_profile = request.user.get_profile()
        stripe_customer = stripe.Customer.retrieve(my_profile.stripe_customer_id)
        stripe_customer.card = zebra_form.cleaned_data['stripe_token']
        stripe_customer.save()

        my_profile.last_4_digits = zebra_form.cleaned_data['last_4_digits']
        my_profile.stripe_customer_id = stripe_customer.id
        my_profile.save()

        # Do something kind for the user

else:
    zebra_form = StripePaymentForm()

Template Tags

There are a couple of template tags that take care of setting up the stripe env, and rendering a basic cc update form. Note that it’s expected your StripePaymentForm is called either zebra_form or form.

To use in a template:

{% extends "base.html" %}{% load zebra_tags %}

{% block head %}{{block.super}}
    {% zebra_head_and_stripe_key %}
{% endblock %}

{% block content %}
    {% zebra_card_form %}
{% endblock %}

That’s it - all the stripe tokeny goodness happens, and errors are displayed to your users.

Models and Mixins

Model and Mixin docs coming. For now, the code is pretty self-explanatory, and decently documented inline.

Other Useful Bits

Zebra comes with a manage.py command to clear out all the test customers from your account.

To use it, run:

./manage.py clear_stripe_test_customers

It responds to –verbosity=[0-3].

Credits

I did not write any of stripe. It just makes me happy to use, and inspired to make better APIs for my users. For Stripe info, ask them: [stripe.com](http://stripe.com)

Code credits are in the AUTHORS file. Pull requests welcome!

History

0.6.1

Fix some Python3 compatability issue.

0.6.0

Add working logging into webhooks.

0.5.0

Introduction of django-quagga, a semi-updated version of the original django-zebra designed to [mostly] work with up-to-date Django.

0.4.5

The last public release of django-zebra.

Metadata

Release files for django-quagga 0.6.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-quagga 0.6.1
File Size Uploaded Provenance
django-quagga-0.6.1.tar.gz 18.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for django-quagga 0.6.1
File Interpreter ABI Platform
django_quagga-0.6.1-py2.py3-none-any.whl Python 3, Python 2 none any Details

Total release size: 44.6 kB

Release files / django-quagga-0.6.1.tar.gz

Download URL django-quagga-0.6.1.tar.gz
Size 18.6 kB
Tags Source
SHA-256 checksum
How to use checksums
18f0fce3c3a3dc8178cff7c201e4adab2a1251ee799e6b88ac1e9064b5926740
BLAKE2b-256 checksum
How to use checksums
99989e09c6939288b0b381089401775c59d2a519100675e9c2c07955971e2476
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.10.0 pkginfo/1.4.1 requests/2.18.4 setuptools/36.2.7 requests-toolbelt/0.8.0 tqdm/4.15.0 CPython/3.6.2

Release files / django_quagga-0.6.1-py2.py3-none-any.whl

Download URL django_quagga-0.6.1-py2.py3-none-any.whl
Size 26.0 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
b4c5ea3905254f6a60e9a9f876e6720b78e760ae40a8bcddba56300e6a779eb8
BLAKE2b-256 checksum
How to use checksums
f71f8cd67a27af2cbd8bd73ad002dd2e3af0d773a70981008476824d2493c6c8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.10.0 pkginfo/1.4.1 requests/2.18.4 setuptools/36.2.7 requests-toolbelt/0.8.0 tqdm/4.15.0 CPython/3.6.2

Security for django-quagga 0.6.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page