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