Skip to content

Commit

Permalink
Add Single Product
Browse files Browse the repository at this point in the history
  • Loading branch information
derrickobedgiu1 committed Apr 23, 2024
1 parent 52bf370 commit d92f1e1
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 0 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,24 @@ $whatsapp_cloud_api->sendButton(
);
```

### Send Single Product Message
```php
<?php

$catalog_id = '<catalog-id>';
$sku_id = '<product-sku-id>';
$body = 'Hello! Here\'s your requested product. Thanks for shopping with us.';
$footer = 'Subject to T&C';

$whatsapp_cloud_api->sendSingleProduct(
'<destination-phone-number>',
$catalog_id,
$sku_id,
$body, // body: optional
$footer // footer: optional
);
```

### Replying messages

You can reply a previous sent message:
Expand Down Expand Up @@ -410,6 +428,7 @@ Fields list: https://developers.facebook.com/docs/whatsapp/cloud-api/reference/b
- Send Contacts
- Send Lists
- Send Buttons
- Send Single Product
- Upload media resources to WhatsApp servers
- Download media resources from WhatsApp servers
- Mark messages as read
Expand Down
52 changes: 52 additions & 0 deletions src/Message/SingleProductMessage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace Netflie\WhatsAppCloudApi\Message;

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

private int $catalog_id;

private string $product_retailer_id;

private ?string $body;

private ?string $footer;

/**
* {@inheritdoc}
*/
public function __construct(string $to, int $catalog_id, string $product_retailer_id, ?string $body, ?string $footer, ?string $reply_to)
{
$this->catalog_id = $catalog_id;
$this->product_retailer_id = $product_retailer_id;
$this->body = $body;
$this->footer = $footer;

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

public function catalog_id(): int
{
return $this->catalog_id;
}

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

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

public function footer(): ?string
{
return $this->footer;
}
}
42 changes: 42 additions & 0 deletions src/Request/MessageRequest/RequestSingleProductMessage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Netflie\WhatsAppCloudApi\Request\MessageRequest;

use Netflie\WhatsAppCloudApi\Request\MessageRequest;

final class RequestSingleProductMessage 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' => [
'catalog_id' => $this->message->catalog_id(),
'product_retailer_id' => $this->message->product_retailer_id(),
],
],
];

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;
}
}
26 changes: 26 additions & 0 deletions src/WhatsAppCloudApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,32 @@ public function markMessageAsRead(string $message_id): Response
return $this->client->sendMessage($request);
}

/**
* Sends a single product message to a specified recipient.
*
* @param string $to The WhatsApp ID or phone number for the person you want to send the message to.
* @param int $catalog_id The ID of the catalog where the product is located.
* @param string $product_retailer_id The retailer-specific ID of the product.
* @param string|null $body The body of the message. Defaults to an empty string if not provided.
* @param string|null $footer The footer of the message. Defaults to an empty string if not provided.
*
* @return Response The response object containing the result of the API request.
*
* @throws Response\ResponseException If there is an error with the API request.
*/
public function sendSingleProduct(string $to, int $catalog_id, string $product_retailer_id, ?string $body = '', ?string $footer = '')
{
$message = new Message\SingleProductMessage($to, $catalog_id, $product_retailer_id, $body, $footer, $this->reply_to);
$request = new Request\MessageRequest\RequestSingleProductMessage(
$message,
$this->app->accessToken(),
$this->app->fromPhoneNumberId(),
$this->timeout
);

return $this->client->sendMessage($request);
}

/**
* Get Business Profile
*
Expand Down
23 changes: 23 additions & 0 deletions tests/Integration/WhatsAppCloudApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,29 @@ public function test_send_reply_buttons()
$this->assertEquals(false, $response->isError());
}

public function test_send_single_product()
{
$this->markTestIncomplete(
'This test requires real catalog id and product sku id.'
);

$catalog_id = '<catalog-id>';
$sku_id = '<product-sku-id>';
$body = 'Hello! Here\'s your requested product. Thanks for shopping with us.';
$footer = 'Subject to T&C';

$response = $this->whatsapp_app_cloud_api->sendSingleProduct(
WhatsAppCloudApiTestConfiguration::$to_phone_number_id,
$catalog_id,
$sku_id,
$body, // body: optional
$footer // footer: optional
);

$this->assertEquals(200, $response->httpStatusCode());
$this->assertEquals(false, $response->isError());
}

public function test_upload_media()
{
$response = $this->whatsapp_app_cloud_api->uploadMedia('tests/Support/netflie.png');
Expand Down
47 changes: 47 additions & 0 deletions tests/Unit/WhatsAppCloudApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1145,6 +1145,53 @@ public function test_update_business_profile()
$this->assertEquals(false, $response->isError());
}

public function test_send_single_product()
{
$to = $this->faker->phoneNumber;
$url = $this->buildMessageRequestUri();
$message = $this->faker->text(1024);
$footer = $this->faker->text(60);
$catalog_id = $this->faker->randomNumber();
$product_retailer_id = $this->faker->uuid();

$body = [
'messaging_product' => 'whatsapp',
'recipient_type' => 'individual',
'to' => $to,
'type' => 'interactive',
'interactive' => [
'type' => 'product',
'body' => ['text' => $message],
'footer' => ['text' => $footer],
'action' => [
'catalog_id' => $catalog_id,
'product_retailer_id' => $product_retailer_id,
],
],
];
$headers = [
'Authorization' => 'Bearer ' . $this->access_token,
];

$this->client_handler
->postJsonData($url, $body, $headers, Argument::type('int'))
->shouldBeCalled()
->willReturn(new RawResponse($headers, $this->successfulMessageNodeResponse(), 200));

$response = $this->whatsapp_app_cloud_api->sendSingleProduct(
$to,
$catalog_id,
$product_retailer_id,
$message,
$footer
);

$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_mark_a_message_as_read()
{
$url = $this->buildMessageRequestUri();
Expand Down

0 comments on commit d92f1e1

Please sign in to comment.