Your IP : 13.59.188.23


Current Path : /home/bitrix/ext_www/crm.klimatlend.ua/bitrix/modules/messageservice/lib/sender/sms/
Upload File :
Current File : /home/bitrix/ext_www/crm.klimatlend.ua/bitrix/modules/messageservice/lib/sender/sms/smsru.php

<?php
namespace Bitrix\MessageService\Sender\Sms;

use Bitrix\Main\Application;
use Bitrix\Main\Config\Option;
use Bitrix\Main\Error;
use Bitrix\Main\Localization\Loc;
use Bitrix\Main\Result;
use Bitrix\Main\Web\HttpClient;
use Bitrix\Main\Web\Json;
use Bitrix\Main\Loader;

use Bitrix\MessageService\Sender;
use Bitrix\MessageService\Sender\Result\MessageStatus;
use Bitrix\MessageService\Sender\Result\SendMessage;

use Bitrix\MessageService;

Loc::loadMessages(__FILE__);

class SmsRu extends Sender\BaseConfigurable
{
	public static function isSupported()
	{
		if (Loader::includeModule('bitrix24'))
		{
			return in_array(\CBitrix24::getPortalZone(), ['ru', 'kz', 'by']);
		}
		return true;
	}

	public function getId()
	{
		return 'smsru';
	}

	public function getName()
	{
		return Loc::getMessage('MESSAGESERVICE_SENDER_SMS_SMSRU_NAME');
	}

	public function getShortName()
	{
		return 'sms.ru';
	}

	public function isDemo()
	{
		return false;
	}

	public function getDemoBalance()
	{
		$params = array(
			'embed_id' => $this->getOption('embed_id')
		);
		$apiResult = $this->callExternalMethod('my/free', $params);

		$balance = array(
			'total_free' => 0,
			'used_today' => 0,
			'available_today' => 0
		);

		if ($apiResult->isSuccess())
		{
			$balanceData = $apiResult->getData();
			$balance['total_free'] = (int)$balanceData['total_free'];
			$balance['used_today'] = (int)$balanceData['used_today'];
			$balance['available_today'] = max(0, $balance['total_free'] - $balance['used_today']);
		}

		return $balance;
	}

	public function getFromList()
	{
		$from = $this->getOption('from_list');
		return is_array($from) ? $from : array();
	}

	public function isConfirmed()
	{
		return ($this->getOption('is_confirmed') === true);
	}

	public function isRegistered()
	{
		return ($this->getOption('embed_id') !== null);
	}

	public function register(array $fields)
	{
		$userPhone = \NormalizePhone($fields['user_phone']);
		$params = array(
			'user_phone' => $userPhone,
			'user_firstname' => $fields['user_firstname'],
			'user_lastname' => $fields['user_lastname'],
			'user_email' => $fields['user_email'],
			'embed_partner' => $this->getEmbedPartner(),
			'embed_hash' => $this->getEmbedHash($userPhone)
		);

		$result = $this->callExternalMethod('embed/register', $params);
		if ($result->isSuccess())
		{
			$data = $result->getData();

			$this->setOption('embed_id', $data['embed_id']);
			$this->setOption('user_phone', $userPhone);
			if (!empty($params['user_firstname']))
			{
				$this->setOption('user_firstname', $params['user_firstname']);
			}
			if (!empty($params['user_lastname']))
			{
				$this->setOption('user_lastname', $params['user_lastname']);
			}
			if (!empty($params['user_email']))
			{
				$this->setOption('user_email', $params['user_email']);
			}

			if (!empty($data['confirmed']))
			{
				$this->setOption('is_confirmed', true);
			}
		}

		return $result;
	}

	/**
	 * @return array [
	 * 	'phone' => '',
	 *  'firstName' => '',
	 *  'lastName' => '',
	 *  'email' => ''
	 * ]
	 */
	public function getOwnerInfo()
	{
		return array(
			'phone' => $this->getOption('user_phone'),
			'firstName' => $this->getOption('user_firstname'),
			'lastName' => $this->getOption('user_lastname'),
			'email' => $this->getOption('user_email')
		);
	}

