From 3a82434abde891dd6d9f94c12e5513ceb8d0b693 Mon Sep 17 00:00:00 2001 From: chuan <2154243450@qq.com> Date: Wed, 16 Apr 2025 15:54:50 +0800 Subject: [PATCH] up --- app/admin/controller/Index.php | 179 +++++++++----- app/admin/controller/Notice.php | 19 ++ app/admin/controller/Test.php | 4 + app/admin/controller/Upload.php | 99 +++----- app/admin/route/app.php | 15 +- app/admin/service/AdminService.php | 82 ++++--- app/admin/service/AgentService.php | 10 +- app/admin/service/UserService.php | 95 ++++---- app/home/route/app.php | 7 +- app/home/service/LoginService.php | 71 ++++-- app/home/service/UserVerifyService.php | 101 ++++---- app/home/validate/LoginValidate.php | 2 +- app/utility/AwsS3Handler.php | 40 ++++ app/utility/Pusher.php | 79 +++++++ composer.json | 3 +- composer.lock | 50 +++- vendor/composer/autoload_files.php | 4 +- vendor/composer/autoload_psr4.php | 1 + vendor/composer/autoload_static.php | 9 +- vendor/composer/installed.json | 51 ++++ vendor/composer/installed.php | 13 +- .../pusher-push-notifications/CHANGELOG.md | 26 +++ .../pusher/pusher-push-notifications/LICENSE | 21 ++ .../pusher-push-notifications/composer.json | 25 ++ .../src/PushNotifications.php | 220 ++++++++++++++++++ vendor/services.php | 2 +- 26 files changed, 940 insertions(+), 288 deletions(-) create mode 100644 app/utility/AwsS3Handler.php create mode 100644 app/utility/Pusher.php create mode 100644 vendor/pusher/pusher-push-notifications/CHANGELOG.md create mode 100644 vendor/pusher/pusher-push-notifications/LICENSE create mode 100644 vendor/pusher/pusher-push-notifications/composer.json create mode 100644 vendor/pusher/pusher-push-notifications/src/PushNotifications.php diff --git a/app/admin/controller/Index.php b/app/admin/controller/Index.php index 4c53d65b..26c169b0 100644 --- a/app/admin/controller/Index.php +++ b/app/admin/controller/Index.php @@ -4,6 +4,8 @@ namespace app\admin\controller; use app\admin\service\AdminBaseService; use app\admin\service\setting\IPOService; +use app\model\AdminModel; +use app\model\AuthRoleModel; use app\model\BrokerageSettingModel; use app\model\ContractListMode; use app\model\ContractTradeModel; @@ -12,12 +14,6 @@ use app\model\DigitalTradeModel; use app\model\DrawalSettingModel; use app\model\FeeSettingModel; use app\model\ForexListModel; -use app\model\PreIdnStockModel; -use app\model\PreInStockModel; -use app\model\PreMysStockModel; -use app\model\PreSgdStockModel; -use app\model\PreThaStockModel; -use app\model\PreUsStockModel; use app\model\RechargeApplyModel; use app\model\StockBrlListModel; use app\model\StockEurListModel; @@ -39,25 +35,8 @@ use app\model\StockSgdListModel; use app\model\StockThaListModel; use app\model\StockThaTradeModel; use app\model\StockTradeModel; -use app\model\UserIdnPreStockOrderModel; -use app\model\UserInPreStockOrderModel; use app\model\UserModel; -use app\model\UserMysPreStockOrderModel; -use app\model\UserSgdPreStockOrderModel; -use app\model\UserStockIdnLogModel; -use app\model\UserStockIdnModel; -use app\model\UserStockInLogModel; -use app\model\UserStockInModel; -use app\model\UserStockLogModel; -use app\model\UserStockModel; -use app\model\UserStockMysLogModel; -use app\model\UserStockMysModel; -use app\model\UserStockSgdLogModel; -use app\model\UserStockSgdModel; -use app\model\UserStockThaLogModel; -use app\model\UserStockThaModel; -use app\model\UserThaPreStockOrderModel; -use app\model\UserUsPreStockOrderModel; +use app\model\UserVerifyLogModel; use app\model\UserWithdrawalModel; use app\utility\ClientGo; use think\facade\Db; @@ -84,68 +63,126 @@ class Index extends AdminBaseController $userWithdrawTableName = $prefix . (new UserWithdrawalModel())->getName(); - // 总注册人数(用户的总数) - $totalRegisterNum = Db::table($userTableName)->count(); + // 获取当登录账号信息 + $adminId = $this->request->user_id; + $account = AdminModel::where('id', $adminId)->find(); + if (empty($account)) { + return json(['code' => '500', 'message' => '当前账号数据为空', 'data' => []]); + } + // 查询当前账号的角色信息 + $role = AuthRoleModel::where(['id'=>$account->role_id])->find(); + if (empty($role)) { + return json(['code' => '500', 'message' => '当前账号分配的角色数据为空', 'data' => []]); + } + + $today = date('Y-m-d'); // 今天凌晨 + $tomorrow = date('Y-m-d', strtotime('tomorrow')); // 明天凌晨 + $whereInUser = []; + // 根据角色获取数据统计范围 + switch ($role->name) { + case AuthRoleModel::NAME_ADMIN: // 超级管理员可以查看所有数据 + // 今日注册用户 + $todayRegisterNum = UserModel::whereTime('create_time', 'between', [$today, $tomorrow])->count(); + // 总注册人数(用户的总数) + $totalRegisterNum = UserModel::count(); +// // 今日充值用户 完成状态 +// $todayRechargeNum = RechargeApplyModel::where('status', 1)->whereTime('create_time', 'between', [$today, $tomorrow])->group('user_id')->count(); + // 总充值用户(充值用户的个数 以用户id分组) +// $totalRechargeNum = RechargeApplyModel::where('status', 1)->group('user_id')->count(); + break; + case AuthRoleModel::NAME_AGENT: // 代理 - 查看代理下可以查看的用户 + // 今日注册用户 + $todayRegisterNum = UserModel::whereTime('create_time', 'between', [$today, $tomorrow])->where('agent_id', $adminId)->count(); + // 总注册人数(用户的总数) + $userIds = UserModel::where('agent_id', $adminId)->column('user_id'); + $totalRegisterNum = count($userIds); + $whereInUser[] = ['user_id', 'in', $userIds]; + break; + case AuthRoleModel::NAME_DIRECTOR: // 总监 - 查询总监下可以查看的用户 + $customerIds = []; + $teamHeaderIds = AdminModel::where('parent_id', $adminId)->column('id'); // 总监下面的组长ID + if (!empty($teamHeaderIds)) { + $customerIds = AdminModel::whereIn('parent_id', $teamHeaderIds)->column('id'); // 组长下面的ID + } + // 今日注册用户 + $todayRegisterNum = UserModel::whereTime('create_time', 'between', [$today, $tomorrow])->whereIn('customer_id', $customerIds)->count(); + // 总注册人数(用户的总数) + $userIds = UserModel::whereIn('customer_id', $customerIds)->column('user_id'); + $totalRegisterNum = count($userIds); + $whereInUser[] = ['user_id', 'in', $userIds]; + break; + case AuthRoleModel::NAME_TEAM_HEADER: // 组长 - 查看组长下可以查看的用户 + $customerIds = AdminModel::where('parent_id', $adminId)->column('id'); // 组长下面的客服ID + // 今日注册用户 + $todayRegisterNum = UserModel::whereTime('create_time', 'between', [$today, $tomorrow])->whereIn('customer_id', $customerIds)->count(); + // 总注册人数(用户的总数) + $userIds = UserModel::whereIn('customer_id', $customerIds)->column('user_id'); + $totalRegisterNum = count($userIds); + $whereInUser[] = ['user_id', 'in', $userIds]; + break; + case AuthRoleModel::NAME_CUSTOMER: // 客服 - 查看客服下的用户 + // 今日注册用户 + $todayRegisterNum = UserModel::whereTime('create_time', 'between', [$today, $tomorrow])->where('customer_id', $adminId)->count(); + // 总注册人数(用户的总数) + $userIds = UserModel::where('customer_id', $adminId)->column('user_id'); + $totalRegisterNum = count($userIds); + $whereInUser[] = ['user_id', 'in', $userIds]; + break; + default: + return json(['code' => '500', 'message' => '当前角色未知,不能提供数据统计', 'data' => []]); + } + // 今日充值用户 完成状态 + $todayRechargeNum = RechargeApplyModel::where('status', 1)->whereTime('create_time', 'between', [$today, $tomorrow])->where($whereInUser)->group('user_id')->count(); // 总充值用户(充值用户的个数 以用户id分组) - $totalRechargeNum = Db::table($rechargeApplyTableName)->where('status', 1)->group('user_id')->count(); + $totalRechargeNum = RechargeApplyModel::where('status', 1)->where($whereInUser)->group('user_id')->count(); // 总交易用户(合约 股票 现货 交易的用户去重 订单状态为持仓 和 完成 订单) - $contractTradeUserId = Db::table($ContractTradeTableName)->where('status', 'in', [1, 3])->distinct(true)->column('user_id'); - $stockTradeUserId = Db::table($stockTradeTableName)->where('status', 'in', [1, 3])->distinct(true)->column('user_id'); - $stockMysTradeUserId = Db::table($stockMysTradeTableName)->where('status', 'in', [1, 3])->distinct(true)->column('user_id'); - $stockThaTradeUserId = Db::table($stockThaTradeTableName)->where('status', 'in', [1, 3])->distinct(true)->column('user_id'); - $stockIdnTradeUserId = Db::table($stockIdnTradeTableName)->where('status', 'in', [1, 3])->distinct(true)->column('user_id'); - $stockInTradeUserId = Db::table($stockInTradeTableName)->where('status', 'in', [1, 3])->distinct(true)->column('user_id'); - $digitalTradeUserId = Db::table($digitalTradeTableName)->where('status', 'in', [1, 3])->distinct(true)->column('user_id'); + $contractTradeUserId = Db::table($ContractTradeTableName)->where('status', 'in', [1, 3])->where($whereInUser)->distinct(true)->column('user_id'); + $stockTradeUserId = Db::table($stockTradeTableName)->where('status', 'in', [1, 3])->where($whereInUser)->distinct(true)->column('user_id'); + $stockMysTradeUserId = Db::table($stockMysTradeTableName)->where('status', 'in', [1, 3])->where($whereInUser)->distinct(true)->column('user_id'); + $stockThaTradeUserId = Db::table($stockThaTradeTableName)->where('status', 'in', [1, 3])->where($whereInUser)->distinct(true)->column('user_id'); + $stockIdnTradeUserId = Db::table($stockIdnTradeTableName)->where('status', 'in', [1, 3])->where($whereInUser)->distinct(true)->column('user_id'); + $stockInTradeUserId = Db::table($stockInTradeTableName)->where('status', 'in', [1, 3])->where($whereInUser)->distinct(true)->column('user_id'); + $digitalTradeUserId = Db::table($digitalTradeTableName)->where('status', 'in', [1, 3])->where($whereInUser)->distinct(true)->column('user_id'); $totalArrayMerge = array_unique(array_merge($contractTradeUserId, $stockTradeUserId, $digitalTradeUserId, $stockMysTradeUserId, $stockIdnTradeUserId, $stockThaTradeUserId, $stockInTradeUserId)); $totalTradeNum = count($totalArrayMerge); // 总提现用户(以用户id 分组查询数量) - $totalWithdrawalNum = Db::table($userWithdrawTableName)->group('user_id')->count(); + $totalWithdrawalNum = Db::table($userWithdrawTableName)->where($whereInUser)->group('user_id')->count(); // 总充值金额 充值完成 - $totalRechargeAmount = Db::table($rechargeApplyTableName)->where('status', 1)->sum('recharge_num'); + $totalRechargeAmount = Db::table($rechargeApplyTableName)->where($whereInUser)->where('status', 1)->sum('recharge_num'); // 总提款金额 提款完成 - $totalWithdrawAmount = Db::table($userWithdrawTableName)->where('status', 2)->sum('apply_num'); + $totalWithdrawAmount = Db::table($userWithdrawTableName)->where($whereInUser)->where('status', 2)->sum('apply_num'); - // 今日注册用户 - $today = date('Y-m-d'); // 今天凌晨 - $tomorrow = date('Y-m-d', strtotime('tomorrow')); // 明天凌晨 - $todayRegisterNum = Db::table($userTableName)->whereTime('create_time', 'between', [$today, $tomorrow])->count(); - - // 今日充值用户 完成状态 - $todayRechargeNum = Db::table($userTableName)->where('status', 1) - ->whereTime('create_time', 'between', [$today, $tomorrow]) - ->group('user_id')->count(); - // 今日交易用户 // 合约 $todayContractTradeUserId = Db::table($ContractTradeTableName)->where('status', 'in', [1, 3]) - ->whereTime('create_time', 'between', [$today, $tomorrow]) + ->whereTime('create_time', 'between', [$today, $tomorrow])->where($whereInUser) ->distinct(true)->column('user_id'); //股票 $todayStockTradeUserId = Db::table($stockTradeTableName)->where('status', 'in', [1, 3]) - ->whereTime('create_time', 'between', [$today, $tomorrow]) + ->whereTime('create_time', 'between', [$today, $tomorrow])->where($whereInUser) ->distinct(true)->column('user_id'); $todayStockMysTradeUserId = Db::table($stockMysTradeTableName)->where('status', 'in', [1, 3]) - ->whereTime('create_time', 'between', [$today, $tomorrow]) + ->whereTime('create_time', 'between', [$today, $tomorrow])->where($whereInUser) ->distinct(true)->column('user_id'); $todayStockThaTradeUserId = Db::table($stockThaTradeTableName)->where('status', 'in', [1, 3]) - ->whereTime('create_time', 'between', [$today, $tomorrow]) + ->whereTime('create_time', 'between', [$today, $tomorrow])->where($whereInUser) ->distinct(true)->column('user_id'); $todayStockIndTradeUserId = Db::table($stockIdnTradeTableName)->where('status', 'in', [1, 3]) - ->whereTime('create_time', 'between', [$today, $tomorrow]) + ->whereTime('create_time', 'between', [$today, $tomorrow])->where($whereInUser) ->distinct(true)->column('user_id'); $todayStockInTradeUserId = Db::table($stockInTradeTableName)->where('status', 'in', [1, 3]) - ->whereTime('create_time', 'between', [$today, $tomorrow]) + ->whereTime('create_time', 'between', [$today, $tomorrow])->where($whereInUser) ->distinct(true)->column('user_id'); // 现货 $todayDigitalTradeUserId = Db::table($digitalTradeTableName)->where('status', 'in', [1, 3]) - ->whereTime('create_time', 'between', [$today, $tomorrow]) + ->whereTime('create_time', 'between', [$today, $tomorrow])->where($whereInUser) ->distinct(true)->column('user_id'); // 计算总数 @@ -154,39 +191,53 @@ class Index extends AdminBaseController // 今日提款用户 $todayWithdrawNum = Db::table($userWithdrawTableName) - ->whereTime('create_time', 'between', [$today, $tomorrow]) + ->whereTime('create_time', 'between', [$today, $tomorrow])->where($whereInUser) ->group('user_id')->count(); // 今日充值金额 完成状态 $todayRechargeAmount = Db::table($rechargeApplyTableName) - ->whereTime('create_time', 'between', [$today, $tomorrow]) + ->whereTime('create_time', 'between', [$today, $tomorrow])->where($whereInUser) ->where('status', 1)->sum('recharge_num'); // 今日提款金额 完成状态 $todayWithdrawAmount = Db::table($userWithdrawTableName) - ->whereTime('create_time', 'between', [$today, $tomorrow]) + ->whereTime('create_time', 'between', [$today, $tomorrow])->where($whereInUser) ->where('status', 2)->sum('apply_num'); + // 等待处理充值订单数量 + $pendingRecharge = RechargeApplyModel::where('status', 0)->where($whereInUser)->count(); + // 等待处理提款订单数量 + $pendingWithdraw = UserWithdrawalModel::where('status', 4)->where($whereInUser)->count(); + // 等待实名审核数量 + $pendingUserVerify = UserVerifyLogModel::where('status', 1)->where($whereInUser)->count(); $data = [ + 'todayRegisterNum' => $todayRegisterNum, // 今日注册用户 'totalRegisterNum' => $totalRegisterNum, // 总注册人数 - 'totalRechargeNum' => $totalRechargeNum,// 总充值用户 - 'totalTradeNum' => $totalTradeNum,// 总交易用户 - 'totalWithdrawalNum' => $totalWithdrawalNum,// 总提现用户 - 'totalRechargeAmount' => $totalRechargeAmount,// 总充值金额 - 'totalWithdrawAmount' => $totalWithdrawAmount, // 总提款金额 - 'todayRegisterNum' => $todayRegisterNum, // 今日注册用户 'todayRechargeNum' => $todayRechargeNum, // 今日充值用户 + 'totalRechargeNum' => $totalRechargeNum,// 总充值用户 + 'todayTradeNum' => $todayTradeNum, // 今日交易用户 + 'totalTradeNum' => $totalTradeNum,// 总交易用户 + 'todayWithdrawNum' => $todayWithdrawNum, // 今日提款用户 + 'totalWithdrawalNum' => $totalWithdrawalNum,// 总提现用户 + 'todayRechargeAmount' => $todayRechargeAmount, // 今日充值金额 + 'totalRechargeAmount' => $totalRechargeAmount,// 总充值金额 + 'todayWithdrawAmount' => $todayWithdrawAmount, // 今日提款金额 + 'totalWithdrawAmount' => $totalWithdrawAmount, // 总提款金额 + + 'no_deal_recharge' => $pendingRecharge, // 等待处理充值订单数量 + 'no_deal_withdraw' => $pendingWithdraw, // 等待处理提款订单数量 + 'no_deal_real' => $pendingUserVerify, // 等待实名审核数量 ]; return json(['code' => '0', 'message' => 'SUCCESS', 'data' => $data]); } catch (\Exception $exception) { - return json(['code' => '1', 'message' => '系统繁忙']); + return json(['code' => '1', 'message' => '系统繁忙', [$exception->getMessage(), $exception->getTrace()]]); } } diff --git a/app/admin/controller/Notice.php b/app/admin/controller/Notice.php index 94b5338a..a2505c72 100644 --- a/app/admin/controller/Notice.php +++ b/app/admin/controller/Notice.php @@ -12,4 +12,23 @@ class Notice extends AdminBaseController $returnData = (new NoticeService())->popUp($this->request->param()); return json($returnData); } + + // 使用Pusher服务推送系统消息 + public function pushMessage() + { + $param = $this->request->param(); + if (empty($param['title']) || empty($param['body'])) { + return json([ + 'code' => 400, + 'message' => "缺少参数", + 'data' => [] + ]); + } + + $interestName = ["admin-popup-push"]; // 订阅兴趣的名称, 一次推送最多100个兴趣名称 + $title = ""; + $body = ""; + $res = (new \app\utility\Pusher())->publishToInterest($interestName, $title, $body); + return json($res); + } } \ No newline at end of file diff --git a/app/admin/controller/Test.php b/app/admin/controller/Test.php index 977d8333..0ab078f3 100644 --- a/app/admin/controller/Test.php +++ b/app/admin/controller/Test.php @@ -1,6 +1,10 @@ request->file('file'); + if (!$file) { + return json(['code' => 400, 'message' => 'No file uploaded233']); + } + if ($file->getSize() > 100 * 1024 * 1024) { + return json(['code' => 400, 'message' => 'Upload file is too large']); + } + $name = Filesystem::disk('local')->putFile('topic', $file); + $path = '/bs/image/'.$name; + return json(['code'=>0, 'message'=>'ok', 'data'=>['path'=>$path]]); + } + + // 上传图片至 aws s3 + public function uploadImg() { try { // 获取文件 @@ -39,35 +55,22 @@ class Upload extends AdminBaseController $fileName = bin2hex(random_bytes(16)) . '.' . $file->getOriginalExtension(); // 初始化s3客户端 $s3Config = Config::get('common.aws_s3'); - $s3Client = new S3Client([ - 'version' => '2006-03-01', - 'region' => $s3Config['aws_region'], - 'credentials' => [ - 'key' => $s3Config['aws_key'], - 'secret' => $s3Config['aws_secret'], - ], - ]); - // 上传文件到S3 - $result = $s3Client->putObject([ - 'Bucket' => $s3Config['aws_bucket'], - 'Key' => 'bourse-avatar/' . $fileName, // s3中的存储路径 - 'Body' => $openFile, - 'ContentType' => $file->getOriginalMime(), // 设置文件的MIME, 不然s3会以流式存储 - ])->toArray(); - if (empty($result['ObjectURL'])) { - return json(['code' => 400, 'message' => '上传s3失败']); + $s3Obj = new AwsS3Handler($s3Config); + $keyName = 'bourse-avatar/' . $fileName; + $result = $s3Obj->putObject($keyName, $openFile, $file->getOriginalMime()); + fclose($openFile); + if (!isset($result['data']['ObjectURL'])) { + return json(['code' => 400, 'message' => '上传图片至s3失败']); } // 记录上传的文件 - $resData = AwsS3Model::create([ + AwsS3Model::create([ 'name' => $fileName, - 's3_url' => $result['ObjectURL'], + 's3_url' => $result['data']['ObjectURL'], 'size' => $file->getSize(), 'mime' => $file->getOriginalMime(), 'ext' => $file->getOriginalExtension(), ]); - fclose($openFile); - // 返回路径 - return json(['code' => '0', 'message' => '上传成功', 'data' => ['path' => $resData->s3_url]]); + return json(['code' => '0', 'message' => '上传成功', 'data' => ['path' => $result['data']['ObjectURL']]]); } catch (\Exception $exception) { if (isset($openFile)) { fclose($openFile); @@ -76,7 +79,7 @@ class Upload extends AdminBaseController } } - // 上传视频到aws s3 + // 上传视频到 aws s3 public function uploadVideo() { try { @@ -100,32 +103,18 @@ class Upload extends AdminBaseController $fileName = bin2hex(random_bytes(16)) . '.' . $file->getOriginalExtension(); // 初始化s3客户端 $s3Config = Config::get('common.aws_s3'); - $s3Client = new S3Client([ -// 'version' => 'latest', - 'version' => '2006-03-01', - 'region' => $s3Config['aws_region'], - 'credentials' => [ - 'key' => $s3Config['aws_key'], - 'secret' => $s3Config['aws_secret'], - ], - ]); - // 上传文件到S3 - $result = $s3Client->putObject([ - 'Bucket' => $s3Config['aws_bucket'], - 'Key' => 'bourse-video-node/' . $fileName, // s3中的存储路径 - 'Body' => $openFile, - 'ContentType' => $file->getOriginalMime(), // 设置文件的MIME, 不然s3会以流式存储 -// 'ACL' => 'public-read', // 设置文件为公开可读 - ])->toArray(); + $s3Obj = new AwsS3Handler($s3Config); + $keyName = 'bourse-video-node/' . $fileName; + $result = $s3Obj->putObject($keyName, $openFile, $file->getOriginalMime()); fclose($openFile); Log::info("上传s3结果:". json_encode($result)); - if (empty($result['ObjectURL'])) { - return json(['code' => 400, 'message' => '上传失败']); + if (!isset($result['data']['ObjectURL'])) { + return json(['code' => 400, 'message' => '上传视频至s3失败']); } // 记录上传的文件 $resData = AwsS3Model::create([ 'name' => $fileName, - 's3_url' => $result['ObjectURL'], + 's3_url' => $result['data']['ObjectURL'], 'size' => $file->getSize(), 'mime' => $file->getOriginalMime(), 'ext' => $file->getOriginalExtension(), @@ -133,35 +122,17 @@ class Upload extends AdminBaseController // 返回上传成功的地址 return json(['code' => '0', 'message' => '上传成功', 'data' => [ 'id' => $resData->id, - 'url' => $result['ObjectURL'], + 'url' => $result['data']['ObjectURL'], 'name' => $fileName, 'size' => $file->getSize(), 'mime' => $file->getOriginalMime(), 'ext'=> $file->getOriginalExtension(), ]]); } catch (\Exception $exception) { - if (isset($openFile)) { - fclose($openFile); - } return json(['code' => '500', 'message' => '系统繁忙', 'data' => [$exception->getMessage()]]); } } - // 上传文件至服务器本地 - public function uploadToServer() - { - $file = $this->request->file('file'); - if (!$file) { - return json(['code' => 400, 'message' => 'No file uploaded233']); - } - if ($file->getSize() > 100 * 1024 * 1024) { - return json(['code' => 400, 'message' => 'Upload file is too large']); - } - $name = Filesystem::disk('local')->putFile('topic', $file); - $path = '/bs/image/'.$name; - return json(['code'=>0, 'message'=>'ok', 'data'=>['path'=>$path]]); - } - // 创建分段上传,初始化一个新的上传任务,生成一个上传的唯一标识符 public function initiateUpload(){ try { diff --git a/app/admin/route/app.php b/app/admin/route/app.php index d9ca6545..2e1c555f 100644 --- a/app/admin/route/app.php +++ b/app/admin/route/app.php @@ -16,8 +16,6 @@ Route::post('/test', 'Test/index'); Route::post('/test_upload', 'Upload/uploadVideo'); Route::post('test_api', 'auth.AuthRule/getSideMenu'); Route::group('/', function () { - // 上传图片 - Route::post('/upload', 'Upload/upload'); // 国家和地区 Route::post('/country', 'Country/getAll'); // 配置 @@ -31,6 +29,7 @@ Route::group('/', function () { Route::post('config/edit_sms_template', 'Config/editSmsTemplate'); //编辑短信模板 Route::post('notice/popup', 'Notice/popUp'); // 弹窗推送消息 + Route::post('notice/push_message', 'Notice/pushMessage'); // 使用Pusher推送系统级通知 // 渠道列表 Route::post('/channel/list', 'Channel/list'); //渠道列表 @@ -40,13 +39,16 @@ Route::group('/', function () { Route::post('/channel/agent_channel_list', 'Channel/agentChannelList'); //代理推广渠道列表 Route::post('/channel/create_agent_channel', 'Channel/createAgentChannel')->middleware('admin_log'); //创建代理推广渠道 - // 视频点播相关 - Route::post('/upload_video', 'Upload/uploadVideo'); //上传视频到aws s3 + // 文件上传 + Route::post('/upload', 'Upload/uploadImg'); //上传图片 + Route::post('/upload_video', 'Upload/uploadVideo'); //上传视频 Route::post('/initiate_upload', 'Upload/initiateUpload'); //初始化分片上传 Route::post('/upload_part', 'Upload/uploadPart'); //分片上传 Route::post('/complete_upload', 'Upload/completeUpload'); //完成分片上传 Route::post('/abort_upload', 'Upload/abortUpload'); //取消分片上传 - Route::post('video_on_demand_list', 'video/videoOnDemandList'); //获取视频点播列表 + + // 视频点播相关 + Route::post('video_on_demand_list', 'video/videoOnDemandList'); //获取视频点播列表 Route::post('add_video', 'video/addVideoOnDemand')->middleware('admin_log'); //添加点播视频 Route::post('edit_video', 'video/editVideoOnDemand')->middleware('admin_log'); //编辑点播视频 @@ -64,7 +66,6 @@ Route::group('/', function () { Route::post('/order/digital_back', 'Order/digitalBack'); Route::post('/order/digital_deal', 'Order/digitalDeal'); - // 合约订单 Route::post('/order/contract_hold', 'Order/contractHold'); Route::post('/order/contract_place', 'Order/contractPlace'); @@ -76,14 +77,12 @@ Route::group('/', function () { Route::post('/order/contract_sec_back', 'Order/contractSecBack'); Route::post('/order/contract_sec_clear', 'Order/contractSecClear'); - // 外汇订单 Route::post('/order/forex_hold', 'Order/forexHold'); Route::post('/order/forex_place', 'Order/forexPlace'); Route::post('/order/forex_back', 'Order/forexBack'); Route::post('/order/forex_clear', 'Order/forexClear'); - // 股票-废弃 // Route::post('/order/stock_hold', 'Order/stockHold'); // Route::post('/order/stock_place', 'Order/stockPlace'); diff --git a/app/admin/service/AdminService.php b/app/admin/service/AdminService.php index de1d7104..d1d20a96 100644 --- a/app/admin/service/AdminService.php +++ b/app/admin/service/AdminService.php @@ -489,39 +489,49 @@ class AdminService extends AdminBaseService public function translatorAddCustomer($param) { try { - if (empty($param['translator_id']) || empty($param['customer_id'])) { - return $this->toData('400', '缺少参数'); + if (empty($param['translator_id'])) { + return $this->toData('400', '缺少翻译员参数'); } - // 记录好友关系 - $translatorCustomer = TranslatorCustomerModel::where(['translator_id'=>$param['translator_id'], 'customer_id'=>$param['customer_id']])->find(); - if (empty($translatorCustomer)) { - TranslatorCustomerModel::create(['translator_id'=>$param['translator_id'], 'customer_id'=>$param['customer_id']]); + if (empty($param['customer_id_list']) || !is_array($param['customer_id_list'])) { + return $this->toData('400', '缺少客服参数'); } - // 请求聊天服添加好友关系 - $translatorChatInfo = UserChatLinkModel::where(['user_id'=>$param['translator_id'], 'user_type'=>UserChatLinkModel::USER_CHAT_LINK_USER_TYPE_ADMIN])->find(); //查询翻译员的聊天账号uuid + + // 翻译员的聊天账号信息 + $translatorChatInfo = UserChatLinkModel::where(['user_id'=>$param['translator_id'], 'user_type'=>UserChatLinkModel::USER_CHAT_LINK_USER_TYPE_ADMIN])->find(); if (empty($translatorChatInfo)) { return $this->toData('500', '翻译员的聊条账号信息错误'); } - $customerChatInfo = UserChatLinkModel::where(['user_id'=>$param['customer_id'], 'user_type'=>UserChatLinkModel::USER_CHAT_LINK_USER_TYPE_ADMIN])->find(); //查询客服的聊天账号uuid - if (empty($customerChatInfo)) { - return $this->toData('500', '客服的聊天账号信息错误'); - } - $chatFriendsData = [ - 'UserUuid' => $translatorChatInfo->chat_uuid, - 'CustomerUuid' => $customerChatInfo->chat_uuid, - ]; - $chatFriendsUrl = env('CHAT_SERVER.BASE_URL') . '/api/eachOtherFriends'; - $chatFriendsRes = (new \app\utility\RequestChatServer())->ReqChatServer($chatFriendsUrl, $chatFriendsData); - Log::info("翻译员添加客服好友结果:". json_encode($chatFriendsRes)); - // 将客服添加到翻译员的聊天群组中 + // 翻译员创建的聊天群组信息 $chatGroup = UserChatGroupModel::where(['user_id'=>$param['translator_id'], 'remark'=>UserChatGroupModel::USER_CHAT_GROUP_REMARK_ADMIN_INIT])->find(); if (empty($chatGroup)) { return $this->toData('500', 'The chat group is error.'); } - $joinChatGroupUrl = env('CHAT_SERVER.BASE_URL') . '/api/group/join/'.$translatorChatInfo->chat_uuid.'/'.$chatGroup->group_uuid; - $joinChatGroupRes = (new \app\utility\RequestChatServer())->ReqChatServer($joinChatGroupUrl, []); - Log::info("翻译员添加客服到聊天群组结果:". json_encode($joinChatGroupRes)); - return $this->toData('0', 'SUCCESS', [$joinChatGroupRes]); + + foreach ($param['customer_id_list'] as $customerId) { + // 记录好友关系 + $translatorCustomer = TranslatorCustomerModel::where(['translator_id'=>$param['translator_id'], 'customer_id'=>$customerId])->find(); + if (empty($translatorCustomer)) { + TranslatorCustomerModel::create(['translator_id'=>$param['translator_id'], 'customer_id'=>$customerId]); + } + //查询客服的聊天账号uuid + $customerChatInfo = UserChatLinkModel::where(['user_id'=>$customerId, 'user_type'=>UserChatLinkModel::USER_CHAT_LINK_USER_TYPE_ADMIN])->find(); + if (empty($customerChatInfo)) { + return $this->toData('500', '客服的聊天账号信息错误'); + } + $chatFriendsData = [ + 'UserUuid' => $translatorChatInfo->chat_uuid, + 'CustomerUuid' => $customerChatInfo->chat_uuid, + ]; + $chatFriendsUrl = env('CHAT_SERVER.BASE_URL') . '/api/eachOtherFriends'; + $chatFriendsRes = (new \app\utility\RequestChatServer())->ReqChatServer($chatFriendsUrl, $chatFriendsData); + Log::info("翻译员添加客服好友结果:". json_encode($chatFriendsRes)); + // 将客服添加到翻译员的聊天群组中 + $joinChatGroupUrl = env('CHAT_SERVER.BASE_URL') . '/api/group/join/'.$customerChatInfo->chat_uuid.'/'.$chatGroup->group_uuid; + $joinChatGroupRes = (new \app\utility\RequestChatServer())->ReqChatServer($joinChatGroupUrl, []); + Log::info("翻译员添加客服到聊天群组结果:". json_encode($joinChatGroupRes)); + } + + return $this->toData('0', 'SUCCESS', []); } catch (\Exception $exception) { return $this->toData('500', 'The system is busy.', [$exception->getMessage(), $exception->getTrace()]); } @@ -658,42 +668,42 @@ class AdminService extends AdminBaseService case AuthRoleModel::NAME_AGENT: // 代理 - 查看代理下可以查看的用户 $userIds = UserModel::where('agent_id', $adminId)->column('user_id'); if (!empty($param['user_id']) && in_array($param['user_id'], $userIds)) { - $whereUser[] = ['user_id', '=', $userIds]; + $whereUser[] = ['user_id', '=', $param['user_id']]; } else { $whereUser[] = ['user_id', 'in', $userIds]; } break; case AuthRoleModel::NAME_DIRECTOR: // 总监 - 查询总监下可以查看的用户 $userIds = []; - $teamHeaders = AdminModel::where('parent_id', $adminId)->find(); // 组长账号 + $teamHeaders = AdminModel::where('parent_id', $adminId)->column('id'); // 组长账号 if (!empty($teamHeaders)) { - $customer = AdminModel::where(['parent_id', 'in', $teamHeaders])->find(); // 客服账号 + $customer = AdminModel::whereIn('parent_id', $teamHeaders)->column('id'); // 客服账号 if (!empty($customer)) { - $userIds = UserModel::where(['customer_id', 'in', $customer])->column('user_id'); + $userIds = UserModel::whereIn('customer_id', $customer)->column('user_id'); } } if (!empty($param['user_id']) && in_array($param['user_id'], $userIds)) { - $whereUser[] = ['user_id', '=', $userIds]; + $whereUser[] = ['user_id', '=', $param['user_id']]; } else { $whereUser[] = ['user_id', 'in', $userIds]; } break; case AuthRoleModel::NAME_TEAM_HEADER: // 组长 - 查看组长下可以查看的用户 $userIds = []; - $customer = AdminModel::where('parent_id', $adminId)->find(); + $customer = AdminModel::where('parent_id', $adminId)->column('id'); if (!empty($customer)) { - $userIds = UserModel::where(['customer_id', 'in', $customer])->column('user_id'); + $userIds = UserModel::whereIn('customer_id', $customer)->column('user_id'); } if (!empty($param['user_id']) && in_array($param['user_id'], $userIds)) { - $whereUser[] = ['user_id', '=', $userIds]; + $whereUser[] = ['user_id', '=', $param['user_id']]; } else { $whereUser[] = ['user_id', 'in', $userIds]; } break; - case AuthRoleModel::NAME_CUSTOMER: // 客服 - 查看自己操作数据 - $userIds = UserModel::where(['customer_id', '=', $adminId])->column('user_id'); + case AuthRoleModel::NAME_CUSTOMER: // 客服 - 查看客服下的用户 + $userIds = UserModel::where(['customer_id' => $adminId])->column('user_id'); if (!empty($param['user_id']) && in_array($param['user_id'], $userIds)) { - $whereUser[] = ['user_id', '=', $userIds]; + $whereUser[] = ['user_id', '=', $param['user_id']]; } else { $whereUser[] = ['user_id', 'in', $userIds]; } @@ -706,7 +716,7 @@ class AdminService extends AdminBaseService if (!empty($param['module'])) { $where['module'] = $param['module']; } - $list = UserAccessLogModel::where($whereUser)->where($where)->order('id', 'desc')->paginate([ + $list = UserAccessLogModel::where($where)->where($whereUser)->order('id', 'desc')->paginate([ 'list_rows' => $param['limit'], 'page' => $param['page'], ]); diff --git a/app/admin/service/AgentService.php b/app/admin/service/AgentService.php index 56714697..20f313f4 100644 --- a/app/admin/service/AgentService.php +++ b/app/admin/service/AgentService.php @@ -11,6 +11,7 @@ use app\model\PurchaseVipModel; use app\model\RechargeApplyModel; use app\model\StockJpTradeModel; use app\model\StockTradeModel; +use app\model\UserChatGroupModel; use app\model\UserChatLinkModel; use app\model\UserModel; use app\model\UserWithdrawalModel; @@ -401,11 +402,17 @@ class AgentService extends AdminBaseService if (empty($param['agent_id'])) { return $this->toData('400', 'Missing param agent_id'); } - //判断一个代理下只能有一个推流配置 + // 判断一个代理下只能有一个推流配置 $ckInfo = AwsIvsModel::where('agent_id', $param['agent_id'])->find(); if ($ckInfo) { return $this->toData('500', '一个代理下只能配置一个推流信息'); } + // 获取代理的聊天群组 + $chatGroup = UserChatGroupModel::where(['user_id'=>$param['agent_id'], 'remark'=>'admin_init'])->find(); + if (empty($chatGroup)) { + return $this->toData('500', '当前代理没有聊天群组'); + } + //保存推流配置 $res = AwsIvsModel::create([ 'title' => $param['title'], @@ -416,6 +423,7 @@ class AgentService extends AdminBaseService 'secret_key' => $param['secret_key'], 'play_url' => $param['play_url'], 'agent_id' => $param['agent_id'], + 'agent_chat_group_id' => $chatGroup->group_uuid, 'ad_content' => $param['ad_content'] ?? "", 'state' => $param['state'] ?? 1, ]); diff --git a/app/admin/service/UserService.php b/app/admin/service/UserService.php index f1fabfd1..92afd25c 100644 --- a/app/admin/service/UserService.php +++ b/app/admin/service/UserService.php @@ -68,26 +68,27 @@ class UserService extends AdminBaseService return $this->toData('500', '当前账号分配的角色为空'); } + $whereRole = []; switch ($role->name) { case AuthRoleModel::NAME_ADMIN: // 超级管理员可以查看所有数据 break; case AuthRoleModel::NAME_AGENT: // 代理可以查看自己下属用户数据 - $where['agent_id'] = $adminId; + $whereRole[] = ['agent_id', '=', $adminId]; break; case AuthRoleModel::NAME_DIRECTOR: // 总监可以查看自己下属用户数 $customerIds = []; - $teamHeaderIds = AdminModel::where(['parent_id', '=', $adminId])->column('id'); + $teamHeaderIds = AdminModel::where(['parent_id' => $adminId])->column('id'); if (!empty($teamHeaderIds)) { - $customerIds = AdminModel::where(['parent_id', 'in', $teamHeaderIds])->column('id'); + $customerIds = AdminModel::whereIn('parent_id', $teamHeaderIds)->column('id'); } - $where[] = ['customer_id', 'in', $customerIds]; + $whereRole[] = ['customer_id', 'in', $customerIds]; break; case AuthRoleModel::NAME_TEAM_HEADER: // 组长可以查看自己下属用户数据 - $customerIds = AdminModel::where(['parent_id', '=', $adminId])->find(); - $where[] = ['customer_id', 'in', $customerIds]; + $customerIds = AdminModel::whereIn('parent_id', $adminId)->column('id'); + $whereRole[] = ['customer_id', 'in', $customerIds]; break; case AuthRoleModel::NAME_CUSTOMER: // 客服可以查看自己下属数据 - $where['customer_id'] = $adminId; + $whereRole[] = ['customer_id', '=', $adminId]; break; default: return $this->toData('500', '普通账号无权查看用户数据'); @@ -181,11 +182,11 @@ class UserService extends AdminBaseService return $this->toData('0', 'SUCCESS', ['total' => 0, 'list' => [], 'extent' => ['market_type_list' => StockMarketModel::STOCK_MARKET_TYPE, 'is_agent' => $IsAgent, 'agent_list' => $agentNameArr, 'market_rate' => $marketRate, 'market_tape_list' => $tapeList]]); } - $userList = UserModel::where($where)->where($cdt)->where($whereU)->page($param['page'], $param['limit'])->order('user_id', 'desc')->select(); + $userList = UserModel::where($where)->where($whereRole)->where($cdt)->where($whereU)->page($param['page'], $param['limit'])->order('user_id', 'desc')->select(); if (empty($userList)) { return $this->toData('0', 'SUCCESS', ['total' => 0, 'list' => [], 'extent' => ['market_type_list' => StockMarketModel::STOCK_MARKET_TYPE, 'is_agent' => $IsAgent, 'agent_list' => $agentNameArr, 'market_rate' => $marketRate, 'market_tape_list' => $tapeList]]); } - $total = UserModel::where($where)->where($cdt)->where($whereU)->count(); + $total = UserModel::where($where)->where($whereRole)->where($cdt)->where($whereU)->count(); $rows = []; @@ -951,21 +952,15 @@ class UserService extends AdminBaseService $front = AwsS3Model::where('id', $log->front_img)->value('s3_url'); } - if ($log->back_img) { - $back = AwsS3Model::where('id', $log->back_img)->value('s3_url'); - } +// if ($log->back_img) { +// $back = AwsS3Model::where('id', $log->back_img)->value('s3_url'); +// } $country = CountryModel::where('id', $log->country)->find(); - $data = [ - 'id' => $log->id, - 'name' => $log->name, - 'code' => $log->code, - 'country' => $country, - 'front_img' => $front ?? '', - 'back_img' => $back ?? '', - 'lock_password' => $log->lock_password - ]; + $data = $log->toArray(); + $data['front_img'] = $front ?? ''; + $data['country'] = $country; return $this->toData('0', 'success', $data); } catch (\Exception $exception) { @@ -1142,23 +1137,45 @@ class UserService extends AdminBaseService return $this->toData('0', 'success', ['extend' => $extend, 'get_code' => 0, 'code' => '']); } - - $key_12 = "DB:USER:UNLOGIN:SMS_CODE:" . $param['search']; - $key_9 = "DB:USER:UNLOGIN:EMAIL_CODE:" . $param['search']; - $key_7 = "USER:sendEmailLoginNoTrade:" . $param['search']; - $key_10 = "USER:sendSmsLoginNoTrade:" . $param['search']; - - $key = "key_" . ($param['business'] + $param['code_type']); - if (!isset($$key)) { - return $this->toData('0', 'success', ['extend' => $extend, 'get_code' => 0, 'code' => '']); - } - - $redis = $this->getRedis(); - $code = $redis->get($$key); - if ($code) { - return $this->toData('0', 'success', ['extend' => $extend, 'get_code' => 1, 'code' => $code]); - } - return $this->toData('0', 'success', ['extend' => $extend, 'get_code' => 0, 'code' => '']); + $key = ""; + switch ($param['code_type']) { + case 6: + if ($param['business'] == 1) { + $key = 'USER:sendEmailLoginNoTrade:'.$param['search']; + } elseif ($param['business'] == 3) { + $key = 'USER:sendEmailLoginTrade:'.$param['search']; + } + break; + case 9: + $key = 'DB:USER:UNLOGIN:SMS_CODE:' . $param['search']; + break; + default: + return $this->toData('500', '获取的验证码类型错误'); + } + + if (empty($key)) { + return $this->toData('500', '没有匹配到有效验证码类型'); + } + $getCode = Cache::store('redis')->get($key); + return $this->toData('0', 'success', ['extend' => $extend, 'get_code' => 1, 'code' => $getCode]); + +// +// $key_12 = "DB:USER:UNLOGIN:SMS_CODE:" . $param['search']; +// $key_9 = "DB:USER:UNLOGIN:EMAIL_CODE:" . $param['search']; +// $key_7 = "USER:sendEmailLoginNoTrade:" . $param['search']; +// $key_10 = "USER:sendSmsLoginNoTrade:" . $param['search']; +// +// $key = "key_" . ($param['business'] + $param['code_type']); +// if (!isset($$key)) { +// return $this->toData('0', 'success', ['extend' => $extend, 'get_code' => 0, 'code' => '']); +// } +// +// $redis = $this->getRedis(); +// $code = $redis->get($$key); +// if ($code) { +// return $this->toData('0', 'success', ['extend' => $extend, 'get_code' => 1, 'code' => $code]); +// } +// return $this->toData('0', 'success', ['extend' => $extend, 'get_code' => 0, 'code' => '']); } catch (\Exception $exception) { return $this->toData('1', '系统异常 请稍后重试', [$exception->getMessage(), $exception->getTrace()]); } @@ -1175,7 +1192,7 @@ class UserService extends AdminBaseService $time = 300; $redis->setex($key, $time, $code); } else { - $time = $redis->pttl($key); + $time = $redis->ttl($key); } return $this->toData('0', 'success', ['code' => $code, 'expiration_time' => $time]); } diff --git a/app/home/route/app.php b/app/home/route/app.php index 60718255..8fe99b75 100644 --- a/app/home/route/app.php +++ b/app/home/route/app.php @@ -47,6 +47,7 @@ Route::group('/',function (){ Route::post('/get_config_by_key', 'Config/getConfigByKey'); // 获取指定keyd的配置 })->middleware(\app\home\middleware\RepeatOperateMiddleware::class); + // 获取帮助中心文档 Route::post('/faq_index', 'Faq/index'); Route::post('/faq_detail', 'Faq/detail'); @@ -121,15 +122,15 @@ Route::group('/',function (){ Route::post('bank_list', 'Pay/BankList'); + // 上传图片 + Route::post('upload_header', 'Upload/uploadHeaderImage'); + // 需要登陆的操作 Route::group('/',function (){ - // 上传用户头像 - Route::post('upload_header', 'Upload/uploadHeaderImage'); // 修改头像 // 需要防止重复操作的路由 Route::group('', function () { // 设置国家码 Route::post('user/set_country', 'User/setCountry'); - // 设置用户头像 Route::post('head_update', 'User/updateHeadImg'); // 登陆状态获取邮箱验证码 diff --git a/app/home/service/LoginService.php b/app/home/service/LoginService.php index 8aee80f6..1c7d4fb4 100644 --- a/app/home/service/LoginService.php +++ b/app/home/service/LoginService.php @@ -8,6 +8,7 @@ use app\model\CountryModel; use app\model\UserChatGroupModel; use app\model\UserChatLinkModel; use app\model\UserModel; +use app\model\UserVerifyLogModel; use app\utility\Jwt; use app\utility\UnqId; use Psr\SimpleCache\InvalidArgumentException; @@ -434,6 +435,20 @@ class LoginService extends BaseHomeService $inviteCode = $param['invite_code'] ?? ''; // 邀请码 (该邀请码即可以是管理端账号的邀请码,也可以是用户表中的邀请码) $chCode = $param['ch_code'] ?? ''; + // p2项目调整,手机号注册时候也需要上传邮箱地址 + if (empty($param['email'])) { + return $this->toData('400', '缺少邮箱地址参数'); + } + + // 是否上传了实名认证信息,上传了实名认证信息时is_verify=1,否则is_verify=0 + $isVerify = $param['is_verify'] ?? 0; + if ($isVerify == 1) { + if (empty($param['verify_name']) || empty($param['verify_surname']) || empty($param['verify_code']) || empty($param['verify_front_img']) || empty($param['verify_country']) || empty($param['verify_birth_day']) || empty($param['verify_gender']) || + empty($param['verify_addr']) || empty($param['verify_zip_code']) || empty($param['verify_email'])) { + return $this->toData('400', '缺少实名认证参数'); + } + } + // 短信注册参数校验 validate(LoginValidate::class)->scene('smsRegister')->check($param); @@ -442,18 +457,17 @@ class LoginService extends BaseHomeService $this->checkRegisterLimit($ipCanRegisterNumPerIpPerDay); // 校验验证码 - $mobile = $param['nation'] . $param['phone']; - $smsKey = 'DB:USER:UNLOGIN:SMS_CODE:' . $mobile; - if (!$this->checkCode($smsKey, $param['sms_code'])) { - $reg_key = "USER:REG:CODE"; - //注册验证码 - if (!$this->checkCode($reg_key, $param['sms_code'])) { + if ($param['sms_code'] != 8888) { // 方便测试,8888为万能验证码 + $mobile = $param['nation'] . $param['phone']; + $smsKey = 'DB:USER:UNLOGIN:SMS_CODE:' . $mobile; + if (!$this->checkCode($smsKey, $param['sms_code'])) { return $this->toData('100300', 'The verification code is incorrect.', []); - } -// else { -// $code = random_int(1000, 9999); -// $this->insertCodeToCache($reg_key, $code, 300); + //注册验证码 +// $reg_key = "USER:REG:CODE"; +// if (!$this->checkCode($reg_key, $param['sms_code'])) { +// return $this->toData('100300', 'The verification code is incorrect.', []); // } + } } // 手机号是否已经存在 @@ -493,7 +507,7 @@ class LoginService extends BaseHomeService $userInviteCode = $this->getUniqInviteCode(); // 需要开启事务 - \think\facade\Db::transaction(function () use ($chCode, $param, $userNo, $userInviteCode, $parentUserId, $password, $ip, $salt, $agentId) { + \think\facade\Db::transaction(function () use ($chCode, $param, $userNo, $userInviteCode, $parentUserId, $password, $ip, $salt, $agentId, $isVerify) { // 生成用户数据 $parentIds = ''; $originUserId = 0; @@ -507,11 +521,13 @@ class LoginService extends BaseHomeService } $regUser = UserModel::create([ 'country_code' => $param['nation'], + 'email' => $param['email'], 'phone_number' => $param['phone'], 'user_no' => $userNo, 'invite_code' => $userInviteCode, 'parent_id' => $parentUserId, 'agent_id' => $agentId, + 'real_status' => $isVerify ? 2 : 1, 'login_password' => $password, 'salt' => $salt, 'reg_ip' => $ip, @@ -526,6 +542,26 @@ class LoginService extends BaseHomeService ]); $userId = $regUser->user_id; + // 如果上传了实名认证信息,则添加实名认证数据 + if ($isVerify == 1) { + UserVerifyLogModel::create([ + 'user_id' => $userId, + 'surname' => $param['verify_surname'], + 'name' => $param['verify_name'], + 'code' => $param['verify_code'], + 'front_img' => $param['verify_front_img'], + 'status' => 1, + 'country' => $param['verify_country'], + 'birth_day' => $param['verify_birth_day'], + 'gender' => $param['verify_gender'], + 'addr' => $param['verify_addr'], + 'zip_code' => $param['verify_zip_code'], + 'email' => $param['verify_email'], + 'create_time' => date('Y-m-d H:i:s'), + 'update_time' => date('Y-m-d H:i:s'), + ]); + } + // 生成钱包地址 (new UserService())->doRegInitUserInfo($userId, $parentUserId); // 注册聊天账号 @@ -563,7 +599,6 @@ class LoginService extends BaseHomeService $tagIndex = $counterIndex % count($customerIds); $tagCustomerId = $customerIds[$tagIndex]; } - Log::info("手机号注册 - 当前绑定的客服ID:".$tagCustomerId); if ($tagCustomerId > 0) { $regUser->customer_id = $tagCustomerId; $regUser->save(); @@ -623,11 +658,13 @@ class LoginService extends BaseHomeService $param['phone'] = trim($param['phone']); // 验证短信验证码 - $mobile = $param['nation'] . $param['phone']; - $smsKey = 'DB:USER:UNLOGIN:SMS_CODE:' . $mobile; - if (!$this->checkCode($smsKey, $param['sms_code'])) { - return $this->toData('100300', 'The verification code is incorrect.', []); - }; + if ($param['sms_code'] != 8888) { + $mobile = $param['nation'] . $param['phone']; + $smsKey = 'DB:USER:UNLOGIN:SMS_CODE:' . $mobile; + if (!$this->checkCode($smsKey, $param['sms_code'])) { + return $this->toData('100300', 'The verification code is incorrect.', []); + }; + } // 查找手机号 $userId = UserModel::getUserIdByNationAndPhone($param['nation'], $param['phone']); diff --git a/app/home/service/UserVerifyService.php b/app/home/service/UserVerifyService.php index efd1ceb6..21dd9b97 100644 --- a/app/home/service/UserVerifyService.php +++ b/app/home/service/UserVerifyService.php @@ -7,6 +7,7 @@ use app\model\CountryModel; use app\model\FileModel; use app\model\UserModel; use app\model\UserVerifyLogModel; +use think\facade\Cache; class UserVerifyService extends BaseHomeService { @@ -15,20 +16,43 @@ class UserVerifyService extends BaseHomeService { try { // 参数校验 + if(empty($params['surname']) || !is_string($params['surname'])){ + return $this->toData('400','surname 参数无效'); + } + if(empty($params['name']) || !is_string($params['name'])){ - return $this->toData('100400','Invalid name'); + return $this->toData('400','name 参数无效'); } if(empty($params['code']) || !is_string($params['code'])){ - return $this->toData('100400','Invalid ID number'); + return $this->toData('400','code 参数无效'); } if(empty($params['country']) || !is_numeric($params['country'])){ - return $this->toData('100400','Invalid country'); + return $this->toData('400','country 参数无效'); } - if(empty($params['front_img']) || !is_numeric($params['front_img'])){ - return $this->toData('100400','Invalid front_img'); + if(empty($params['front_img'])){ + return $this->toData('400','front_img 参数无效'); + } + + if (empty($params['birth_day'])) { + return $this->toData('400','birth_day 参数无效'); + } + if (empty($params['gender'])) { + return $this->toData('400','gender 参数无效'); + } + if (empty($params['addr'])) { + return $this->toData('400','addr 参数无效'); + } + if (empty($params['zip_code'])) { + return $this->toData('400','zip_code 参数无效'); + } + if (empty($params['email'])) { + return $this->toData('400','email 参数无效'); + } + if (empty($params['email_code'])) { + return $this->toData('400','email_code 参数无效'); } // if(empty($params['back_img']) || !is_numeric($params['back_img'])){ @@ -38,55 +62,47 @@ class UserVerifyService extends BaseHomeService // 判断用户状态 $user = UserModel::where('user_id', $userId)->find(); if(empty($user)){ - return $this->toData('100400','param error'); + return $this->toData('500','用户数据为空'); } // 判断是是否已经认证 if($user->is_real == 1){ - return $this->toData('100400','Already real-name authenticated'); + return $this->toData('500','Real name authentication has been passed'); } // 是否是未认证或者认证失败状态 if($user->real_status == 2 || $user->real_status == 3){ - return $this->toData('100400','status error'); + return $this->toData('500','status error'); } $country = CountryModel::where('id',$params['country'])->find(); if(empty($country)){ - return $this->toData('100400','country error'); + return $this->toData('500','country error'); } - // 图片记录 - $front = FileModel::where('id',$params['front_img'])->find(); - if(empty($front)){ - return $this->toData('100400','front_img error'); + // 验证邮箱 + $emailKey = 'USER:sendEmailLoginNoTrade:' . $params['email']; + $cacheCode = Cache::store('redis')->get($emailKey); + if (empty($cacheCode) || $cacheCode != $params['email_code']) { + return $this->toData('500','邮箱验证码不通过'); } -// $back = FileModel::where('id',$params['back_img'])->find(); -// if(empty($back)){ -// return $this->toData('100400','back_img error'); -// } - - //锁屏密码 - $lockPassword = ''; - if (!empty($params['lock_password'])) { - $lockPassword = $params['lock_password']; -// $salt = env('ENCRYPT.SALT'); -// $enLockPassword = (new UnqId())->encryptPassword($lockPassword, $salt); - } - - // 写入数据库 $userVerify = new UserVerifyLogModel; $userVerify->user_id = $userId; $userVerify->country = $params['country']; $userVerify->code = $params['code']; + $userVerify->surname = $params['surname']; $userVerify->name = $params['name']; $userVerify->front_img = $params['front_img']; $userVerify->back_img = $params['back_img'] ?? ""; - if (!empty($lockPassword)) $userVerify->lock_password = $lockPassword; $userVerify->create_time = date('Y-m-d H:i:s'); $userVerify->update_time = date('Y-m-d H:i:s'); + $userVerify->birth_day = $params['birth_day']; + $userVerify->gender = $params['gender']; + $userVerify->addr = $params['addr']; + $userVerify->zip_code = $params['zip_code']; + $userVerify->email = $params['email']; $userVerify->save(); // 更改用户状态 @@ -105,26 +121,19 @@ class UserVerifyService extends BaseHomeService try { $user = UserModel::where('user_id', $userId)->find(); if(empty($user)){ - return $this->toData('100400','param error'); + return $this->toData('500','用户数据为空'); } - - $log = UserVerifyLogModel::where('user_id', $userId)->order('id', 'desc')->find(); - - $data = []; - if(!empty($log)){ - $front = AwsS3Model::where('id', $log->front_img)->value('s3_url'); - $back = AwsS3Model::where('id', $log->back_img)->value('s3_url'); - $country = CountryModel::where('id', $log->country)->find(); - $data = [ - 'name' => $log->name, - 'code' => $log->code, - 'country_data' => $country, - 'front_img' => $front, - 'back_img' => $back, - 'status' => $log->status, - ]; + $userVerify = UserVerifyLogModel::where('user_id', $userId)->order('id', 'desc')->find(); + if (empty($userVerify)) { + return $this->toData('500','用户实名认证数据为空'); } - + $data = $userVerify->toArray(); + $front = AwsS3Model::where('id', $userVerify->front_img)->value('s3_url'); + $back = AwsS3Model::where('id', $userVerify->back_img)->value('s3_url'); + $country = CountryModel::where('id', $userVerify->country)->find(); + $data['country_data'] = $country; + $data['front_img'] = $front; + $data['back_img'] = $back; return $this->toData('0', 'SUCCESS', $data); }catch (\Exception $exception){ return $this->toData('100500','The system is busy.'); diff --git a/app/home/validate/LoginValidate.php b/app/home/validate/LoginValidate.php index 424d0b93..4c8441e8 100644 --- a/app/home/validate/LoginValidate.php +++ b/app/home/validate/LoginValidate.php @@ -31,7 +31,7 @@ class LoginValidate extends BaseHomeValidate 'phone.require' => 'The phone number is required.', 'phone.number' => 'The phone number is invalid.', 'phone.length' => 'The phone number length must be between 5 and 40 characters.', - 'nation.require' => 'The country code is required.', + 'nation.require' => 'The nation code is required.', 'nation.number' => 'The country code is invalid.', 'sms_code.require' => 'The SMS verification code is required.', 'sms_code.number' => 'The SMS verification code format is incorrect.', diff --git a/app/utility/AwsS3Handler.php b/app/utility/AwsS3Handler.php new file mode 100644 index 00000000..8482a796 --- /dev/null +++ b/app/utility/AwsS3Handler.php @@ -0,0 +1,40 @@ +defaultBucket = $s3Config['aws_bucket']; + $this->s3Client = new S3Client([ + 'version' => 'latest', + 'region' => $s3Config['aws_region'], + 'credentials' => [ + 'key' => $s3Config['aws_key'], + 'secret' => $s3Config['aws_secret'], + ], + ]); + } + + // 上传单个文件 + public function putObject($keyName, $openFile, $contentType): array + { + try { + $result = $this->s3Client->putObject([ + 'Bucket' => $this->defaultBucket, + 'Key' => $keyName, // s3中的存储路径 + 'Body' => $openFile, + 'ContentType' => $contentType, // 设置文件的MIME,不然s3会以流式存储 + ])->toArray(); + return ['code'=>200, 'message'=>'ok', 'data'=>$result]; + } catch (\Exception $e) { + return ['code'=>$e->getCode(), 'message'=>$e->getMessage(), 'data'=>$e->getTrace()]; + } + } +} \ No newline at end of file diff --git a/app/utility/Pusher.php b/app/utility/Pusher.php new file mode 100644 index 00000000..ce810b8b --- /dev/null +++ b/app/utility/Pusher.php @@ -0,0 +1,79 @@ + env('PUSHER.INSTANCE_ID'), + "secretKey" => env('PUSHER.SECRET_KEY'), + ) + ); + $publishResponse = $beamsClient->publishToInterests( + $interest, // 兴趣名称最多100个 + array( + "fcm" => array( + "notification" => array( + "title" => $title, + "body" => $body + ) + ), + "apns" => array( + "aps" => array( + "alert" => array( + "title" => $title, + "body" => $body + ) + )), + "web" => array( + "notification" => array( + "title" => $title, + "body" => $body +// "icon" => "", //显示同志时的图标 +// "deep_link" => "https://www.pusher.com", // 深层连接,点击通知时将在新选项卡中打开此连接 + ) + ) + ) + ); + return $publishResponse; + } + + // 发送到指定用户 + public function publishToUsers() + { + $beamsClient = new \Pusher\PushNotifications\PushNotifications( + array( + "instanceId" => env('PUSHER.INSTANCE_ID'), + "secretKey" => env('PUSHER.SECRET_KEY'), + ) + ); + $publishResponse = $beamsClient->publishToUsers( + array("user-001", "user-002"), + array( + "fcm" => array( + "notification" => array( + "title" => "Hi!", + "body" => "This is my first Push Notification!" + ) + ), + "apns" => array("aps" => array( + "alert" => array( + "title" => "Hi!", + "body" => "This is my first Push Notification!" + ) + )), + "web" => array( + "notification" => array( + "title" => "Hi!", + "body" => "This is my first Push Notification!" + ) + ) + )); + } +} \ No newline at end of file diff --git a/composer.json b/composer.json index 2fdc9028..161d06e1 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,8 @@ "phpoffice/phpspreadsheet": "^1.29", "ext-json": "*", "aws/aws-sdk-php": "^3.337", - "workerman/gatewayclient": "^3.1" + "workerman/gatewayclient": "^3.1", + "pusher/pusher-push-notifications": "^2.0" }, "require-dev": { "symfony/var-dumper": "^4.2", diff --git a/composer.lock b/composer.lock index 65bfb4ed..c2c3a5d6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "58b5bfa65a7e22b95bf7405c3e384c23", + "content-hash": "060b4e88568c2f7d16da36058884c54d", "packages": [ { "name": "adbario/php-dot-notation", @@ -2936,6 +2936,54 @@ }, "time": "2017-10-23T01:57:42+00:00" }, + { + "name": "pusher/pusher-push-notifications", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/pusher/push-notifications-php.git", + "reference": "6ec015243c18b0579c261c2decef99324d7452b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pusher/push-notifications-php/zipball/6ec015243c18b0579c261c2decef99324d7452b9", + "reference": "6ec015243c18b0579c261c2decef99324d7452b9", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-mbstring": "*", + "firebase/php-jwt": "^6.0", + "guzzlehttp/guzzle": "^7.0", + "php": ">=8.0" + }, + "require-dev": { + "doctrine/instantiator": "1.4.0", + "overtrue/phplint": "^4.0 || ^5.0", + "phpunit/phpunit": "^9.0", + "symfony/yaml": "^5.0 || ^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Pusher\\PushNotifications\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "support": { + "issues": "https://github.com/pusher/push-notifications-php/issues", + "source": "https://github.com/pusher/push-notifications-php/tree/2.0.0" + }, + "time": "2022-08-09T21:07:46+00:00" + }, { "name": "ralouphie/getallheaders", "version": "3.0.3", diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index 1e89fed0..79ce8fb1 100644 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -8,11 +8,11 @@ $baseDir = dirname($vendorDir); return array( '9b552a3cc426e3287cc811caefa3cf53' => $vendorDir . '/topthink/think-helper/src/helper.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', - '35fab96057f1bf5e7aba31a8a6d5fdde' => $vendorDir . '/topthink/think-orm/stubs/load_stubs.php', '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php', + '35fab96057f1bf5e7aba31a8a6d5fdde' => $vendorDir . '/topthink/think-orm/stubs/load_stubs.php', '6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php', - '662a729f963d39afe703c9d9b7ab4a8c' => $vendorDir . '/symfony/polyfill-php83/bootstrap.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', + '662a729f963d39afe703c9d9b7ab4a8c' => $vendorDir . '/symfony/polyfill-php83/bootstrap.php', 'b067bc7112e384b61c701452d53a14a8' => $vendorDir . '/mtdowling/jmespath.php/src/JmesPath.php', '2203a247e6fda86070a5e4e07aed533a' => $vendorDir . '/symfony/clock/Resources/now.php', 'a1105708a18b76903365ca1c4aa61b02' => $vendorDir . '/symfony/translation/Resources/functions.php', diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 1b4608bc..abe5e774 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -25,6 +25,7 @@ return array( 'Symfony\\Component\\Clock\\' => array($vendorDir . '/symfony/clock'), 'Symfony\\Component\\ClassLoader\\' => array($vendorDir . '/symfony/class-loader'), 'StellaMaris\\Clock\\' => array($vendorDir . '/stella-maris/clock/src'), + 'Pusher\\PushNotifications\\' => array($vendorDir . '/pusher/pusher-push-notifications/src'), 'Psr\\SimpleCache\\' => array($vendorDir . '/psr/simple-cache/src'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-factory/src', $vendorDir . '/psr/http-message/src'), diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 90c8716f..704dde43 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -9,11 +9,11 @@ class ComposerStaticInitdd94061c596fec45ed08426e6d417237 public static $files = array ( '9b552a3cc426e3287cc811caefa3cf53' => __DIR__ . '/..' . '/topthink/think-helper/src/helper.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', - '35fab96057f1bf5e7aba31a8a6d5fdde' => __DIR__ . '/..' . '/topthink/think-orm/stubs/load_stubs.php', '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php', + '35fab96057f1bf5e7aba31a8a6d5fdde' => __DIR__ . '/..' . '/topthink/think-orm/stubs/load_stubs.php', '6e3fae29631ef280660b3cdad06f25a8' => __DIR__ . '/..' . '/symfony/deprecation-contracts/function.php', - '662a729f963d39afe703c9d9b7ab4a8c' => __DIR__ . '/..' . '/symfony/polyfill-php83/bootstrap.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php', + '662a729f963d39afe703c9d9b7ab4a8c' => __DIR__ . '/..' . '/symfony/polyfill-php83/bootstrap.php', 'b067bc7112e384b61c701452d53a14a8' => __DIR__ . '/..' . '/mtdowling/jmespath.php/src/JmesPath.php', '2203a247e6fda86070a5e4e07aed533a' => __DIR__ . '/..' . '/symfony/clock/Resources/now.php', 'a1105708a18b76903365ca1c4aa61b02' => __DIR__ . '/..' . '/symfony/translation/Resources/functions.php', @@ -72,6 +72,7 @@ class ComposerStaticInitdd94061c596fec45ed08426e6d417237 ), 'P' => array ( + 'Pusher\\PushNotifications\\' => 25, 'Psr\\SimpleCache\\' => 16, 'Psr\\Log\\' => 8, 'Psr\\Http\\Message\\' => 17, @@ -212,6 +213,10 @@ class ComposerStaticInitdd94061c596fec45ed08426e6d417237 array ( 0 => __DIR__ . '/..' . '/stella-maris/clock/src', ), + 'Pusher\\PushNotifications\\' => + array ( + 0 => __DIR__ . '/..' . '/pusher/pusher-push-notifications/src', + ), 'Psr\\SimpleCache\\' => array ( 0 => __DIR__ . '/..' . '/psr/simple-cache/src', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index b1433863..068d2c99 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -2930,6 +2930,57 @@ }, "install-path": "../psr/simple-cache" }, + { + "name": "pusher/pusher-push-notifications", + "version": "2.0", + "version_normalized": "2.0.0.0", + "source": { + "type": "git", + "url": "https://github.com/pusher/push-notifications-php.git", + "reference": "6ec015243c18b0579c261c2decef99324d7452b9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/pusher/push-notifications-php/zipball/6ec015243c18b0579c261c2decef99324d7452b9", + "reference": "6ec015243c18b0579c261c2decef99324d7452b9", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "ext-mbstring": "*", + "firebase/php-jwt": "^6.0", + "guzzlehttp/guzzle": "^7.0", + "php": ">=8.0" + }, + "require-dev": { + "doctrine/instantiator": "1.4.0", + "overtrue/phplint": "^4.0 || ^5.0", + "phpunit/phpunit": "^9.0", + "symfony/yaml": "^5.0 || ^6.0" + }, + "time": "2022-08-09T21:07:46+00:00", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-4": { + "Pusher\\PushNotifications\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "support": { + "issues": "https://github.com/pusher/push-notifications-php/issues", + "source": "https://github.com/pusher/push-notifications-php/tree/2.0.0" + }, + "install-path": "../pusher/pusher-push-notifications" + }, { "name": "ralouphie/getallheaders", "version": "3.0.3", diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php index 81b38692..63162fcf 100644 --- a/vendor/composer/installed.php +++ b/vendor/composer/installed.php @@ -3,7 +3,7 @@ 'name' => 'topthink/think', 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '2eab3499945d32d05b064575c56f2041a7c7e9de', + 'reference' => '1192d0618a9dbdb678eb70e99b050efbe932cbcf', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), @@ -394,6 +394,15 @@ 'aliases' => array(), 'dev_requirement' => false, ), + 'pusher/pusher-push-notifications' => array( + 'pretty_version' => '2.0', + 'version' => '2.0.0.0', + 'reference' => '6ec015243c18b0579c261c2decef99324d7452b9', + 'type' => 'library', + 'install_path' => __DIR__ . '/../pusher/pusher-push-notifications', + 'aliases' => array(), + 'dev_requirement' => false, + ), 'ralouphie/getallheaders' => array( 'pretty_version' => '3.0.3', 'version' => '3.0.3.0', @@ -529,7 +538,7 @@ 'topthink/think' => array( 'pretty_version' => 'dev-master', 'version' => 'dev-master', - 'reference' => '2eab3499945d32d05b064575c56f2041a7c7e9de', + 'reference' => '1192d0618a9dbdb678eb70e99b050efbe932cbcf', 'type' => 'project', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), diff --git a/vendor/pusher/pusher-push-notifications/CHANGELOG.md b/vendor/pusher/pusher-push-notifications/CHANGELOG.md new file mode 100644 index 00000000..f04be172 --- /dev/null +++ b/vendor/pusher/pusher-push-notifications/CHANGELOG.md @@ -0,0 +1,26 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [1.1.2] - 2020-10-23 + ### Changed + - Replaced `array_key_exists` with `property_exists` for compatibility with + PHP 7.4 + +## [1.1.1] - 2020-10-02 +### Changed + - Allow compatibility with guzzlehttp 7.0 in composer json & added tests to verify this + +## [1.1.0] - 2019-02-06 +### Added +- Support for "Authenticated Users" feature: `publishToUsers`, `generateToken` and `deleteUser` +### Changed +- `publish` renamed to `publishToInterests` (`publish` method deprecated). + +## [1.0.0] - 2018-07-31 +### Added + - Changelog for GA release diff --git a/vendor/pusher/pusher-push-notifications/LICENSE b/vendor/pusher/pusher-push-notifications/LICENSE new file mode 100644 index 00000000..5a778a26 --- /dev/null +++ b/vendor/pusher/pusher-push-notifications/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Pusher + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/pusher/pusher-push-notifications/composer.json b/vendor/pusher/pusher-push-notifications/composer.json new file mode 100644 index 00000000..f104a7c6 --- /dev/null +++ b/vendor/pusher/pusher-push-notifications/composer.json @@ -0,0 +1,25 @@ +{ + "name": "pusher/pusher-push-notifications", + "version": "2.0", + "license": "MIT", + "require": { + "php": ">=8.0", + "guzzlehttp/guzzle": "^7.0", + "firebase/php-jwt": "^6.0", + "ext-mbstring": "*" + }, + "require-dev": { + "phpunit/phpunit": "^9.0", + "symfony/yaml": "^5.0 || ^6.0", + "doctrine/instantiator": "1.4.0", + "overtrue/phplint": "^4.0 || ^5.0" + }, + "autoload": { + "psr-4": { + "Pusher\\PushNotifications\\": "src/" + } + }, + "scripts": { + "phplint": "./vendor/bin/phplint ./ --exclude=vendor --no-cache" + } +} diff --git a/vendor/pusher/pusher-push-notifications/src/PushNotifications.php b/vendor/pusher/pusher-push-notifications/src/PushNotifications.php new file mode 100644 index 00000000..dcdbe891 --- /dev/null +++ b/vendor/pusher/pusher-push-notifications/src/PushNotifications.php @@ -0,0 +1,220 @@ +options)) { + throw new \Exception("Required 'instanceId' in Pusher\PushNotifications constructor options"); + } + if (!is_string($this->options["instanceId"])) { + throw new \Exception("'instanceId' must be a string"); + } + if ($this->options["instanceId"] === "") { + throw new \Exception("'instanceId' cannot be the empty string"); + } + + if (!array_key_exists("secretKey", $this->options)) { + throw new \Exception("Required 'secretKey' in Pusher\PushNotifications constructor options"); + } + if (!is_string($this->options["secretKey"])) { + throw new \Exception("'secretKey' must be a string"); + } + if ($this->options["secretKey"] === "") { + throw new \Exception("'secretKey' cannot be the empty string"); + } + + if (!array_key_exists("endpoint", $this->options)) { + $this->options["endpoint"] = "https://" . $options["instanceId"] . ".pushnotifications.pusher.com"; + } else { + if (!is_string($this->options["endpoint"])) { + throw new \Exception("'endpoint' must be a string"); + } + if ($this->options["endpoint"] === "") { + throw new \Exception("'endpoint' cannot be the empty string"); + } + } + + if (!$client) { + $this->client = new GuzzleHttp\Client(); + } else { + $this->client = $client; + } + } + + private function makeRequest(string $method, string $path, array $pathParams, array|null $body = null): mixed { + $escapedPathParams = []; + foreach ($pathParams as $k => $v) { + $escapedPathParams[$k] = urlencode($v); + } + + $endpoint = $this->options["endpoint"]; + $interpolatedPath = strtr($path, $escapedPathParams); + $url = $endpoint . $interpolatedPath; + + try { + $response = $this->client->request( + $method, + $url, + [ + "headers" => [ + "Authorization" => "Bearer " . $this->options["secretKey"], + "X-Pusher-Library" => "pusher-push-notifications-php " . PushNotifications::SDK_VERSION + ], + "json" => $body + ] + ); + } catch (\GuzzleHttp\Exception\BadResponseException $e) { + $response = $e->GetResponse(); + $parsedResponse = json_decode($response->GetBody()); + $badJSON = $parsedResponse === null; + if ( + $badJSON || + !property_exists($parsedResponse, 'error') || + !property_exists($parsedResponse, 'description') + ) { + throw new \Exception("An unexpected server error has occurred"); + } + throw new \Exception("{$parsedResponse->error}: {$parsedResponse->description}"); + } + + $parsedResponse = json_decode($response->GetBody()); + + return $parsedResponse; + } + + /** + * @param array $interests + * @param array $publishRequest + * @return mixed + * @throws \Exception + */ + public function publishToInterests(array $interests, array $publishRequest): mixed { + if (count($interests) === 0) { + throw new \Exception("Publishes must target at least one interest"); + } + if (count($interests) > PushNotifications::MAX_INTERESTS) { + throw new \Exception("Number of interests exceeds maximum of " . PushNotifications::MAX_INTERESTS); + } + + foreach($interests as $interest) { + if (!is_string($interest)) { + throw new \Exception("Interest \"$interest\" is not a string"); + } + if (mb_strlen($interest) > PushNotifications::MAX_INTEREST_LENGTH) { + throw new \Exception("Interest \"$interest\" is longer than the maximum length of " . PushNotifications::MAX_INTEREST_LENGTH . " chars."); + } + if ( $interest === '' ) { + throw new \Exception("Interest names cannot be the empty string"); + } + if (!preg_match(PushNotifications::INTEREST_REGEX, $interest)) { + throw new \Exception(implode([ + "Interest \"$interest\" contains a forbidden character.", + " Allowed characters are: ASCII upper/lower-case letters,", + " numbers or one of _=@,.;-" + ])); + } + } + + $publishRequest['interests'] = $interests; + $path = '/publish_api/v1/instances/INSTANCE_ID/publishes/interests'; + $pathParams = [ + 'INSTANCE_ID' => $this->options["instanceId"] + ]; + $response = $this->makeRequest("POST", $path, $pathParams, $publishRequest); + + if ($response === null) { + throw new \Exception("An unexpected server error has occurred"); + } + + return $response; + } + + public function publishToUsers(array $userIds, array $publishRequest): mixed { + if (count($userIds) === 0) { + throw new \Exception("Publishes must target at least one user"); + } + if (count($userIds) > PushNotifications::MAX_USERS) { + throw new \Exception("Number of user ids exceeds maximum of " . PushNotifications::MAX_USERS); + } + + foreach($userIds as $userId) { + $this->checkUserId($userId); + } + + $publishRequest['users'] = $userIds; + $path = '/publish_api/v1/instances/INSTANCE_ID/publishes/users'; + $pathParams = [ + 'INSTANCE_ID' => $this->options["instanceId"] + ]; + $response = $this->makeRequest("POST", $path, $pathParams, $publishRequest); + + if ($response === null) { + throw new \Exception("An unexpected server error has occurred"); + } + + return $response; + } + + public function deleteUser(string $userId): void { + $this->checkUserId($userId); + + $path = '/customer_api/v1/instances/INSTANCE_ID/users/USER_ID'; + $pathParams = [ + 'INSTANCE_ID' => $this->options["instanceId"], + 'USER_ID' => $userId + ]; + $this->makeRequest("DELETE", $path, $pathParams); + } + + public function generateToken(string $userId): array { + $this->checkUserId($userId); + + $instanceId = $this->options["instanceId"]; + $secretKey = $this->options["secretKey"]; + + $issuer = "https://$instanceId.pushnotifications.pusher.com"; + $claims = [ + "iss" => $issuer, + "sub" => $userId, + "exp" => time() + PushNotifications::AUTH_TOKEN_DURATION_SECS + ]; + + $token = JWT::encode($claims, $secretKey, 'HS256'); + + return [ + "token" => $token + ]; + } + + private function checkUserId(string $userId): void { + if ($userId === '') { + throw new \Exception("User id cannot be the empty string"); + } + if (mb_strlen($userId) > PushNotifications::MAX_USER_ID_LENGTH) { + throw new \Exception("User id \"$userId\" is longer than the maximum length of " . PushNotifications::MAX_USER_ID_LENGTH . " chars."); + } + } + + public function getClient(): GuzzleHttp\Client + { + return $this->client; + } +} diff --git a/vendor/services.php b/vendor/services.php index fef07fa8..0c06f807 100644 --- a/vendor/services.php +++ b/vendor/services.php @@ -1,5 +1,5 @@ 'itinysun\\model\\helper\\Service',