Skip to content

Commit af207a5

Browse files
Feature/messages v1 ga (#319)
* Skeleton messages architecture, need to implement more interface methods * More scaffolding * More scaffolding, first test passing * MMS implementation, message objects * WhatsApp basic structure for testing * WhatsApp extended implementation * Messenger implementation * Viber implementation * Fix failing test due to a find and replace mistake * ViberService trait for image * Docs update in readme * Update Readme to include Messages API * Add the messages client into the core mapper * Change API URL, set errors on 200 to false * Refactor to reuse common outputs * Refactor to adhere to some DRY, added custom error handler for API responses plus tests * Take out needless links from readme * Fix collection names * Quick confiig move for base url * Channel namespace change * Update README.md Co-authored-by: Chris Tankersley <chris@ctankersley.com> * Update README.md Co-authored-by: Chris Tankersley <chris@ctankersley.com> Co-authored-by: Chris Tankersley <chris@ctankersley.com>
1 parent a031483 commit af207a5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+2252
-11
lines changed

README.md

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ For APIs that would usually hit `rest.nexmo.com`, supplying a `base_rest_url` as
7373
Examples
7474
--------
7575

76-
### Sending a Message
76+
### Sending a Message via the SMS API
7777

7878
To use [Vonage's SMS API][doc_sms] to send an SMS message, call the `$client->sms()->send()` method.
7979

@@ -164,6 +164,71 @@ $isValid = $signature->check($_GET['sig']);
164164

165165
Using your signature secret and the other supplied parameters, the signature can be calculated and checked against the incoming signature value.
166166

167+
### Sending a Message via. the Messages API
168+
169+
The [Messages API](https://developer.vonage.com/api/messages-olympus) is used to send a variety of outbound messages.
170+
The following platforms are currently supported:
171+
* **SMS**
172+
* **MMS**
173+
* **WhatsApp**
174+
* **Messenger**
175+
* **Viber**
176+
177+
Each one of these platforms has a different category of message you can send (for example, with WhatsApp you can send
178+
text, an image, audio, video, a file or a template but for Viber you can only send a text or an image). You can find
179+
all the sendable message types under the namespace `\Vonage\Messages\Channel`. The reason each type is separated
180+
out this way is that the platform and message type requires different parameters in the API call.
181+
182+
The `\Vonage\Messages\Client` is configured in a similar way to the SMS API Client. The difference is that the
183+
authentication can be either a JSON Web Token (JWT) or Basic Authentication. You can find more info on how to set
184+
up your Client's credentials under the 'Usage' section of this ReadMe.
185+
186+
Here some examples:
187+
188+
### Sending a WhatsApp Text
189+
190+
First, we need to create a new WhatsAppText object like so:
191+
192+
```php
193+
$whatsAppText = new Vonage\Messages\Channel\WhatsApp\WhatsAppText(
194+
FROM_NUMBER,
195+
TO_NUMBER,
196+
'this is a WA text from vonage'
197+
);
198+
```
199+
200+
The Messages API Client has one method, `send()` where you can send any of the message types provided. So, to send this
201+
message, the following code will do that, assuming you have already set up your Vonage client correctly:
202+
203+
```php
204+
$client->messages()->send($whatsAppText);
205+
```
206+
207+
Your response will be a JSON payload if the error range is with 200, or will throw a relevant `APIException` if it's
208+
within 400/500.
209+
210+
### Send a Viber Image
211+
212+
Some `Channel` objects require more arguments in order to be created. You can see the rough mapping of these
213+
requirements by comparing the constructor arguments vs. the API Documentation. Some of these messages take custom
214+
reusable objects (that are under the `\Vonage\Messages\MessageObjects` namespace). One of these is an image - so
215+
here is an example of how to send a Viber Image:
216+
217+
```php
218+
$imageObject = Vonage\Messages\MessageObjects\ImageObject(
219+
'https://picsum.photos/200/300',
220+
'image caption'
221+
);
222+
223+
$viberImage = new Vonage\Messages\Channel\Viber\ViberImage(
224+
FROM_NUMBER,
225+
TO_NUMBER,
226+
$imageObject
227+
);
228+
229+
$client->messages()->send($viberImage);
230+
```
231+
167232
### Starting a Verification
168233

169234
Vonage's [Verify API][doc_verify] makes it easy to prove that a user has provided their own phone number during signup,
@@ -743,7 +808,7 @@ Check out the [documentation](https://developer.nexmo.com/number-insight/code-sn
743808
| Dispatch API | Beta ||
744809
| External Accounts API | Beta ||
745810
| Media API | Beta ||
746-
| Messages API | Beta ||
811+
| Messages API | General Availability ||
747812
| Number Insight API | General Availability ||
748813
| Number Management API | General Availability ||
749814
| Pricing API | General Availability ||

src/Client.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
use Vonage\Redact\ClientFactory as RedactClientFactory;
5353
use Vonage\Secrets\ClientFactory as SecretsClientFactory;
5454
use Vonage\SMS\ClientFactory as SMSClientFactory;
55+
use Vonage\Messages\ClientFactory as MessagesClientFactory;
5556
use Vonage\Verify\ClientFactory as VerifyClientFactory;
5657
use Vonage\Verify\Verification;
5758
use Vonage\Voice\ClientFactory as VoiceClientFactory;
@@ -76,6 +77,7 @@
7677
*
7778
* @method Account\Client account()
7879
* @method Message\Client message()
80+
* @method Messages\Client messages()
7981
* @method Application\Client applications()
8082
* @method Conversion\Client conversion()
8183
* @method Insights\Client insights()
@@ -205,6 +207,7 @@ public function __construct(CredentialsInterface $credentials, $options = [], ?C
205207
'conversion' => ConversionClientFactory::class,
206208
'insights' => InsightsClientFactory::class,
207209
'numbers' => NumbersClientFactory::class,
210+
'messages' => MessagesClientFactory::class,
208211
'redact' => RedactClientFactory::class,
209212
'secrets' => SecretsClientFactory::class,
210213
'sms' => SMSClientFactory::class,
@@ -587,7 +590,10 @@ protected static function requiresAuthInUrlNotBody(RequestInterface $request): b
587590
{
588591
$path = $request->getUri()->getPath();
589592

590-
return strpos($path, '/v1/redact') === 0;
593+
$isRedact = strpos($path, '/v1/redact') === 0;
594+
$isMessages = strpos($path, '/v1/messages') === 0;
595+
596+
return $isRedact || $isMessages;
591597
}
592598

593599
protected function needsKeypairAuthentication(RequestInterface $request): bool
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
<?php
2+
3+
namespace Vonage\Messages\Channel;
4+
5+
abstract class BaseMessage implements Message
6+
{
7+
protected string $subType;
8+
protected string $to;
9+
protected string $from;
10+
protected string $channel;
11+
protected ?string $clientRef = null;
12+
13+
public const MESSAGES_SUBTYPE_TEXT = 'text';
14+
public const MESSAGES_SUBTYPE_IMAGE = 'image';
15+
public const MESSAGES_SUBTYPE_VCARD = 'vcard';
16+
public const MESSAGES_SUBTYPE_AUDIO = 'audio';
17+
public const MESSAGES_SUBTYPE_VIDEO = 'video';
18+
public const MESSAGES_SUBTYPE_FILE = 'file';
19+
public const MESSAGES_SUBTYPE_TEMPLATE = 'template';
20+
public const MESSAGES_SUBTYPE_CUSTOM = 'custom';
21+
22+
public function getClientRef(): ?string
23+
{
24+
return $this->clientRef;
25+
}
26+
27+
public function setClientRef(string $clientRef): void
28+
{
29+
$this->clientRef = $clientRef;
30+
}
31+
32+
public function getSubType(): string
33+
{
34+
return $this->subType;
35+
}
36+
37+
public function getFrom(): string
38+
{
39+
return $this->from;
40+
}
41+
42+
public function setFrom(string $from): void
43+
{
44+
$this->from = $from;
45+
}
46+
47+
public function getChannel(): string
48+
{
49+
return $this->channel;
50+
}
51+
52+
public function getTo(): string
53+
{
54+
return $this->to;
55+
}
56+
57+
public function setTo(string $to): void
58+
{
59+
$this->to = $to;
60+
}
61+
62+
public function getBaseMessageUniversalOutputArray(): array
63+
{
64+
$returnArray = [
65+
'message_type' => $this->getSubType(),
66+
'to' => $this->getTo(),
67+
'from' => $this->getFrom(),
68+
'channel' => $this->getChannel(),
69+
];
70+
71+
if ($this->getClientRef()) {
72+
$returnArray['client_ref'] = $this->getClientRef();
73+
}
74+
75+
return $returnArray;
76+
}
77+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace Vonage\Messages\Channel\MMS;
4+
5+
use Vonage\Messages\MessageObjects\AudioObject;
6+
use Vonage\Messages\Channel\BaseMessage;
7+
8+
class MMSAudio extends BaseMessage
9+
{
10+
protected string $channel = 'mms';
11+
protected string $subType = BaseMessage::MESSAGES_SUBTYPE_AUDIO;
12+
protected AudioObject $audioObject;
13+
14+
public function __construct(
15+
string $to,
16+
string $from,
17+
AudioObject $audioObject
18+
) {
19+
$this->to = $to;
20+
$this->from = $from;
21+
$this->audioObject = $audioObject;
22+
}
23+
24+
public function toArray(): array
25+
{
26+
$returnArray = $this->getBaseMessageUniversalOutputArray();
27+
$returnArray['audio'] = $this->audioObject->toArray();
28+
29+
return $returnArray;
30+
}
31+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace Vonage\Messages\Channel\MMS;
4+
5+
use Vonage\Messages\MessageObjects\ImageObject;
6+
use Vonage\Messages\Channel\BaseMessage;
7+
8+
class MMSImage extends BaseMessage
9+
{
10+
protected string $channel = 'mms';
11+
protected string $subType = BaseMessage::MESSAGES_SUBTYPE_IMAGE;
12+
protected ImageObject $image;
13+
14+
public function __construct(
15+
string $to,
16+
string $from,
17+
ImageObject $image
18+
) {
19+
$this->to = $to;
20+
$this->from = $from;
21+
$this->image = $image;
22+
}
23+
24+
public function toArray(): array
25+
{
26+
$returnArray = $this->getBaseMessageUniversalOutputArray();
27+
$returnArray['image'] = $this->image->toArray();
28+
29+
return $returnArray;
30+
}
31+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace Vonage\Messages\Channel\MMS;
4+
5+
use Vonage\Messages\MessageObjects\AudioObject;
6+
use Vonage\Messages\MessageObjects\VideoObject;
7+
use Vonage\Messages\Channel\BaseMessage;
8+
9+
class MMSVideo extends BaseMessage
10+
{
11+
protected string $channel = 'mms';
12+
protected string $subType = BaseMessage::MESSAGES_SUBTYPE_VIDEO;
13+
protected VideoObject $videoObject;
14+
15+
public function __construct(
16+
string $to,
17+
string $from,
18+
VideoObject $videoObject
19+
) {
20+
$this->to = $to;
21+
$this->from = $from;
22+
$this->videoObject = $videoObject;
23+
}
24+
25+
public function toArray(): array
26+
{
27+
$returnArray = $this->getBaseMessageUniversalOutputArray();
28+
$returnArray['video'] = $this->videoObject->toArray();
29+
30+
return $returnArray;
31+
}
32+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace Vonage\Messages\Channel\MMS;
4+
5+
use Vonage\Messages\MessageObjects\VCardObject;
6+
use Vonage\Messages\Channel\BaseMessage;
7+
8+
class MMSvCard extends BaseMessage
9+
{
10+
protected string $channel = 'mms';
11+
protected string $subType = BaseMessage::MESSAGES_SUBTYPE_VCARD;
12+
protected VCardObject $vCard;
13+
14+
public function __construct(
15+
string $to,
16+
string $from,
17+
VCardObject $vCard
18+
) {
19+
$this->to = $to;
20+
$this->from = $from;
21+
$this->vCard = $vCard;
22+
}
23+
24+
public function toArray(): array
25+
{
26+
$returnArray = $this->getBaseMessageUniversalOutputArray();
27+
$returnArray['vcard'] = $this->vCard->toArray();
28+
29+
return $returnArray;
30+
}
31+
}

src/Messages/Channel/Message.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
/**
4+
* Vonage Client Library for PHP
5+
*
6+
* @copyright Copyright (c) 2016-2020 Vonage, Inc. (http://vonage.com)
7+
* @license https://github.com/Vonage/vonage-php-sdk-core/blob/master/LICENSE.txt Apache License 2.0
8+
*/
9+
10+
declare(strict_types=1);
11+
12+
namespace Vonage\Messages\Channel;
13+
14+
interface Message
15+
{
16+
public function toArray(): array;
17+
public function getTo(): string;
18+
public function setTo(string $to): void;
19+
public function getFrom(): string;
20+
public function setFrom(string $from): void;
21+
public function getClientRef(): ?string;
22+
public function getChannel(): string;
23+
public function getSubType(): string;
24+
public function setClientRef(string $clientRef): void;
25+
26+
/**
27+
* All message types have shared outputs required by the endpoint.
28+
* Child classes are required to call this before assembling their
29+
* own specific output
30+
*
31+
* @return array
32+
*/
33+
public function getBaseMessageUniversalOutputArray(): array;
34+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Vonage\Messages\Channel\Messenger;
4+
5+
class InvalidCategoryException extends \Exception
6+
{
7+
}

0 commit comments

Comments
 (0)