GoodCloud / django-zebra

Forms, widgets, template tags and examples that make Stripe + Django easier.
MIT License
193 stars 68 forks source link

Update Zebra to handle Stripe's new webhooks. #10

Closed sivy closed 12 years ago

sivy commented 12 years ago

Stripe recently updated their webhooks[1] such that they send a webhook post for many different events[2]. I've written an implementation of these new webhooks for Zebra.

I've maintained backwards compatibility so that anyone using the old webhook system can continue to do so until it's retired. The new webhooks view defaults to /zebra/webhooks2/.

zebra.signals contains the new signals, and also provides a WEBHOOKS_MAP structure that maps events keys to signals. When an event arrives from Stripe, the json structure has a key in it called "type", that is now a dot-delimited name, following the 'resource'.'event' scheme. So invoice_ready is now invoice.created. The new webhooks2 endpoint first converts invoice.created to invoice_created then uses this map to lookup the correct signal:

    event_json = simplejson.loads(request.raw_post_data)
    event_key = event_json['type'].replace('.', '_')

    if event_key in WEBHOOK_MAP:
        WEBHOOK_MAP[event_key].send( sender=None, 
            full_json=event_json )

In the app using Zebra, this map can also be used to connect webhooks:

from zebra.signals import *

def webhook_logger(sender, full_json, **kwargs):
    log.info ('STRIPE EVENT: %s DATA: \n%s' % (full_json['type'], repr(full_json)))

zebra_webhook_invoice_created.connect(webhook_logger)
# same thing
WEBHOOK_MAP['invoice_created'].connect(webhook_logger)

I'm not married to the implementation, but it seemed clean and it's working. Would love to hear your thoughts!

--Steve

[1] https://stripe.com/blog/webhooks [2] https://stripe.com/docs/api#event_types

skoczen commented 12 years ago

Hey Steve,

This looks great at first glance - this weekend's a bit crazy for me, but I'll hopefully have time to do a deep dive and merge it in tomorrow.

Thanks for the pull!

-Steven

skoczen commented 12 years ago

Steve,

So sorry this took me so long to get to. Your implementation looks great.

One minor change I'd love to see before merging this in - can you change it from webhooks2 to webhooks/v2/ (also webhooks2 -> webhooks_v2, etc)?

I expect v3 will happen some day, and having a naming scheme that shows that clearly would be ideal.

Other than that, this looks fantastic - I'll merge it in right away with the changes!

Thanks for all your help and patience!

-Steven

sivy commented 12 years ago

Steve:

Done! Check it out and let me know if this works for you.

sivy commented 12 years ago

One thing to note:

Signal handlers must now do their own work in finding the relevant objects, for example, the customer object, since that data is stored differently for different webhook calls from Stripe. It's a pain, and I suppose we could lean on Stripe to be more consistent, but for now we're just passing in the JSON struct that Stripe sends us.

skoczen commented 12 years ago

Hi Steve,

Thanks for the quick update - looks great, merging now!

As far as the signal handlers - I think that's fine. Our goal here is to provide an easy interface to hook into Stripe, and do it as flexibly as possible. Simply passing the JSON back and keeping it magic-free is the right approach in my mind.

Thanks for your work on this! I'm adding you to the AUTHORS file - if you'd like accreditation/links differently, feel free to send those as a pull.

-S