info('setUserRegId', compact('uid', 'regId', 'provider', 'package')); // 获取缓存 $userCacheRegId = PushCache::getUserPushRegId($uid); if ($regId === $userCacheRegId) { return true; } // 加锁 $token = md5($provider . ':' . $regId); $lock = LockCache::getLock($token, 3); if (!$lock) { return false; } myLog('push')->info('setUserRegId', compact('uid', 'regId', 'provider', 'token', 'lock')); // 获取包信息 $packageInfo = QappPackage::getPackageByPackage($package); $packageId = getProp($packageInfo, 'id'); $channelId = getProp($packageInfo, 'channel_id'); $company = getProp($packageInfo, 'company'); myLog('push')->info('setUserRegId', compact('packageId', 'channelId', 'company')); if (empty($packageId)) { return false; } // 获取app信息 $pushApp = QappPushApp::getPushAppByPackageIdAndProvider($packageId, $provider); $pushAppId = getProp($pushApp, 'app_id'); myLog('push')->info('setUserRegId', compact('pushAppId')); if (!$pushAppId) { return false; } // 设置 $pushUser = QappPushUser::getPushUserByUid($uid); $pushUserRegId = (string)getProp($pushUser, 'reg_id'); myLog('push')->info('setUserRegId', compact('pushUserRegId')); if ($pushUserRegId === $regId) { PushCache::setUserPushRegId($uid, $regId); return true; } // 初始化用户Push信息 if (!$pushUser) { // 初始化push_users QappPushUser::initPushUser($uid, $regId, $pushAppId, $provider, $channelId); // 针对华为用户需要主动订阅topic,方便后续全量推送 if ($provider === PushConst::PROVIDER_HW) { $client = new HwPushCommon($pushAppId, getProp($pushApp, 'app_secret')); $client->subscribeTopic(PushConst::TOPIC_ALL, [$regId]); } } // 更新用户数据库中reg_id $result = QappPushUser::setUserRegId($uid, $regId); if ($result) { // 更新缓存 PushCache::setUserPushRegId($uid, $regId); } // 释放锁 // LockCache::releaseLock($token); return $result; } /** * 推送消息 * @param $taskId * @return bool * @throws GuzzleException */ public static function pushMessageByTaskId($taskId): bool { if (empty($taskId)) { return false; } // 获取任务数据,判断任务状态及发送时间 $pushTask = QappPushTask::getPushTaskById($taskId); if ((int)getProp($pushTask, 'status') !== PushConst::STATUS_TODO || (int)getProp($pushTask, 'select_user_status') !== PushConst::SELECT_USER_OK || getProp($pushTask, 'push_time') > date('Y-m-d H:i:s')) { return false; } // 获取全部子任务,判断子任务是否有效 $subTasks = QappPushTaskLogs::getPushTaskLogsByTaskId($taskId); if (!$subTasks) { // 更新主任务失败状态及原因 QappPushTask::updateMainTaskStatus($taskId, PushConst::STATUS_FAIL, '无有效子任务'); return false; } // 获取推送应用信息 $pushAppIds = array_column($subTasks, 'app_id'); $pushApps = QappPushApp::getPushAppByAppIds($pushAppIds); if (!$pushApps) { // 更新主任务失败状态及原因 QappPushTask::updateMainTaskStatus($taskId, PushConst::STATUS_FAIL, '无有效推送APP'); return false; } // 更新主任务状态为开始状态 QappPushTask::updateMainTaskStatus($taskId, PushConst::STATUS_DOING, '无有效推送APP'); // 全量发送走标签,否则走批量 if (getProp($pushTask, 'push_filter') === PushConst::FILTER_ALL_USERS) { $result = self::pushMessageToAll($pushTask, $subTasks, $pushApps); } else { $result = self::pushMessageToUsers($pushTask, $subTasks, $pushApps); } // 更新主任务最终状态(成功/失败) $status = $result ? PushConst::STATUS_SUCCESS : PushConst::STATUS_FAIL; QappPushTask::updateMainTaskStatus($taskId, $status, $result); return $result; } /** * 全部发送 * @param $pushTask * @param $subTasks * @param $pushApps * @return bool * @throws GuzzleException */ private static function pushMessageToAll($pushTask, $subTasks, $pushApps): bool { if (empty($pushTask) || empty($subTasks) || empty($pushApps)) { return false; } // 推送结果、推送内容 $pushResult = true; $title = getProp($pushTask, 'title'); $content = getProp($pushTask, 'content'); $url = getProp($pushTask, 'url'); // 循环群发 foreach ($subTasks as $subTask) { $appId = getProp($subTask, 'app_id'); $subTaskId = getProp($subTask, 'id'); $pushApp = collect($pushApps)->firstWhere('app_id', $appId); if (empty($pushApp)) { continue; } // push app相关 $provider = getProp($pushApp, 'provider'); $package = getProp($pushApp, 'package'); $appId = getProp($pushApp, 'app_id'); $appSecret = getProp($pushApp, 'app_secret'); $appKey = getProp($pushApp, 'app_key'); $masterSecret = getProp($pushApp, 'master_secret'); $topic = PushConst::TOPIC_ALL; // 更新开始状态 QappPushTaskLogs::updateSubTaskStatus($subTaskId, PushConst::STATUS_DOING); $result = []; try { // 针对渠道做不同处理 switch ($provider) { // 华为 case PushConst::PROVIDER_HW: // 开发状态还是生产状态 $target = env('APP_ENV') === 'production' ? 2 : 1; // 设置相关配置 $client = new HwPushCommon($appId, $appSecret); $client->setFastAppTarget($target); $client->setTopic($topic); $client->setBigTag('Task_' . getProp($pushTask, 'id')); // 推送 $result = $client->sendPushMessage($title, $content, $url); break; // 小米 case PushConst::PROVIDER_MI: $client = new MiPushCommon($package, $appSecret); $result = $client->sendMessageToAll($title, $content, $url); break; // OPPO case PushConst::PROVIDER_OPPO: $client = new OPPOPushCommon($appKey, $masterSecret); $messageId = $client->getMessageId($title, $content, $url); $result = $client->broadCastAll($messageId); break; } } catch (Exception $e) { // 最终结果 $pushResult = 0 && $pushResult; // 更新子任务失败状态 QappPushTaskLogs::updateSubTaskStatus($subTaskId, PushConst::STATUS_FAIL, $result); continue; } // 更新成功状态 QappPushTaskLogs::updateSubTaskStatus($subTaskId, PushConst::STATUS_SUCCESS, $result); } return $pushResult; } /** * @param $pushTask * @param $subTasks * @param $pushApps * @return bool * @throws GuzzleException */ private static function pushMessageToUsers($pushTask, $subTasks, $pushApps) { // 获取需要推送的人 $taskId = getProp($pushTask, 'id'); $taskUsers = QappPushTaskUsers::getTaskUsers($taskId); if (!$taskUsers) { // 更新主任务失败状态及原因 QappPushTask::updateMainTaskStatus($taskId, PushConst::STATUS_FAIL, '未设置推送用户'); return false; } // 推送结果、推送内容 $pushResult = true; $title = getProp($pushTask, 'title'); $content = getProp($pushTask, 'content'); $url = getProp($pushTask, 'url'); // 推送 foreach ($subTasks as $subTask) { $subTaskId = getProp($subTask, 'id'); $appId = getProp($subTask, 'app_id'); $pushApp = collect($pushApps)->firstWhere('app_id', $appId); $uids = collect($taskUsers)->where('app_id', $appId)->pluck('uid'); $users = QappPushUser::getPushUserByUids($uids); $regIds = array_column($users, 'reg_id'); // push app相关 $provider = getProp($pushApp, 'provider'); $package = getProp($pushApp, 'package'); $appId = getProp($pushApp, 'app_id'); $appSecret = getProp($pushApp, 'app_secret'); $appKey = getProp($pushApp, 'app_key'); $masterSecret = getProp($pushApp, 'master_secret'); // 更新开始状态 QappPushTaskLogs::updateSubTaskStatus($subTaskId, PushConst::STATUS_DOING); // 循环批量 $regIdArr = array_chunk($regIds, 1000); try { switch ($provider) { // 华为 case PushConst::PROVIDER_HW: // 初始化huawei推送 $client = new HwPushCommon($appId, $appSecret); // 循环推送 $i = 0; foreach ($regIdArr as $regIdList) { $client->setToken($regIdList); $result = $client->sendPushMessage($title, $content, $url); // 一般的应用默认消息流控是针对单个应用3000QPS(每秒不能超过3000个token数) $i++; if ($i % 3 === 0) { sleep(1); } } break; // 小米 case PushConst::PROVIDER_MI: // 初始化小米推送 $client = new MiPushCommon($package, $appSecret); // 循环推送 $i = 0; foreach ($regIdArr as $regIdList) { $client->setRegArr($regIdList); $result = $client->sendMessage($title, $content, $url); // 一般的应用默认消息流控是针对单个应用3000QPS(每秒不能超过3000个token数) $i++; if ($i % 3 === 0) { sleep(1); } } break; // OPPO case PushConst::PROVIDER_OPPO: // 初始化oppo推送 $client = new OPPOPushCommon($appKey, $masterSecret); $messageId = $client->getMessageId($title, $content, $url); // 循环推送 $i = 0; foreach ($regIdArr as $regIdList) { $client->setRegArr($regIdList); $result = $client->broadCastRegIds($messageId); // 一般的应用默认消息流控是针对单个应用3000QPS(每秒不能超过3000个token数) $i++; if ($i % 3 === 0) { sleep(1); } } break; } } catch (Exception $e) { // 最终结果 $pushResult = 0 && $pushResult; // 更新子任务失败状态 QappPushTaskLogs::updateSubTaskStatus($subTaskId, PushConst::STATUS_FAIL, $result); continue; } // 更新成功状态 QappPushTaskLogs::updateSubTaskStatus($subTaskId, PushConst::STATUS_SUCCESS, $result); } return $pushResult; } }