master
elf 2 years ago
parent 97380a7d60
commit 29d0fca345

@ -36,7 +36,7 @@ class JinlingCommand extends HyperfCommand
public function handle() public function handle()
{ {
Lanhuo::addUser([ /* Lanhuo::addUser([
'user_id' => 111, 'user_id' => 111,
'account' => 'bbbbbbbabc111', 'account' => 'bbbbbbbabc111',
'phone' => '18888888888', 'phone' => '18888888888',
@ -45,6 +45,52 @@ class JinlingCommand extends HyperfCommand
'name' =>'哈哈哈', 'name' =>'哈哈哈',
'id_card' => '350824199911111111', 'id_card' => '350824199911111111',
'is_real' => 1, // 是否实名(1-实名 0-未实名) '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)
]); ]);
} }
} }

@ -0,0 +1,31 @@
<?php
namespace App\Contract;
interface SmsSender {
/**
* 发送短信验证码
*
* @param string $mobile 手机号
* @param string $code 验证码
* @param int $activeMinute 验证码有效期
*/
public function sendCode($mobile, $code, $activeMinute = 0);
/**
* 发送短信
*
* @param string $mobile 手机号
* @param string $content 短信内容
*/
public function send($mobile, $content);
/**
* 批量发送短信
*
* @param array $mobiles 手机号
* @param string $content 短信内容
*/
public function sendBatch(array $mobiles, $content);
}

@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
namespace App\Controller;
use App\Exception\BusinessException;
use App\Helper\Queue;
use App\Job\SmsJob;
use App\Service\SmsService;
class SmsController extends AbstractController
{
/**
* @var SmsService
*/
protected $smsService;
public function __construct(SmsService $smsService)
{
$this->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('验证成功');
}
}

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace App\Factory;
use App\Helper\SmsSender\JhSmsSender;
use App\Helper\SmsSender\XgSmsSender;
use App\Helper\SmsSender\ZwSmsSender;
use Psr\Container\ContainerInterface;
use App\Model\Tool;
class SmsSenderFactory
{
protected $senders = [
'sms_set' => 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;
}
}

@ -62,11 +62,11 @@ class Lanhuo
public static function addOrder($data) public static function addOrder($data)
{ {
$params = [ $params = [
'order_code' => $data['pay_order_number'], 'order_code' => $data['order_code'],
'user_id' => $data['user_id'], 'user_id' => $data['user_id'],
'account' => $data['account'], 'account' => $data['account'],
'service_id' => $data['service_id'], 'server_id' => $data['server_id'],
'service_name' => $data['service_name'], 'server_name' => $data['server_name'],
'role_id' => $data['role_id'], 'role_id' => $data['role_id'],
'role_name' => $data['role_name'], 'role_name' => $data['role_name'],
'game_name' => $data['game_name'], 'game_name' => $data['game_name'],
@ -81,8 +81,8 @@ class Lanhuo
{ {
$params = [ $params = [
'user_id' => $data['user_id'], 'user_id' => $data['user_id'],
'service_id' => $data['service_id'], 'server_id' => $data['server_id'],
'service_name' => $data['service_name'], 'server_name' => $data['server_name'],
'role_id' => $data['role_id'], 'role_id' => $data['role_id'],
'role_name' => $data['role_name'], 'role_name' => $data['role_name'],
'role_level' => $data['role_level'], 'role_level' => $data['role_level'],

@ -0,0 +1,94 @@
<?php
declare(strict_types=1);
namespace App\Helper\SmsSender;
use App\Contract\SmsSender;
use App\Exception\BusinessException;
use App\Model\Tool;
use GuzzleHttp\Client;
use Hyperf\Guzzle\CoroutineHandler;
use GuzzleHttp\HandlerStack;
class JhSmsSender implements SmsSender
{
public $channel = 'juhe';
protected $baseUrl = 'http://v.juhe.cn';
protected $key;
protected $tplId;
protected $client;
public function __construct(Tool $tool)
{
$this->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,
],
]);
}
}

@ -0,0 +1,96 @@
<?php
declare(strict_types=1);
namespace App\Helper\SmsSender;
use App\Contract\SmsSender;
use App\Exception\BusinessException;
use App\Model\Tool;
use GuzzleHttp\Client;
use Hyperf\Guzzle\CoroutineHandler;
use GuzzleHttp\HandlerStack;
class XgSmsSender implements SmsSender
{
public $channel = 'xigu';
protected $baseUrl = 'http://api.vlpush.com';
protected $appId;
protected $apiKey;
protected $templateId;
protected $client;
public function __construct(Tool $tool)
{
$this->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,
],
]);
}
}

@ -0,0 +1,119 @@
<?php
declare(strict_types=1);
namespace App\Helper\SmsSender;
use App\Contract\SmsSender;
use App\Exception\BusinessException;
use App\Model\Tool;
use GuzzleHttp\Client;
use Hyperf\Guzzle\CoroutineHandler;
use GuzzleHttp\HandlerStack;
class ZwSmsSender implements SmsSender
{
public $channel = 'zhongwang';
protected $baseUrl = 'http://139.224.36.226:382';
protected $account;
protected $password;
protected $client;
protected $company = '【海南万盟天下游戏】';
protected $templates = [
'common-code' => '您的验证码为{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,
],
]);
}
}

@ -18,6 +18,6 @@ class AfterLoginJob extends Job
* @var UserService $userService * @var UserService $userService
*/ */
$userService = make(UserService::class); $userService = make(UserService::class);
$userService->afterLogin($userId, $gameId, $loginTime); $userService->afterLogin($gameId, $userId, $loginTime);
} }
} }

