Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
twilio.php
1<?php
3
15
21
22Loc::loadMessages(__FILE__);
23
25{
26 public const ID = 'twilio';
27
29 public const ON_BEFORE_TWILIO_MESSAGE_SEND = 'OnBeforeTwilioMessageSend';
30
31 public function getId()
32 {
33 return static::ID;
34 }
35
36 public function getName()
37 {
38 return Loc::getMessage('MESSAGESERVICE_SENDER_SMS_TWILIO_NAME');
39 }
40
41 public function getShortName()
42 {
43 return 'twilio.com';
44 }
45
46 public function isRegistered()
47 {
48 return ($this->getOption('account_sid') !== null);
49 }
50
51 public function isDemo()
52 {
53 return false;
54 }
55
56 public function canUse()
57 {
58 return $this->isRegistered();
59 }
60
61 public function getFromList()
62 {
63 $from = $this->getOption('from_list');
64 return is_array($from) ? $from : array();
65 }
66
67 public function register(array $fields)
68 {
69 $sid = (string)$fields['account_sid'];
70 $token = (string)$fields['account_token'];
71
72 $result = $this->callExternalMethod(
74 'Accounts/'.$sid, array(), $sid, $token
75 );
76 if ($result->isSuccess())
77 {
78 $data = $result->getData();
79
80 if ($data['status'] !== 'active')
81 {
82 $result->addError(new Error(Loc::getMessage('MESSAGESERVICE_SENDER_SMS_TWILIO_ERROR_ACCOUNT_INACTIVE')));
83 }
84 else
85 {
86 $this->setOption('account_sid', $sid);
87 $this->setOption('account_token', $token);
88 $this->setOption('account_friendly_name', $data['friendly_name']);
89 }
90 }
91
92 return $result;
93 }
94
95 public function getOwnerInfo()
96 {
97 return array(
98 'sid' => $this->getOption('account_sid'),
99 'friendly_name' => $this->getOption('account_friendly_name')
100 );
101 }
102
103 public function getExternalManageUrl()
104 {
105 return 'https://www.twilio.com/console';
106 }
107
108 public function sendMessage(array $messageFields): SendMessage
109 {
110 $sid = $this->getOption('account_sid');
111
112 if (!$sid)
113 {
114 $result = new SendMessage();
115 $result->addError(new Error(Loc::getMessage('MESSAGESERVICE_SENDER_SMS_TWILIO_CAN_USE_ERROR')));
116 return $result;
117 }
118
119 $eventResults = self::fireEventBeforeMessageSend($messageFields);
120 foreach ($eventResults as $eventResult)
121 {
122 $eventParams = $eventResult->getParameters();
123
124 if ($eventResult->getType() === \Bitrix\Main\EventResult::ERROR)
125 {
126 $result = new SendMessage();
127 if ($eventParams && is_string($eventParams))
128 {
129 $result->addError(new Error($eventParams));
130 }
131 else
132 {
133 $result->addError(new Error(Loc::getMessage("MESSAGESERVICE_SENDER_SMS_TWILIO_MESSAGE_HAS_NOT_BEEN_SENT")));
134 }
135 return $result;
136 }
137
138 if (is_array($eventParams))
139 {
140 $messageFields = array_merge($messageFields, $eventParams);
141 }
142 }
143
144 if (isset($messageFields['MESSAGE_FROM_ALPHANUMERIC']))
145 {
146 $apiResult = $this->sendMessageByAlphanumericNumber($sid, $messageFields);
147 if (
148 !$apiResult->isSuccess()
149 && $this->checkSupportErrorAlphanumericNumber($apiResult->getErrorCollection())
150 )
151 {
152 $apiResult = $this->sendMessageByNumber($sid, $messageFields);
153 }
154 }
155 else
156 {
157 $apiResult = $this->sendMessageByNumber($sid, $messageFields);
158 }
159
160 $result = new SendMessage();
161 $result->setServiceRequest($apiResult->getHttpRequest());
162 $result->setServiceResponse($apiResult->getHttpResponse());
163
164 if (!$apiResult->isSuccess())
165 {
166 $result->addErrors($apiResult->getErrors());
167 }
168 else
169 {
170 $resultData = $apiResult->getData();
171 if (isset($resultData['sid']))
172 {
173 $result->setExternalId($resultData['sid']);
174 }
175 $result->setAccepted();
176 }
177
178 return $result;
179 }
180
181 public function getMessageStatus(array $messageFields)
182 {
183 $result = new MessageStatus();
184 $result->setId($messageFields['ID']);
185 $result->setExternalId($messageFields['EXTERNAL_ID']);
186
187 $sid = $this->getOption('account_sid');
188 if (!$sid)
189 {
190 $result->addError(new Error(Loc::getMessage('MESSAGESERVICE_SENDER_SMS_TWILIO_CAN_USE_ERROR')));
191 return $result;
192 }
193
194 $apiResult = $this->callExternalMethod(
196 'Accounts/'.$sid.'/Messages/'.$result->getExternalId()
197 );
198 if (!$apiResult->isSuccess())
199 {
200 $result->addErrors($apiResult->getErrors());
201 }
202 else
203 {
204 $resultData = $apiResult->getData();
205 $result->setStatusCode($resultData['status']);
206 $result->setStatusText($resultData['status']);
207 if (in_array($resultData['status'],
208 array('accepted', 'queued', 'sending', 'sent', 'delivered', 'undelivered', 'failed')))
209 {
210 $result->setStatusText(
211 Loc::getMessage('MESSAGESERVICE_SENDER_SMS_TWILIO_MESSAGE_STATUS_'.mb_strtoupper($resultData['status']))
212 );
213 }
214 }
215
216 return $result;
217 }
218
219 public static function resolveStatus($serviceStatus)
220 {
221 $status = parent::resolveStatus($serviceStatus);
222
223 switch ((string)$serviceStatus)
224 {
225 case 'accepted':
226 return MessageService\MessageStatus::ACCEPTED;
227 break;
228 case 'queued':
229 return MessageService\MessageStatus::QUEUED;
230 break;
231 case 'sending':
232 return MessageService\MessageStatus::SENDING;
233 break;
234 case 'sent':
235 return MessageService\MessageStatus::SENT;
236 break;
237 case 'delivered':
238 return MessageService\MessageStatus::DELIVERED;
239 break;
240 case 'undelivered':
241 return MessageService\MessageStatus::UNDELIVERED;
242 break;
243 case 'failed':
244 return MessageService\MessageStatus::FAILED;
245 break;
246 }
247
248 return $status;
249 }
250
251 public function sync()
252 {
253 if ($this->isRegistered())
254 {
255 $this->loadFromList();
256 }
257 return $this;
258 }
259
260 private function callExternalMethod($httpMethod, $apiMethod, array $params = array(), $sid = null, $token = null): Sender\Result\HttpRequestResult
261 {
262 $url = $this->getRequestUrl($apiMethod);
263
264 $httpClient = new HttpClient(array(
265 "socketTimeout" => $this->socketTimeout,
266 "streamTimeout" => $this->streamTimeout,
267 "waitResponse" => true,
268 ));
269 $httpClient->setHeader('User-Agent', 'Bitrix24');
270 $httpClient->setCharset('UTF-8');
271
272 if (!$sid || !$token)
273 {
274 $sid = $this->getOption('account_sid');
275 $token = $this->getOption('account_token');
276 }
277
278 $httpClient->setAuthorization($sid, $token);
279
280 $isUtf = Application::getInstance()->isUtfMode();
281
282 if (!$isUtf)
283 {
284 $params = \Bitrix\Main\Text\Encoding::convertEncoding($params, SITE_CHARSET, 'UTF-8');
285 }
286
287 $result = new Sender\Result\HttpRequestResult();
288 $answer = array();
289
290 $result->setHttpRequest(new MessageService\DTO\Request([
291 'method' => HttpClient::HTTP_POST,
292 'uri' => $url,
293 'headers' => method_exists($httpClient, 'getRequestHeaders') ? $httpClient->getRequestHeaders()->toArray() : [],
294 'body' => $params,
295 ]));
296 if ($httpClient->query($httpMethod, $url, $params))
297 {
298 try
299 {
300 $answer = Json::decode($httpClient->getResult());
301 }
302 catch (ArgumentException $e)
303 {
304 $result->addError(new Error('Service error'));
305 }
306
307 $httpStatus = $httpClient->getStatus();
308 if ($httpStatus >= 400)
309 {
310 $errorInformant = new ErrorInformant($answer['message'], $answer['code'], $answer['more_info'], $httpStatus);
311 $result->addError($errorInformant->getError());
312 // if (isset($answer['message']) && isset($answer['code']))
313 // {
314 // $result->addError(new Error($answer['message'], $answer['code']));
315 // }
316 // else
317 // {
318 // $result->addError(new Error('Service error (HTTP Status '.$httpStatus.')'));
319 // }
320 }
321 }
322 $result->setHttpResponse(new MessageService\DTO\Response([
323 'statusCode' => $httpClient->getStatus(),
324 'headers' => $httpClient->getHeaders()->toArray(),
325 'body' => $httpClient->getResult(),
326 'error' => Sender\Util::getHttpClientErrorString($httpClient)
327 ]));
328
329 if ($result->isSuccess())
330 {
331 $result->setData($answer);
332 }
333
334 return $result;
335 }
336
337 private function loadFromList()
338 {
339 $sid = $this->getOption('account_sid');
340 $result = $this->callExternalMethod(
342 'Accounts/'.$sid.'/IncomingPhoneNumbers'
343 );
344
345 if ($result->isSuccess())
346 {
347 $from = array();
348 $resultData = $result->getData();
349 if (isset($resultData['incoming_phone_numbers']) && is_array($resultData['incoming_phone_numbers']))
350 {
351 foreach ($resultData['incoming_phone_numbers'] as $phoneNumber)
352 {
353 if ($phoneNumber['capabilities']['sms'] === true)
354 {
355 $from[] = array(
356 'id' => $phoneNumber['phone_number'],
357 'name' => $phoneNumber['friendly_name']
358 );
359 }
360 }
361 }
362
363 $this->setOption('from_list', $from);
364 }
365 }
366
367 private function checkSupportErrorAlphanumericNumber(ErrorCollection $collection): bool
368 {
369 if ($collection->getErrorByCode(self::NOT_SUPPORT_ALPHANUMERIC_NUMBER_STATUS_CODE))
370 {
371 return true;
372 }
373
374 return false;
375 }
376
382 private function sendMessageByAlphanumericNumber(string $sid, array $messageFields): Sender\Result\HttpRequestResult
383 {
384 $params = [
385 'To' => $messageFields['MESSAGE_TO'],
386 'Body' => $this->prepareMessageBodyForSend($messageFields['MESSAGE_BODY']),
387 'From' => $messageFields['MESSAGE_FROM_ALPHANUMERIC'],
388 'StatusCallback' => $this->getCallbackUrl()
389 ];
390
391 return $this->callExternalMethod(
393 'Accounts/'.$sid.'/Messages/',
394 $params
395 );
396 }
397
403 private function sendMessageByNumber(string $sid, array $messageFields): Sender\Result\HttpRequestResult
404 {
405 $params = [
406 'To' => $messageFields['MESSAGE_TO'],
407 'Body' => $this->prepareMessageBodyForSend($messageFields['MESSAGE_BODY']),
408 'From' => $messageFields['MESSAGE_FROM'],
409 'StatusCallback' => $this->getCallbackUrl()
410 ];
411
412 if (!$params['From'])
413 {
414 $params['From'] = $this->getDefaultFrom();
415 }
416 if (is_string($params['From']) && mb_strlen($params['From']) === 34) //unique id of the Messaging Service
417 {
418 $params['MessagingServiceSid'] = $params['From'];
419 unset($params['From']);
420 }
421
422 return $this->callExternalMethod(
424 'Accounts/'.$sid.'/Messages/',
425 $params
426 );
427 }
428
433 public static function fireEventBeforeMessageSend(array $messageFields): array
434 {
435 $event = new Event('messageservice', self::ON_BEFORE_TWILIO_MESSAGE_SEND, $messageFields);
436 $event->send();
437
438 return $event->getResults();
439 }
440
441 private function getRequestUrl(string $apiMethod): string
442 {
443 $url = Option::get(
444 'messageservice',
445 'twilio_api_uri_tpl',
446 'https://api.twilio.com/2010-04-01/%apiMethod%.json'
447 );
448
449 return str_replace('%apiMethod%', $apiMethod, $url);
450 }
451}
static loadMessages($file)
Definition loc.php:64
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29
getOption($optionName, $defaultValue=null)
prepareMessageBodyForSend(string $text)
Definition base.php:176
static fireEventBeforeMessageSend(array $messageFields)
Definition twilio.php:433
sendMessage(array $messageFields)
Definition twilio.php:108
static resolveStatus($serviceStatus)
Definition twilio.php:219
getMessageStatus(array $messageFields)
Definition twilio.php:181