From 9b20d71d38b2d4183881734c3e96ded1071933c6 Mon Sep 17 00:00:00 2001 From: Michal Proszek Date: Thu, 24 Aug 2017 16:10:37 +0200 Subject: [PATCH] RO-1090 - [BE] add webhook_pre_parse signal --- aa_stripe/models.py | 15 ++++++++++++++- tests/test_webhooks.py | 37 ++++++++++++++++++++++++++++++++----- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/aa_stripe/models.py b/aa_stripe/models.py index cfe45f4..6683ffd 100644 --- a/aa_stripe/models.py +++ b/aa_stripe/models.py @@ -4,6 +4,7 @@ import simplejson as json import stripe +from django import dispatch from django.conf import settings from django.contrib.contenttypes import fields as generic from django.contrib.contenttypes.models import ContentType @@ -17,6 +18,9 @@ USER_MODEL = getattr(settings, "STRIPE_USER_MODEL", settings.AUTH_USER_MODEL) +# signals +webhook_pre_parse = dispatch.Signal(providing_args=["instance", "event_type", "event_model", "event_action"]) + class StripeBasicModel(models.Model): created = models.DateTimeField(auto_now_add=True) @@ -424,8 +428,17 @@ def parse(self, save=False): raise StripeWebhookAlreadyParsed event_type = self.raw_data.get("type") - if "." in event_type: + try: event_model, event_action = event_type.rsplit(".", 1) + except ValueError: + event_model, event_action = None, None + + webhook_pre_parse.send( + sender=self.__class__, instance=self, event_type=event_type, event_model=event_model, + event_action=event_action) + + # parse + if event_model: if event_model == "coupon": self._parse_coupon_notification(event_action) diff --git a/tests/test_webhooks.py b/tests/test_webhooks.py index b70e6e7..4b263b9 100644 --- a/tests/test_webhooks.py +++ b/tests/test_webhooks.py @@ -1,3 +1,4 @@ +import mock import requests_mock import simplejson as json from rest_framework.reverse import reverse @@ -271,10 +272,15 @@ def test_coupon_delete(self): url = reverse("stripe-webhooks") self.client.credentials(**self._get_signature_headers(payload)) - response = self.client.post(url, data=payload, format="json") - coupon.refresh_from_db() - self.assertEqual(response.status_code, 201) - self.assertTrue(coupon.is_deleted) + with mock.patch("aa_stripe.models.webhook_pre_parse.send") as mocked_signal: + response = self.client.post(url, data=payload, format="json") + coupon.refresh_from_db() + self.assertEqual(response.status_code, 201) + self.assertTrue(coupon.is_deleted) + webhook = StripeWebhook.objects.first() + self.assertTrue(webhook.is_parsed) + mocked_signal.assert_called_with(event_action="deleted", event_model="coupon", event_type="coupon.deleted", + instance=webhook, sender=StripeWebhook) # test deleting event that has already been deleted - should not raise any errors # it will just make sure is_deleted is set for this coupon @@ -287,7 +293,28 @@ def test_coupon_delete(self): self.assertTrue(coupon.is_deleted) # make sure trying to parse already parsed webhook is impossible - webhook = StripeWebhook.objects.first() self.assertTrue(webhook.is_parsed) with self.assertRaises(StripeWebhookAlreadyParsed): webhook.parse() + + # test receiving ping event (the only event without "." inside the event name) + StripeWebhook.objects.all().delete() + payload = json.loads("""{ + "id": "evt_1Atthtasdsaf6pRwkdLOhKls", + "object": "event", + "api_version": "2017-06-05", + "created": 1503474921, + "livemode": false, + "pending_webhooks": 1, + "request": { + "id": "req_9UO71nsJyzhQfi", + "idempotency_key": null + }, + "type": "ping" + }""") + self.client.credentials(**self._get_signature_headers(payload)) + with mock.patch("aa_stripe.models.webhook_pre_parse.send") as mocked_signal: + response = self.client.post(url, data=payload, format="json") + self.assertEqual(response.status_code, 201) + mocked_signal.assert_called_with(event_action=None, event_model=None, event_type="ping", + instance=StripeWebhook.objects.first(), sender=StripeWebhook)