瀏覽代碼

add:push model;

Wang Chen 4 年之前
父節點
當前提交
095869bb77

+ 79 - 0
app/Modules/Push/Models/QappPushApp.php

@@ -0,0 +1,79 @@
+<?php
+
+
+namespace App\Modules\Push\Models;
+
+
+use Illuminate\Database\Eloquent\Model;
+
+class QappPushApp extends Model
+{
+    protected $table = 'qapp_push_app';
+    protected $fillable = ['uid', 'package_id', 'package', 'app_id', 'app_secret', 'app_key', 'master_key',
+        'name', 'config_json', 'provider', 'status'];
+
+    public static function getPushAppByAppId($appId)
+    {
+        if (empty($appId)) {
+            return [];
+        }
+
+        return self::where('app_id', $appId)->where('status', 1)->first();
+    }
+
+    /**
+     * @param $package
+     * @param $provider
+     * @return array
+     */
+    public static function getPushAppByPackageAndProvider($package, $provider)
+    {
+        if (empty($package) || empty($provider)) {
+            return [];
+        }
+
+        return self::where('package', $package)->where('provider', strtolower($provider))->where('status', 1)->first();
+    }
+
+    /**
+     * @param $packageId
+     * @param $provider
+     * @return array
+     */
+    public static function getPushAppByPackageIdAndProvider($packageId, $provider)
+    {
+        if (empty($packageId) || empty($provider)) {
+            return [];
+        }
+
+        return self::where('package_id', $packageId)->where('provider', strtolower($provider))->where('status', 1)->first();
+    }
+
+    /**
+     * @param $packageId
+     * @return array
+     */
+    public static function getPushAppByPackageId($packageId): array
+    {
+        if (empty($packageId)) {
+            return [];
+        }
+
+        $result = self::where('package_id', $packageId)->where('status', 1)->get();
+        return $result ? $result->toArray() : [];
+    }
+
+    /**
+     * @param $appIds
+     * @return array
+     */
+    public static function getPushAppByAppIds($appIds): array
+    {
+        if (empty($appIds)) {
+            return [];
+        }
+
+        $result = self::whereIn('app_id', $appIds)->where('status', 1)->get();
+        return $result ? $result->toArray() : [];
+    }
+}

+ 42 - 0
app/Modules/Push/Models/QappPushTask.php

@@ -0,0 +1,42 @@
+<?php
+
+
+namespace App\Modules\Push\Models;
+
+
+use Illuminate\Database\Eloquent\Model;
+
+class QappPushTask extends Model
+{
+    protected $table = 'qapp_push_task';
+    protected $fillable = ['uid', 'package_id', 'type', 'title', 'content', 'url', 'num',
+        'status', 'providers', 'push_time', 'push_filter', 'push_result'];
+
+    /**
+     * @param $id
+     * @return array
+     */
+    public static function getPushTaskById($id): array
+    {
+        if (empty($id)) {
+            return [];
+        }
+
+        $result = self::where('id', $id)->first();
+        return $result ? $result->toArray() : [];
+    }
+
+    /**
+     * @param $id
+     * @param $data
+     * @return bool
+     */
+    public static function updatePushTask($id, $data): bool
+    {
+        if (empty($id) || empty($data)) {
+            return false;
+        }
+
+        return self::where('id', $id)->update($data);
+    }
+}

+ 41 - 0
app/Modules/Push/Models/QappPushTaskLogs.php

@@ -0,0 +1,41 @@
+<?php
+
+
+namespace App\Modules\Push\Models;
+
+
+use Illuminate\Database\Eloquent\Model;
+
+class QappPushTaskLogs extends Model
+{
+    protected $table = 'qapp_push_task_logs';
+    protected $fillable = ['task_id', 'app_id', 'num', 'status', 'push_time', 'push_result'];
+
+    /**
+     * @param $taskId
+     * @return array
+     */
+    public static function getPushTaskLogsByTaskId($taskId): array
+    {
+        if (empty($taskId)) {
+            return [];
+        }
+
+        $result = self::where('task_id', $taskId)->get();
+        return $result ? $result->toArray() : [];
+    }
+
+    /**
+     * @param $where
+     * @param $data
+     * @return bool
+     */
+    public static function updateData($where, $data)
+    {
+        if (empty($where) || empty($data)) {
+            return false;
+        }
+
+        return self::where($where)->update($data);
+    }
+}

