diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index f34af0d..4caf803 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -10,7 +10,7 @@ jobs: strategy: fail-fast: true matrix: - php: [7.4, 8.0, 8.1] + php: [8.1, 8.2, 8.3, 8.4] name: Tests on PHP ${{ matrix.php }} - ${{ matrix.stability }} diff --git a/.gitignore b/.gitignore index b1f7502..a201441 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ composer.phar .phpunit.result.cache composer.lock .php-cs-fixer.cache -.idea/ \ No newline at end of file +.idea/ +.phpunit.cache \ No newline at end of file diff --git a/README.md b/README.md index d9a28d1..505dcb3 100644 --- a/README.md +++ b/README.md @@ -503,6 +503,112 @@ $whatsapp_cloud_api->updateBusinessProfile([ ]); ``` +### Create a Template +```php + 'your-configured-from-phone-number-id', + 'access_token' => 'your-facebook-whatsapp-application-token', + 'business_id' => 'your-business-id', +]); + +$whatsapp->createTemplate( + 'seasonal_promotion', + 'MARKETING', // UTILITY | MARKETING | AUTHENTICATION + 'en_US', + [ + [ + 'type' => 'HEADER', + 'format' => 'TEXT', + 'text' => 'Our {{1}} is on!', + 'example' => [ + 'header_text' => ['Summer Sale'] + ] + ], + [ + 'type' => 'BODY', + 'text' => 'Shop now through {{1}} and use code {{2}} to get {{3}} off of all merchandise.', + 'example' => [ + 'body_text' => [[ 'the end of August', '25OFF', '25%' ]] + ] + ], + [ + 'type' => 'FOOTER', + 'text' => 'Use the buttons below to manage your marketing subscriptions' + ], + [ + 'type' => 'BUTTONS', + 'buttons' => [ + [ + 'type' => 'QUICK_REPLY', + 'text' => 'Unsubscribe from Promos' + ], + [ + 'type' => 'QUICK_REPLY', + 'text' => 'Unsubscribe from All' + ] + ] + ] + ] +); +``` + +### Update a Template +```php + 'your-configured-from-phone-number-id', + 'access_token' => 'your-facebook-whatsapp-application-token', + 'business_id' => 'your-business-id', +]); + +$template_id = 'your-template-id'; + +// New payload to update the template +$payload = [ + 'category' => 'MARKETING', + 'language' => 'en_US', + 'components' => [ + [ + 'type' => 'HEADER', + 'format' => 'TEXT', + 'text' => 'Hello {{1}} is live now!', + 'example' => [ + 'header_text' => ['Flash Sale'] + ] + ], + [ + 'type' => 'BODY', + 'text' => 'Buy now before {{1}} ends. Use code {{2}} to get {{3}} off!', + 'example' => [ + 'body_text' => [['midnight', 'FLASH20', '20%']] + ] + ], + [ + 'type' => 'FOOTER', + 'text' => 'Tap below to shop.' + ], + [ + 'type' => 'BUTTONS', + 'buttons' => [ + [ + 'type' => 'QUICK_REPLY', + 'text' => 'Show Me Deals' + ], + [ + 'type' => 'QUICK_REPLY', + 'text' => 'Stop Promotions' + ] + ] + ] + ] +]; + +$whatsapp->updateTemplateById($template_id, $payload); +``` + Fields list: https://developers.facebook.com/docs/whatsapp/cloud-api/reference/business-profiles ## Features @@ -528,6 +634,8 @@ Fields list: https://developers.facebook.com/docs/whatsapp/cloud-api/reference/b - Get/Update Business Profile - Webhook verification - Webhook notifications +- Create Template +- Update Template ## Getting Help - Ask a question on the [Discussions forum](https://github.com/netflie/whatsapp-cloud-api/discussions "Discussions forum") diff --git a/UPGRADE.md b/UPGRADE.md index 6200c99..7993d28 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,7 +1,132 @@ -# Upgrade to v2 +# Upgrade Guide All instructions to upgrade this project from one major version to the next will be documented in this file. Upgrades must be run sequentially, meaning you should not skip major releases while upgrading (fix releases can be skipped). +## 2.x to 3.x + +### PHP version requirement + +PHP 7.4 and PHP 8.0 are no longer supported. The minimum required PHP version is now **PHP 8.1**. Update your environment accordingly before upgrading. + +### `MessageNotificationFactory` is now `final` + +`Netflie\WhatsAppCloudApi\WebHook\Notification\MessageNotificationFactory` has been marked as `final`. If you have extended this class, you must refactor your code to use composition instead of inheritance. + +### `Media` constructor signature changed + +A new required `MediaType $type` parameter has been added to the `Media` constructor. If you are instantiating `Netflie\WhatsAppCloudApi\WebHook\Notification\Media` directly, you must pass a `Netflie\WhatsAppCloudApi\Message\Media\MediaType` instance as the eighth argument (before `$received_at_timestamp`). + +Before: +```php +new Media($id, $business, $image_id, $mime_type, $sha256, $filename, $caption, $received_at_timestamp); +``` + +After: +```php +use Netflie\WhatsAppCloudApi\Message\Media\MediaType; + +new Media($id, $business, $image_id, $mime_type, $sha256, $filename, $caption, new MediaType('image'), $received_at_timestamp); +``` + +### `Context` constructor signature changed + +A new `bool $frequently_forwarded` parameter has been added to the `Context` constructor between `$forwarded` and `$referred_product`. If you are instantiating `Netflie\WhatsAppCloudApi\WebHook\Notification\Support\Context` directly, update your call accordingly. + +Before: +```php +new Context($replying_to_message_id, $forwarded, $referred_product); +``` + +After: +```php +new Context($replying_to_message_id, $forwarded, $frequently_forwarded, $referred_product); +``` + +### `Referral` constructor signature changed + +A new required `string $ctwa_clid` parameter has been appended to the `Referral` constructor. If you are instantiating `Netflie\WhatsAppCloudApi\WebHook\Notification\Support\Referral` directly, pass the Click to WhatsApp click ID as the last argument. + +Before: +```php +new Referral($source_id, $source_url, $source_type, $headline, $body, $media_type, $media_url, $thumbnail_url); +``` + +After: +```php +new Referral($source_id, $source_url, $source_type, $headline, $body, $media_type, $media_url, $thumbnail_url, $ctwa_clid); +``` + +### New features + +The following new features are available in 3.x: + +#### Send Single Product Message + +```php +$whatsapp_cloud_api->sendSingleProduct( + '', + '', + '', + 'Optional body text', + 'Optional footer text' +); +``` + +#### Create and Update Templates + +Template management now requires a `business_id` in the `WhatsAppCloudApi` constructor: + +```php +$whatsapp = new WhatsAppCloudApi([ + 'from_phone_number_id' => 'your-phone-number-id', + 'access_token' => 'your-access-token', + 'business_id' => 'your-business-id', +]); + +// Create a template +$whatsapp->createTemplate('template_name', 'MARKETING', 'en_US', $components); + +// Update a template by ID +$whatsapp->updateTemplateById('', $payload); +``` + +#### Frequently forwarded messages + +`MessageNotification` and `Context` now expose an `isFrequentlyForwarded()` method: + +```php +$notification->isFrequentlyForwarded(); +$notification->context()->isFrequentlyForwarded(); +``` + +#### Media type in Webhook notifications + +`Media` notifications now expose the media type via `type()`, which returns a `MediaType` enum value: + +```php +$notification->type(); // returns a MediaType enum instance +``` + +#### Click to WhatsApp click ID in Referral + +`Referral` now exposes the `ctwaClid()` method: + +```php +$notification->referral()->ctwaClid(); +``` + +#### `VerificationRequest` response code + +`VerificationRequest::verify()` no longer calls `http_response_code()` when headers have already been sent. You can now read the resulting HTTP status code via the new `responseCode()` method: + +```php +$verificationRequest = new VerificationRequest($verify_token); +$challenge = $verificationRequest->verify($payload); +$code = $verificationRequest->responseCode(); // 200 or 403 +``` + +--- + ## 1.x to 2.x # Final classes diff --git a/composer.json b/composer.json index a32e80d..7b61dd6 100644 --- a/composer.json +++ b/composer.json @@ -14,13 +14,13 @@ ], "license": "MIT", "require": { - "php": "^7.4 || ^8.0 || ^8.1", + "php": ">=8.1", "guzzlehttp/guzzle": "^7.0", "vlucas/phpdotenv": "^5.4", "myclabs/php-enum": "^1.8" }, "require-dev": { - "phpunit/phpunit": "^9.0", + "phpunit/phpunit": ">=10.0", "symfony/var-dumper": "^5.0", "phpspec/prophecy-phpunit": "^2.0", "fakerphp/faker": "^1.19", @@ -38,7 +38,7 @@ } }, "scripts": { - "unit-test": "vendor/bin/phpunit --group unit", - "integration-test": "vendor/bin/phpunit --group integration" + "unit-test": "vendor/bin/phpunit --testsuite unit", + "integration-test": "vendor/bin/phpunit --testsuite integration" } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 79355f1..172707a 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,10 +1,5 @@ - - - - src/ - - + tests/Unit @@ -16,4 +11,9 @@ - \ No newline at end of file + + + src/ + + + diff --git a/src/Client.php b/src/Client.php index 05c2a96..667ac5b 100644 --- a/src/Client.php +++ b/src/Client.php @@ -4,6 +4,8 @@ use Netflie\WhatsAppCloudApi\Http\ClientHandler; use Netflie\WhatsAppCloudApi\Http\GuzzleClientHandler; +use Netflie\WhatsAppCloudApi\Request\TemplateRequest\CreateTemplateRequest; +use Netflie\WhatsAppCloudApi\Request\TemplateRequest\UpdateTemplateRequest; class Client { @@ -191,4 +193,46 @@ private function buildRequestUri(string $node_path): string { return $this->buildBaseUri() . '/' . $node_path; } + + /** + * Handles sending a template request (create/update) and processing the response. + * + * @param object $request The request object with required methods. + * + * @return Response + * + * @throws \Netflie\WhatsAppCloudApi\Response\ResponseException + */ + private function sendTemplateRequest($request): Response + { + $raw_response = $this->handler->postJsonData( + $this->buildRequestUri($request->nodePath()), + $request->body(), + $request->headers(), + $request->timeout() + ); + + $return_response = new Response( + $request, + $raw_response->body(), + $raw_response->httpResponseCode(), + $raw_response->headers() + ); + + if ($return_response->isError()) { + $return_response->throwException(); + } + + return $return_response; + } + + public function createTemplate(CreateTemplateRequest $request): Response + { + return $this->sendTemplateRequest($request); + } + + public function updateTemplate(UpdateTemplateRequest $request): Response + { + return $this->sendTemplateRequest($request); + } } diff --git a/src/Message/Media/MediaType.php b/src/Message/Media/MediaType.php new file mode 100644 index 0000000..2b83cd7 --- /dev/null +++ b/src/Message/Media/MediaType.php @@ -0,0 +1,30 @@ +payload = $payload; + $this->business_id = $business_id; + + parent::__construct($access_token, $timeout); + } + + /** + * Returns the payload to be sent as the request body. + * + * @return array The request body. + */ + public function body(): array + { + return $this->payload; + } + + /** + * Returns the Graph API node path for creating the template. + * + * @return string The URI path segment (e.g., {business_id}/message_templates). + */ + public function nodePath(): string + { + return $this->business_id . '/message_templates'; + } +} diff --git a/src/Request/TemplateRequest/UpdateTemplateRequest.php b/src/Request/TemplateRequest/UpdateTemplateRequest.php new file mode 100644 index 0000000..e450494 --- /dev/null +++ b/src/Request/TemplateRequest/UpdateTemplateRequest.php @@ -0,0 +1,57 @@ +template_id = $template_id; + $this->payload = $payload; + + parent::__construct($access_token, $timeout); + } + + /** + * Returns the payload to be sent as the request body. + * + * @return array The request body. + */ + public function body(): array + { + return $this->payload; + } + + /** + * Returns the Graph API node path for updating the template. + * + * @return string The URI path segment (e.g., template ID). + */ + public function nodePath(): string + { + return $this->template_id; + } +} diff --git a/src/WebHook/Notification/Media.php b/src/WebHook/Notification/Media.php index 77ef4a2..9a57d26 100644 --- a/src/WebHook/Notification/Media.php +++ b/src/WebHook/Notification/Media.php @@ -2,6 +2,8 @@ namespace Netflie\WhatsAppCloudApi\WebHook\Notification; +use Netflie\WhatsAppCloudApi\Message\Media\MediaType; + final class Media extends MessageNotification { private string $image_id; @@ -14,6 +16,8 @@ final class Media extends MessageNotification private string $caption; + private MediaType $type; + public function __construct( string $id, Support\Business $business, @@ -22,6 +26,7 @@ public function __construct( string $sha256, string $filename, string $caption, + MediaType $type, string $received_at_timestamp ) { parent::__construct($id, $business, $received_at_timestamp); @@ -31,6 +36,7 @@ public function __construct( $this->sha256 = $sha256; $this->filename = $filename; $this->caption = $caption; + $this->type = $type; } public function imageId(): string @@ -57,4 +63,9 @@ public function caption(): string { return $this->caption; } + + public function type(): MediaType + { + return $this->type; + } } diff --git a/src/WebHook/Notification/MessageNotification.php b/src/WebHook/Notification/MessageNotification.php index 6919aa5..145adac 100644 --- a/src/WebHook/Notification/MessageNotification.php +++ b/src/WebHook/Notification/MessageNotification.php @@ -35,6 +35,15 @@ public function isForwarded(): bool return $this->context->isForwarded(); } + public function isFrequentlyForwarded(): bool + { + if (!$this->context) { + return false; + } + + return $this->context->isFrequentlyForwarded(); + } + public function context(): ?Support\Context { return $this->context; diff --git a/src/WebHook/Notification/MessageNotificationFactory.php b/src/WebHook/Notification/MessageNotificationFactory.php index 8db65cf..75a4632 100644 --- a/src/WebHook/Notification/MessageNotificationFactory.php +++ b/src/WebHook/Notification/MessageNotificationFactory.php @@ -2,7 +2,9 @@ namespace Netflie\WhatsAppCloudApi\WebHook\Notification; -class MessageNotificationFactory +use Netflie\WhatsAppCloudApi\Message\Media\MediaType; + +final class MessageNotificationFactory { public function buildFromPayload(array $metadata, array $message, array $contact): MessageNotification { @@ -43,6 +45,7 @@ private function buildMessageNotification(array $metadata, array $message): Mess $message[$message['type']]['sha256'], $message[$message['type']]['filename'] ?? '', $message[$message['type']]['caption'] ?? '', + new MediaType($message['type']), $message['timestamp'] ); case 'location': @@ -130,7 +133,7 @@ private function decorateNotification(MessageNotification $notification, array $ if ($contact) { $notification->withCustomer(new Support\Customer( $contact['wa_id'], - $contact['profile']['name'], + $contact['profile']['name'] ?? '', $message['from'] )); } @@ -146,6 +149,7 @@ private function decorateNotification(MessageNotification $notification, array $ $notification->withContext(new Support\Context( $message['context']['id'] ?? null, $message['context']['forwarded'] ?? false, + $message['context']['frequently_forwarded'] ?? false, $referred_product ?? null )); } diff --git a/src/WebHook/Notification/Support/Context.php b/src/WebHook/Notification/Support/Context.php index e254d6e..42ffc86 100644 --- a/src/WebHook/Notification/Support/Context.php +++ b/src/WebHook/Notification/Support/Context.php @@ -8,15 +8,19 @@ final class Context private bool $forwarded; + private bool $frequently_forwarded; + private ?ReferredProduct $referred_product; public function __construct( - string $replying_to_message_id = null, + ?string $replying_to_message_id = null, bool $forwarded = false, - ReferredProduct $referred_product = null + bool $frequently_forwarded = false, + ?ReferredProduct $referred_product = null ) { $this->replying_to_message_id = $replying_to_message_id; $this->forwarded = $forwarded; + $this->frequently_forwarded = $frequently_forwarded; $this->referred_product = $referred_product; } @@ -30,6 +34,11 @@ public function isForwarded(): bool return $this->forwarded; } + public function isFrequentlyForwarded(): bool + { + return $this->frequently_forwarded; + } + public function hasReferredProduct(): bool { return null !== $this->referred_product; diff --git a/src/WebHook/VerificationRequest.php b/src/WebHook/VerificationRequest.php index 1d8b976..56be232 100644 --- a/src/WebHook/VerificationRequest.php +++ b/src/WebHook/VerificationRequest.php @@ -9,6 +9,7 @@ final class VerificationRequest * @link https://developers.facebook.com/docs/graph-api/webhooks/getting-started?locale=en_US#configure-webhooks-product */ protected string $verify_token; + private int $response_code = 200; public function __construct(string $verify_token) { @@ -22,13 +23,27 @@ public function validate(array $payload): string $challenge = $payload['hub_challenge'] ?? ''; if ('subscribe' !== $mode || $token !== $this->verify_token) { - http_response_code(403); + $this->setResponseCode(403); return $challenge; } - http_response_code(200); + $this->setResponseCode(200); return $challenge; } + + public function responseCode(): int + { + return $this->response_code; + } + + private function setResponseCode(int $response_code): void + { + $this->response_code = $response_code; + + if (!headers_sent()) { + http_response_code($response_code); + } + } } diff --git a/src/WhatsAppCloudApi.php b/src/WhatsAppCloudApi.php index 9ee9124..b9b4032 100644 --- a/src/WhatsAppCloudApi.php +++ b/src/WhatsAppCloudApi.php @@ -10,6 +10,7 @@ use Netflie\WhatsAppCloudApi\Message\MultiProduct\Action as MultiProductAction; use Netflie\WhatsAppCloudApi\Message\OptionsList\Action; use Netflie\WhatsAppCloudApi\Message\Template\Component; +use Netflie\WhatsAppCloudApi\Request\TemplateRequest\CreateTemplateRequest; class WhatsAppCloudApi { @@ -609,4 +610,57 @@ public function replyTo(string $message_id): self return $this; } + + /** + * Creates a new WhatsApp message template. + * + * @param string $name The name of the template. + * @param string $category The category of the template (e.g., MARKETING, TRANSACTIONAL). + * @param string $language The language code (e.g., en_US). + * @param array $components Array of template components (header, body, footer, buttons). + * + * @return Response The API response. + * + * @throws \RuntimeException If the template already exists or has conflicting parameters. + * @throws \Netflie\WhatsAppCloudApi\Response\ResponseException For other API errors. + */ + public function createTemplate(string $name, string $category, string $language, array $components): Response + { + $request = new CreateTemplateRequest( + $this->app->accessToken(), + $this->app->businessId(), + [ + 'name' => $name, + 'category' => $category, + 'language' => $language, + 'components' => $components, + ], + $this->timeout + ); + + return $this->client->createTemplate($request); + } + + /** + * Updates an existing WhatsApp message template by ID. + * + * @param string $template_id The ID of the template to update. + * @param array $payload The update payload (components, name, etc.). + * + * @return Response The API response. + * + * @throws \RuntimeException If the template update fails due to conflict or invalid data. + * @throws \Netflie\WhatsAppCloudApi\Response\ResponseException For other API errors. + */ + public function updateTemplateById(string $template_id, array $payload): Response + { + $request = new Request\TemplateRequest\UpdateTemplateRequest( + $this->app->accessToken(), + $template_id, + $payload, + $this->timeout + ); + + return $this->client->updateTemplate($request); + } } diff --git a/tests/Integration/WhatsAppCloudApiTest.php b/tests/Integration/WhatsAppCloudApiTest.php index ea7bb1a..0a24d0d 100644 --- a/tests/Integration/WhatsAppCloudApiTest.php +++ b/tests/Integration/WhatsAppCloudApiTest.php @@ -475,4 +475,40 @@ public function test_update_business_profile() $this->assertEquals(200, $response->httpStatusCode()); $this->assertEquals(false, $response->isError()); } + + public function test_create_template() + { + $name = 'test_template_' . uniqid(); + $category = 'MARKETING'; + $language = 'en_US'; + $components = [ + [ + 'type' => 'BODY', + 'text' => 'Test body', + ], + ]; + + $response = $this->whatsapp_app_cloud_api->createTemplate($name, $category, $language, $components); + + $this->assertInstanceOf(\Netflie\WhatsAppCloudApi\Response::class, $response); + $this->assertFalse($response->isError(), $response->body()); + } + + public function test_update_template_by_id() + { + $templateId = WhatsAppCloudApiTestConfiguration::$template_id; + $payload = [ + 'components' => [ + [ + 'type' => 'BODY', + 'text' => 'Updated body', + ], + ], + ]; + + $response = $this->whatsapp_app_cloud_api->updateTemplateById($templateId, $payload); + + $this->assertInstanceOf(\Netflie\WhatsAppCloudApi\Response::class, $response); + $this->assertFalse($response->isError(), $response->body()); + } } diff --git a/tests/Unit/WebHook/NotificationFactoryTest.php b/tests/Unit/WebHook/NotificationFactoryTest.php index b21e935..32701c4 100644 --- a/tests/Unit/WebHook/NotificationFactoryTest.php +++ b/tests/Unit/WebHook/NotificationFactoryTest.php @@ -2,6 +2,7 @@ namespace Netflie\WhatsAppCloudApi\Tests\Unit\WebHook; +use Netflie\WhatsAppCloudApi\Message\Media\MediaType; use Netflie\WhatsAppCloudApi\WebHook\Notification; use Netflie\WhatsAppCloudApi\WebHook\NotificationFactory; use PHPUnit\Framework\TestCase; @@ -44,6 +45,7 @@ public function test_build_from_payload_can_build_a_notification() "from": "PHONE_NUMBER", "id": "wamid.ID", "forwarded": true, + "frequently_forwarded": true, "referred_product": { "catalog_id": "CATALOG_ID", "product_retailer_id": "PRODUCT_ID" @@ -81,6 +83,7 @@ public function test_build_from_payload_can_build_a_notification() $this->assertEquals('PHONE_NUMBER_ID', $notification->businessPhoneNumberId()); $this->assertEquals('PHONE_NUMBER', $notification->businessPhoneNumber()); $this->assertTrue($notification->isForwarded()); + $this->assertTrue($notification->isFrequentlyForwarded()); $this->assertEquals('WHATSAPP_ID', $notification->customer()->id()); $this->assertEquals('NAME', $notification->customer()->name()); $this->assertEquals('ADID', $notification->referral()->sourceId()); @@ -331,6 +334,7 @@ public function test_build_from_payload_can_build_an_image_notification() $this->assertEquals('IMAGE_HASH', $notification->sha256()); $this->assertEquals('image/jpeg', $notification->mimeType()); $this->assertEquals('CAPTION_TEXT', $notification->caption()); + $this->assertEquals(MediaType::IMAGE(), $notification->type()); } public function test_build_from_payload_can_build_an_document_notification() @@ -379,6 +383,7 @@ public function test_build_from_payload_can_build_an_document_notification() $this->assertEquals('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', $notification->mimeType()); $this->assertEquals('CAPTION_TEXT', $notification->caption()); $this->assertEquals('FILENAME', $notification->filename()); + $this->assertEquals(MediaType::DOCUMENT(), $notification->type()); } public function test_build_from_payload_can_build_a_sticker_notification() @@ -431,6 +436,7 @@ public function test_build_from_payload_can_build_a_sticker_notification() $this->assertEquals('STICKER_ID', $notification->imageId()); $this->assertEquals('STICKER_HASH', $notification->sha256()); $this->assertEquals('image/webp', $notification->mimeType()); + $this->assertEquals(MediaType::STICKER(), $notification->type()); } public function test_build_from_payload_can_build_an_unknown_notification() @@ -1446,4 +1452,41 @@ public function test_build_from_payload_can_build_a_service_status_notification( $this->assertTrue($notification->isMessageDelivered()); $this->assertTrue($notification->isMessageSent()); } + + public function test_build_from_payload_without_contact_profile_can_build_a_notification() + { + $payload = json_decode('{ + "object": "whatsapp_business_account", + "entry": [{ + "id": "WHATSAPP_BUSINESS_ACCOUNT_ID", + "changes": [{ + "value": { + "messaging_product": "whatsapp", + "metadata": { + "display_phone_number": "PHONE_NUMBER", + "phone_number_id": "PHONE_NUMBER_ID" + }, + "contacts": [{ + "wa_id": "PHONE_NUMBER" + }], + "messages": [{ + "from": "PHONE_NUMBER", + "id": "wamid.ID", + "timestamp": "1669233778", + "text": { + "body": "MESSAGE_BODY" + }, + "type": "text" + }] + }, + "field": "messages" + }] + }] + }', true); + + $notification = $this->notification_factory->buildFromPayload($payload); + + $this->assertInstanceOf(Notification\Text::class, $notification); + $this->assertEquals('MESSAGE_BODY', $notification->message()); + } } diff --git a/tests/Unit/WebHook/VerificationRequestTest.php b/tests/Unit/WebHook/VerificationRequestTest.php index 8f0a26f..9adb16e 100644 --- a/tests/Unit/WebHook/VerificationRequestTest.php +++ b/tests/Unit/WebHook/VerificationRequestTest.php @@ -21,7 +21,7 @@ public function test_verification_request_succeeded() ]); $this->assertEquals('challenge_code', $response); - $this->assertEquals(200, http_response_code()); + $this->assertEquals(200, $verification_request->responseCode()); } public function test_verification_request_fails() @@ -35,6 +35,6 @@ public function test_verification_request_fails() ]); $this->assertEquals('challenge_code', $response); - $this->assertEquals(403, http_response_code()); + $this->assertEquals(403, $verification_request->responseCode()); } } diff --git a/tests/Unit/WebHookTest.php b/tests/Unit/WebHookTest.php index a6e2bb2..7d79251 100644 --- a/tests/Unit/WebHookTest.php +++ b/tests/Unit/WebHookTest.php @@ -28,6 +28,5 @@ public function test_verify_a_webhook() ], 'verify-token'); $this->assertEquals('challenge_code', $response); - $this->assertEquals(200, http_response_code()); } } diff --git a/tests/WhatsAppCloudApiTestConfiguration.php.dist b/tests/WhatsAppCloudApiTestConfiguration.php.dist index e91757e..abfdade 100644 --- a/tests/WhatsAppCloudApiTestConfiguration.php.dist +++ b/tests/WhatsAppCloudApiTestConfiguration.php.dist @@ -20,4 +20,6 @@ class WhatsAppCloudApiTestConfiguration { public static $catalog_id = ''; public static $product_sku_id = ''; + public static $template_id = ''; + }