Skip to content

Commit 607cdfe

Browse files
committed
Added Delivery Receipt incoming webhook
1 parent 02d0016 commit 607cdfe

File tree

9 files changed

+446
-10
lines changed

9 files changed

+446
-10
lines changed
Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Nexmo\SMS\Webhook;
5+
6+
class DeliveryReceipt
7+
{
8+
/**
9+
* Message was delivered successfully
10+
*/
11+
const CODE_DELIVERED = 0;
12+
13+
/**
14+
* Message was not delivered, and no reason could be determined
15+
*/
16+
const CODE_UKNOWN = 1;
17+
18+
/**
19+
* Message was not delivered because handset was temporarily unavailable - retry
20+
*/
21+
const CODE_ABSENT_TEMPORARY = 2;
22+
23+
/**
24+
* The number is no longer active and should be removed from your database
25+
*/
26+
const CODE_ABSENT_PERMANENT = 3;
27+
28+
/**
29+
* This is a permanent error.
30+
* The number should be removed from your database and the user must
31+
* contact their network operator to remove the bar
32+
*/
33+
const CODE_BARRED = 4;
34+
35+
/**
36+
* There is an issue relating to portability of the number and you should contact the network operator to resolve it
37+
*/
38+
const CODE_PORTABILITY_ERROR = 5;
39+
40+
/**
41+
* The message has been blocked by a carrier's anti-spam filter
42+
*/
43+
const CODE_SPAM_REJECTION = 6;
44+
45+
/**
46+
* The handset was not available at the time the message was sent - retry
47+
*/
48+
const CODE_HANDSET_BUSY = 7;
49+
50+
/**
51+
* The message failed due to a network error - retry
52+
*/
53+
const CODE_NETWORK_ERROR = 8;
54+
55+
/**
56+
* The user has specifically requested not to receive messages from a specific service
57+
*/
58+
const CODE_ILLEGAL_NUMBER = 9;
59+
60+
/**
61+
* There is an error in a message parameter, e.g. wrong encoding flag
62+
*/
63+
const CODE_ILLEGAL_MESSAGE = 10;
64+
65+
/**
66+
* Nexmo cannot find a suitable route to deliver the message
67+
68+
*/
69+
const CODE_UNROUTABLE = 11;
70+
71+
/**
72+
* A route to the number cannot be found - confirm the recipient's number
73+
*/
74+
const CODE_UNREACHABLE = 12;
75+
76+
/**
77+
* The target cannot receive your message due to their age
78+
*/
79+
const CODE_AGE_RESTRICTION = 13;
80+
81+
/**
82+
* The recipient should ask their carrier to enable SMS on their plan
83+
*/
84+
const CODE_CARRIER_BLOCK = 14;
85+
86+
/**
87+
* The recipient is on a prepaid plan and does not have enough credit to receive your message
88+
*/
89+
const CODE_INSUFFICIENT_FUNDS = 15;
90+
91+
/**
92+
* Typically refers to an error in the route
93+
94+
*/
95+
const CODE_GENERAL_ERROR = 99;
96+
97+
/**
98+
* Message has been accepted for delivery, but has not yet been delivered
99+
*/
100+
const STATUS_ACCEPTED = 'accepted';
101+
102+
/**
103+
* Message has been delivered
104+
*/
105+
const STATUS_DELIVERED = 'delivered';
106+
107+
/**
108+
* Message has been buffered for later delivery
109+
*/
110+
const STATUS_BUFFERED = 'buffered';
111+
112+
/**
113+
* Message was held at downstream carrier's retry scheme and could not be delivered within the expiry time
114+
*/
115+
const STATUS_EXPIRED = 'expired';
116+
117+
/**
118+
* Message not delivered
119+
*/
120+
const STATUS_FAILED = 'failed';
121+
122+
/**
123+
* Downstream carrier refuses to deliver message
124+
*/
125+
const STATUS_REJECTED = 'rejected';
126+
127+
/**
128+
* No useful information available
129+
*/
130+
const STATUS_UNKNOWN = 'unknown';
131+
132+
public static $requiredFields = [
133+
'err-code', 'message-timestamp', 'messageId', 'msisdn', 'network-code',
134+
'price', 'scts', 'status', 'to'
135+
];
136+
137+
/**
138+
* @var int
139+
*/
140+
protected $errCode;
141+
142+
/**
143+
* @var \DateTimeImmutable
144+
*/
145+
protected $messageTimestamp;
146+
147+
/**
148+
* @var string
149+
*/
150+
protected $messageId;
151+
152+
/**
153+
* @var string
154+
*/
155+
protected $msisdn;
156+
157+
/**
158+
* @var string
159+
*/
160+
protected $networkCode;
161+
162+
/**
163+
* @var string
164+
*/
165+
protected $price;
166+
167+
/**
168+
* @var string
169+
*/
170+
protected $scts;
171+
172+
/**
173+
* @var string
174+
*/
175+
protected $status;
176+
177+
/**
178+
* @var string
179+
*/
180+
protected $to;
181+
182+
/**
183+
* @var string
184+
*/
185+
protected $apiKey;
186+
187+
/**
188+
* @param array<string, string> $data
189+
*/
190+
public function __construct(array $data)
191+
{
192+
foreach (static::$requiredFields as $key) {
193+
if (!array_key_exists($key, $data)) {
194+
throw new \InvalidArgumentException('Delivery Receipt missing required data `' . $key . '`');
195+
}
196+
}
197+
198+
$this->errCode = filter_var($data['err-code'], FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE);
199+
$this->messageTimestamp = new \DateTimeImmutable($data['message-timestamp']);
200+
$this->messageId = $data['messageId'];
201+
$this->msisdn = $data['msisdn'];
202+
$this->networkCode = $data['network-code'];
203+
$this->price = $data['price'];
204+
$this->scts = $data['scts'];
205+
$this->status = $data['status'];
206+
$this->to = $data['to'];
207+
$this->apiKey = $data['api-key'];
208+
}
209+
210+
public function getErrCode() : int
211+
{
212+
return $this->errCode;
213+
}
214+
215+
public function getMessageTimestamp() : \DateTimeImmutable
216+
{
217+
return $this->messageTimestamp;
218+
}
219+
220+
public function getMessageId() : string
221+
{
222+
return $this->messageId;
223+
}
224+
225+
public function getMsisdn() : string
226+
{
227+
return $this->msisdn;
228+
}
229+
230+
public function getNetworkCode() : string
231+
{
232+
return $this->networkCode;
233+
}
234+
235+
public function getPrice() : string
236+
{
237+
return $this->price;
238+
}
239+
240+
public function getScts() : string
241+
{
242+
return $this->scts;
243+
}
244+
245+
public function getStatus() : string
246+
{
247+
return $this->status;
248+
}
249+
250+
public function getTo() : string
251+
{
252+
return $this->to;
253+
}
254+
255+
public function getApiKey() : string
256+
{
257+
return $this->apiKey;
258+
}
259+
}

