初始化仓库

This commit is contained in:
wangxiaowei
2025-04-22 14:09:52 +08:00
commit 8b100110bb
5155 changed files with 664201 additions and 0 deletions

View File

@ -0,0 +1,203 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\common\service\sms;
use app\common\enum\notice\NoticeEnum;
use app\common\enum\notice\SmsEnum;
use app\common\enum\YesNoEnum;
use app\common\model\Notice;
use app\common\model\notice\SmsLog;
use app\common\service\ConfigService;
/**
* 短信驱动
* Class SmsDriver
* @package app\common\service\sms
*/
class SmsDriver
{
/**
* 错误信息
* @var
*/
protected $error = null;
/**
* 默认短信引擎
* @var
*/
protected $defaultEngine;
/**
* 短信引擎
* @var
*/
protected $engine;
/**
* 架构方法
* SmsDriver constructor.
*/
public function __construct()
{
// 初始化
$this->initialize();
}
/**
* @notes 初始化
* @return bool
* @author 段誉
* @date 2022/9/15 16:29
*/
public function initialize()
{
try {
$defaultEngine = ConfigService::get('sms', 'engine', false);
if($defaultEngine === false) {
throw new \Exception('请开启短信配置');
}
$this->defaultEngine = $defaultEngine;
$classSpace = __NAMESPACE__ . '\\engine\\' . ucfirst(strtolower($defaultEngine)) . 'Sms';
if (!class_exists($classSpace)) {
throw new \Exception('没有相应的短信驱动类');
}
$engineConfig = ConfigService::get('sms', strtolower($defaultEngine), false);
if($engineConfig === false) {
throw new \Exception($defaultEngine . '未配置');
}
if ($engineConfig['status'] != 1) {
throw new \Exception('短信服务未开启');
}
$this->engine = new $classSpace($engineConfig);
if(!is_null($this->engine->getError())) {
throw new \Exception($this->engine->getError());
}
return true;
} catch (\Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
/**
* @notes 获取错误信息
* @return null
* @author 段誉
* @date 2022/9/15 16:29
*/
public function getError()
{
return $this->error;
}
/**
* @notes 发送短信
* @param $mobile
* @param $data
* @return false
* @author 段誉
* @date 2022/9/15 16:29
*/
public function send($mobile, $data)
{
try {
// 发送频率限制
$this->sendLimit($mobile);
// 开始发送
$result = $this->engine
->setMobile($mobile)
->setTemplateId($data['template_id'])
->setTemplateParams($data['params'])
->send();
if(false === $result) {
throw new \Exception($this->engine->getError());
}
return $result;
} catch(\Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
/**
* @notes 发送频率限制
* @param $mobile
* @throws \Exception
* @author 段誉
* @date 2022/9/15 16:29
*/
public function sendLimit($mobile)
{
$smsLog = SmsLog::where([
['mobile', '=', $mobile],
['send_status', '=', SmsEnum::SEND_SUCCESS],
['scene_id', 'in', NoticeEnum::SMS_SCENE],
])
->order('send_time', 'desc')
->findOrEmpty()
->toArray();
if(!empty($smsLog) && ($smsLog['send_time'] > time() - 60)) {
throw new \Exception('同一手机号1分钟只能发送1条短信');
}
}
/**
* @notes 校验手机验证码
* @param $mobile
* @param $code
* @return bool
* @author 段誉
* @date 2022/9/15 16:29
*/
public function verify($mobile, $code, $sceneId = 0)
{
$where = [
['mobile', '=', $mobile],
['send_status', '=', SmsEnum::SEND_SUCCESS],
['scene_id', 'in', NoticeEnum::SMS_SCENE],
['is_verify', '=', YesNoEnum::NO],
];
if (!empty($sceneId)) {
$where[] = ['scene_id', '=', $sceneId];
}
$smsLog = SmsLog::where($where)
->order('send_time', 'desc')
->findOrEmpty();
// 没有验证码 或 最新验证码已校验 或 已过期(有效期5分钟)
if($smsLog->isEmpty() || $smsLog->is_verify || ($smsLog->send_time < time() - 5 * 60) ) {
return false;
}
// 更新校验状态
if($smsLog->code == $code) {
$smsLog->check_num = $smsLog->check_num + 1;
$smsLog->is_verify = YesNoEnum::YES;
$smsLog->save();
return true;
}
// 更新验证次数
$smsLog->check_num = $smsLog->check_num + 1;
$smsLog->save();
return false;
}
}

View File

@ -0,0 +1,180 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\common\service\sms;
use app\common\enum\notice\NoticeEnum;
use app\common\enum\notice\SmsEnum;
use app\common\logic\NoticeLogic;
use app\common\model\notice\NoticeSetting;
use app\common\model\notice\SmsLog;
use app\common\service\ConfigService;
/**
* 短信服务
* Class SmsMessageService
* @package app\common\service
*/
class SmsMessageService
{
protected $notice;
protected $smsLog;
public function send($params)
{
try {
// 通知设置
$noticeSetting = NoticeSetting::where('scene_id', $params['scene_id'])->findOrEmpty()->toArray();
// 替换通知模板参数
$content = $this->contentFormat($noticeSetting, $params);
// 添加短信记录
$this->smsLog = $this->addSmsLog($params, $content);
// 添加通知记录
$this->notice = NoticeLogic::addNotice($params, $noticeSetting, NoticeEnum::SMS, $content);
// 发送短信
$smsDriver = new SmsDriver();
if(!is_null($smsDriver->getError())) {
throw new \Exception($smsDriver->getError());
}
$result = $smsDriver->send($params['params']['mobile'], [
'template_id' => $noticeSetting['sms_notice']['template_id'],
'params' => $this->setSmsParams($noticeSetting, $params)
]);
if ($result === false) {
// 发送失败更新短信记录
$this->updateSmsLog($this->smsLog['id'], SmsEnum::SEND_FAIL, $smsDriver->getError());
throw new \Exception($smsDriver->getError());
}
// 发送成功更新短信记录
$this->updateSmsLog($this->smsLog['id'], SmsEnum::SEND_SUCCESS, $result);
return true;
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
}
/**
* @notes 格式化消息内容
* @param $noticeSetting
* @param $params
* @return array|mixed|string|string[]
* @author 段誉
* @date 2022/9/15 16:24
*/
public function contentFormat($noticeSetting, $params)
{
$content = $noticeSetting['sms_notice']['content'];
foreach($params['params'] as $k => $v) {
$search = '${' . $k . '}';
$content = str_replace($search, $v, $content);
}
return $content;
}
/**
* @notes 添加短信记录
* @param $params
* @param $content
* @return SmsLog|\think\Model
* @author 段誉
* @date 2022/9/15 16:24
*/
public function addSmsLog($params, $content)
{
$data = [
'scene_id' => $params['scene_id'],
'mobile' => $params['params']['mobile'],
'content' => $content,
'code' => $params['params']['code'] ?? '',
'send_status' => SmsEnum::SEND_ING,
'send_time' => time(),
];
return SmsLog::create($data);
}
/**
* @notes 处理腾讯云短信参数
* @param $noticeSetting
* @param $params
* @return array|mixed
* @author 段誉
* @date 2022/9/15 16:25
*/
public function setSmsParams($noticeSetting, $params)
{
$defaultEngine = ConfigService::get('sms', 'engine', false);
// 阿里云 且是 验证码类型
if($defaultEngine != 'TENCENT' && in_array($params['scene_id'], NoticeEnum::SMS_SCENE)) {
return ['code' => $params['params']['code']];
}
if($defaultEngine != 'TENCENT') {
return $params['params'];
}
//腾讯云特殊处理
$arr = [];
$content = $noticeSetting['sms_notice']['content'];
foreach ($params['params'] as $item => $val) {
$search = '${' . $item . '}';
if(strpos($content, $search) !== false && !in_array($item, $arr)) {
//arr => 获的数组[nickname, order_sn] //顺序可能是乱的
$arr[] = $item;
}
}
//arr2 => 获得数组[nickname, order_sn] //调整好顺序的变量名数组
$arr2 = [];
if (!empty($arr)) {
foreach ($arr as $v) {
$key = strpos($content, $v);
$arr2[$key] = $v;
}
}
//格式化 arr2 => 以小到大的排序的数组
ksort($arr2);
$arr3 = array_values($arr2);
//arr4 => 获取到变量数组的对应的值 [mofung, 123456789]
$arr4 = [];
foreach ($arr3 as $v2) {
if(isset($params['params'][$v2])) {
$arr4[] = $params['params'][$v2] . "";
}
}
return $arr4;
}
/**
* @notes 更新短信记录
* @param $id
* @param $status
* @param $result
* @author 段誉
* @date 2022/9/15 16:25
*/
public function updateSmsLog($id, $status, $result)
{
SmsLog::update([
'id' => $id,
'send_status' => $status,
'results' => json_encode($result, JSON_UNESCAPED_UNICODE)
]);
}
}

View File

@ -0,0 +1,135 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\common\service\sms\engine;
use AlibabaCloud\Client\AlibabaCloud;
/**
* 阿里云短信
* Class AliSms
* @package app\common\service\sms\engine
*/
class AliSms
{
protected $error = null;
protected $config;
protected $mobile;
protected $templateId;
protected $templateParams;
public function __construct($config)
{
if(empty($config)) {
$this->error = '请联系管理员配置参数';
return false;
}
$this->config = $config;
}
/**
* @notes 设置手机号
* @param $mobile
* @return $this
* @author 段誉
* @date 2022/9/15 16:28
*/
public function setMobile($mobile)
{
$this->mobile = $mobile;
return $this;
}
/**
* @notes 设置模板id
* @param $templateId
* @return $this
* @author 段誉
* @date 2022/9/15 16:28
*/
public function setTemplateId($templateId)
{
$this->templateId = $templateId;
return $this;
}
/**
* @notes 设置模板参数
* @param $templateParams
* @return $this
* @author 段誉
* @date 2022/9/15 16:28
*/
public function setTemplateParams($templateParams)
{
$this->templateParams = json_encode($templateParams, JSON_UNESCAPED_UNICODE);
return $this;
}
/**
* @notes 错误信息
* @return string|null
* @author 段誉
* @date 2022/9/15 16:27
*/
public function getError()
{
return $this->error;
}
/**
* @notes 发送短信
* @return array|false
* @author 段誉
* @date 2022/9/15 16:27
*/
public function send()
{
try {
AlibabaCloud::accessKeyClient($this->config['app_key'], $this->config['secret_key'])
->regionId('cn-hangzhou')
->asDefaultClient();
$result = AlibabaCloud::rpcRequest()
->product('Dysmsapi')
->host('dysmsapi.aliyuncs.com')
->version('2017-05-25')
->action('SendSms')
->method('POST')
->options([
'query' => [
'PhoneNumbers' => $this->mobile, //发送手机号
'SignName' => $this->config['sign'], //短信签名
'TemplateCode' => $this->templateId, //短信模板CODE
'TemplateParam' => $this->templateParams, //自定义随机数
],
])
->request();
$res = $result->toArray();
if (isset($res['Code']) && $res['Code'] == 'OK') {
return $res;
}
$message = $res['Message'] ?? $res;
throw new \Exception('阿里云短信错误:' . $message);
} catch(\Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
}

View File

@ -0,0 +1,138 @@
<?php
// +----------------------------------------------------------------------
// | likeadmin快速开发前后端分离管理后台PHP版
// +----------------------------------------------------------------------
// | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
// | 开源版本可自由商用可去除界面版权logo
// | gitee下载https://gitee.com/likeshop_gitee/likeadmin
// | github下载https://github.com/likeshop-github/likeadmin
// | 访问官网https://www.likeadmin.cn
// | likeadmin团队 版权所有 拥有最终解释权
// +----------------------------------------------------------------------
// | author: likeadminTeam
// +----------------------------------------------------------------------
namespace app\common\service\sms\engine;
use TencentCloud\Sms\V20190711\SmsClient;
use TencentCloud\Sms\V20190711\Models\SendSmsRequest;
use TencentCloud\Common\Exception\TencentCloudSDKException;
use TencentCloud\Common\Credential;
use TencentCloud\Common\Profile\ClientProfile;
use TencentCloud\Common\Profile\HttpProfile;
/**
* 腾讯云短信
* Class TencentSms
* @package app\common\service\sms\engine
*/
class TencentSms
{
protected $error = null;
protected $config;
protected $mobile;
protected $templateId;
protected $templateParams;
public function __construct($config)
{
if(empty($config)) {
$this->error = '请联系管理员配置参数';
return false;
}
$this->config = $config;
}
/**
* @notes 设置手机号
* @param $mobile
* @return $this
* @author 段誉
* @date 2022/9/15 16:26
*/
public function setMobile($mobile)
{
$this->mobile = $mobile;
return $this;
}
/**
* @notes 设置模板id
* @param $templateId
* @return $this
* @author 段誉
* @date 2022/9/15 16:26
*/
public function setTemplateId($templateId)
{
$this->templateId = $templateId;
return $this;
}
/**
* @notes 设置模板参数
* @param $templateParams
* @return $this
* @author 段誉
* @date 2022/9/15 16:27
*/
public function setTemplateParams($templateParams)
{
$this->templateParams = $templateParams;
return $this;
}
/**
* @notes 获取错误信息
* @return string|null
* @author 段誉
* @date 2022/9/15 16:27
*/
public function getError()
{
return $this->error;
}
/**
* @notes 发送短信
* @return false|mixed
* @author 段誉
* @date 2022/9/15 16:27
*/
public function send()
{
try {
$cred = new Credential($this->config['secret_id'], $this->config['secret_key']);
$httpProfile = new HttpProfile();
$httpProfile->setEndpoint("sms.tencentcloudapi.com");
$clientProfile = new ClientProfile();
$clientProfile->setHttpProfile($httpProfile);
$client = new SmsClient($cred, 'ap-guangzhou', $clientProfile);
$params = [
'PhoneNumberSet' => ['+86' . $this->mobile],
'TemplateID' => $this->templateId,
'Sign' => $this->config['sign'],
'TemplateParamSet' => $this->templateParams,
'SmsSdkAppid' => $this->config['app_id'],
];
$req = new SendSmsRequest();
$req->fromJsonString(json_encode($params));
$resp = json_decode($client->SendSms($req)->toJsonString(), true);
if (isset($resp['SendStatusSet']) && $resp['SendStatusSet'][0]['Code'] == 'Ok') {
return $resp;
} else {
$message = $res['SendStatusSet'][0]['Message'] ?? json_encode($resp);
throw new \Exception('腾讯云短信错误:' . $message);
}
} catch(\Exception $e) {
$this->error = $e->getMessage();
return false;
}
}
}