From 29d0fca345f2c750d0f965b87e209ec2624a8285 Mon Sep 17 00:00:00 2001 From: elf <360197197@qq.com> Date: Tue, 13 Sep 2022 00:55:15 +0800 Subject: [PATCH] yh --- app/Command/JinlingCommand.php | 48 ++++++++++- app/Contract/SmsSender.php | 31 +++++++ app/Controller/SmsController.php | 57 +++++++++++++ app/Factory/SmsSenderFactory.php | 38 +++++++++ app/Helper/Client/Lanhuo.php | 10 +-- app/Helper/SmsSender/JhSmsSender.php | 94 +++++++++++++++++++++ app/Helper/SmsSender/XgSmsSender.php | 96 +++++++++++++++++++++ app/Helper/SmsSender/ZwSmsSender.php | 119 ++++++++++++++++++++++++++ app/Job/AfterLoginJob.php | 2 +- app/Job/Job.php | 8 +- app/Job/SmsJob.php | 53 ++++++++++++ app/Model/Model.php | 2 + app/Model/Sms.php | 23 +++++ app/Model/Tool.php | 2 - app/Process/SmsQueueConsumer.php | 19 +++++ app/Service/PlayerRoleService.php | 2 +- app/Service/RebateService.php | 3 - app/Service/SmsService.php | 121 +++++++++++++++++++++++++++ config/autoload/async_queue.php | 11 +++ config/autoload/dependencies.php | 1 + config/routes.php | 6 ++ 21 files changed, 726 insertions(+), 20 deletions(-) create mode 100644 app/Contract/SmsSender.php create mode 100644 app/Controller/SmsController.php create mode 100644 app/Factory/SmsSenderFactory.php create mode 100644 app/Helper/SmsSender/JhSmsSender.php create mode 100644 app/Helper/SmsSender/XgSmsSender.php create mode 100644 app/Helper/SmsSender/ZwSmsSender.php create mode 100644 app/Job/SmsJob.php create mode 100644 app/Model/Sms.php create mode 100644 app/Process/SmsQueueConsumer.php create mode 100644 app/Service/SmsService.php diff --git a/app/Command/JinlingCommand.php b/app/Command/JinlingCommand.php index 49ea701..fe03c66 100644 --- a/app/Command/JinlingCommand.php +++ b/app/Command/JinlingCommand.php @@ -36,7 +36,7 @@ class JinlingCommand extends HyperfCommand public function handle() { - Lanhuo::addUser([ + /* Lanhuo::addUser([ 'user_id' => 111, 'account' => 'bbbbbbbabc111', 'phone' => '18888888888', @@ -45,6 +45,52 @@ class JinlingCommand extends HyperfCommand 'name' =>'哈哈哈', 'id_card' => '350824199911111111', 'is_real' => 1, // 是否实名(1-实名 0-未实名) + ]); */ + + /* Lanhuo::addRole([ + 'user_id' => 111, + 'server_id' => 1, + 'server_name' => '测试', + 'role_id' => '111', + 'role_name' => '测试', + 'role_level' => 23, + 'profession_id' => '', // 职业ID + 'profession_name' => '', // 职业名称 + 'power' => '', // 战力 + ]); */ + + /* Lanhuo::addLoginLog([ + 'user_id' => 111, + 'account' => 'bbbbbbbabc111', + 'phone' => '18888888888', + 'device_type' => 2, // 设备类型(1-andriod 2-ios) + 'device_number' => 'ABCD', + ]); */ + + /* Lanhuo::updateUser([ + 'user_id' => 111, + 'phone' => '18888888888', + 'device_type' => 2, // 设备类型(1-andriod 2-ios) + 'device_number' => 'AsssBCD', + 'name' =>'哈哈哈', + 'id_card' => '350824199911111111', + 'is_real' => 1, // 是否实名(1-实名 0-未实名) + ]); */ + + Lanhuo::addOrder([ + 'order_code' => 'sdflsdkflskdfsll', + 'user_id' => 111, + 'account' => 'bbbbbbbabc111', + // 'service_id' => 1, + // 'service_name' => '测试', + 'server_id' => 1, + 'server_name' => '测试', + 'role_id' => '111', + 'role_name' => '测试', + 'game_name' => '测试', + 'order_amount' => '6.00', + 'pay_time' => date('Y-m-d H:i:s'), + 'status' => 1, //支付状态(待支付 0 已支付 1 支付失败 2) ]); } } \ No newline at end of file diff --git a/app/Contract/SmsSender.php b/app/Contract/SmsSender.php new file mode 100644 index 0000000..3126852 --- /dev/null +++ b/app/Contract/SmsSender.php @@ -0,0 +1,31 @@ +smsService = $smsService; + } + + public function send() + { + $mobile = $this->request->input('mobile', null); + $options = $this->request->input('options', []); + if (!$mobile) { + throw new BusinessException('缺少参数[mobile]'); + } + if (!isset($options['type'])) { + throw new BusinessException('缺少参数options[type]'); + } + Queue::push(SmsJob::class, [ + 'mobile' => $mobile, + 'options' => $options, + ]); + return $this->success(); + } + + public function check() + { + $mobile = $this->request->input('mobile', ''); + $code = $this->request->input('code', ''); + + if (!$mobile) { + throw new BusinessException('缺少参数[mobile]'); + } + if (!$code) { + throw new BusinessException('缺少参数[code]'); + } + if (!$this->smsService->check($mobile, $code)) { + throw new BusinessException('验证失败'); + } + return $this->success('验证成功'); + } +} \ No newline at end of file diff --git a/app/Factory/SmsSenderFactory.php b/app/Factory/SmsSenderFactory.php new file mode 100644 index 0000000..13d3dd7 --- /dev/null +++ b/app/Factory/SmsSenderFactory.php @@ -0,0 +1,38 @@ + XgSmsSender::class, + 'zhongwang' => ZwSmsSender::class, + 'juhedata' => JhSmsSender::class, + ]; + + public function __invoke(ContainerInterface $container) + { + $tool = Tool::getActiveByGroup('sms'); + if (!$tool) { + return null; + } + $senderClass = $this->getSenderClass($tool); + if ($senderClass) { + return make($senderClass, compact('tool')); + } + return null; + } + + protected function getSenderClass(Tool $tool) + { + return $this->senders[$tool->name] ?? null; + } +} \ No newline at end of file diff --git a/app/Helper/Client/Lanhuo.php b/app/Helper/Client/Lanhuo.php index caada65..3e34591 100644 --- a/app/Helper/Client/Lanhuo.php +++ b/app/Helper/Client/Lanhuo.php @@ -62,11 +62,11 @@ class Lanhuo public static function addOrder($data) { $params = [ - 'order_code' => $data['pay_order_number'], + 'order_code' => $data['order_code'], 'user_id' => $data['user_id'], 'account' => $data['account'], - 'service_id' => $data['service_id'], - 'service_name' => $data['service_name'], + 'server_id' => $data['server_id'], + 'server_name' => $data['server_name'], 'role_id' => $data['role_id'], 'role_name' => $data['role_name'], 'game_name' => $data['game_name'], @@ -81,8 +81,8 @@ class Lanhuo { $params = [ 'user_id' => $data['user_id'], - 'service_id' => $data['service_id'], - 'service_name' => $data['service_name'], + 'server_id' => $data['server_id'], + 'server_name' => $data['server_name'], 'role_id' => $data['role_id'], 'role_name' => $data['role_name'], 'role_level' => $data['role_level'], diff --git a/app/Helper/SmsSender/JhSmsSender.php b/app/Helper/SmsSender/JhSmsSender.php new file mode 100644 index 0000000..6ddf382 --- /dev/null +++ b/app/Helper/SmsSender/JhSmsSender.php @@ -0,0 +1,94 @@ +key = $tool->get('key'); + $this->tplId = $tool->get('tpl_id'); + $this->initClient(); + } + + public function sendCode($mobile, $code, $activeMinute = 10) + { + $tplValue = urlencode('#code#=' . $code . '&#m#=' . $activeMinute); + $data = [ + 'mobile' => $mobile, + 'tpl_id' => $this->tplId, + 'tpl_value' => $tplValue, + 'key' => $this->key, + ]; + + $result = $this->post('/sms/send', $this->parseData($data)); + $this->parseResult($result); + } + + public function send($mobile, $content) + { + throw new BusinessException('该短信服务不可用'); + } + + public function sendBatch(array $mobiles, $content) + { + throw new BusinessException('该短信服务不可用'); + } + + protected function parseData($data) + { + return http_build_query($data); + } + + protected function parseResult($result) + { + $result = json_decode($result, true); + if (!$result) { + throw new BusinessException('系统异常'); + } + if (!$result['error_code'] == 0) { + throw new BusinessException($result['reason']); + } + } + + protected function post($uri, $data) + { + $response = $this->client->post($uri, [ + 'verify' => false, + 'body' => $data + ]); + return (string)$response->getBody(); + } + + protected function initClient() + { + $this->client = new Client([ + 'base_uri' => $this->baseUrl, + 'handler' => HandlerStack::create(new CoroutineHandler()), + 'headers' => [ + 'Content-Type' => 'application/x-www-form-urlencoded', + ], + 'swoole' => [ + 'timeout' => 10, + 'socket_buffer_size' => 1024 * 1024 * 2, + ], + ]); + } +} \ No newline at end of file diff --git a/app/Helper/SmsSender/XgSmsSender.php b/app/Helper/SmsSender/XgSmsSender.php new file mode 100644 index 0000000..cc65973 --- /dev/null +++ b/app/Helper/SmsSender/XgSmsSender.php @@ -0,0 +1,96 @@ +appId = $tool->get('smtp'); + $this->apiKey = $tool->get('smtp_account'); + $this->templateId = $tool->get('smtp_password'); + $this->initClient(); + } + + public function sendCode($mobile, $code, $activeMinute = 10) + { + $data = [ + 'appid' => $this->appId, + 'apikey' => $this->apiKey, + 'templateid' => $this->templateId, + 'phone' => $mobile, + 'param' => $code . ',' . $activeMinute, + ]; + + $result = $this->post('/sms/send_sms', $this->parseData($data)); + $this->parseResult($result); + } + + public function send($mobile, $content) + { + throw new BusinessException('该短信服务不可用'); + } + + public function sendBatch(array $mobiles, $content) + { + throw new BusinessException('该短信服务不可用'); + } + + protected function parseData($data) + { + return http_build_query($data); + } + + protected function parseResult($result) + { + $result = json_decode($result, true); + if (!$result) { + throw new BusinessException('系统异常'); + } + if ($result['code'] != 200) { + throw new BusinessException($result['msg']); + } + } + + protected function post($uri, $data) + { + $response = $this->client->post($uri, [ + 'verify' => false, + 'body' => $data + ]); + return (string)$response->getBody(); + } + + protected function initClient() + { + $this->client = new Client([ + 'base_uri' => $this->baseUrl, + 'handler' => HandlerStack::create(new CoroutineHandler()), + 'headers' => [ + 'Content-Type' => 'application/x-www-form-urlencoded', + ], + 'swoole' => [ + 'timeout' => 10, + 'socket_buffer_size' => 1024 * 1024 * 2, + ], + ]); + } +} \ No newline at end of file diff --git a/app/Helper/SmsSender/ZwSmsSender.php b/app/Helper/SmsSender/ZwSmsSender.php new file mode 100644 index 0000000..a3b6f08 --- /dev/null +++ b/app/Helper/SmsSender/ZwSmsSender.php @@ -0,0 +1,119 @@ + '您的验证码为{code},{activeMinute}分钟内有效,为保证账户安全,请勿向他人泄露验证信息。', + ]; + + public function __construct(Tool $tool) + { + $this->account = $tool->get('smtp_account'); + $this->password = $tool->get('smtp_password'); + $this->initClient(); + } + + public function sendCode($mobile, $code, $activeMinute = 10) + { + $content = $this->getContent('common-code', ['code' => $code, 'activeMinute' => $activeMinute]); + return $this->send($mobile, $content); + } + + public function send($mobile, $content) + { + $data = [ + 'apName' => $this->account, + 'apPassword' => $this->password, + 'srcId' => '', + 'serviceId' => '', + 'calledNumber' => $mobile, + 'content' => $this->company . $content, + 'sendTime' => date('YmdHis'), + ]; + $result = $this->post('/wgws/OrderServlet4J', $this->parseData($data)); + $this->parseResult($result); + } + + public function sendBatch(array $mobiles, $content) + { + $data = [ + 'apName' => $this->account, + 'apPassword' => $this->password, + 'srcId' => '', + 'serviceId' => '', + 'calledNumber' => implode(',', $mobiles), + 'content' => $this->company . $content, + 'sendTime' => date('YmdHis'), + ]; + return $this->post('/wgws/BatchSubmit4J', $this->parseData($data)); + } + + public function parseData($data) + { + return http_build_query($data); + } + + protected function parseResult($result) + { + $result = json_decode($result, true); + if (!$result) { + throw new BusinessException('系统异常'); + } + if ($result['error'] != 0) { + throw new BusinessException($result['message'] ?? '发送失败'); + } + } + + protected function post($uri, $data) + { + $response = $this->client->post($uri, [ + 'verify' => false, + 'body' => $data + ]); + return (string)$response->getBody(); + } + + protected function getContent($name, $params) + { + $content = $this->templates[$name] ?? ''; + foreach ($params as $key => $value) { + $content = str_replace('{' . $key . '}', $value, $content); + } + return $content; + } + + protected function initClient() + { + $this->client = new Client([ + 'base_uri' => $this->baseUrl, + 'handler' => HandlerStack::create(new CoroutineHandler()), + 'headers' => [ + 'Content-Type' => 'application/x-www-form-urlencoded', + ], + 'swoole' => [ + 'timeout' => 10, + 'socket_buffer_size' => 1024 * 1024 * 2, + ], + ]); + } +} \ No newline at end of file diff --git a/app/Job/AfterLoginJob.php b/app/Job/AfterLoginJob.php index 96deada..fe9b270 100644 --- a/app/Job/AfterLoginJob.php +++ b/app/Job/AfterLoginJob.php @@ -18,6 +18,6 @@ class AfterLoginJob extends Job * @var UserService $userService */ $userService = make(UserService::class); - $userService->afterLogin($userId, $gameId, $loginTime); + $userService->afterLogin($gameId, $userId, $loginTime); } } \ No newline at end of file diff --git a/app/Job/Job.php b/app/Job/Job.php index 5b9905c..4be0efa 100644 --- a/app/Job/Job.php +++ b/app/Job/Job.php @@ -12,17 +12,11 @@ class Job extends BaseJob * @var array */ public $params; - - /** - * @var array - */ - public $context; protected $queueName = 'default'; - public function __construct(array $params, array $context) + public function __construct(array $params) { - $this->context = $context; $this->params = $this->prepare($params); } diff --git a/app/Job/SmsJob.php b/app/Job/SmsJob.php new file mode 100644 index 0000000..7b2e70a --- /dev/null +++ b/app/Job/SmsJob.php @@ -0,0 +1,53 @@ +params = $params; + } + + public function handle() + { + $mobile = $this->params['mobile'] ?? null; + $options = $this->params['options'] ?? []; + $type = $options['type'] ?? ''; + if (!$mobile) { + throw new BusinessException('缺少手机号'); + } + if (!$type) { + throw new BusinessException('缺少类型'); + } + + /** + * @var SmsService $smsService + */ + $smsService = make(SmsService::class); + if ($type == 'content') { + $content = $options['content'] ?? ''; + $smsService->send($mobile, $content); + } elseif ($type == 'code') { + $clientIp = $options['client_ip'] ?? ''; + $smsService->sendCode($mobile, ['client_ip' => $clientIp]); + } elseif ($type == 'batch') { + if (!is_array($mobile)) { + $mobile = [$mobile]; + } + $content = $options['content'] ?? ''; + $smsService->sendBatch($mobile, $content); + } else { + throw new BusinessException('类型错误'); + } + } +} \ No newline at end of file diff --git a/app/Model/Model.php b/app/Model/Model.php index 28d67bd..60aab03 100644 --- a/app/Model/Model.php +++ b/app/Model/Model.php @@ -11,6 +11,8 @@ abstract class Model extends BaseModel { use CommonTimeScopes; + public $timestamps = false; + public static function alias($alias = null) { $name = with(new static)->getTable(); diff --git a/app/Model/Sms.php b/app/Model/Sms.php new file mode 100644 index 0000000..c8ee538 --- /dev/null +++ b/app/Model/Sms.php @@ -0,0 +1,23 @@ +created_at) + self::ACTIVE_MINUTE * 60; + if (time() > $expiredTime) { + return true; + } + return false; + } +} \ No newline at end of file diff --git a/app/Model/Tool.php b/app/Model/Tool.php index d62d7ef..073a5d6 100644 --- a/app/Model/Tool.php +++ b/app/Model/Tool.php @@ -12,8 +12,6 @@ class Tool extends Model private $configItems; - public $timestamps = false; - public static $groups = [ 'sms' => ['sms_set', 'zhongwang', 'juhedata'], ]; diff --git a/app/Process/SmsQueueConsumer.php b/app/Process/SmsQueueConsumer.php new file mode 100644 index 0000000..65ca8aa --- /dev/null +++ b/app/Process/SmsQueueConsumer.php @@ -0,0 +1,19 @@ +saveRebateGifts($gameId, 'G', $gList); $this->saveRebateGifts($gameId, 'H', $hList); $this->saveRebateGifts($gameId, 'I', $iList); */ - $this->saveRebateGifts($gameId, 'k', $kList); - $gameId = 79; - $this->saveRebateGifts($gameId, 'k', $kList); } public function initRebateGifts79() diff --git a/app/Service/SmsService.php b/app/Service/SmsService.php new file mode 100644 index 0000000..9da8b14 --- /dev/null +++ b/app/Service/SmsService.php @@ -0,0 +1,121 @@ +send($mobile, $content); + } + + public function sendBatch(array $mobile, $content) + { + $smsSender = make(SmsSender::class); + + if (!$smsSender) { + throw new BusinessException('系统异常,请联系客服'); + } + + $smsSender->sendBatch($mobile, $content); + } + + public function sendCode($mobile, array $options) + { + $clientIp = $options['client_ip'] ?? ''; + $smsSender = make(SmsSender::class); + + if (!$smsSender) { + throw new BusinessException('系统异常,请联系客服'); + } + if ($clientIp && $this->isIpOutOfDayCount($clientIp)) { + throw new BusinessException('每天发送数量不能超过' . self::IP_DAY_COUNT . '条'); + } + if ($this->isOutOfRate($mobile)) { + throw new BusinessException('发送过于频繁,请稍后再试'); + } + + $code = $this->getCode(); + $sms = new Sms(); + $sms->code = $code; + $sms->mobile = $mobile; + $sms->client_ip = $clientIp; + $sms->channel = $smsSender->channel; + $sms->save(); + + try { + $smsSender->sendCode($mobile, $code, Sms::ACTIVE_MINUTE); + $sms->status = Sms::STATUS_SUCCESS; + $sms->result = 'success'; + $sms->save(); + } catch (\Exception $e) { + $sms->status = Sms::STATUS_ERROR; + $sms->result = 'error'; + $sms->save(); + Log::error( + 'SMS_SEND_ERROR: ' . $e->getMessage(), + ['mobile' => $mobile, 'options' => $options], + 'sms' + ); + } + } + + public function check($mobile, $code): bool + { + $sms = Sms::where('mobile', $mobile) + ->where('is_checked', 0) + ->where('status', Sms::STATUS_SUCCESS) + ->orderBy('created_at', 'desc') + ->first(); + if (!$sms) { + return false; + } + if ($sms->isExpired()) { + return false; + } + if ($sms->code == $code) { + $sms->is_checked = 1; + $sms->save(); + return true; + } + return false; + } + + private function getCode() + { + return rand(100000, 999999); + } + + private function isOutOfRate($mobile): bool + { + $lastSms = Sms::select(['created_at'])->where(['mobile' => $mobile])->orderBy('created_at', 'desc')->first(); + if ($lastSms && strtotime($lastSms->created_at) + self::INTERVAL_MINUTE * 60 > time()) { + return true; + } + return false; + } + + private function isIpOutOfDayCount($ip): bool + { + $count = Sms::where('client_ip', $ip) + ->where('status', Sms::STATUS_SUCCESS) + ->whereBetween('created_at', [date('Y-m-d 00:00:00'), date('Y-m-d 23:59:59')]) + ->count(); + return $count > self::IP_DAY_COUNT; + } +} \ No newline at end of file diff --git a/config/autoload/async_queue.php b/config/autoload/async_queue.php index b115ddf..ae172bb 100644 --- a/config/autoload/async_queue.php +++ b/config/autoload/async_queue.php @@ -24,4 +24,15 @@ return [ 'limit' => 10, ], ], + 'sms' => [ + 'driver' => Hyperf\AsyncQueue\Driver\RedisDriver::class, + 'channel' => '{sms.queue}', + 'timeout' => 2, + 'retry_seconds' => 5, + 'handle_timeout' => 10, + 'processes' => 1, + 'concurrent' => [ + 'limit' => 5, + ], + ], ]; diff --git a/config/autoload/dependencies.php b/config/autoload/dependencies.php index f46bd96..bb38048 100644 --- a/config/autoload/dependencies.php +++ b/config/autoload/dependencies.php @@ -10,4 +10,5 @@ declare(strict_types=1); * @license https://github.com/hyperf/hyperf/blob/master/LICENSE */ return [ + \App\Contract\SmsSender::class => \App\Factory\SmsSenderFactory::class ]; diff --git a/config/routes.php b/config/routes.php index c0a2f5c..4010e85 100644 --- a/config/routes.php +++ b/config/routes.php @@ -3,6 +3,7 @@ declare(strict_types=1); use App\Controller\GameEventController; +use App\Controller\SmsController; use App\Controller\StatisticsController; use Hyperf\HttpServer\Router\Router; @@ -21,4 +22,9 @@ Router::addGroup('/statistics', function () { Router::post('/player-retention', [StatisticsController::class, 'playerRetention']); }); +Router::addGroup('/message', function () { + Router::post('/sms-send', [SmsController::class, 'send']); + Router::post('/sms-check', [SmsController::class, 'check']); +}); + // loadRoutes(BASE_PATH . '/routes'); \ No newline at end of file