diff --git a/README.md b/README.md index a28abd4..9617a5b 100644 --- a/README.md +++ b/README.md @@ -222,6 +222,25 @@ $whatsapp_cloud_api->sendList( ); ``` +### Send a CTA URL message + +```php +sendCtaUrl( + '', + 'See Dates', + 'https://www.example.com', + $header, + 'Tap the button below to see available dates.', + 'Dates subject to change.', +); +``` + ### Send a button reply message ```php diff --git a/src/Message/CtaUrl/Header.php b/src/Message/CtaUrl/Header.php new file mode 100644 index 0000000..462b035 --- /dev/null +++ b/src/Message/CtaUrl/Header.php @@ -0,0 +1,15 @@ +type = $type; + } + + abstract public function getBody(): array; +} diff --git a/src/Message/CtaUrl/ImageHeader.php b/src/Message/CtaUrl/ImageHeader.php new file mode 100644 index 0000000..9fda513 --- /dev/null +++ b/src/Message/CtaUrl/ImageHeader.php @@ -0,0 +1,25 @@ +link = $link; + } + + public function getBody(): array + { + return [ + 'type' => $this->type, + 'image' => [ + 'link' => $this->link, + ], + ]; + } +} diff --git a/src/Message/CtaUrl/TitleHeader.php b/src/Message/CtaUrl/TitleHeader.php new file mode 100644 index 0000000..6540e63 --- /dev/null +++ b/src/Message/CtaUrl/TitleHeader.php @@ -0,0 +1,25 @@ +title = $title; + } + + public function getBody(): array + { + return [ + 'type' => $this->type, + 'text' => $this->title, + ]; + } +} diff --git a/src/Message/CtaUrlMessage.php b/src/Message/CtaUrlMessage.php new file mode 100644 index 0000000..335cfed --- /dev/null +++ b/src/Message/CtaUrlMessage.php @@ -0,0 +1,80 @@ +displayText = $displayText; + $this->url = $url; + $this->header = $header; + $this->body = $body; + $this->footer = $footer; + + parent::__construct($to, $reply_to); + } + + public function getDisplayText(): string + { + return $this->displayText; + } + + public function getUrl(): string + { + return $this->url; + } + + public function header(): ?array + { + return is_null($this->header) ? null : $this->header->getBody(); + } + + public function body(): ?string + { + return $this->body; + } + + public function footer(): ?string + { + return $this->footer; + } + + public function action(): array + { + return [ + 'name' => $this->type, + 'parameters' => [ + 'display_text' => $this->displayText, + 'url' => $this->url, + ], + ]; + } +} diff --git a/src/Request/MessageRequest/RequestCtaUrlMessage.php b/src/Request/MessageRequest/RequestCtaUrlMessage.php new file mode 100644 index 0000000..7c1e8fb --- /dev/null +++ b/src/Request/MessageRequest/RequestCtaUrlMessage.php @@ -0,0 +1,43 @@ + $this->message->messagingProduct(), + 'recipient_type' => $this->message->recipientType(), + 'to' => $this->message->to(), + 'type' => 'interactive', + 'interactive' => [ + 'type' => $this->message->type(), + 'action' => $this->message->action(), + ], + ]; + + if ($this->message->header()) { + $body['interactive']['header'] = $this->message->header(); + } + + if ($this->message->body()) { + $body['interactive']['body'] = ['text' => $this->message->body()]; + } + + if ($this->message->footer()) { + $body['interactive']['footer'] = ['text' => $this->message->footer()]; + } + + if ($this->message->replyTo()) { + $body['context']['message_id'] = $this->message->replyTo(); + } + + return $body; + } +} diff --git a/src/WhatsAppCloudApi.php b/src/WhatsAppCloudApi.php index 3d03ff8..d9eed05 100644 --- a/src/WhatsAppCloudApi.php +++ b/src/WhatsAppCloudApi.php @@ -5,6 +5,7 @@ use Netflie\WhatsAppCloudApi\Message\ButtonReply\ButtonAction; use Netflie\WhatsAppCloudApi\Message\Contact\ContactName; use Netflie\WhatsAppCloudApi\Message\Contact\Phone; +use Netflie\WhatsAppCloudApi\Message\CtaUrl\Header; use Netflie\WhatsAppCloudApi\Message\Media\MediaID; use Netflie\WhatsAppCloudApi\Message\OptionsList\Action; use Netflie\WhatsAppCloudApi\Message\Template\Component; @@ -302,6 +303,33 @@ public function sendList(string $to, string $header, string $body, string $foote return $this->client->sendMessage($request); } + /** + * Sends a CTA URL + * + * @param string $to WhatsApp ID or phone number for the person you want to send a message to. + * @param string $displayText The display text. + * @param string $url The URL. + * @param ?Header $header The header. + * @param ?string $body The body. + * @param ?string $footer The footer. + * + * @return Response + * + * @throws Response\ResponseException + */ + public function sendCtaUrl(string $to, string $displayText, string $url, ?Header $header, ?string $body, ?string $footer): Response + { + $message = new Message\CtaUrlMessage($to, $displayText, $url, $header, $body, $footer, $this->reply_to); + $request = new Request\MessageRequest\RequestCtaUrlMessage( + $message, + $this->app->accessToken(), + $this->app->fromPhoneNumberId(), + $this->timeout + ); + + return $this->client->sendMessage($request); + } + public function sendButton(string $to, string $body, ButtonAction $action, ?string $header = null, ?string $footer = null): Response { $message = new Message\ButtonReplyMessage( diff --git a/tests/Integration/WhatsAppCloudApiTest.php b/tests/Integration/WhatsAppCloudApiTest.php index 51ff656..e4c89cd 100644 --- a/tests/Integration/WhatsAppCloudApiTest.php +++ b/tests/Integration/WhatsAppCloudApiTest.php @@ -7,6 +7,7 @@ use Netflie\WhatsAppCloudApi\Message\Contact\ContactName; use Netflie\WhatsAppCloudApi\Message\Contact\Phone; use Netflie\WhatsAppCloudApi\Message\Contact\PhoneType; +use Netflie\WhatsAppCloudApi\Message\CtaUrl\TitleHeader; use Netflie\WhatsAppCloudApi\Message\Media\LinkID; use Netflie\WhatsAppCloudApi\Message\Media\MediaObjectID; use Netflie\WhatsAppCloudApi\Message\OptionsList\Action; @@ -260,6 +261,23 @@ public function test_send_list() $this->assertEquals(false, $response->isError()); } + public function test_send_cta_url() + { + $header = new TitleHeader('The header'); + + $response = $this->whatsapp_app_cloud_api->sendCtaUrl( + '', + 'Button text', + 'https://www.example.com', + $header, + 'The body', + 'The footer', + ); + + $this->assertEquals(200, $response->httpStatusCode()); + $this->assertEquals(false, $response->isError()); + } + public function test_send_reply_buttons() { $buttonRows = [ diff --git a/tests/Unit/WhatsAppCloudApiTest.php b/tests/Unit/WhatsAppCloudApiTest.php index 7a4f6e8..b391dbb 100644 --- a/tests/Unit/WhatsAppCloudApiTest.php +++ b/tests/Unit/WhatsAppCloudApiTest.php @@ -11,6 +11,7 @@ use Netflie\WhatsAppCloudApi\Message\Contact\ContactName; use Netflie\WhatsAppCloudApi\Message\Contact\Phone; use Netflie\WhatsAppCloudApi\Message\Contact\PhoneType; +use Netflie\WhatsAppCloudApi\Message\CtaUrl\TitleHeader; use Netflie\WhatsAppCloudApi\Message\Media\LinkID; use Netflie\WhatsAppCloudApi\Message\Media\MediaObjectID; use Netflie\WhatsAppCloudApi\Message\OptionsList\Action; @@ -899,6 +900,67 @@ public function test_send_list() $this->assertEquals(false, $response->isError()); } + public function test_send_cta_url() + { + $to = $this->faker->phoneNumber; + $url = $this->buildMessageRequestUri(); + $reply_to = $this->faker->uuid; + + $ctaHeader = ['type' => 'text', 'text' => $this->faker->text(60)]; + $ctaBody = ['text' => $this->faker->text(1024)]; + $ctaFooter = ['text' => $this->faker->text(60)]; + $ctaAction = [ + 'name' => 'cta_url', + 'parameters' => [ + 'display_text' => $this->faker->text(24), + 'url' => $this->faker->url, + ] + ]; + + $body = [ + 'messaging_product' => 'whatsapp', + 'recipient_type' => 'individual', + 'to' => $to, + 'type' => 'interactive', + 'interactive' => [ + 'type' => 'cta_url', + 'header' => $ctaHeader, + 'body' => $ctaBody, + 'footer' => $ctaFooter, + 'action' => $ctaAction, + ], + 'context' => [ + 'message_id' => $reply_to, + ], + ]; + $headers = [ + 'Authorization' => 'Bearer ' . $this->access_token, + ]; + + $this->client_handler + ->postJsonData($url, $body, $headers, Argument::type('int')) + ->shouldBeCalled() + ->willReturn(new RawResponse($headers, $this->successfulMessageNodeResponse(), 200)); + + $header = new TitleHeader($ctaHeader['text']); + + $response = $this->whatsapp_app_cloud_api + ->replyTo($reply_to) + ->sendCtaUrl( + $to, + $ctaAction['parameters']['display_text'], + $ctaAction['parameters']['url'], + $header, + $ctaBody['text'], + $ctaFooter['text'], + ); + + $this->assertEquals(200, $response->httpStatusCode()); + $this->assertEquals(json_decode($this->successfulMessageNodeResponse(), true), $response->decodedBody()); + $this->assertEquals($this->successfulMessageNodeResponse(), $response->body()); + $this->assertEquals(false, $response->isError()); + } + public function test_send_reply_buttons() { $to = $this->faker->phoneNumber;