Skip to content
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
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,30 @@ $whatsapp_cloud_api = new WhatsAppCloudApi([
$whatsapp_cloud_api->sendTextMessage('34676104574', 'Hey there! I\'m using WhatsApp Cloud API. Visit https://www.netflie.es');
```

### Send a message using BSUID recipient
```php
<?php

$recipient_bsuid = 'US.13491208655302741918';

// Send using BSUID only
$whatsapp_cloud_api->sendTextMessage(null, 'Hello from BSUID', false, $recipient_bsuid);

// Send both values in the same request (WhatsApp Cloud API gives precedence to `to`)
$whatsapp_cloud_api->sendTextMessage('34676104574', 'Hello with both identifiers', false, $recipient_bsuid);
```

The same optional `$recipient` parameter is available in all `send*` methods that send messages to `/messages`.

For `sendContact`, pass the BSUID before the phone entries:

```php
$contact_name = new \Netflie\WhatsAppCloudApi\Message\Contact\ContactName('John', 'Doe');
$phone = new \Netflie\WhatsAppCloudApi\Message\Contact\Phone('+14155550100', \Netflie\WhatsAppCloudApi\Message\Contact\PhoneType::CELL());

$whatsapp_cloud_api->sendContact(null, $contact_name, $recipient_bsuid, $phone);
```

### Send a document
You can send documents in two ways: by uploading a file to the WhatsApp Cloud servers (where you will receive an identifier) or from a link to a document published on internet.

Expand Down Expand Up @@ -200,7 +224,7 @@ use Netflie\WhatsAppCloudApi\Message\Contact\PhoneType;
$name = new ContactName('Adams', 'Smith');
$phone = new Phone('34676204577', PhoneType::CELL());

$whatsapp_cloud_api->sendContact('<destination-phone-number>', $name, $phone);
$whatsapp_cloud_api->sendContact('<destination-phone-number>', $name, null, $phone);
```

### Send a list message
Expand Down
4 changes: 2 additions & 2 deletions src/Message/AudioMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ final class AudioMessage extends Message
/**
* {@inheritdoc}
*/
public function __construct(string $to, MediaID $id, ?string $reply_to)
public function __construct(?string $to, MediaID $id, ?string $recipient, ?string $reply_to)
{
$this->id = $id;

parent::__construct($to, $reply_to);
parent::__construct($to, $recipient, $reply_to);
}
Comment on lines +24 to 29

Copilot AI Apr 14, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AudioMessage’s constructor parameter order and defaults are inconsistent with the other Message subclasses (recipient is required in the signature and comes before $reply_to). This makes it easy to accidentally swap $recipient/$reply_to and is also a backwards-incompatible change for anyone instantiating AudioMessage directly. Consider aligning it with the common pattern used elsewhere (e.g., $reply_to first, and $recipient optional at the end).

Copilot uses AI. Check for mistakes.

public function identifierType(): string
Expand Down
4 changes: 2 additions & 2 deletions src/Message/ButtonReplyMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ class ButtonReplyMessage extends Message

private ButtonAction $action;

public function __construct(string $to, string $body, ButtonAction $action, ?string $header = null, ?string $footer = null, ?string $reply_to = null)
public function __construct(?string $to, string $body, ButtonAction $action, ?string $header = null, ?string $footer = null, ?string $reply_to = null, ?string $recipient = null)
{
$this->body = $body;
$this->action = $action;
$this->header = $header;
$this->footer = $footer;

parent::__construct($to, $reply_to);
parent::__construct($to, $recipient, $reply_to);
}

public function header(): ?string
Expand Down
4 changes: 2 additions & 2 deletions src/Message/CatalogMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ final class CatalogMessage extends Message
/**
* {@inheritdoc}
*/
public function __construct(string $to, string $body, ?string $footer, ?string $thumbnail_product_retailer_id, ?string $reply_to)
public function __construct(?string $to, string $body, ?string $footer, ?string $thumbnail_product_retailer_id, ?string $reply_to, ?string $recipient = null)
{
$this->body = $body;
$this->footer = $footer;
$this->thumbnail_product_retailer_id = $thumbnail_product_retailer_id;

parent::__construct($to, $reply_to);
parent::__construct($to, $recipient, $reply_to);
}

public function body(): string
Expand Down
4 changes: 2 additions & 2 deletions src/Message/ContactMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ final class ContactMessage extends Message
/**
* {@inheritdoc}
*/
public function __construct(string $to, ContactName $name, ?string $reply_to, Phone ...$phones)
public function __construct(?string $to, ContactName $name, ?string $reply_to, ?string $recipient = null, Phone ...$phones)
{
$this->name = $name;
$this->phones = new Phones(...$phones);

parent::__construct($to, $reply_to);
parent::__construct($to, $recipient, $reply_to);
}

public function fullName(): string
Expand Down
7 changes: 4 additions & 3 deletions src/Message/CtaUrlMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,22 @@ final class CtaUrlMessage extends Message
* {@inheritdoc}
*/
public function __construct(
string $to,
?string $to,
string $displayText,
string $url,
?Header $header,
?string $body,
?string $footer,
?string $reply_to
?string $reply_to,
?string $recipient = null
) {
$this->displayText = $displayText;
$this->url = $url;
$this->header = $header;
$this->body = $body;
$this->footer = $footer;

parent::__construct($to, $reply_to);
parent::__construct($to, $recipient, $reply_to);
}

public function getDisplayText(): string
Expand Down
4 changes: 2 additions & 2 deletions src/Message/DocumentMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ final class DocumentMessage extends Message
/**
* {@inheritdoc}
*/
public function __construct(string $to, MediaID $id, string $name, ?string $caption, ?string $reply_to)
public function __construct(?string $to, MediaID $id, string $name, ?string $caption, ?string $reply_to, ?string $recipient = null)
{
$this->id = $id;
$this->name = $name;
$this->caption = $caption;

parent::__construct($to, $reply_to);
parent::__construct($to, $recipient, $reply_to);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/Message/ImageMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ final class ImageMessage extends Message
/**
* {@inheritdoc}
*/
public function __construct(string $to, MediaID $id, ?string $caption = '', ?string $reply_to = null)
public function __construct(?string $to, MediaID $id, ?string $caption = '', ?string $reply_to = null, ?string $recipient = null)
{
$this->id = $id;
$this->caption = $caption;

parent::__construct($to, $reply_to);
parent::__construct($to, $recipient, $reply_to);
}

public function caption(): ?string
Expand Down
4 changes: 2 additions & 2 deletions src/Message/LocationMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ final class LocationMessage extends Message
/**
* {@inheritdoc}
*/
public function __construct(string $to, float $longitude, float $latitude, string $name = '', string $address = '', ?string $reply_to = null)
public function __construct(?string $to, float $longitude, float $latitude, string $name = '', string $address = '', ?string $reply_to = null, ?string $recipient = null)
{
if ($address && !$name) {
throw new InvalidMessage('Name is required.');
Expand All @@ -36,7 +36,7 @@ public function __construct(string $to, float $longitude, float $latitude, strin
$this->name = $name;
$this->address = $address;

parent::__construct($to, $reply_to);
parent::__construct($to, $recipient, $reply_to);
}

public function longitude(): float
Expand Down
4 changes: 2 additions & 2 deletions src/Message/LocationRequestMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ final class LocationRequestMessage extends Message
/**
* {@inheritdoc}
*/
public function __construct(string $to, string $body, ?string $reply_to)
public function __construct(?string $to, string $body, ?string $reply_to, ?string $recipient = null)
{
$this->body = $body;

parent::__construct($to, $reply_to);
parent::__construct($to, $recipient, $reply_to);
}

public function body(): string
Expand Down
27 changes: 22 additions & 5 deletions src/Message/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace Netflie\WhatsAppCloudApi\Message;

use Netflie\WhatsAppCloudApi\Message\Error\InvalidMessage;

abstract class Message
{
/**
Expand All @@ -20,9 +22,14 @@ abstract class Message
private string $recipient_type = 'individual';

/**
* @var string WhatsApp ID or phone number for the person you want to send a message to.
* @var string|null WhatsApp ID or phone number for the person you want to send a message to.
*/
private string $to;
private ?string $to;

/**
* @var string|null Business-scoped user id (BSUID) recipient.
*/
private ?string $recipient;

/**
* The WhatsApp Message ID to reply to.
Expand All @@ -32,22 +39,32 @@ abstract class Message
/**
* Creates a new Message class.
*/
public function __construct(string $to, ?string $reply_to)
public function __construct(?string $to, ?string $recipient, ?string $reply_to)
{
$this->to = $to;
$this->recipient = $recipient;
$this->reply_to = $reply_to;

if (empty($this->to) && empty($this->recipient)) {
throw new InvalidMessage('Either `to` or `recipient` is required.');
}
}

/**
* Return the WhatsApp ID or phone number for the person you want to send a message to.
*
* @return string
* @return string|null
*/
public function to(): string
public function to(): ?string
{
return $this->to;
}

public function recipient(): ?string
{
return $this->recipient;
}

/**
* Return the type of message object.
*
Expand Down
4 changes: 2 additions & 2 deletions src/Message/MultiProductMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ final class MultiProductMessage extends Message
/**
* {@inheritdoc}
*/
public function __construct(string $to, int $catalog_id, Action $action, string $header, string $body, ?string $footer, ?string $reply_to)
public function __construct(?string $to, int $catalog_id, Action $action, string $header, string $body, ?string $footer, ?string $reply_to, ?string $recipient = null)
{
$this->header = $header;
$this->body = $body;
$this->catalog_id = $catalog_id;
$this->footer = $footer;
$this->action = $action;

parent::__construct($to, $reply_to);
parent::__construct($to, $recipient, $reply_to);
}

public function header(): array
Expand Down
4 changes: 2 additions & 2 deletions src/Message/OptionsListMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ final class OptionsListMessage extends Message
/**
* {@inheritdoc}
*/
public function __construct(string $to, string $header, string $body, string $footer, Action $action, ?string $reply_to)
public function __construct(?string $to, string $header, string $body, string $footer, Action $action, ?string $reply_to, ?string $recipient = null)
{
$this->header = $header;
$this->body = $body;
$this->footer = $footer;
$this->action = $action;

parent::__construct($to, $reply_to);
parent::__construct($to, $recipient, $reply_to);
}

public function header(): string
Expand Down
4 changes: 2 additions & 2 deletions src/Message/ReactionMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ final class ReactionMessage extends Message
/**
* {@inheritdoc}
*/
public function __construct(string $to, string $message_id, string $emoji)
public function __construct(?string $to, string $message_id, string $emoji, ?string $recipient = null)
{
$this->emoji = $emoji;
$this->message_id = $message_id;

parent::__construct($to, null);
parent::__construct($to, $recipient, null);
}

public function emoji(): string
Expand Down
4 changes: 2 additions & 2 deletions src/Message/SingleProductMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ final class SingleProductMessage extends Message
/**
* {@inheritdoc}
*/
public function __construct(string $to, int $catalog_id, string $product_retailer_id, ?string $body, ?string $footer, ?string $reply_to)
public function __construct(?string $to, int $catalog_id, string $product_retailer_id, ?string $body, ?string $footer, ?string $reply_to, ?string $recipient = null)
{
$this->catalog_id = $catalog_id;
$this->product_retailer_id = $product_retailer_id;
$this->body = $body;
$this->footer = $footer;

parent::__construct($to, $reply_to);
parent::__construct($to, $recipient, $reply_to);
}

public function catalog_id(): int
Expand Down
4 changes: 2 additions & 2 deletions src/Message/StickerMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ final class StickerMessage extends Message
/**
* {@inheritdoc}
*/
public function __construct(string $to, MediaID $id, ?string $reply_to)
public function __construct(?string $to, MediaID $id, ?string $reply_to, ?string $recipient = null)
{
$this->id = $id;

parent::__construct($to, $reply_to);
parent::__construct($to, $recipient, $reply_to);
}

public function identifierType(): string
Expand Down
4 changes: 2 additions & 2 deletions src/Message/TemplateMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ final class TemplateMessage extends Message
/**
* {@inheritdoc}
*/
public function __construct(string $to, string $name, string $language = 'en_US', ?Component $components = null, ?string $reply_to = null)
public function __construct(?string $to, string $name, string $language = 'en_US', ?Component $components = null, ?string $reply_to = null, ?string $recipient = null)
{
$this->name = $name;
$this->language = $language;
$this->components = $components;

parent::__construct($to, $reply_to);
parent::__construct($to, $recipient, $reply_to);
}

public function name(): string
Expand Down
6 changes: 3 additions & 3 deletions src/Message/TextMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@ final class TextMessage extends Message
/**
* Creates a new message of type text.
*
* @param string $to
* @param ?string $to
* @param string $text
* @param bool $preview_url
*/
public function __construct(string $to, string $text, bool $preview_url = false, ?string $reply_to = null)
public function __construct(?string $to, string $text, bool $preview_url = false, ?string $reply_to = null, ?string $recipient = null)
{
$this->assertTextIsValid($text);

$this->text = $text;
$this->preview_url = $preview_url;

parent::__construct($to, $reply_to);
parent::__construct($to, $recipient, $reply_to);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/Message/VideoMessage.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ final class VideoMessage extends Message
/**
* {@inheritdoc}
*/
public function __construct(string $to, MediaID $id, ?string $caption = '', ?string $reply_to = null)
public function __construct(?string $to, MediaID $id, ?string $caption = '', ?string $reply_to = null, ?string $recipient = null)
{
$this->id = $id;
$this->caption = $caption;

parent::__construct($to, $reply_to);
parent::__construct($to, $recipient, $reply_to);
}

public function caption(): ?string
Expand Down
Loading
Loading