From 8a20b86b17ac577cce17bd7e363a869950a36969 Mon Sep 17 00:00:00 2001 From: Alex Komarichev Date: Mon, 24 Jun 2024 20:21:41 +0300 Subject: [PATCH 1/3] Add templates interaction --- src/Bot/Client.php | 39 +- src/Bot/Model/Entity/Template/Template.php | 385 ++++++++++++++++++ .../Entity/Template/TemplateVariables.php | 88 ++++ src/Bot/Model/Request/TemplateSendRequest.php | 77 ++++ tests/Bot/Tests/TemplatesTest.php | 113 +++++ tests/Resources/templates.json | 56 +++ 6 files changed, 755 insertions(+), 3 deletions(-) create mode 100644 src/Bot/Model/Entity/Template/Template.php create mode 100644 src/Bot/Model/Entity/Template/TemplateVariables.php create mode 100644 src/Bot/Model/Request/TemplateSendRequest.php create mode 100644 tests/Bot/Tests/TemplatesTest.php create mode 100644 tests/Resources/templates.json diff --git a/src/Bot/Client.php b/src/Bot/Client.php index fe0b59d..9a0784d 100644 --- a/src/Bot/Client.php +++ b/src/Bot/Client.php @@ -11,9 +11,8 @@ namespace RetailCrm\Mg\Bot; use Psr\Http\Message\ResponseInterface; -use RetailCrm\Common\Url; use RetailCrm\Common\Serializer; -use RetailCrm\Mg\Bot\Model\ModelAdapter; +use RetailCrm\Common\Url; use RetailCrm\Mg\Bot\Model\Entity\Bot; use RetailCrm\Mg\Bot\Model\Entity\Channel\Channel; use RetailCrm\Mg\Bot\Model\Entity\Chat\Chat; @@ -22,13 +21,15 @@ use RetailCrm\Mg\Bot\Model\Entity\Command; use RetailCrm\Mg\Bot\Model\Entity\Customer; use RetailCrm\Mg\Bot\Model\Entity\Dialog; use RetailCrm\Mg\Bot\Model\Entity\Message\Message; +use RetailCrm\Mg\Bot\Model\Entity\Template\Template; use RetailCrm\Mg\Bot\Model\Entity\User; +use RetailCrm\Mg\Bot\Model\ModelAdapter; use RetailCrm\Mg\Bot\Model\Request\UploadFileByUrlRequest; use RetailCrm\Mg\Bot\Model\Response\AssignResponse; -use RetailCrm\Mg\Bot\Model\Response\UnassignResponse; use RetailCrm\Mg\Bot\Model\Response\ErrorOnlyResponse; use RetailCrm\Mg\Bot\Model\Response\FullFileResponse; use RetailCrm\Mg\Bot\Model\Response\MessageSendResponse; +use RetailCrm\Mg\Bot\Model\Response\UnassignResponse; use RetailCrm\Mg\Bot\Model\Response\UploadFileResponse; /** @@ -460,6 +461,38 @@ class Client return $adapter->getResponseModel($response); } + + /** + * Returns templates list + * + * @return array + * @throws \Exception + */ + public function templates() + { + $response = $this->client->makeRequest( + '/templates', + HttpClient::METHOD_GET + ); + + $adapter = new ModelAdapter(Template::class); + + return $adapter->getResponseList($response); + } + + public function templateSend(string $templateId, Model\Request\TemplateSendRequest $request) + { + $response = $this->client->makeRequest( + sprintf('/templates/%d/send', $templateId), + HttpClient::METHOD_POST, + $request + ); + + $adapter = new ModelAdapter(MessageSendResponse::class); + + return $adapter->getResponseModel($response); + } + /** * Returns filtered users list * diff --git a/src/Bot/Model/Entity/Template/Template.php b/src/Bot/Model/Entity/Template/Template.php new file mode 100644 index 0000000..c4ea038 --- /dev/null +++ b/src/Bot/Model/Entity/Template/Template.php @@ -0,0 +1,385 @@ +id; + } + + /** + * @param int $id + */ + public function setId(int $id): void + { + $this->id = $id; + } + + /** + * @return string|null + */ + public function getCode(): ?string + { + return $this->code; + } + + /** + * @param string $code + */ + public function setCode(string $code): void + { + $this->code = $code; + } + + /** + * @return int|null + */ + public function getChannelId(): ?int + { + return $this->channelId; + } + + /** + * @param int $channelId + */ + public function setChannelId(int $channelId): void + { + $this->channelId = $channelId; + } + + /** + * @return string|null + */ + public function getName(): ?string + { + return $this->name; + } + + /** + * @param string $name + */ + public function setName(string $name): void + { + $this->name = $name; + } + + /** + * @return bool|null + */ + public function getEnabled(): ?bool + { + return $this->enabled; + } + + /** + * @param bool $enabled + */ + public function setEnabled(bool $enabled): void + { + $this->enabled = $enabled; + } + + /** + * @return string|null + */ + public function getType(): ?string + { + return $this->type; + } + + /** + * @param string $type + */ + public function setType(string $type): void + { + $this->type = $type; + } + + /** + * @return array|null + */ + public function getTemplate(): ?array + { + return $this->template; + } + + /** + * @param mixed $template + */ + public function setTemplate($template): void + { + $this->template = $template; + } + + /** + * @return string|null + */ + public function getBody(): ?string + { + return $this->body; + } + + /** + * @param string $body + */ + public function setBody(string $body): void + { + $this->body = $body; + } + + /** + * @return string|null + */ + public function getVerificationStatus(): ?string + { + return $this->verificationStatus; + } + + /** + * @param string $verificationStatus + */ + public function setVerificationStatus(string $verificationStatus): void + { + $this->verificationStatus = $verificationStatus; + } + + /** + * @return string|null + */ + public function getLang(): ?string + { + return $this->lang; + } + + /** + * @param string $lang + */ + public function setLang(string $lang): void + { + $this->lang = $lang; + } + + /** + * @return string|null + */ + public function getCategory(): ?string + { + return $this->category; + } + + /** + * @param string $category + */ + public function setCategory(string $category): void + { + $this->category = $category; + } + + /** + * @return string|null + */ + public function getRejectionReason(): ?string + { + return $this->rejectionReason; + } + + /** + * @param string $rejectionReason + */ + public function setRejectionReason(string $rejectionReason): void + { + $this->rejectionReason = $rejectionReason; + } + + /** + * @return string|null + */ + public function getQuality(): ?string + { + return $this->quality; + } + + public function setQuality(string $quality): void + { + $this->quality = $quality; + } + + /** + * @return array|null + */ + public function getHeader(): ?array + { + return $this->header; + } + + /** + * @param array $header + */ + public function setHeader(array $header): void + { + $this->header = $header; + } + + /** + * @return array|null + */ + public function getButtons(): ?array + { + return $this->buttons; + } + + /** + * @param array $buttons + */ + public function setButtons(array $buttons): void + { + $this->buttons = $buttons; + } +} diff --git a/src/Bot/Model/Entity/Template/TemplateVariables.php b/src/Bot/Model/Entity/Template/TemplateVariables.php new file mode 100644 index 0000000..8469a29 --- /dev/null +++ b/src/Bot/Model/Entity/Template/TemplateVariables.php @@ -0,0 +1,88 @@ + $buttons + * + * @Type("array") + * @Accessor(getter="getButtons",setter="setButtons") + */ + private $buttons; + + /** + * @return array|null + */ + public function getHeader(): ?array + { + return $this->header; + } + + /** + * @param array $header + */ + public function setHeader(array $header): void + { + $this->header = $header; + } + + /** + * @return array|null + */ + public function getBody(): ?array + { + return $this->body; + } + + /** + * @param array $body + */ + public function setBody(array $body): void + { + $this->body = $body; + } + + /** + * @return array[]|null + */ + public function getButtons(): ?array + { + return $this->buttons; + } + + /** + * @param array[] $buttons + */ + public function setButtons(array $buttons): void + { + $this->buttons = $buttons; + } +} diff --git a/src/Bot/Model/Request/TemplateSendRequest.php b/src/Bot/Model/Request/TemplateSendRequest.php new file mode 100644 index 0000000..0dfd6e6 --- /dev/null +++ b/src/Bot/Model/Request/TemplateSendRequest.php @@ -0,0 +1,77 @@ +phone; + } + + /** + * @param string $phone + */ + public function setPhone(string $phone): void + { + $this->phone = $phone; + } + + /** + * @return TemplateVariables|null + */ + public function getArgs(): ?TemplateVariables + { + return $this->args; + } + + /** + * @param TemplateVariables $args + */ + public function setArgs(TemplateVariables $args): void + { + $this->args = $args; + } +} diff --git a/tests/Bot/Tests/TemplatesTest.php b/tests/Bot/Tests/TemplatesTest.php new file mode 100644 index 0000000..696c4d5 --- /dev/null +++ b/tests/Bot/Tests/TemplatesTest.php @@ -0,0 +1,113 @@ +getJsonResponse('templates') + ); + + $response = $client->templates(); + + static::assertCount(2, $response, "Incorrect templates count"); + static::assertInstanceOf(Template\Template::class, $response[0], "Incorrect template instance"); + + $templateType = $response[0]->getHeader()['content']['type']; + static::assertStringContainsString("video", $templateType, "Incorrect template type"); + } + + /** + * @group("templates") + * @throws \Exception + */ + public function testTemplateSendNotFound() + { + $this->expectException(NotFoundException::class); + + $client = self::getApiClient( + null, + null, + false, + $this->getErrorsResponse(404, "template id=3 was not found") + ); + + $request = new TemplateSendRequest(); + $request->setPhone('123'); + + $client->templateSend(3, $request); + } + + /** + * @group("templates") + * @throws \Exception + */ + public function testTemplateSendVariablesError() + { + $this->expectException(NotFoundException::class); + + $client = self::getApiClient( + null, + null, + false, + $this->getErrorsResponse(404, "variables number doesn't match template") + ); + + $request = new TemplateSendRequest(); + $request->setPhone('123'); + + $client->templateSend(2, $request); + } + + /** + * @group("templates") + * @throws \Exception + */ + public function testTemplateSendSuccess() + { + $client = self::getApiClient( + null, + null, + false, + $this->getResponse( + '{"message_id":4242,"time":"2019-06-24T06:02:04.434291791Z"}', + 201 + ) + ); + + $request = new TemplateSendRequest(); + $request->setPhone('123'); + + $response = $client->templateSend(1, $request); + + self::assertInstanceOf(MessageSendResponse::class, $response); + + if ($response instanceof MessageSendResponse) { + self::assertTrue($response->isSuccessful()); + self::assertCount(0, $response->getErrors()); + self::assertEquals(4242, $response->getMessageId()); + } + } +} diff --git a/tests/Resources/templates.json b/tests/Resources/templates.json new file mode 100644 index 0000000..9ee1e08 --- /dev/null +++ b/tests/Resources/templates.json @@ -0,0 +1,56 @@ +[ + { + "id": 1, + "code": "test1#ru", + "channel_id": 1, + "name": "test1", + "enabled": true, + "type": "media", + "template": [ + "test1Template" + ], + "body": "test1Template", + "lang": "ru", + "category": "marketing", + "verification_status": "approved", + "header": { + "content": { + "type": "video" + } + } + }, + { + "id": 2, + "code": "test2#ru", + "channel_id": 5, + "name": "test2", + "enabled": true, + "type": "media", + "template": [ + "Вы не завершили покупку на нашем сайте.\n", + { + "var": "custom" + }, + "Пройдите по ссылке чтобы оформить заказ." + ], + "body": "Вы не завершили покупку на нашем сайте.\n{{1}}Пройдите по ссылке чтобы оформить заказ.", + "lang": "ru", + "category": "marketing", + "verification_status": "approved", + "header": { + "content": { + "body": "Товары в вашей корзине ждут вас!", + "type": "text" + } + }, + "buttons": { + "items": [ + { + "label": "Перейти в корзину", + "url": "https://test-url/{{1}}", + "type": "url" + } + ] + } + } +] \ No newline at end of file From 4b5041b05b702604afb3267156ae944ebc135a84 Mon Sep 17 00:00:00 2001 From: Alex Komarichev Date: Mon, 24 Jun 2024 21:07:47 +0300 Subject: [PATCH 2/3] phpstan --- src/Bot/Client.php | 7 ++++--- src/Bot/Model/Entity/Template/Template.php | 20 +++++++++---------- .../Entity/Template/TemplateVariables.php | 18 ++++++++--------- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/Bot/Client.php b/src/Bot/Client.php index 9a0784d..85a0fc5 100644 --- a/src/Bot/Client.php +++ b/src/Bot/Client.php @@ -24,6 +24,7 @@ use RetailCrm\Mg\Bot\Model\Entity\Message\Message; use RetailCrm\Mg\Bot\Model\Entity\Template\Template; use RetailCrm\Mg\Bot\Model\Entity\User; use RetailCrm\Mg\Bot\Model\ModelAdapter; +use RetailCrm\Mg\Bot\Model\ModelInterface; use RetailCrm\Mg\Bot\Model\Request\UploadFileByUrlRequest; use RetailCrm\Mg\Bot\Model\Response\AssignResponse; use RetailCrm\Mg\Bot\Model\Response\ErrorOnlyResponse; @@ -465,10 +466,10 @@ class Client /** * Returns templates list * - * @return array + * @return Template[] * @throws \Exception */ - public function templates() + public function templates(): array { $response = $this->client->makeRequest( '/templates', @@ -480,7 +481,7 @@ class Client return $adapter->getResponseList($response); } - public function templateSend(string $templateId, Model\Request\TemplateSendRequest $request) + public function templateSend(string $templateId, Model\Request\TemplateSendRequest $request): ModelInterface { $response = $this->client->makeRequest( sprintf('/templates/%d/send', $templateId), diff --git a/src/Bot/Model/Entity/Template/Template.php b/src/Bot/Model/Entity/Template/Template.php index c4ea038..b67ce56 100644 --- a/src/Bot/Model/Entity/Template/Template.php +++ b/src/Bot/Model/Entity/Template/Template.php @@ -72,7 +72,7 @@ class Template implements ModelInterface private $type; /** - * @var array $template + * @var array $template * * @Type("array") * @Accessor(getter="getTemplate",setter="setTemplate") @@ -129,7 +129,7 @@ class Template implements ModelInterface private $quality; /** - * @var array $header + * @var array $header * * @Type("array") * @Accessor(getter="getHeader",setter="setHeader") @@ -138,7 +138,7 @@ class Template implements ModelInterface private $header; /** - * @var array $header + * @var array> $buttons * * @Type("array") * @Accessor(getter="getButtons",setter="setButtons") @@ -243,7 +243,7 @@ class Template implements ModelInterface } /** - * @return array|null + * @return array|null */ public function getTemplate(): ?array { @@ -251,9 +251,9 @@ class Template implements ModelInterface } /** - * @param mixed $template + * @param array $template */ - public function setTemplate($template): void + public function setTemplate(array $template): void { $this->template = $template; } @@ -352,7 +352,7 @@ class Template implements ModelInterface } /** - * @return array|null + * @return array|null */ public function getHeader(): ?array { @@ -360,7 +360,7 @@ class Template implements ModelInterface } /** - * @param array $header + * @param array $header */ public function setHeader(array $header): void { @@ -368,7 +368,7 @@ class Template implements ModelInterface } /** - * @return array|null + * @return array>|null */ public function getButtons(): ?array { @@ -376,7 +376,7 @@ class Template implements ModelInterface } /** - * @param array $buttons + * @param array> $buttons */ public function setButtons(array $buttons): void { diff --git a/src/Bot/Model/Entity/Template/TemplateVariables.php b/src/Bot/Model/Entity/Template/TemplateVariables.php index 8469a29..1c2ffeb 100644 --- a/src/Bot/Model/Entity/Template/TemplateVariables.php +++ b/src/Bot/Model/Entity/Template/TemplateVariables.php @@ -15,7 +15,7 @@ use RetailCrm\Mg\Bot\Model\ModelInterface; class TemplateVariables implements ModelInterface { /** - * @var array $header + * @var array $header * * @Type("array") * @Accessor(getter="getHeader",setter="setHeader") @@ -23,7 +23,7 @@ class TemplateVariables implements ModelInterface private $header; /** - * @var array $body + * @var array $body * * @Type("array") * @Accessor(getter="getBody",setter="setBody") @@ -31,7 +31,7 @@ class TemplateVariables implements ModelInterface private $body; /** - * @var array $buttons + * @var array> $buttons * * @Type("array") * @Accessor(getter="getButtons",setter="setButtons") @@ -39,7 +39,7 @@ class TemplateVariables implements ModelInterface private $buttons; /** - * @return array|null + * @return array|null */ public function getHeader(): ?array { @@ -47,7 +47,7 @@ class TemplateVariables implements ModelInterface } /** - * @param array $header + * @param array $header */ public function setHeader(array $header): void { @@ -55,7 +55,7 @@ class TemplateVariables implements ModelInterface } /** - * @return array|null + * @return array|null */ public function getBody(): ?array { @@ -63,7 +63,7 @@ class TemplateVariables implements ModelInterface } /** - * @param array $body + * @param array $body */ public function setBody(array $body): void { @@ -71,7 +71,7 @@ class TemplateVariables implements ModelInterface } /** - * @return array[]|null + * @return array>|null */ public function getButtons(): ?array { @@ -79,7 +79,7 @@ class TemplateVariables implements ModelInterface } /** - * @param array[] $buttons + * @param array> $buttons */ public function setButtons(array $buttons): void { From 33e816ce97f308e77b42e989692567036ad330d9 Mon Sep 17 00:00:00 2001 From: Alex Komarichev Date: Tue, 25 Jun 2024 11:20:01 +0300 Subject: [PATCH 3/3] Add templateSend phpdoc --- src/Bot/Client.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Bot/Client.php b/src/Bot/Client.php index 85a0fc5..750bd44 100644 --- a/src/Bot/Client.php +++ b/src/Bot/Client.php @@ -481,6 +481,15 @@ class Client return $adapter->getResponseList($response); } + /** + * Send a template message + * + * @param string $templateId + * @param Model\Request\TemplateSendRequest $request Request parameters + * + * @return \RetailCrm\Mg\Bot\Model\ModelInterface + * @throws \Exception + */ public function templateSend(string $templateId, Model\Request\TemplateSendRequest $request): ModelInterface { $response = $this->client->makeRequest(