17 public const ID =
'ednaruimhpx';
23 private const ENDPOINT_OPTION =
'connector_endpoint';
24 private const LOGIN_OPTION =
'login';
25 private const PASSWORD_OPTION =
'password';
26 private const SUBJECT_OPTION =
'subject_id';
30 return defined(
'MESSAGESERIVICE_ALLOW_IMHPX') && MESSAGESERIVICE_ALLOW_IMHPX ===
true;
40 return 'Edna.ru IMHPX';
45 return 'Edna.ru IMHPX';
50 return defined(
'MESSAGESERIVICE_ALLOW_IMHPX') && MESSAGESERIVICE_ALLOW_IMHPX ===
true;
60 $id = $this->
getOption(self::SUBJECT_OPTION);
83 self::ENDPOINT_OPTION => $this->
getOption(self::ENDPOINT_OPTION),
84 self::LOGIN_OPTION => $this->
getOption(self::LOGIN_OPTION),
85 self::PASSWORD_OPTION => $this->
getOption(self::PASSWORD_OPTION),
86 self::SUBJECT_OPTION => $this->
getOption(self::SUBJECT_OPTION),
92 return parent::getCallbackUrl();
105 return $result->addError(
new Error(
'Service is unavailable'));
111 if (!$requestResult->isSuccess())
113 $result->addErrors($requestResult->getErrors());
118 $response = $requestResult->getHttpResponse();
131 switch ($serviceStatus)
147 case 'no-match-template':
160 <subject>Bitrix24</subject>
161 <priority>{$this->getPriority()}</priority>
162 <content>{$messageText}</content>
163 <sendTimeoutSeconds>60</sendTimeoutSeconds>
164 <validityPeriodMinutes>30</validityPeriodMinutes>
167 $address = static::normalizePhoneNumberForOutgoing(
$messageFields[
'MESSAGE_TO']);
170 $login = $ownerInfo[static::LOGIN_OPTION];
171 $password = $ownerInfo[static::PASSWORD_OPTION];
172 $mailbox = $ownerInfo[static::SUBJECT_OPTION];
175<?xml
version=
"1.0" encoding=
"UTF-8" standalone=
"no"?>
176<consumeInstantMessageRequest>
185 <instantMessage clientId=
"{$messageFields['ID']}">
186 <address>{$address}</address>
187 <subject>{$mailbox}</subject>
189 <instantMessageType>{$this->
getMessageType()}</instantMessageType>
190 <contentType>text</contentType>
192 <text>{$messageText}</text>
196 </instantMessageList>
198</consumeInstantMessageRequest>
207 "socketTimeout" => $this->socketTimeout,
208 "streamTimeout" => $this->streamTimeout,
209 'waitResponse' =>
true,
211 $httpClient->setHeader(
'User-Agent',
'Bitrix24');
212 $httpClient->setHeader(
'Content-type',
'text/xml');
216 'method' => HttpClient::HTTP_POST,
218 'headers' => method_exists($httpClient,
'getRequestHeaders') ? $httpClient->getRequestHeaders()->toArray() : [],
222 if (!$httpClient->query(HttpClient::HTTP_POST, $this->getServiceEndpoint(), $body))
227 $httpError = $httpClient->getError();
228 $errorCode = array_key_first($httpError);
229 $result->addError(
new Error($httpError[$errorCode], $errorCode));
234 'statusCode' => $httpClient->getStatus(),
235 'headers' => $httpClient->getHeaders()->toArray(),
236 'body' => $httpClient->getResult(),
238 $result->setHttpResponse($httpResponse);
271 $result->addError(
new Error(
"Response status code is {$response->statusCode}",
'WRONG_SERVICE_RESPONSE_CODE'));
274 $parseResult = $this->parseXml(
$response->body);
275 if (!$parseResult->isSuccess())
279 'XML parse error: ' . implode(
'; ', $parseResult->getErrorMessages()),
287 $instantMessageResponse = $parseResult->getData()[
'root'];
290 $instantMessageResponse = Json::decode(Json::encode($instantMessageResponse));
294 !isset($instantMessageResponse[
'payload'])
295 || (!isset($instantMessageResponse[
'payload'][
'code'])
296 && !isset($instantMessageResponse[
'payload'][
'instantMessageList'])
300 $result->addError(
new Error(
'Wrong xml response structure',
'SERVICE_RESPONSE_PARSE_ERROR'));
304 if ($instantMessageResponse[
'payload'][
'code'] !==
'ok')
307 $result->addError(
new Error($instantMessageResponse[
'payload'][
'code'], $instantMessageResponse[
'payload'][
'code']));
311 foreach ($instantMessageResponse[
'payload'][
'instantMessageList'] as $instantMessage)
313 if ($instantMessage[
'code'] ===
'ok' && isset($instantMessage[
'@attributes'][
'providerId']))
315 $result->setExternalId($instantMessage[
'@attributes'][
'providerId']);
321 $result->addError(
new Error(
'', $instantMessage[
'code']));
327 $result->addError(
new Error(
'Could not find message status in response',
'SERVICE_RESPONSE_PARSE_ERROR'));
351 public function processIncomingRequest(
string $incomingRequestBody): DTO\Response
356 $parseResult = $this->parseIncomingRequest($incomingRequestBody);
357 if (!$parseResult->isSuccess())
366 $statusUpdateList = $parseResult->getData();
367 foreach ($statusUpdateList as $statusUpdate)
370 if (
$message && $statusUpdate->providerStatus !=
'')
372 $message->updateStatusByExternalStatus($statusUpdate->providerStatus);
400 public function parseIncomingRequest(
string $incomingRequestBody): Result
403 $parseResult = $this->parseXml($incomingRequestBody);
404 if (!$parseResult->isSuccess())
406 return $result->addErrors($parseResult->getErrors());
410 $incomingRequest = $parseResult->getData()[
'root'];
413 if ($incomingRequest->getName() !=
'provideInstantMessageDlvStatusResponse')
419 $incomingRequest = Json::decode(Json::encode($incomingRequest));
421 !isset($incomingRequest[
'payload'])
422 || (!isset($incomingRequest[
'payload'][
'code'])
423 && !isset($incomingRequest[
'payload'][
'instantMessageList'])
427 return $result->addError(
new Error(
'Wrong XML structure'));
430 $statusUpdateList = [];
434 $instantMessageList = $incomingRequest[
'payload'][
'instantMessageList'][
'instantMessage'];
435 if (!is_array($instantMessageList))
438 return $result->setData($statusUpdateList);
441 if (Collection::isAssociative($instantMessageList))
443 $instantMessageList = [$instantMessageList];
446 foreach ($instantMessageList as $instantMessage)
448 $statusUpdateList[] =
new DTO\StatusUpdate([
449 'externalId' => (
int)$instantMessage[
'@attributes'][
'providerId'],
450 'providerStatus' => $instantMessage[
'instantMessageDlvStatus'][
'dlvStatus'],
451 'deliveryStatus' => static::resolveStatus($instantMessage[
'instantMessageDlvStatus'][
'dlvStatus']),
452 'deliveryError' => $instantMessage[
'instantMessageDlvStatus'][
'dlvError']
456 return $result->setData($statusUpdateList);
464 protected function parseXml(
string $xmlString): Result
468 if ($xmlString ===
'')
473 libxml_use_internal_errors(
true);
474 libxml_clear_errors();
475 $parsedBody = simplexml_load_string($xmlString);
476 $parseErrors = libxml_get_errors();
478 if (!empty($parseErrors))
481 foreach ($parseErrors as $parseError)
483 $result->addError(
new Error($parseError->message, $parseError->code));
489 'root' => $parsedBody
496 return $this::DEFAULT_PRIORITY;
501 return $this::MESSAGE_TYPE;
506 return $this->
getOption(static::ENDPOINT_OPTION);
512 if (mb_strpos($phoneNumber,
'+') === 0)
514 return mb_substr($phoneNumber, 1);