Наверняка счастливые обладатели CMS Bitrix сталкивались с ситуацией когда количество подписок на ПУШ уведомления мобильных устройств пользователей становится запредельно большим. Как правило это хороший показатель, это говорит о популярности вашего интернет ресурса и мобильного приложения построенного на основе Bitrix.
ПУШ уведомления на мобильные устройства выступают в этом случае отличным инструментом маркетинга. Вы можете привлечь клиентов разослав им сообщения об предстоящих акциях, предложениях и т.д.
Как известно из кода Bitrix, отправка ПУШей от вашего сайта происходит на сервер компании Bitrix в специально подготовленном формате, а дальше оно уже через сервисы Google и Яблока доставляются до конечного устройства. Сама же отправка на сервер Bitrix происходит в обычном цикле через POST запрос.
На каждую интеграцию цикла происходит 1-н POST запрос, это обычная классическая схема однопоточного режима. Если у вас в очереди 1000 пушей – то это не создаст проблем. В среднем у вас получится отправлять по 3-и пуша в секунду.
Если количество пушей переваливает за 10000 штук и выше, вы можете не успеть оповестить всех пользователей о новой акции, так как через сутки это уже будет не актуально. Выходом может стать модификация класса отправки ПУШей в режиме много поточности через CURL.
Ниже привожу класс для такого режима работы. В своём коде вам нужно будет обращаться к этому классу для отправки ПУШа из Bitrix CMS.
• Возможные проблемы: Сервер Bitrix может не одобрить большого количества запросов с вашего сайта на их сервер.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
<?php //Пример отправки $arMessages[] = array(//Сообщение в специальном формате по Bitrix "USER_ID" => 1111, "TITLE" => 'Мега Акция', "APP_ID" => 'myapp.app', "MESSAGE" => 'Привет Семён! Купи у нас слона за 999руб.', "EXPIRY" => 60, "BADGE" => 0, ); $pushMe = new \CustomPushSender(); //Класс с multi curl $result = $pushMe->SendMessage($arMessages); #- отправка /** *Класс отправки с Multi Curl */ if (!class_exists('CustomPushSender')) { class CustomPushSender extends CPushManager { protected static $remoteProviderUrl = "https://cloud-messaging.bitrix24.com/send/"; public function SendMessage($arMessages = Array(), $arDevices = Array()) { if (empty($arMessages)) { return false; } $uniqueHashes = Array(); $arTmpMessages = Array(); foreach ($arMessages as $message) { if (!$message["USER_ID"]) { continue; } $uniqueHashes[] = CPullPush::getUniqueHash($message["USER_ID"], $message["APP_ID"]); $uniqueHashes[] = CPullPush::getUniqueHash($message["USER_ID"], $message["APP_ID"] . "_bxdev"); if (!array_key_exists("USER_" . $message["USER_ID"], $arTmpMessages)) { $arTmpMessages["USER_" . $message["USER_ID"]] = Array(); } $arTmpMessages["USER_" . $message["USER_ID"]][] = htmlspecialcharsback($message); } $filter = array( "UNIQUE_HASH" => array_unique($uniqueHashes) ); if (empty($arDevices)) { $dbDevices = CPullPush::GetList(Array("DEVICE_TYPE" => "ASC"), $filter); while ($row = $dbDevices->Fetch()) { $arDevices[] = $row; } } $arServicesIDs = array_keys(self::$pushServices); $arPushMessages = Array(); foreach ($arDevices as $arDevice) { if (in_array($arDevice["DEVICE_TYPE"], $arServicesIDs)) { $tmpMessage = $arTmpMessages["USER_" . $arDevice["USER_ID"]]; $mode = "PRODUCTION"; if (strpos($arDevice["APP_ID"], "_bxdev") > 0) { $mode = "SANDBOX"; } $arPushMessages[$arDevice["DEVICE_TYPE"]][$arDevice["DEVICE_TOKEN"]] = Array( "messages" => $tmpMessage, "mode" => $mode ); } } if (empty($arPushMessages)) { return false; } $batches = array(); /** * @var CPushService $obPush */ $batchMessageCount = CPullOptions::GetPushMessagePerHit(); $useChunks = ($batchMessageCount > 0); foreach ($arServicesIDs as $serviceID) { if ($arPushMessages[$serviceID]) { if (class_exists(self::$pushServices[$serviceID]["CLASS"])) { $obPush = new self::$pushServices[$serviceID]["CLASS"]; if (method_exists($obPush, "getBatch")) { if (!$useChunks) { if (count($batches) > 0) { $batches[0] .= $obPush->getBatch($arPushMessages[$serviceID]); } else { $batches[] = $obPush->getBatch($arPushMessages[$serviceID]); } } else { $offset = 0; $counter = 1; $messages = null; while ($messages = array_slice($arPushMessages[$serviceID], $offset, $batchMessageCount)) { $batches[] = $obPush->getBatch($messages); $offset += count($messages); $counter++; } } } } } } $this->sendBatch($batches); return true; } public function sendBatch($batches) { require_once($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/classes/general/update_client.php"); $key = CUpdateClient::GetLicenseKey(); if (strlen($key) > 0 && !empty($batches)) { $arSender = array(); foreach ($batches as $key => $chunkBatch) { $arSender[$key]['MESSAGE'] = $chunkBatch; $arSender[$key]['URL'] = self::$remoteProviderUrl . "?key=" . md5($key); $arSender[$key]['PUSH']['Action'] = 'SendMessage'; $arSender[$key]['PUSH']['MessageBody'] = $chunkBatch; } $this->sentRequesCurlMulti($arSender); return true; } return false; } protected function sentRequesCurlMulti($arUrl, $arOptions = array()) { if (empty($arUrl)) { return false; } $curls = array(); $result = array(); if (!function_exists('curl_multi_init')) { die('curl_multi_init не установлен'); } $mh = curl_multi_init(); foreach ($arUrl as $id => $arValue) { $curls[$id] = curl_init(); $url = $arValue['URL']; curl_setopt($curls[$id], CURLOPT_URL, $url); curl_setopt($curls[$id], CURLOPT_CONNECTTIMEOUT, 30); curl_setopt($curls[$id], CURLOPT_RETURNTRANSFER, 1); curl_setopt($curls[$id], CURLOPT_FOLLOWLOCATION, FALSE); curl_setopt($curls[$id], CURLOPT_POST, 1); curl_setopt($curls[$id], CURLOPT_POSTFIELDS, http_build_query($arValue['PUSH'])); if (!empty($arOptions)) { curl_setopt_array($curls[$id], $arOptions); } curl_multi_add_handle($mh, $curls[$id]); } $running = null; do { curl_multi_exec($mh, $running); } while ($running > 0); foreach ($curls as $id => $content) { $arCurlInfo = curl_getinfo($curls[$id]); //http_code $result[$id]['PAGE'] = curl_multi_getcontent($content); $result[$id]['URL'] = $arUrl[$id]['url']; $result[$id]['MESSAGE'] = $arUrl[$id]['message']; curl_multi_remove_handle($mh, $content); } curl_multi_close($mh); return $result; } } } |