	/**
	 * @param array $fields
	 * @return Result
	 */
	public function confirmRegistration(array $fields)
	{
		$embedId = $this->getOption('embed_id');
		$params = array(
			'embed_id' => $embedId,
			'confirm' => $fields['confirm']
		);
		$result = $this->callExternalMethod('embed/confirm', $params);

		if ($result->isSuccess())
		{
			$this->setOption('is_confirmed', true);
			$callBackResult = $this->callExternalMethod('callback/add', array(
				'embed_id' => $embedId,
				'url' => $this->getCallbackUrl()
			));
			if ($callBackResult->isSuccess())
			{
				$this->setOption('callback_set', true);
			}
		}

		return $result;
	}

	public function sendConfirmationCode()
	{
		if ($this->isRegistered())
		{
			$ownerInfo = $this->getOwnerInfo();
			$result = $this->register(array(
				'user_phone' => $ownerInfo['phone'],
				'user_firstname' => $ownerInfo['firstName'],
				'user_lastname' => $ownerInfo['lastName'],
				'user_email' => $ownerInfo['email'],
			));
		}
		else
		{
			$result = new Result();
			$result->addError(new Error('Provider is not registered.'));
		}

		return $result;
	}

	public function getExternalManageUrl()
	{
		if ($this->isRegistered())
		{
			return 'https://sms.ru/?panel=login&action=login&embed_id='.$this->getOption('embed_id');
		}
		return 'https://sms.ru/?panel=login';
	}

	public function sendMessage(array $messageFields)
	{
		if (!$this->canUse())
		{
			$result = new SendMessage();
			$result->addError(new Error(Loc::getMessage('MESSAGESERVICE_SENDER_SMS_SMSRU_CAN_USE_ERROR')));
			return $result;
		}

		$params = array(
			'to' => $messageFields['MESSAGE_TO'],
			'text' => $messageFields['MESSAGE_BODY'],
			'embed_id' => $this->getOption('embed_id')
		);

		if ($this->isDemo())
		{
			$params['to'] = $this->getOption('user_phone');
		}

		if ($messageFields['MESSAGE_FROM'])
		{
			$params['from'] = $messageFields['MESSAGE_FROM'];
		}

		$result = new SendMessage();
		$apiResult = $this->callExternalMethod('sms/send', $params);
		$resultData = $apiResult->getData();

		if (!$apiResult->isSuccess())
		{
			if ((int)$resultData['status_code'] == 206)
			{
				$result->setStatus(MessageService\MessageStatus::DEFERRED);
				$result->addError(new Error($this->getErrorMessage($resultData['status_code'])));
			}
			else
			{
				$result->addErrors($apiResult->getErrors());
			}
		}
		else
		{
			$smsData = current($resultData['sms']);

			if (isset($smsData['sms_id']))
			{
				$result->setExternalId($smsData['sms_id']);
			}

			if ((int)$smsData['status_code'] !== 100)
			{
				$result->addError(new Error($this->getErrorMessage($smsData['status_code'])));
			}
			elseif ((int)$smsData['status_code'] == 206)
			{
				$result->setStatus(MessageService\MessageStatus::DEFERRED);
				$result->addError(new Error($this->getErrorMessage($smsData['status_code'])));
			}
			else
			{
				$result->setAccepted();
			}
		}

		return $result;
	}

	public function getMessageStatus(array $messageFields)
	{
		$result = new MessageStatus();
		$result->setId($messageFields['ID']);
		$result->setExternalId($messageFields['EXTERNAL_ID']);

		if (!$this->canUse())
		{
			$result->addError(new Error(Loc::getMessage('MESSAGESERVICE_SENDER_SMS_SMSRU_CAN_USE_ERROR')));
			return $result;
		}

		$params = array(
			'sms_id' => $result->getExternalId(),
			'embed_id' => $this->getOption('embed_id')
		);

		$apiResult = $this->callExternalMethod('sms/status', $params);
		if (!$apiResult->isSuccess())
		{
			$result->addErrors($apiResult->getErrors());
		}
		else
		{
			$resultData = $apiResult->getData();
			$smsData = current($resultData['sms']);

			$result->setStatusCode($smsData['status_code']);
			$result->setStatusText($smsData['status_text']);

			if ((int)$resultData['status_code'] !== 100)
			{
				$result->addError(new Error($this->getErrorMessage($smsData['status_code'])));
			}
		}

		return $result;
	}

