From 086d7381a0a6fc0b1d1c9275fbf429fb064a8064 Mon Sep 17 00:00:00 2001 From: ag84ark Date: Tue, 26 May 2026 19:21:56 +0200 Subject: [PATCH] feat: add createdAt and testmode fields to webhook event --- docs/Webhooks.md | 1 + src/API/Resources/WebhookEvent.php | 7 +++++++ src/API/Webhooks/Webhook.php | 4 +++- src/API/Webhooks/WebhookPayload.php | 11 +++++++++++ tests/Webhooks/WebhookTest.php | 9 ++++++++- 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/docs/Webhooks.md b/docs/Webhooks.md index 852ac4c..ab83bb9 100644 --- a/docs/Webhooks.md +++ b/docs/Webhooks.md @@ -39,6 +39,7 @@ The SDK provides a helper to parse and verify incoming webhooks. | `entityId` | `string` | ID of the resource this event relates to. | | `object` | `object\|null` | The full resource payload at the time of the event. | | `createdAt` | `string\|null` | When the event occurred (ISO 8601). | +| `testmode` | `bool` | Whether this event was generated in test mode. | diff --git a/src/API/Resources/WebhookEvent.php b/src/API/Resources/WebhookEvent.php index 3dee113..83380d5 100644 --- a/src/API/Resources/WebhookEvent.php +++ b/src/API/Resources/WebhookEvent.php @@ -47,5 +47,12 @@ class WebhookEvent extends BaseResource */ public $object = null; + /** + * @example 2023-08-11T10:48:51+02:00 + */ + public string $createdAt; + + public bool $testmode; + public WebhookEventLinks $links; } diff --git a/src/API/Webhooks/Webhook.php b/src/API/Webhooks/Webhook.php index 1205266..c6f274f 100644 --- a/src/API/Webhooks/Webhook.php +++ b/src/API/Webhooks/Webhook.php @@ -35,7 +35,7 @@ public static function parse(string $payload, string $signature, string $secret) ); } - foreach (['id', 'resource', 'eventName', 'entityType', 'entityId'] as $field) { + foreach (['id', 'resource', 'eventName', 'entityType', 'entityId', 'createdAt', 'testmode'] as $field) { if (! isset($decoded->{$field})) { throw new \InvalidArgumentException( "Webhook payload is missing required field: {$field}" @@ -56,6 +56,8 @@ public static function parse(string $payload, string $signature, string $secret) $decoded->eventName, $decoded->entityType, $decoded->entityId, + $decoded->testmode, + $decoded->createdAt, $object, ); } diff --git a/src/API/Webhooks/WebhookPayload.php b/src/API/Webhooks/WebhookPayload.php index 977aa82..108a6d0 100644 --- a/src/API/Webhooks/WebhookPayload.php +++ b/src/API/Webhooks/WebhookPayload.php @@ -54,12 +54,21 @@ class WebhookPayload */ public ?object $object; + /** + * @example 2023-08-11T10:48:51+02:00 + */ + public string $createdAt; + + public bool $testmode; + public function __construct( string $id, string $resource, string $eventName, string $entityType, string $entityId, + bool $testmode, + string $createdAt, ?object $object = null, ) { $this->id = $id; @@ -68,5 +77,7 @@ public function __construct( $this->entityType = $entityType; $this->entityId = $entityId; $this->object = $object; + $this->testmode = $testmode; + $this->createdAt = $createdAt; } } diff --git a/tests/Webhooks/WebhookTest.php b/tests/Webhooks/WebhookTest.php index df6e1a5..6e6605b 100644 --- a/tests/Webhooks/WebhookTest.php +++ b/tests/Webhooks/WebhookTest.php @@ -23,6 +23,8 @@ private function makePayload(array $overrides = []): string 'entityType' => 'order', 'entityId' => 'order_Hn5xWqVfKm8RjTgYbUcP', 'object' => ['id' => 'order_Hn5xWqVfKm8RjTgYbUcP', 'resource' => 'order'], + 'createdAt' => '2023-01-11T10:50:50+02:00', + 'testmode' => true, ], $overrides); return json_encode($data); @@ -48,9 +50,12 @@ public function test_it_parses_a_valid_webhook(): void $this->assertSame('order_Hn5xWqVfKm8RjTgYbUcP', $event->entityId); $this->assertIsObject($event->object); $this->assertSame('order_Hn5xWqVfKm8RjTgYbUcP', $event->object->id); + $this->assertSame('order', $event->object->resource); + $this->assertTrue($event->testmode); + $this->assertSame('2023-01-11T10:50:50+02:00', $event->createdAt); } - public function test_it_parses_a_webhook_without_object_and_created_at(): void + public function test_it_parses_a_webhook_without_object(): void { $data = [ 'id' => 'webhook_event_Qk8pRtSvWm2NjLhYcZaE', @@ -58,6 +63,8 @@ public function test_it_parses_a_webhook_without_object_and_created_at(): void 'eventName' => 'order.paid', 'entityType' => 'order', 'entityId' => 'order_Hn5xWqVfKm8RjTgYbUcP', + 'createdAt' => '2023-01-11T10:50:50+02:00', + 'testmode' => true, ]; $payload = json_encode($data); $signature = $this->sign($payload);