Skip to content

Commit

Permalink
Merge pull request #186 from jfradj/dev-cta
Browse files Browse the repository at this point in the history
Implement CTA URL message (With text & Image support)
  • Loading branch information
aalbarca committed Apr 22, 2024
2 parents cb3079a + 428ae59 commit 52bf370
Show file tree
Hide file tree
Showing 9 changed files with 315 additions and 0 deletions.
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 @@ -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(
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

0 comments on commit 52bf370

Please sign in to comment.