diff --git a/src/Messages/Channel/RCS/RcsCustom.php b/src/Messages/Channel/RCS/RcsCustom.php new file mode 100644 index 00000000..b94c733d --- /dev/null +++ b/src/Messages/Channel/RCS/RcsCustom.php @@ -0,0 +1,77 @@ +to = $to; + $this->from = $from; + $this->custom = $custom; + } + + public function getCustom(): array + { + return $this->custom; + } + + public function setCustom(array $custom): RcsCustom + { + $this->custom = $custom; + return $this; + } + + public function setTtl(?int $ttl): void + { + $range = [ + 'options' => [ + 'min_range' => self::RCS_TEXT_MIN_TTL, + 'max_range' => self::RCS_TEXT_MAX_TTL + ] + ]; + + if (!filter_var($ttl, FILTER_VALIDATE_INT, $range)) { + throw new RcsInvalidTtlException('Timeout ' . $ttl . ' is not valid'); + } + + $this->ttl = $ttl; + } + + public function toArray(): array + { + $returnArray = $this->getBaseMessageUniversalOutputArray(); + + $returnArray['custom'] = $this->getCustom(); + + if ($this->getClientRef()) { + $returnArray['client_ref'] = $this->getClientRef(); + } + + if ($this->getWebhookUrl()) { + $returnArray['webhook_url'] = $this->getWebhookUrl(); + } + + if ($this->getTtl()) { + $returnArray['ttl'] = $this->getTtl(); + } + + return $returnArray; + } +} diff --git a/src/Messages/Channel/RCS/RcsFile.php b/src/Messages/Channel/RCS/RcsFile.php new file mode 100644 index 00000000..1dc575cb --- /dev/null +++ b/src/Messages/Channel/RCS/RcsFile.php @@ -0,0 +1,77 @@ +to = $to; + $this->from = $from; + $this->file = $file; + } + + public function setTtl(?int $ttl): void + { + $range = [ + 'options' => [ + 'min_range' => self::RCS_TEXT_MIN_TTL, + 'max_range' => self::RCS_TEXT_MAX_TTL + ] + ]; + + if (!filter_var($ttl, FILTER_VALIDATE_INT, $range)) { + throw new RcsInvalidTtlException('Timeout ' . $ttl . ' is not valid'); + } + + $this->ttl = $ttl; + } + + public function getFile(): FileObject + { + return $this->file; + } + + public function setFile(FileObject $fileObject): RcsFile + { + $this->file = $fileObject; + return $this; + } + + public function toArray(): array + { + $returnArray = $this->getBaseMessageUniversalOutputArray(); + + $returnArray['file'] = $this->getFile()->toArray(); + + if ($this->getClientRef()) { + $returnArray['client_ref'] = $this->getClientRef(); + } + + if ($this->getWebhookUrl()) { + $returnArray['webhook_url'] = $this->getWebhookUrl(); + } + + if ($this->getTtl()) { + $returnArray['ttl'] = $this->getTtl(); + } + + return $returnArray; + } +} diff --git a/src/Messages/Channel/RCS/RcsImage.php b/src/Messages/Channel/RCS/RcsImage.php new file mode 100644 index 00000000..25031298 --- /dev/null +++ b/src/Messages/Channel/RCS/RcsImage.php @@ -0,0 +1,77 @@ +to = $to; + $this->from = $from; + $this->image = $image; + } + + public function setTtl(?int $ttl): void + { + $range = [ + 'options' => [ + 'min_range' => self::RCS_TEXT_MIN_TTL, + 'max_range' => self::RCS_TEXT_MAX_TTL + ] + ]; + + if (!filter_var($ttl, FILTER_VALIDATE_INT, $range)) { + throw new RcsInvalidTtlException('Timeout ' . $ttl . ' is not valid'); + } + + $this->ttl = $ttl; + } + + public function getImage(): ImageObject + { + return $this->image; + } + + public function setImage(ImageObject $image): RcsImage + { + $this->image = $image; + return $this; + } + + public function toArray(): array + { + $returnArray = $this->getBaseMessageUniversalOutputArray(); + + $returnArray['image'] = $this->getImage()->toArray(); + + if ($this->getClientRef()) { + $returnArray['client_ref'] = $this->getClientRef(); + } + + if ($this->getWebhookUrl()) { + $returnArray['webhook_url'] = $this->getWebhookUrl(); + } + + if ($this->getTtl()) { + $returnArray['ttl'] = $this->getTtl(); + } + + return $returnArray; + } +} diff --git a/src/Messages/Channel/RCS/RcsInvalidTtlException.php b/src/Messages/Channel/RCS/RcsInvalidTtlException.php new file mode 100644 index 00000000..b7866a99 --- /dev/null +++ b/src/Messages/Channel/RCS/RcsInvalidTtlException.php @@ -0,0 +1,7 @@ +to = $to; + $this->from = $from; + $this->text = $message; + } + + public function setTtl(?int $ttl): void + { + $range = [ + 'options' => [ + 'min_range' => self::RCS_TEXT_MIN_TTL, + 'max_range' => self::RCS_TEXT_MAX_TTL + ] + ]; + + if (!filter_var($ttl, FILTER_VALIDATE_INT, $range)) { + throw new RcsInvalidTtlException('Timeout ' . $ttl . ' is not valid'); + } + + $this->ttl = $ttl; + } + + public function toArray(): array + { + $returnArray = $this->getBaseMessageUniversalOutputArray(); + $returnArray['text'] = $this->getText(); + + if ($this->getClientRef()) { + $returnArray['client_ref'] = $this->getClientRef(); + } + + if ($this->getWebhookUrl()) { + $returnArray['webhook_url'] = $this->getWebhookUrl(); + } + + if ($this->getTtl()) { + $returnArray['ttl'] = $this->getTtl(); + } + + return $returnArray; + } +} diff --git a/src/Messages/Channel/RCS/RcsVideo.php b/src/Messages/Channel/RCS/RcsVideo.php new file mode 100644 index 00000000..254fba31 --- /dev/null +++ b/src/Messages/Channel/RCS/RcsVideo.php @@ -0,0 +1,77 @@ +to = $to; + $this->from = $from; + $this->video = $videoObject; + } + + public function setTtl(?int $ttl): void + { + $range = [ + 'options' => [ + 'min_range' => self::RCS_TEXT_MIN_TTL, + 'max_range' => self::RCS_TEXT_MAX_TTL + ] + ]; + + if (!filter_var($ttl, FILTER_VALIDATE_INT, $range)) { + throw new RcsInvalidTtlException('Timeout ' . $ttl . ' is not valid'); + } + + $this->ttl = $ttl; + } + + public function getVideo(): VideoObject + { + return $this->video; + } + + public function setVideo(VideoObject $videoObject): RcsVideo + { + $this->video = $videoObject; + return $this; + } + + public function toArray(): array + { + $returnArray = $this->getBaseMessageUniversalOutputArray(); + + $returnArray['video'] = $this->getVideo()->toArray(); + + if ($this->getClientRef()) { + $returnArray['client_ref'] = $this->getClientRef(); + } + + if ($this->getWebhookUrl()) { + $returnArray['webhook_url'] = $this->getWebhookUrl(); + } + + if ($this->getTtl()) { + $returnArray['ttl'] = $this->getTtl(); + } + + return $returnArray; + } +} diff --git a/test/Messages/ClientTest.php b/test/Messages/ClientTest.php index f510b306..00d68f5b 100644 --- a/test/Messages/ClientTest.php +++ b/test/Messages/ClientTest.php @@ -19,6 +19,12 @@ use Vonage\Messages\Channel\MMS\MMSImage; use Vonage\Messages\Channel\MMS\MMSvCard; use Vonage\Messages\Channel\MMS\MMSVideo; +use Vonage\Messages\Channel\RCS\RcsCustom; +use Vonage\Messages\Channel\RCS\RcsFile; +use Vonage\Messages\Channel\RCS\RcsImage; +use Vonage\Messages\Channel\RCS\RcsInvalidTtlException; +use Vonage\Messages\Channel\RCS\RcsText; +use Vonage\Messages\Channel\RCS\RcsVideo; use Vonage\Messages\Channel\SMS\SMSText; use Vonage\Messages\Channel\Viber\ViberFile; use Vonage\Messages\Channel\Viber\ViberImage; @@ -960,6 +966,236 @@ public function testCanSendViberVideo(): void $this->assertArrayHasKey('message_uuid', $result); } + public function testCanSendRcsText(): void + { + $payload = [ + 'to' => '447700900000', + 'from' => '16105551212', + 'text' => 'Reticulating Splines', + 'client_ref' => 'RCS Message', + 'ttl' => 330, + 'webhook_url' => 'https://example.com/incoming' + ]; + + $message = new RcsText($payload['to'], $payload['from'], $payload['text']); + $message->setClientRef($payload['client_ref']); + $message->setTtl($payload['ttl']); + $message->setWebhookUrl($payload['webhook_url']); + + $this->vonageClient->send(Argument::that(function (Request $request) use ($payload) { + $this->assertEquals( + 'Bearer ', + mb_substr($request->getHeaders()['Authorization'][0], 0, 7) + ); + $this->assertRequestJsonBodyContains('to', $payload['to'], $request); + $this->assertRequestJsonBodyContains('from', $payload['from'], $request); + $this->assertRequestJsonBodyContains('text', $payload['text'], $request); + $this->assertRequestJsonBodyContains('client_ref', $payload['client_ref'], $request); + $this->assertRequestJsonBodyContains('webhook_url', $payload['webhook_url'], $request); + $this->assertRequestJsonBodyContains('ttl', $payload['ttl'], $request); + $this->assertRequestJsonBodyContains('channel', 'rcs', $request); + $this->assertRequestJsonBodyContains('message_type', 'text', $request); + $this->assertEquals('POST', $request->getMethod()); + + return true; + }))->willReturn($this->getResponse('rcs-success', 202)); + + $result = $this->messageClient->send($message); + $this->assertIsArray($result); + $this->assertArrayHasKey('message_uuid', $result); + } + + public function testCannotSendRcsTtlOutOfRange() + { + $this->expectException(RcsInvalidTtlException::class); + + $payload = [ + 'to' => '447700900000', + 'from' => '16105551212', + 'text' => 'Reticulating Splines', + 'ttl' => 100, + ]; + + $message = new RcsText($payload['to'], $payload['from'], $payload['text']); + $message->setTtl($payload['ttl']); + } + + public function testCanSendRcsImage() + { + $image = new ImageObject('https://my-image.com'); + + $payload = [ + 'to' => '447700900000', + 'from' => '16105551212', + 'text' => 'Reticulating Splines', + 'client_ref' => 'RCS Message', + 'ttl' => 330, + 'webhook_url' => 'https://example.com/incoming', + 'image' => $image + ]; + + $message = new RcsImage($payload['to'], $payload['from'], $payload['image']); + $message->setClientRef($payload['client_ref']); + $message->setTtl($payload['ttl']); + $message->setWebhookUrl($payload['webhook_url']); + + $this->vonageClient->send(Argument::that(function (Request $request) use ($payload) { + $this->assertEquals( + 'Bearer ', + mb_substr($request->getHeaders()['Authorization'][0], 0, 7) + ); + $this->assertRequestJsonBodyContains('to', $payload['to'], $request); + $this->assertRequestJsonBodyContains('from', $payload['from'], $request); + $this->assertRequestJsonBodyContains('client_ref', $payload['client_ref'], $request); + $this->assertRequestJsonBodyContains('webhook_url', $payload['webhook_url'], $request); + $this->assertRequestJsonBodyContains('ttl', $payload['ttl'], $request); + $this->assertRequestJsonBodyContains('channel', 'rcs', $request); + $this->assertRequestJsonBodyContains('message_type', 'image', $request); + $this->assertRequestJsonBodyContains('image', ['url' => 'https://my-image.com'], $request); + $this->assertEquals('POST', $request->getMethod()); + + return true; + }))->willReturn($this->getResponse('rcs-success', 202)); + + $result = $this->messageClient->send($message); + $this->assertIsArray($result); + $this->assertArrayHasKey('message_uuid', $result); + } + + public function testCanSendRcsVideo(): void + { + $videoObject = new VideoObject('https://my-image.com'); + + $payload = [ + 'to' => '447700900000', + 'from' => '16105551212', + 'text' => 'Reticulating Splines', + 'client_ref' => 'RCS Message', + 'ttl' => 330, + 'webhook_url' => 'https://example.com/incoming', + 'video' => $videoObject + ]; + + $message = new RcsVideo($payload['to'], $payload['from'], $payload['video']); + $message->setClientRef($payload + ['client_ref']); + $message->setTtl($payload['ttl']); + $message->setWebhookUrl($payload['webhook_url']); + + $this->vonageClient->send(Argument::that(function (Request $request) use ($payload) { + $this->assertEquals( + 'Bearer ', + mb_substr($request->getHeaders()['Authorization'][0], 0, 7) + ); + $this->assertRequestJsonBodyContains('to', $payload['to'], $request); + $this->assertRequestJsonBodyContains('from', $payload['from'], $request); + $this->assertRequestJsonBodyContains('client_ref', $payload['client_ref'], $request); + $this->assertRequestJsonBodyContains('webhook_url', $payload['webhook_url'], $request); + $this->assertRequestJsonBodyContains('ttl', $payload['ttl'], $request); + $this->assertRequestJsonBodyContains('channel', 'rcs', $request); + $this->assertRequestJsonBodyContains('message_type', 'video', $request); + $this->assertRequestJsonBodyContains('video', ['url' => 'https://my-image.com'], $request); + $this->assertEquals('POST', $request->getMethod()); + + return true; + }))->willReturn($this->getResponse('rcs-success', 202)); + + $result = $this->messageClient->send($message); + $this->assertIsArray($result); + $this->assertArrayHasKey('message_uuid', $result); + } + + public function testCanSendRcsFile(): void + { + $fileObject = new FileObject('https://example.com/file.pdf'); + + $payload = [ + 'to' => '447700900000', + 'from' => '16105551212', + 'text' => 'Reticulating Splines', + 'client_ref' => 'RCS Message', + 'ttl' => 330, + 'webhook_url' => 'https://example.com/incoming', + 'file' => $fileObject + ]; + + $message = new RcsFile($payload['to'], $payload['from'], $payload['file']); + $message->setClientRef($payload['client_ref']); + $message->setTtl($payload['ttl']); + $message->setWebhookUrl($payload['webhook_url']); + + $this->vonageClient->send(Argument::that(function (Request $request) use ($payload) { + $this->assertEquals( + 'Bearer ', + mb_substr($request->getHeaders()['Authorization'][0], 0, 7) + ); + $this->assertRequestJsonBodyContains('to', $payload['to'], $request); + $this->assertRequestJsonBodyContains('from', $payload['from'], $request); + $this->assertRequestJsonBodyContains('client_ref', $payload['client_ref'], $request); + $this->assertRequestJsonBodyContains('webhook_url', $payload['webhook_url'], $request); + $this->assertRequestJsonBodyContains('ttl', $payload['ttl'], $request); + $this->assertRequestJsonBodyContains('channel', 'rcs', $request); + $this->assertRequestJsonBodyContains('message_type', 'file', $request); + $this->assertRequestJsonBodyContains('file', ['url' => 'https://example.com/file.pdf'], $request); + $this->assertEquals('POST', $request->getMethod()); + + return true; + }))->willReturn($this->getResponse('rcs-success', 202)); + + $result = $this->messageClient->send($message); + $this->assertIsArray($result); + $this->assertArrayHasKey('message_uuid', $result); + } + + public function testCanSendRcsCustom() + { + $customObject = [ + 'custom_key' => 'custom_value', + ]; + + $payload = [ + 'to' => '447700900000', + 'from' => '16105551212', + 'text' => 'Reticulating Splines', + 'client_ref' => 'RCS Message', + 'ttl' => 330, + 'webhook_url' => 'https://example.com/incoming', + 'custom' => $customObject + ]; + + $message = new RcsCustom($payload['to'], $payload['from'], $payload['custom']); + $message->setClientRef($payload['client_ref']); + $message->setTtl($payload['ttl']); + $message->setWebhookUrl($payload['webhook_url']); + + $this->vonageClient->send(Argument::that(function (Request $request) use ($payload) { + $this->assertEquals( + 'Bearer ', + mb_substr($request->getHeaders()['Authorization'][0], 0, 7) + ); + $this->assertRequestJsonBodyContains('to', $payload['to'], $request); + $this->assertRequestJsonBodyContains('from', $payload['from'], $request); + $this->assertRequestJsonBodyContains('client_ref', $payload['client_ref'], $request); + $this->assertRequestJsonBodyContains('webhook_url', $payload['webhook_url'], $request); + $this->assertRequestJsonBodyContains('ttl', $payload['ttl'], $request); + $this->assertRequestJsonBodyContains('channel', 'rcs', $request); + $this->assertRequestJsonBodyContains('message_type', 'file', $request); + $this->assertRequestJsonBodyContains('custom', ['custom_key' => 'custom_value'], $request); + $this->assertEquals('POST', $request->getMethod()); + + return true; + }))->willReturn($this->getResponse('rcs-success', 202)); + + $result = $this->messageClient->send($message); + $this->assertIsArray($result); + $this->assertArrayHasKey('message_uuid', $result); + } + + public function testCanUpdateRcsMessage() + { + $this->markTestIncomplete(); + } + public function stickerTypeProvider(): array { return [ diff --git a/test/Messages/Fixtures/Responses/rcs-success.json b/test/Messages/Fixtures/Responses/rcs-success.json new file mode 100644 index 00000000..d9cb1168 --- /dev/null +++ b/test/Messages/Fixtures/Responses/rcs-success.json @@ -0,0 +1,3 @@ +{ + "message_uuid": "aaaaaaaa-bbbb-cccc-dddd-0123456789ab" +} \ No newline at end of file