+ 28 - 0
app/Modules/Push/Models/QappPushTaskUsers.php

@@ -0,0 +1,28 @@
+<?php
+
+
+namespace App\Modules\Push\Models;
+
+
+use Illuminate\Database\Eloquent\Model;
+
+class QappPushTaskUsers extends Model
+{
+    protected $table = 'qapp_push_task_users';
+    protected $fillable = ['uid', 'app_id', 'task_id', 'task_log_id'];
+
+    /**
+     * @param $taskId
+     * @return array
+     */
+    public static function getTaskUsers($taskId): array
+    {
+        if (empty($taskId)) {
+            return [];
+        }
+
+        $result = self::where('task_id', $taskId)->get();
+        return $result ? $result->toArray() : [];
+    }
+
+}

+ 79 - 0
app/Modules/Push/Models/QappPushUser.php

@@ -0,0 +1,79 @@
+<?php
+
+
+namespace App\Modules\Push\Models;
+
+
+use DB;
+use Illuminate\Database\Eloquent\Model;
+
+class QappPushUser extends Model
+{
+    protected $table = 'qapp_push_user';
+    protected $fillable = ['uid', 'reg_id', 'provider', 'app_id', 'channel_id'];
+
+    /**
+     * @param $uid
+     * @return array
+     */
+    public static function getPushUserByUid($uid)
+    {
+        if (empty($uid)) {
+            return [];
+        }
+
+        $tableName = 'qapp_push_user';
+        return DB::connection('mysql::write')
+            ->table($tableName)
+            ->where('uid', $uid)->first();
+    }
+
+    public static function getPushUserByUids($uids): array
+    {
+        if (empty($uids)) {
+            return [];
+        }
+
+        $result = self::whereIn('uid', $uids)->get();
+        return $result ? $result->toArray() : [];
+    }
+
+    /**
+     * @param $uid
+     * @param $regId
+     * @param $appId
+     * @param $provider
+     * @param $channelId
+     * @return bool
+     */
+    public static function initPushUser($uid, $regId, $appId, $provider, $channelId): bool
+    {
+        if (empty($uid) || empty($regId) || empty($appId) || empty($provider)) {
+            return false;
+        }
+
+        return self::insert([
+            'uid'        => $uid,
+            'reg_id'     => $regId,
+            'provider'   => strtolower($provider),
+            'app_id'     => $appId,
+            'channel_id' => $channelId,
+            'created_at' => date('Y-m-d H:i:s', SERVER_TIME),
+            'updated_at' => date('Y-m-d H:i:s', SERVER_TIME),
+        ]);
+    }
+
+    /**
+     * @param $uid
+     * @param $regId
+     * @return bool
+     */
+    public static function setUserRegId($uid, $regId): bool
+    {
+        if (empty($uid) || empty($regId)) {
+            return false;
+        }
+
+        return self::where('uid', $uid)->update(['reg_id' => $regId, 'updated_at' => date('Y-m-d H:i:s', SERVER_TIME)]);
+    }
+}

+ 357 - 0
app/Modules/Push/Services/PushService.php

