Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement CTA URL message (With text & Image support) #186

Merged
merged 6 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,25 @@ $whatsapp_cloud_api->sendList(
);
```

### Send a CTA URL message

```php
<?php

use Netflie\WhatsAppCloudApi\Message\CtaUrl\TitleHeader;

$header = new TitleHeader('Booking');

$whatsapp_cloud_api->sendCtaUrl(
'<destination-phone-number>',
'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
Expand Down
15 changes: 15 additions & 0 deletions src/Message/CtaUrl/Header.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Netflie\WhatsAppCloudApi\Message\CtaUrl;

abstract class Header
{
protected string $type;

protected function __construct(string $type)
{
$this->type = $type;
}

abstract public function getBody(): array;
}
25 changes: 25 additions & 0 deletions src/Message/CtaUrl/ImageHeader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Netflie\WhatsAppCloudApi\Message\CtaUrl;

final class ImageHeader extends Header
{
protected string $link;

public function __construct(string $link)
{
parent::__construct('image');

$this->link = $link;
}

public function getBody(): array
{
return [
'type' => $this->type,
'image' => [
'link' => $this->link,
],
];
}
}
25 changes: 25 additions & 0 deletions src/Message/CtaUrl/TitleHeader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace Netflie\WhatsAppCloudApi\Message\CtaUrl;

use Netflie\WhatsAppCloudApi\Message\CtaUrl\Header;

final class TitleHeader extends Header
{
protected string $title;

public function __construct(string $title)
{
parent::__construct('text');

$this->title = $title;
}

public function getBody(): array
{
return [
'type' => $this->type,
'text' => $this->title,
];
}
}
80 changes: 80 additions & 0 deletions src/Message/CtaUrlMessage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

namespace Netflie\WhatsAppCloudApi\Message;

use Netflie\WhatsAppCloudApi\Message\CtaUrl\Header;

final class CtaUrlMessage extends Message
{
/**
* {@inheritdoc}
*/
protected string $type = 'cta_url';

private string $displayText;

private string $url;

private ?Header $header = null;

private ?string $body = null;

private ?string $footer = null;

/**
* {@inheritdoc}
*/
public function __construct(
string $to,
string $displayText,
string $url,
?Header $header,
?string $body,
?string $footer,
?string $reply_to
) {
$this->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,
],
];
}
}
43 changes: 43 additions & 0 deletions src/Request/MessageRequest/RequestCtaUrlMessage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

namespace Netflie\WhatsAppCloudApi\Request\MessageRequest;

use Netflie\WhatsAppCloudApi\Request\MessageRequest;

final class RequestCtaUrlMessage extends MessageRequest
{
/**
* {@inheritdoc}
*/
public function body(): array
{
$body = [
'messaging_product' => $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;
}
}
28 changes: 28 additions & 0 deletions src/WhatsAppCloudApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -289,6 +290,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(
Expand Down
18 changes: 18 additions & 0 deletions tests/Integration/WhatsAppCloudApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(
'<destination-phone-number>',
'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 = [
Expand Down
62 changes: 62 additions & 0 deletions tests/Unit/WhatsAppCloudApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down