СМС оповещения

Примеры

Перед началом работы с методами модуля, необходиом его подключить на страницу.

\Bitrix\Main\Loader::includeModule('bxmaker.smsnotice'); 
$oManager = \Bxmaker\SmsNotice\Manager::getInstance();

Отправка смс

Чтобы отправить одиночное смс (sms) достаточно воспользоваться соответствующим методом, указав номер телефона и текст сообщения, при этому номер телефона может быть в произвольном формате, например: +7(999)111-22-33, 8 999 1112233 и тп.

// 3й парметр - идентификато сайта или null (будет использованы настрйоки текущего сайта)
// 4й параметр - имя отправителя или null (используется имя отправителя из настроек)
// 5й параметр - автотранслит false/true (по умолчанию false - не транслитерировать текст смс)
$result = $oManager->send('79991112233', 'какой-то текст для теста отправки в смс');

/* если  смс успешно отправлено */
if($result->isSuccess())
{
    /* Получение статуса отправки, подробнее в описании класса \Bxmaker\SmsNotic\Result */
    $statusCode = $result->getResult();
}
/* иначе, если есть ошибки */
else
{
    /* вывод сообщений об ошибке, ошибках */
   echo implode(', ', $result->getErrorMessages();
}

Отправка шаблона смс

Отправка смс по шаблону используется для того чтобы отправлять одинаковые или разные смс разным получателям, например пользователю добробную смс, а менеджеру смс с информацией что заказ в принципе оформлен и нужно его подтверждить.

При этом отправку можно произвести вызовом одного метода, не придется что либо дописывать. чтобы изменить количество смс, получателей, текст. Делаем отправку смс конкретного типа, а текст получатели, копии получателей задаются в шаблонах.

Тажке в шаблонах перечисляются тем поля, которые будут в смс заменены на свои занчения, по аналогии с типами почтовых событий.

// 3й парметр - идентификато сайта или null (будет использованы настрйоки текущего сайта)
// 4й параметр - имя отправителя или null (используется имя отправителя из настроек)
$result = $oManager->sendTemplate('ORDER_NEW', array(
    'PHONE' => '79991112233',
    'ORDER_ID' => '10268',
    'PRICE' => '5 536'
));
/* результат отправки типа шаблонов всегда успешный, так как содержит детальную информацию по отправке каждого из шаблонов */
if($result->isSuccess())
{
    /* можно получить сразу полный массив подробной информации */
    $data = $result->getMore();

    /* либо по отделльности каждый из 3-х */

    /* всего найдено и обработано шаблонов */
    $count = $result->getMore('count');

    /* если ошибок нет, то $errors == null, иначе массив ошибок (объект \Bxmaker\SmsNotice\Error) полученных при отправке каждого шаблона */
    $errors = $result->getMore('errors');
    if(is_null($errors))
    {
        /* ошибок нет */
    }
    else
    {
       foreach($errors as $obError)
       {
           /* вывод ошибок */
           echo implode(', ', $obError->getErrorMessages()) . '<br>';
       }
    }

    /* и соответственно массив результатов (объект \Bxmaker\SmsNotice\Result)*/
    $results = $result->getMore('results');
    foreach($results as $obResult)
    {
       /* статус отправки */
       $statusCode = $obResult->getResult();

       /* больше информации */
       $arDataItem = $obResult->getMore();
    
       echo 'На номер: ' . $arDataItem['phone'] . ', было отправлено сообщение - ' . $arDataItem['text'] . '<br>';

    }
}

Отправка смс при почтовом событии

В моделе реализован функционал отправки смс при наступлении почтовых событий. Например при оформлении заказа, возникает почтовой событий и отправляется email, эти события отслеживаются модулем. Таким образом можно в настройках добавить смс шаблон и отметить его как шаблон при почтовом событии.

Отправляются такие смс отдельным методом api модуляавтоматически, но если вдруг возникла необходимость, можно реализовать отправку таких смс с помощью отдельного метода api модуля.

// 3й парметр - идентификато сайта или null (будет использованы настрйоки текущего сайта)
// 4й параметр - имя отправителя или null (используется имя отправителя из настроек)

$result = $oManager->sendTemplateEmail('ORDER_NEW', array(
 'PHONE' => '79991112233',
 'NAME' => 'Евгений',
 'PRICE' => '2000'
 ));

Добавление поля в шаблон

Рассмотрим вариант, когда необходимо доабвить какое-то поле в шаблон смс с информацией о заказе, в данном случае информацию о пункте выдачи заказа.

В свойстве заказа с адресом уже есть идентфииктаор пункта выдачи, поэтмоу возбмем его и по нему получим данные.

Первым делом добавляем тип шаблона для статуса заказа, при смене на который будет отправляться смс с информацией о пункте выдачи.

Добавление типа смс шаблона

В настройках модуля смс оповещений указываем отправку смс с добавленным типом шаблонов смс.

В настройках модуля к статусу привязываем тип отправляемых сообщений

Добавляем СМС шаблон в котором указываем новое поле с кодом филиала (оно будет формироваться обработчиком события далее) Адрес пункта выдачи - https://boxberry.ru/find_an_office/#DELIVERY_BOXBERRY_CODE_FILIALA#/

Добавление шаблона смс для добавленного типа на битриксе

Добавляем обработчик события в файл /bitrix/php_interface/init.php

$eventManager = \Bitrix\Main\EventManager::getInstance(); //подписываем обработчик на событие 

$eventManager->addEventHandler("bxmaker.smsnotice", "OnPreparedOrderData", array(
'CBXmakerEventHandler', 'bxmaker_smsnotice__OnPreparedOrderData'
)); 
 
Class CBXmakerEventHandler { 

    // обоработчик ---- 
    public function bxmaker_smsnotice__OnPreparedOrderData(\Bitrix\Main\Event $event)
    {
          $arOrderData = $event->getParameters();

          $codFiliala = '';
          $deliveryAdress = explode(',',$arOrderData['PROPERTY_VALUE_ADDRESS']);
          foreach($deliveryAdress as $adres)
          {
              $arAdresCol = explode(':', trim($adres));
              if($arAdresCol[0] = 'код филиала')
              {
                  $codFiliala = explode('/', trim($arAdresCol[1]));
                  $codFiliala = $codFiliala[0];
               }
           }

          $arOrderData['DELIVERY_BOXBERRY_CODE_FILIALA'] = $codFiliala;

           $result = new \Bitrix\Main\EventResult(Bitrix\Main\EventResult::SUCCESS, $arOrderData);

           return $result;
    } 
}

В результате получаем

В результате отправляется смс на битриксе покупателю с ссылкой на пункт выдачи

Добавление SMS шлюза самостоятельно

Периодически возникает ситуация, когда в модуле нет варианта подходящего СМС шлюза, либо необходимо добавить собственный не публичный смс шлюз. Для этих случаев мы сделали возможность расширить модуль, добавить свой вариант.

Размещение обработчиков

Во время инициализации, модуль помимо собственной директории с смс сервисами проверяет и дополнительные директории: /bitrix/php_interface/bxamaker.smsnotice/ или /local/php_interface/bxamaker.smsnotice

Соответственно, если в папке есть скрипты, то они будут подгружаться. Описание и пример такого файла будет описан ниже

Обновление статусов

Некоторые смс шлюзы позволяют оповещать сайты о статусе смсю То есть как только изменяется статус смс сообщения (например доставлено) смс шлюз может сделать запрос на ваш сайт с данными о статусе смс. Для этого у модуляе етсь обработчик, который принимает эти оповещения.

Обработчки располагается по адресу - http:// домен /bitrix/tools/bmaker.smsnotice/notice.php. Причем чтобы все работало верно, обработчик должен иметь соответствующие параметры, по которым определяется статус какого именно сообщения изменился и сам статус. Все зависит от конкретного шлюза.

Для примера, смс шлюз, работа с которым описана ниже в соответствующем классе, будет делать запросы по такому адресу: http:// домен /bitrix/tools/bxmaker.smsnotice/notice.php?smsId=1022565&status=1&serviceId=2 при запросе этого ресурса, будет подключен соответствующий сервис обработки, при этом smsId - обязательный параметр значение которого соответствует идентификатору записи о смс сообщении в истории отправленных смс.

Соответственно будет запрошена информация об этом сообщение, подключен автоматически класс для работы с смс сервисом через который отправлялось это смс. После этого сама обработка остальных параметров будет передана методу notice() класса соответствующего смс сервиса.

Применять такие оповещения не обязательно, так как в модуле есть соответствующий агент который самостоятельно ежеминутно проверяет статусы отправленных смс. При этом проверяются не все сразу смс а некоторая часть. чтобы не перегружать смс шлюз своими запросами.

Обработчик для шлюза

// файл /local/php_interface/bxamaker.smsnotice/example.php


    namespace Bxmaker\SmsNotice\Service;

    use Bitrix\Main\Config\Option;
    use Bitrix\Main\Loader;
    use Bitrix\Main\Localization\Loc;
    use Bxmaker\SmsNotice\Error;
    use Bxmaker\SmsNotice\Manager;
    use Bxmaker\SmsNotice\ManagerTable;
    use Bxmaker\SmsNotice\Result;
    use Bxmaker\SmsNotice\Service;

    Loc::loadMessages(__FILE__);


    /**
     * Название класса должно быть уникальным и должно соответствовать названию файла ./example.php
     * Class example
     * @package Bxmaker\SmsNotice\Service
     */
    Class example
    {
        private $module_id = 'bxmaker.smsnotice';

        private $login = '';
        private $pass = '';
        private $notice_path = '';
        private $oHttp = null;

        /**
         * Инициализация сервиса
         * example constructor.
         * @param array $arParams - параметры из настроек сервиса в админке
         */
        public function __construct($arParams = array())
        {
            if (is_null($this->oHttp)) {
                $this->oHttp = new \Bitrix\Main\Web\HttpClient();
            }

            $this->login = $arParams['LOGIN'];
            $this->pass = $arParams['PASS'];

            //  site.ru - ваш сайт, на который могут приходить оповещения от смс шлюза
            //$this->notice_path = 'http://site.ru/bitrix/tools/bxmaker.smsnotice/notice.php';

            $this->notice_path = 'http://' . Option::get('main', 'server_name', '') .  '/bitrix/tools/' . $this->module_id . '/notice.php';
        }


        /**
         * Отправка сообщения, этот метод вызывается уже после добавления смс в локальную базe
         * @param $phone - телефон получателя
         * @param $text - текст
         * @param array $arParams -   smsId - ID записи смс, service - данные о сервисе через который отправляется
         * @return Result - объект класса Result c результатом или ошибкой
         */
        public function send($phone, $text, $arParams = array())
        {
            //делаем запрос для отправки
            //notice_url -  передаем арес по которому нас надо оповещать о статусе смс, в данном примере
            // у сервис эт делает (но не все смс сервисы так делают)
            $res = $this->oHttp->get('http:// домен /api/send_sms.php?' . http_build_query(array(
                    'to' => $phone,
                    'msg' => $text,
                    'notice_url' => $this->getNoticeUrl($arParams)
                )));

            // сервис возвращает ответы в виде цифр
            // 1 - доставлено
            // 8 - отправлено
            // иначе ошибка

            if ($res == 1) {
                // \Bxmaker\SmsNotice\SMS_STATUS_DELIVERED - соответствует статусу сообщения доставлено,
                // а админке в списке отправленных смс для текущего смс будет устанволен статус доставлено
                // а в setMore устанавливаются доп парамтеры, номер телефона и текст, для анализа ошибок
                $result = new Result(\Bxmaker\SmsNotice\SMS_STATUS_DELIVERED);
                $result->setMore('phone', $phone);
                $result->setMore('text', $text);

//                 если возвращается идентификатор сообшений от смс шлюза
//                $result->setMore('params', array(
//                    'messageId' => (isset($match[1]) ? trim($match[1]) : '')
//                ));

            } else {

                if ($res == 8) {
                    // в данном случае отправлено
                    $result = new Result(\Bxmaker\SmsNotice\SMS_STATUS_SENT);
                    $result->setMore('phone', $phone);
                    $result->setMore('text', $text);

//                 если возвращается идентификатор сообшений от смс шлюза
//                $result->setMore('params', array(
//                    'messageId' => (isset($match[1]) ? trim($match[1]) : '')
//                ));

                } else {
                    // здесь мы фиксируем ошибку
                    // в $res будет текст ошибки от сервиса к примеру: не достаточно средств
                    // BXMAKER_SMSNOTICE_SERVICE_SEND_ERROR - это идентификатор типа ошибки
                    // ну и доп параметры для анализа причин ошибок - кому оптравляли. какой текст отправляли
                    $result = new Result(new Error($res, 'BXMAKER_SMSNOTICE_SERVICE_SEND_ERROR', array(
                        'phone' => $phone,
                        'text' => $text
                    )));
                }
            }
            return $result;
        }





        public function sendPack($arPack)
	{
		//		PackItem - array(
		//			"phone"    => $arItem['PHONE'],
		//			  "clientId" => $id,
		//			  "text"     => $arItem['TEXT'],
		//			  "sender"   => $arItem['SENDER']
		//		)

		$result = new Result();

		$arMsg = array();
		foreach ($arPack['messages'] as $msg) {
			$arMsg[$msg['clientId']] = $this->send($msg['phone'], $msg['text']);
		}
		$result->setResult(array('messages' => $arMsg));

		return $result;
	}


        /**
         * для конкретного сервиса возвращает путь с парамтерами дялоповещения сайта о статус конкретной смс от смс шлюза
         * @param array $arParams
         * @return string
         */
        private function getNoticeUrl($arParams = array())
        {
            return $this->notice_path . '?' . http_build_query(array(
                'smsId' => $arParams['smsId'],
                'serviceId' => $arParams['service']['ID'],
                'status' => '%d'
            ));
        }


        /**
         * Проверка баланса
         * @return Result
         */
        public function getBalance()
        {
            $res = $this->oHttp->get('http:// домен /api/get_balance2.php?' . http_build_query(array(
                    'login' => $this->login,
                    'pass' => $this->pass
                )));
            // мсервис в ответ пришлет сумму на балансе в цифровом виде
            if (intval($res)  > 0) {
                $result = new Result($res . ' руб.');
            } else {
                // в $res текст ошибки от сервиса, например - не верный логин или пароль
                $result = new Result(new Error($res, 'BXMAKER_SMSNOTICE_SERVICE_GETBALANCE_ERROR'));
            }
            return $result;
        }

        /**
         * Прием оповещений от смс сервиса по http о статусе соообщения
         * @return Result объект класса Result
         * @throws \Bitrix\Main\ArgumentException
         */
        public function notice()
        {

            /**
             * Не все сервисы поддерживают такие оповещения
             * СМС шлюз, после отправки смс сообщения может прислать нам статус сообщения,
             * в данном случае запрос от сервиса придет по такому url адресу -
             * http:// домен /bitrix/tools/bxmaker.smsnotice/notice.php?smsId=1022565&status=1&serviceId=2
             */

            $req = \Bitrix\Main\Application::getInstance()->getContext()->getRequest();
            $result = new Result();
            $oManagerTable = new ManagerTable();
            $dbr = $oManagerTable->getList(array(
                'filter' => array(
                    'ID' => (int)$req->getQuery('smsId')
                )
            ));

            if ($ar = $dbr->fetch()) {
                // раз найдено то проверим статус
                switch ($req->getQuery('status')) {
                    case 1: {
                        $result->setResult(\Bxmaker\SmsNotice\SMS_STATUS_DELIVERED);
                        break;
                    }
                    case 8: {
                        $result->setResult(\Bxmaker\SmsNotice\SMS_STATUS_SENT);
                        break;
                    }
                    default: {
                        $result->setError(new Error(GetMessage($this->module_id . '.SERVICE.SMS48.NOTICE.BXMAKER_SMSNOTICE_SERVICE_NOTICE_ERROR_UNKNOWN_SMS_STATUS'), 'BXMAKER_SMSNOTICE_SERVICE_NOTICE_ERROR_UNKNOWN_SMS_STATUS', array(
                            'params' => $req->getQueryList()
                        )));
                    }
                }
            } else {
                $result->setError(new Error(GetMessage($this->module_id . '.SERVICE.SMS48.NOTICE.NOT_FOUND_SMS_BY_ID'), 'BXMAKER_SMSNOTICE_SERVICE_NOTICE_ERROR_NOT_FOUN_SMS_BY_ID'));
            }

            $result->setMore('smsId', (int)$req->getQuery('smsId'));
            return $result;
        }


        /**
         * Агент конкретного сервиса вызывается с данными о нескольких смс, для запроса к смс шлюзу и получения статусов
         * @param $arSms
         * @return Result
         */
        public function agent($arSms)
        {
            $result = new Result(true);
            $arResult = array();
            $arError = array();


            foreach ($arSms as $smsId => $arSmsMore) {
                if (isset($arSmsMore['params']['messageId'])) {

                    $res = $this->oHttp->get('http:// домен /api/check_sms.php?' . http_build_query(array(
                            'id' => $arSmsMore['params']['messageId']
                        )));

                    if ($res == 1) {
                        $arResult[$smsId]  = new Result(\Bxmaker\SmsNotice\SMS_STATUS_DELIVERED);
                    } else {

                        if ($res == 8) {
                            $arResult[$smsId]  = new Result(\Bxmaker\SmsNotice\SMS_STATUS_SENT);
                        } else {
                            $arResult[$smsId] = new Result(new Error('UNKNOWN_MESSAGE_ID', \Bxmaker\SmsNotice\SMS_STATUS_ERROR, array(
                                'response' => $res
                            )));
                        }
                    }
                } else {
                    $arError[] = new Error('UNKNOWN_MESSAGE_ID', \Bxmaker\SmsNotice\SMS_STATUS_ERROR);
                    $arResult[$smsId] = new Result(new Error('UNKNOWN_MESSAGE_ID', \Bxmaker\SmsNotice\SMS_STATUS_ERROR));
                }
            }

            $result->setMore('results', $arResult);
            $result->setMore('errors', (!empty($arError) ? $arError : null)); // ошибок нет

            return $result;
        }

        /**
         * Параметры выводимые в админке при выборе текущего смс шлюза
         * @return array
         */
        public function getParams()
        {

            return array(
                'LOGIN' => array(
                    'NAME' => 'Логин',
                    'NAME_HINT' => 'Пояснение к полю',
                    'TYPE' => 'STRING',
                    'VALUE' => ''
                ),
                'PASS' => array(
                    'NAME' => 'Пароль',
                    'NAME_HINT' => 'Пояснение к полю',
                    'TYPE' => 'STRING',
                    'VALUE' => ''
                )
            );
        }

        public function getDescription()
        {
            return 'Здесь описание выподимое над полями, с информацие и ссылками где, что и как заполнять';
        }
    }

В результате при добавлении нового смс-сервиса или изменении добавленного ранее вы увидите в списке сервис с названием = названию класса (и файла), пример класса выше на скриншоте

Скриншот добавленного смс-шлюза