@ -13,16 +13,10 @@ class Job extends BaseJob
*/ */
public $params; public $params;
/**
* @var array
*/
public $context;
protected $queueName = 'default'; protected $queueName = 'default';
public function __construct(array $params, array $context) public function __construct(array $params)
{ {
$this->context = $context;
$this->params = $this->prepare($params); $this->params = $this->prepare($params);
} }

@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
namespace App\Job;
use App\Exception\BusinessException;
use App\Service\SmsService;
class SmsJob extends Job
{
public $params;
protected $queueName = 'sms';
public function __construct($params)
{
$this->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('类型错误');
}
}
}

@ -11,6 +11,8 @@ abstract class Model extends BaseModel
{ {
use CommonTimeScopes; use CommonTimeScopes;
public $timestamps = false;
public static function alias($alias = null) public static function alias($alias = null)
{ {
$name = with(new static)->getTable(); $name = with(new static)->getTable();

@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace App\Model;
class Sms extends Model
{
const STATUS_SUCCESS = 1;
const STATUS_ERROR = 2;
const ACTIVE_MINUTE = 10;
protected $table = 'tab_sms_logs';
public function isExpired()
{
$expiredTime = strtotime($this->created_at) + self::ACTIVE_MINUTE * 60;
if (time() > $expiredTime) {
return true;
}
return false;
}
}

@ -12,8 +12,6 @@ class Tool extends Model
private $configItems; private $configItems;
public $timestamps = false;
public static $groups = [ public static $groups = [
'sms' => ['sms_set', 'zhongwang', 'juhedata'], 'sms' => ['sms_set', 'zhongwang', 'juhedata'],
]; ];

@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace App\Process;
use Hyperf\AsyncQueue\Process\ConsumerProcess;
use Hyperf\Process\Annotation\Process;
/**
* @Process()
*/
class SmsQueueConsumer extends ConsumerProcess
{
/**
* @var string
*/
protected $queue = 'sms';
}

@ -22,7 +22,7 @@ class PlayerRoleService extends Service
$roleName = $params['game_player_name'] ?? 0; $roleName = $params['game_player_name'] ?? 0;
$roleId = $params['game_player_id'] ?? 0; $roleId = $params['game_player_id'] ?? 0;
$roleLevel = $params['role_level'] ?? 0; $roleLevel = $params['role_level'] ?? 0;
$time = $params['time'] ?? 0; $time = (int)($params['time'] ?? 0);
$clientIp = $params['client_ip'] ?? ''; $clientIp = $params['client_ip'] ?? '';
$sdkVersion = $params['sdk_version'] ?? 0; $sdkVersion = $params['sdk_version'] ?? 0;

@ -1126,9 +1126,6 @@ class RebateService extends Service
$this->saveRebateGifts($gameId, 'G', $gList); $this->saveRebateGifts($gameId, 'G', $gList);
$this->saveRebateGifts($gameId, 'H', $hList); $this->saveRebateGifts($gameId, 'H', $hList);
$this->saveRebateGifts($gameId, 'I', $iList); */ $this->saveRebateGifts($gameId, 'I', $iList); */
$this->saveRebateGifts($gameId, 'k', $kList);
$gameId = 79;
$this->saveRebateGifts($gameId, 'k', $kList);
} }
public function initRebateGifts79() public function initRebateGifts79()

@ -0,0 +1,121 @@
<?php
declare(strict_types=1);
namespace App\Service;
use App\Contract\SmsSender;
use App\Model\Sms;
use App\Exception\BusinessException;
use App\Helper\Log;
class SmsService extends Service
{
const INTERVAL_MINUTE = 1;
const IP_DAY_COUNT = 100;
public function send($mobile, $content)
{
$smsSender = make(SmsSender::class);
if (!$smsSender) {
throw new BusinessException('系统异常,请联系客服');
}
$smsSender->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;
}
}

@ -24,4 +24,15 @@ return [
'limit' => 10, '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,
],
],
]; ];

@ -10,4 +10,5 @@ declare(strict_types=1);
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE * @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/ */
return [ return [
\App\Contract\SmsSender::class => \App\Factory\SmsSenderFactory::class
]; ];

@ -3,6 +3,7 @@
declare(strict_types=1); declare(strict_types=1);
use App\Controller\GameEventController; use App\Controller\GameEventController;
use App\Controller\SmsController;
use App\Controller\StatisticsController; use App\Controller\StatisticsController;
use Hyperf\HttpServer\Router\Router; use Hyperf\HttpServer\Router\Router;
@ -21,4 +22,9 @@ Router::addGroup('/statistics', function () {
Router::post('/player-retention', [StatisticsController::class, 'playerRetention']); 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'); // loadRoutes(BASE_PATH . '/routes');
Loading…
Cancel
Save