src/SMS/Webhook/Factory.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@ class Factory extends WebhookFactory
1010
{
1111
public static function createFromArray(array $data)
1212
{
13-
return new InboundSMS($data);
13+
if (array_key_exists('scts', $data)) {
14+
return new DeliveryReceipt($data);
15+
}
16+
17+
if (count(array_intersect(array_keys($data), InboundSMS::$requiredFields))
18+
=== count(InboundSMS::$requiredFields)
19+
) {
20+
return new InboundSMS($data);
21+
}
22+
23+
throw new \InvalidArgumentException("Unable to determine incoming webhook type");
1424
}
1525
}

src/SMS/Webhook/InboundSMS.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55

66
class InboundSMS
77
{
8+
public static $requiredFields = [
9+
'msisdn', 'to', 'messageId', 'text', 'type', 'keyword',
10+
'message-timestamp'
11+
];
12+
813
/**
914
* @var string
1015
*/
@@ -92,12 +97,7 @@ class InboundSMS
9297

9398
public function __construct(array $data)
9499
{
95-
$required = [
96-
'msisdn', 'to', 'messageId', 'text', 'type', 'keyword',
97-
'message-timestamp'
98-
];
99-
100-
foreach ($required as $key) {
100+
foreach (static::$requiredFields as $key) {
101101
if (!array_key_exists($key, $data)) {
102102
throw new \InvalidArgumentException('Incoming SMS missing required data `' . $key . '`');
103103
}

src/Webhook/Factory.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,12 @@ public static function createFromRequest(ServerRequestInterface $request)
3636
$params = $request->getQueryParams();
3737
break;
3838
case 'POST':
39-
$params = json_decode($request->getBody()->getContents(), true);
39+
$type = $request->getHeader('content-type');
40+
if (!isset($type[0]) || $type[0] === 'application/json') {
41+
$params = json_decode($request->getBody()->getContents(), true);
42+
} else {
43+
parse_str($request->getBody()->getContents(), $params);
44+
}
4045
break;
4146
default:
4247
throw new \RuntimeException("Invalid method for incoming webhook");

0 commit comments

Comments
 (0)