diff options
-rw-r--r-- | stripe/_stripe_client.py | 2 | ||||
-rw-r--r-- | stripe/v2/_event.py | 47 | ||||
-rw-r--r-- | tests/test_v2_event.py | 27 |
3 files changed, 62 insertions, 14 deletions
diff --git a/stripe/_stripe_client.py b/stripe/_stripe_client.py index 17f126d8..d3e1284b 100644 --- a/stripe/_stripe_client.py +++ b/stripe/_stripe_client.py @@ -276,7 +276,7 @@ class StripeClient(object): WebhookSignature.verify_header(payload, sig_header, secret, tolerance) - return json.loads(payload) + return ThinEvent(payload) def parse_snapshot_event( self, diff --git a/stripe/v2/_event.py b/stripe/v2/_event.py index 471d7ed5..2abb588d 100644 --- a/stripe/v2/_event.py +++ b/stripe/v2/_event.py @@ -1,8 +1,9 @@ # -*- coding: utf-8 -*- +import json from typing import ClassVar, Optional -from typing_extensions import Literal, TypedDict +from typing_extensions import Literal from stripe._stripe_object import StripeObject @@ -69,25 +70,55 @@ class Event(StripeObject): # The end of the section generated from our OpenAPI spec -class Reason(TypedDict): +class Reason: id: str idempotency_key: str + def __init__(self, d) -> None: + self.id = d["id"] + self.idempotency_key = d["idempotency_key"] -class RelatedObject(TypedDict): + def __repr__(self) -> str: + return f"<Reason id={self.id} idempotency_key={self.idempotency_key}>" + + +class RelatedObject: id: str type: str url: str + def __init__(self, d) -> None: + self.id = d["id"] + self.type_ = d["type"] + self.url = d["url"] + + def __repr__(self) -> str: + return f"<RelatedObject id={self.id} type={self.type_} url={self.url}>" -class ThinEvent(TypedDict): + +class ThinEvent: """ - ThinEvent represents the json that's delivered from an Event Destination. It's a basic `dict` with no additional methods or properties. Use it to check basic information about a delivered event. If you want more details, use `stripe.v2.Event.retrieve(thin_event["id"])` to fetch the full event object. + ThinEvent represents the json that's delivered from an Event Destination. It's a basic `dict` with no additional methods or properties. Use it to check basic information about a delivered event. If you want more details, use `stripe.v2.Event.retrieve(thin_event.id)` to fetch the full event object. """ id: str type: str created: str - context: Optional[str] - related_object: Optional[RelatedObject] - reason: Optional[Reason] + context: Optional[str] = None + related_object: Optional[RelatedObject] = None + reason: Optional[Reason] = None + + def __init__(self, payload: str) -> None: + parsed = json.loads(payload) + + self.id = parsed["id"] + self.type = parsed["type"] + self.created = parsed["created"] + self.context = parsed.get("context") + if parsed.get("related_object"): + self.related_object = RelatedObject(parsed["related_object"]) + if parsed.get("reason"): + self.reason = Reason(parsed["reason"]) + + def __repr__(self) -> str: + return f"<ThinEvent id={self.id} type={self.type} created={self.created} context={self.context} related_object={self.related_object} reason={self.reason}>" diff --git a/tests/test_v2_event.py b/tests/test_v2_event.py index f0fbd2fa..cfc94cf0 100644 --- a/tests/test_v2_event.py +++ b/tests/test_v2_event.py @@ -4,7 +4,6 @@ from typing import Callable import pytest import stripe -from stripe._stripe_object import StripeObject from stripe import ThinEvent from tests.test_webhook import DUMMY_WEBHOOK_SECRET, generate_header @@ -26,6 +25,10 @@ class TestV2Event(object): "url": "/v2/financial_accounts/fa_123", "stripe_context": "acct_123", }, + "reason": { + "id": "foo", + "idempotency_key": "bar", + }, } ) @@ -75,14 +78,28 @@ class TestV2Event(object): return _parse_thin_event - def test_parses_v2_event( + def test_parses_thin_event( self, parse_thin_event: EventParser, v2_payload_no_data: str ): event = parse_thin_event(v2_payload_no_data) - # parse event returns a plain dict - assert not isinstance(event, StripeObject) - assert event == json.loads(v2_payload_no_data) + assert isinstance(event, ThinEvent) + assert event.id == "evt_234" + + assert event.related_object + assert event.related_object.id == "fa_123" + + assert event.reason + assert event.reason.id == "foo" + + def test_parses_thin_event_with_data( + self, parse_thin_event: EventParser, v2_payload_with_data: str + ): + event = parse_thin_event(v2_payload_with_data) + + assert isinstance(event, ThinEvent) + assert not hasattr(event, "data") + assert event.reason is None def test_validates_signature( self, stripe_client: stripe.StripeClient, v2_payload_no_data |