@@ -0,0 +1,357 @@
+<?php
+
+
+namespace App\Modules\Push\Services;
+
+
+use App\Cache\PushCache;
+use App\Consts\PushConst;
+use App\Libs\Push\OPPOPush\OPPOPushCommon;
+use App\Libs\Push\XMPush\MiPushCommon;
+use App\Libs\Utils;
+use App\Consts\ErrorConst;
+use App\Libs\Push\HuaWei\HwPushCommon;
+use App\Modules\Push\Models\QappPushApp;
+use App\Exceptions\ApiException;
+use App\Modules\Push\Models\QappPushTask;
+use App\Modules\Push\Models\QappPushTaskLogs;
+use App\Modules\Push\Models\QappPushTaskUsers;
+use App\Modules\Push\Models\QappPushUser;
+use App\Modules\User\Models\QappPackage;
+use Exception;
+use GuzzleHttp\Exception\GuzzleException;
+
+class PushService
+{
+    /**
+     * 设置用户reg_id
+     * @param        $uid
+     * @param string $regId
+     * @param string $provider
+     * @param string $package
+     * @return bool
+     */
+    public static function setUserRegId($uid, string $regId, string $provider, string $package): bool
+    {
+        myLog('push')->info('setUserRegId', compact('uid', 'regId', 'provider', 'package'));
+
+        // push服务商(转小写)
+        $provider = strtolower($provider);
+        if (empty($uid) || empty($regId) || empty($package) || empty($provider)) {
+            return false;
+        }
+
+        // 获取缓存
+        $userCacheRegId = PushCache::getUserPushRegId($uid);
+        if ($regId === $userCacheRegId) {
+            myLog('push')->info('setUserRegId', ['cache' => 'match']);
+            return true;
+        }
+
+        // 获取包信息
+        $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);
+        }
+
+        return $result;
+    }
+
+    /**
+     * 推送消息
+     * @param $taskId
+     * @return bool
+     * @throws ApiException
+     * @throws GuzzleException
+     */
+    public static function sendMessage($taskId): bool
+    {
+        if (empty($taskId)) {
+            return false;
+        }
+
+        // 获取任务数据
+        $pushTask = QappPushTask::getPushTaskById($taskId);
+        if ((int)getProp($pushTask, 'status') !== 1) {
+            Utils::throwError(ErrorConst::PUSH_TASK_INVALID);
+        }
+
+        // 判断任务时间
+        if (getProp($pushTask, 'push_time') > date('Y-m-d H:i:s')) {
+            Utils::throwError(ErrorConst::PUSH_TASK_NOT_START);
+        }
+
+        // 获取全部子任务
+        $subTasks = QappPushTaskLogs::getPushTaskLogsByTaskId($taskId);
+        if (!$subTasks) {
+            Utils::throwError(ErrorConst::PUSH_TASK_LOGS_NOT_FOUND);
+        }
+
+        // 获取推送应用信息
+        $pushAppIds = array_column($subTasks, 'app_id');
+        $pushApps   = QappPushApp::getPushAppByAppIds($pushAppIds);
+        if (!$pushApps) {
+            Utils::throwError(ErrorConst::PUSH_APP_NOT_SET);
+        }
+
+        // 更新任务开始状态
+        QappPushTask::updatePushTask(getProp($pushTask, 'id'), [
+            'status'     => PushConst::PUSH_STATUS_DOING,
+            'updated_at' => date('Y-m-d H:i:s')
+        ]);
+
+        // 判断是全量发送还是批量发送
+        if (getProp($pushTask, 'push_filter') === 'all') {
+            $result = self::pushMessageToAll($pushTask, $subTasks, $pushApps);
+        } else {
+            $result = self::pushMessageToUsers($pushTask, $subTasks, $pushApps);
+        }
+
+        // 更新任务执行状态
+        QappPushTask::updatePushTask(getProp($pushTask, 'id'), [
+            'status'     => $result ? PushConst::PUSH_STATUS_SUCCESS : PushConst::PUSH_STATUS_FAIL,
+            'updated_at' => date('Y-m-d H:i:s')
+        ]);
+
+        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;
+
+        // 循环群发
+        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相关
+            $title        = getProp($pushTask, 'title');
+            $content      = getProp($pushTask, 'content');
+            $url          = getProp($pushTask, 'url');
+            $provider     = strtolower(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::updateData(['id' => $subTaskId], [
+                'status'     => PushConst::PUSH_STATUS_DOING,
+                'updated_at' => date('Y-m-d H:i:s')
+            ]);
+
+            $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;
+                    case PushConst::PROVIDER_OPPO:
+                        // 实例化OPPO
+                        $client    = new OPPOPushCommon($appKey, $masterSecret);
+                        $messageId = $client->getMessageId($title, $content, $url);
+                        $result    = $client->broadCastAll($messageId);
+                        break;
+                }
+            } catch (Exception $e) {
+                $pushResult = 0 && $pushResult;
+
+                // 更新子任务失败状态
+                QappPushTaskLogs::updateData(['id' => $subTaskId], [
+                    'status'      => PushConst::PUSH_STATUS_FAIL,
+                    'push_result' => json_encode($result, JSON_UNESCAPED_UNICODE),
+                    'updated_at'  => date('Y-m-d H:i:s')
+                ]);
+                continue;
+            }
+
+            // 更新成功状态
+            QappPushTaskLogs::updateData(['id' => $subTaskId], [
+                'status'      => PushConst::PUSH_STATUS_SUCCESS,
+                'push_result' => json_encode($result, JSON_UNESCAPED_UNICODE),
+                'updated_at'  => date('Y-m-d H:i:s')
+            ]);
+        }
+
+        return $pushResult;
+    }
+
+    /**
+     * @param $pushTask
+     * @param $subTasks
+     * @param $pushApps
+     * @return bool
+     * @throws ApiException
+     * @throws GuzzleException
+     */
+    private static function pushMessageToUsers($pushTask, $subTasks, $pushApps)
+    {
+        // 获取需要推送的人
+        $taskId    = getProp($pushTask, 'id');
+        $taskUsers = QappPushTaskUsers::getTaskUsers($taskId);
+        if (!$taskUsers) {
+            Utils::throwError(ErrorConst::PUSH_TASK_NO_USERS);
+        }
+
+        $pushResult = true;
+
+        // 推送
+        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     = strtolower(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');
+            $title        = getProp($pushTask, 'title');
+            $content      = getProp($pushTask, 'content');
+            $url          = getProp($pushTask, 'url');
+
+            // 更新开始状态
+            QappPushTaskLogs::updateData(['id' => $subTaskId], [
+                'status'     => PushConst::PUSH_STATUS_DOING,
+                'updated_at' => date('Y-m-d H:i:s')
+            ]);
+
+            // 循环批量
+            $regIdArr = array_chunk($regIds, 1000);
+            try {
+                switch ($provider) {
+                    // 华为
+                    case PushConst::PROVIDER_HW:
+                        // 初始化huawei推送
+                        $client = new HwPushCommon($appId, $appSecret);
+
+                        // 循环推送
+                        foreach ($regIdArr as $regIdList) {
+                            $client->setToken($regIdList);
+                            $result = $client->sendPushMessage($title, $content, $url);
+                        }
+                        break;
+                    // 小米
+                    case PushConst::PROVIDER_MI:
+                        // 初始化小米推送
+                        $client = new MiPushCommon($package, $appSecret);
+
+                        // 循环推送
+                        foreach ($regIdArr as $regIdList) {
+                            $client->setRegArr($regIdList);
+                            $result = $client->sendMessage($title, $content, $url);
+                        }
+                        break;
+                    // OPPO
+                    case PushConst::PROVIDER_OPPO:
+                        // 初始化oppo推送
+                        $client    = new OPPOPushCommon($appKey, $masterSecret);
+                        $messageId = $client->getMessageId($title, $content, $url);
+
+                        // 循环推送
+                        foreach ($regIdArr as $regIdList) {
+                            $client->setRegArr($regIdList);
+                            $result = $client->broadCastRegIds($messageId);
+                        }
+                        break;
+                }
+            } catch (Exception $e) {
+                $pushResult = 0 && $pushResult;
+
+                // 更新子任务失败状态
+                QappPushTaskLogs::updateData(['id' => $subTaskId], [
+                    'status'      => PushConst::PUSH_STATUS_FAIL,
+                    'push_result' => json_encode($result, JSON_UNESCAPED_UNICODE),
+                    'updated_at'  => date('Y-m-d H:i:s')
+                ]);
+                continue;
+            }
+
+            // 更新成功状态
+            QappPushTaskLogs::updateData(['id' => $subTaskId], [
+                'status'      => PushConst::PUSH_STATUS_SUCCESS,
+                'push_result' => json_encode($result, JSON_UNESCAPED_UNICODE),
+                'updated_at'  => date('Y-m-d H:i:s')
+            ]);
+        }
+
+        return $pushResult;
+    }
+
+}