BxDolSmsSmsRu.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup UnaCore UNA Core
  7. * @{
  8. */
  9. class BxDolSmsSmsRu extends BxDolSms
  10. {
  11. protected $_sApiId;
  12. protected $_sFromNumber;
  13. protected function __construct($aObject, $oTemplate = null, $sDbClassName = '')
  14. {
  15. parent::__construct($aObject, $oTemplate, $sDbClassName);
  16. $this->_sApiId = getParam('sys_sms_smsru_api_id');
  17. $this->_sFromNumber = getParam('sys_sms_smsru_from_number');
  18. }
  19. public function send($sTo, $sMessage, $sFrom = '')
  20. {
  21. $oProvider = new SMSRU($this->_sApiId);
  22. $oData = new stdClass();
  23. $oData->to = $sTo;
  24. $oData->text = $sMessage;
  25. if($sFrom != '')
  26. $oData->from = $this->normalizePhone($sFrom);
  27. else if($this->_sFromNumber != '')
  28. $oData->from = $this->normalizePhone($this->_sFromNumber);
  29. if(($oResult = $oProvider->send_one($oData)) && $oResult->status == "OK")
  30. return true;
  31. $this->_writeLog($oResult->status_code . ': ' . $oResult->status_text, BX_LOG_ERR);
  32. return false;
  33. }
  34. }
  35. /**
  36. * Класс для работы с API сайта sms.ru для PHP 5.3 и выше
  37. * Разработчик WebProgrammer (kl.dm.vl@yandex.ru), легкие корректировки - Роман Гудев <rgudev@bk.ru>
  38. */
  39. class SMSRU {
  40. private $ApiKey;
  41. private $protocol = 'https';
  42. private $domain = 'sms.ru';
  43. private $count_repeat = 5; //количество попыток достучаться до сервера если он не доступен
  44. function __construct($ApiKey) {
  45. $this->ApiKey = $ApiKey;
  46. }
  47. /**
  48. * Совершает отправку СМС сообщения одному или нескольким получателям.
  49. * @param $post
  50. * $post->to = string - Номер телефона получателя (либо несколько номеров, через запятую — до 100 штук за один запрос). Если вы указываете несколько номеров и один из них указан неверно, то на остальные номера сообщения также не отправляются, и возвращается код ошибки.
  51. * $post->msg = string - Текст сообщения в кодировке UTF-8
  52. * $post->multi = array('номер получателя' => 'текст сообщения') - Если вы хотите в одном запросе отправить разные сообщения на несколько номеров, то воспользуйтесь этим параметром (до 100 сообщений за 1 запрос). В этом случае, параметры to и text использовать не нужно
  53. * $post->from = string - Имя отправителя (должно быть согласовано с администрацией). Если не заполнено, в качестве отправителя будет указан ваш номер.
  54. * $post->time = Если вам нужна отложенная отправка, то укажите время отправки. Указывается в формате UNIX TIME (пример: 1280307978). Должно быть не больше 7 дней с момента подачи запроса. Если время меньше текущего времени, сообщение отправляется моментально.
  55. * $post->translit = 1 - Переводит все русские символы в латинские. (по умолчанию 0)
  56. * $post->test = 1 - Имитирует отправку сообщения для тестирования ваших программ на правильность обработки ответов сервера. При этом само сообщение не отправляется и баланс не расходуется. (по умолчанию 0)
  57. * $post->partner_id = int - Если вы участвуете в партнерской программе, укажите этот параметр в запросе и получайте проценты от стоимости отправленных сообщений.
  58. * $post->ip = string - IP адрес пользователя, в случае если вы отправляете код авторизации ему на номер в ответ на его запрос (к примеру, при регистрации). В случае аттаки на ваш сайт, наша система сможет помочь с защитой.
  59. * @return array|mixed|\stdClass
  60. */
  61. public function send_one($post) {
  62. $url = $this->protocol . '://' . $this->domain . '/sms/send';
  63. $request = $this->Request($url, $post);
  64. $resp = $this->CheckReplyError($request, 'send');
  65. if ($resp->status == "OK") {
  66. $temp = (array) $resp->sms;
  67. unset($resp->sms);
  68. $temp = array_pop($temp);
  69. if ($temp) {
  70. return $temp;
  71. } else {
  72. return $resp;
  73. }
  74. } else {
  75. return $resp;
  76. }
  77. }
  78. public function send($post) {
  79. $url = $this->protocol . '://' . $this->domain . '/sms/send';
  80. $request = $this->Request($url, $post);
  81. return $this->CheckReplyError($request, 'send');
  82. }
  83. /**
  84. * Отправка СМС сообщений по электронной почте
  85. * @param $post
  86. * $post->from = string - Ваш электронный адрес
  87. * $post->charset = string - кодировка переданных данных
  88. * $post->send_charset = string - кодировка переданных письма
  89. * $post->subject = string - тема письма
  90. * $post->body = string - текст письма
  91. * @return bool
  92. */
  93. public function sendSmtp($post) {
  94. $post->to = $this->ApiKey . '@' . $this->domain;
  95. $post->subject = $this->sms_mime_header_encode($post->subject, $post->charset, $post->send_charset);
  96. if ($post->charset != $post->send_charset) {
  97. $post->body = iconv($post->charset, $post->send_charset, $post->body);
  98. }
  99. $headers = "From: $post->\r\n";
  100. $headers .= "Content-type: text/plain; charset=$post->send_charset\r\n";
  101. return mail($post->to, $post->subject, $post->body, $headers);
  102. }
  103. public function getStatus($id) {
  104. $url = $this->protocol . '://' . $this->domain . '/sms/status';
  105. $post = new stdClass();
  106. $post->sms_id = $id;
  107. $request = $this->Request($url, $post);
  108. return $this->CheckReplyError($request, 'getStatus');
  109. }
  110. /**
  111. * Возвращает стоимость сообщения на указанный номер и количество сообщений, необходимых для его отправки.
  112. * @param $post
  113. * $post->to = string - Номер телефона получателя (либо несколько номеров, через запятую — до 100 штук за один запрос) Если вы указываете несколько номеров и один из них указан неверно, то возвращается код ошибки.
  114. * $post->text = string - Текст сообщения в кодировке UTF-8. Если текст не введен, то возвращается стоимость 1 сообщения. Если текст введен, то возвращается стоимость, рассчитанная по длине сообщения.
  115. * $post->translit = int - Переводит все русские символы в латинские
  116. * @return mixed|\stdClass
  117. */
  118. public function getCost($post) {
  119. $url = $this->protocol . '://' . $this->domain . '/sms/cost';
  120. $request = $this->Request($url, $post);
  121. return $this->CheckReplyError($request, 'getCost');
  122. }
  123. /**
  124. * Получение состояния баланса
  125. */
  126. public function getBalance() {
  127. $url = $this->protocol . '://' . $this->domain . '/my/balance';
  128. $request = $this->Request($url);
  129. return $this->CheckReplyError($request, 'getBalance');
  130. }
  131. /**
  132. * Получение текущего состояния вашего дневного лимита.
  133. */
  134. public function getLimit() {
  135. $url = $this->protocol . '://' . $this->domain . '/my/limit';
  136. $request = $this->Request($url);
  137. return $this->CheckReplyError($request, 'getLimit');
  138. }
  139. /**
  140. * Получение списка отправителей
  141. */
  142. public function getSenders() {
  143. $url = $this->protocol . '://' . $this->domain . '/my/senders';
  144. $request = $this->Request($url);
  145. return $this->CheckReplyError($request, 'getSenders');
  146. }
  147. /**
  148. * Проверка номера телефона и пароля на действительность.
  149. * @param $post
  150. * $post->login = string - номер телефона
  151. * $post->password = string - пароль
  152. * @return mixed|\stdClass
  153. */
  154. public function authCheck($post) {
  155. $url = $this->protocol . '://' . $this->domain . '/auth/check';
  156. $post->api_id = 'none';
  157. return $this->CheckReplyError($request, 'AuthCheck');
  158. }
  159. /**
  160. * На номера, добавленные в стоплист, не доставляются сообщения (и за них не списываются деньги)
  161. * @param string $phone Номер телефона.
  162. * @param string $text Примечание (доступно только вам).
  163. * @return mixed|\stdClass
  164. */
  165. public function addStopList($phone, $text = "") {
  166. $url = $this->protocol . '://' . $this->domain . '/stoplist/add';
  167. $post = new stdClass();
  168. $post->stoplist_phone = $phone;
  169. $post->stoplist_text = $text;
  170. $request = $this->Request($url, $post);
  171. return $this->CheckReplyError($request, 'addStopList');
  172. }
  173. /**
  174. * Удаляет один номер из стоплиста
  175. * @param string $phone Номер телефона.
  176. * @return mixed|\stdClass
  177. */
  178. public function delStopList($phone) {
  179. $url = $this->protocol . '://' . $this->domain . '/stoplist/del';
  180. $post = new stdClass();
  181. $post->stoplist_phone = $phone;
  182. $request = $this->Request($url, $post);
  183. return $this->CheckReplyError($request, 'delStopList');
  184. }
  185. /**
  186. * Получить номера занесённые в стоплист
  187. */
  188. public function getStopList() {
  189. $url = $this->protocol . '://' . $this->domain . '/stoplist/get';
  190. $request = $this->Request($url);
  191. return $this->CheckReplyError($request, 'getStopList');
  192. }
  193. /**
  194. * Позволяет отправлять СМС сообщения, переданные через XML компании UCS, которая создала ПО R-Keeper CRM (RKeeper). Вам достаточно указать адрес ниже в качестве адреса шлюза и сообщения будут доставляться автоматически.
  195. */
  196. public function ucsSms() {
  197. $url = $this->protocol . '://' . $this->domain . '/ucs/sms';
  198. $request = $this->Request($url);
  199. $output->status = "OK";
  200. $output->status_code = '100';
  201. return $output;
  202. }
  203. /**
  204. * Добавить URL Callback системы на вашей стороне, на которую будут возвращаться статусы отправленных вами сообщений
  205. * @param $post
  206. * $post->url = string - Адрес обработчика (должен начинаться на http://)
  207. * @return mixed|\stdClass
  208. */
  209. public function addCallback($post) {
  210. $url = $this->protocol . '://' . $this->domain . '/callback/add';
  211. $request = $this->Request($url, $post);
  212. return $this->CheckReplyError($request, 'addCallback');
  213. }
  214. /**
  215. * Удалить обработчик, внесенный вами ранее
  216. * @param $post
  217. * $post->url = string - Адрес обработчика (должен начинаться на http://)
  218. * @return mixed|\stdClass
  219. */
  220. public function delCallback($post) {
  221. $url = $this->protocol . '://' . $this->domain . '/callback/del';
  222. $request = $this->Request($url, $post);
  223. return $this->CheckReplyError($request, 'delCallback');
  224. }
  225. /**
  226. * Все имеющиеся у вас обработчики
  227. */
  228. public function getCallback() {
  229. $url = $this->protocol . '://' . $this->domain . '/callback/get';
  230. $request = $this->Request($url);
  231. return $this->CheckReplyError($request, 'getCallback');
  232. }
  233. private function Request($url, $post = FALSE) {
  234. if ($post) {
  235. $r_post = $post;
  236. }
  237. $ch = curl_init($url . "?json=1");
  238. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  239. curl_setopt($ch, CURLOPT_TIMEOUT, 30);
  240. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  241. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  242. curl_setopt($ch, CURLOPT_VERBOSE, 1);
  243. if (!$post) {
  244. $post = new stdClass();
  245. }
  246. if (!empty($post->api_id) && $post->api_id == 'none') {
  247. } else {
  248. $post->api_id = $this->ApiKey;
  249. }
  250. curl_setopt($ch, CURLOPT_POST, 1);
  251. curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query((array) $post));
  252. $body = curl_exec($ch);
  253. if ($body === FALSE) {
  254. $error = curl_error($ch);
  255. } else {
  256. $error = FALSE;
  257. }
  258. curl_close($ch);
  259. if ($error && $this->count_repeat > 0) {
  260. $this->count_repeat--;
  261. return $this->Request($url, $r_post);
  262. }
  263. return $body;
  264. }
  265. private function CheckReplyError($res, $action) {
  266. if (!$res) {
  267. $temp = new stdClass();
  268. $temp->status = "ERROR";
  269. $temp->status_code = "000";
  270. $temp->status_text = "Невозможно установить связь с сервером SMS.RU. Проверьте - правильно ли указаны DNS сервера в настройках вашего сервера (nslookup sms.ru), и есть ли связь с интернетом (ping sms.ru).";
  271. return $temp;
  272. }
  273. $result = json_decode($res);
  274. if (!$result || !$result->status) {
  275. $temp = new stdClass();
  276. $temp->status = "ERROR";
  277. $temp->status_code = "000";
  278. $temp->status_text = "Невозможно установить связь с сервером SMS.RU. Проверьте - правильно ли указаны DNS сервера в настройках вашего сервера (nslookup sms.ru), и есть ли связь с интернетом (ping sms.ru)";
  279. return $temp;
  280. }
  281. return $result;
  282. }
  283. private function sms_mime_header_encode($str, $post_charset, $send_charset) {
  284. if ($post_charset != $send_charset) {
  285. $str = iconv($post_charset, $send_charset, $str);
  286. }
  287. return "=?" . $send_charset . "?B?" . base64_encode($str) . "?=";
  288. }
  289. }
  290. /** @} */