	public static function resolveStatus($serviceStatus)
	{
		$status = parent::resolveStatus($serviceStatus);

		switch ((int)$serviceStatus)
		{
			case 100:
				return MessageService\MessageStatus::ACCEPTED;
				break;
			case 101:
				return MessageService\MessageStatus::SENDING;
				break;
			case 102:
				return MessageService\MessageStatus::SENT;
				break;
			case 103:
				return MessageService\MessageStatus::DELIVERED;
				break;
			case 104: //timeout
			case 105: //removed by moderator
			case 106: //error on receiver`s side
			case 107: //unknown reason
			case 108: //rejected
				return MessageService\MessageStatus::UNDELIVERED;
				break;
			case 110:
				return MessageService\MessageStatus::READ;
				break;
		}

		return $status;
	}

	public function sync()
	{
		if ($this->isRegistered())
		{
			$this->loadFromList();
		}
		return $this;
	}

	private function callExternalMethod($method, $params)
	{
		$url = 'https://sms.ru/'.$method;

		$httpClient = new HttpClient(array(
			"socketTimeout" => 10,
			"streamTimeout" => 30,
			"waitResponse" => true,
		));
		$httpClient->setHeader('User-Agent', 'Bitrix24');
		$httpClient->setCharset('UTF-8');

		$isUtf = Application::getInstance()->isUtfMode();

		if (!$isUtf)
		{
			$params = \Bitrix\Main\Text\Encoding::convertEncoding($params, SITE_CHARSET, 'UTF-8');
		}
		$params['json'] = 1;

		$result = new Result();
		$answer = array();

		if ($httpClient->query(HttpClient::HTTP_POST, $url, $params) && $httpClient->getStatus() == '200')
		{
			$answer = $this->parseExternalAnswer($httpClient->getResult());
		}

		$answerCode = isset($answer['status_code']) ? (int)$answer['status_code'] : 0;

		if ($answerCode !== 100)
		{
			$result->addError(new Error($this->getErrorMessage($answerCode, $answer)));
		}
		$result->setData($answer);

		return $result;
	}

	private function parseExternalAnswer($httpResult)
	{
		try
		{
			$answer = Json::decode($httpResult);
		}
		catch (\Bitrix\Main\ArgumentException $e)
		{
			$data = explode(PHP_EOL, $httpResult);
			$code = (int)array_shift($data);
			$answer = $data;
			$answer['status_code'] = $code;
			$answer['status'] = $code === 100 ? 'OK' : 'ERROR';
		}

		if (!is_array($answer) && is_numeric($answer))
		{
			$answer = array(
				'status' => $answer === 100 ? 'OK' : 'ERROR',
				'status_code' => $answer
			);
		}

		return $answer;
	}

	private function getEmbedPartner()
	{
		return 'bitrix24';//Option::get('messageservice', 'smsru_partner');
	}

	private function getSecretKey()
	{
		return 'P46y811M84W3b4H18SmDpy9KG3pKG3Ok';//Option::get('messageservice', 'smsru_secret_key');
	}

	private function getEmbedHash($phoneNumber)
	{
		return md5($phoneNumber.$this->getSecretKey());
	}

	private function getErrorMessage($errorCode, $answer = null)
	{
		$message = Loc::getMessage('MESSAGESERVICE_SENDER_SMS_SMSRU_ERROR_'.$errorCode);
		if (!$message && $answer && !empty($answer['errors']))
		{
			$errorCode = $answer['errors'][0]['status_code'];
			$message = Loc::getMessage('MESSAGESERVICE_SENDER_SMS_SMSRU_ERROR_'.$errorCode);
			if (!$message)
			{
				$message = $answer['errors'][0]['status_text'];
			}
		}

		return $message ?: Loc::getMessage('MESSAGESERVICE_SENDER_SMS_SMSRU_ERROR_OTHER');
	}

	private function loadFromList()
	{
		$params = array(
			'embed_id' => $this->getOption('embed_id')
		);
		$result = $this->callExternalMethod('my/senders', $params);

		if ($result->isSuccess())
		{
			$from = array();
			$resultData = $result->getData();
			foreach ($resultData['senders'] as $sender)
			{
				if (!empty($sender))
				{
					$from[] = array(
						'id' => $sender,
						'name' => $sender
					);
				}
			}

			$this->setOption('from_list', $from);
		}
	}
}