From e063400406338b9d06ae150caeb6afc6e1e03889 Mon Sep 17 00:00:00 2001 From: chuan <2154243450@qq.com> Date: Tue, 25 Feb 2025 17:26:12 +0800 Subject: [PATCH] up --- app/admin/controller/Admin.php | 7 +++ app/admin/controller/Config.php | 15 +++++ app/admin/route/app.php | 8 ++- app/admin/service/AdminService.php | 61 ++++++++++++++++++ app/admin/service/ConfigService.php | 63 +++++++++++++++++++ .../service/setting/StockMarketService.php | 2 +- app/home/controller/News.php | 27 +++++++- app/home/job/RegDone.php | 34 ++++++++++ app/home/route/app.php | 3 +- app/home/service/BaseHomeService.php | 7 +++ app/home/service/LoginService.php | 17 ++++- app/home/service/UserService.php | 10 +-- app/home/validate/LoginValidate.php | 2 +- app/model/EmailTemplateModel.php | 16 +++++ app/utility/SendEmail.php | 25 ++++---- 15 files changed, 271 insertions(+), 26 deletions(-) create mode 100644 app/admin/service/ConfigService.php create mode 100644 app/home/job/RegDone.php create mode 100644 app/model/EmailTemplateModel.php diff --git a/app/admin/controller/Admin.php b/app/admin/controller/Admin.php index 20027fb1..cc512d08 100644 --- a/app/admin/controller/Admin.php +++ b/app/admin/controller/Admin.php @@ -117,4 +117,11 @@ class Admin extends AdminBaseController $returnData = (new AdminService())->getAdminOperationLog($this->request->param()); return json($returnData); } + + // 赠送用户vip + public function giveVip() + { + $returnData = (new AdminService())->giveVip($this->request->param()); + return json($returnData); + } } diff --git a/app/admin/controller/Config.php b/app/admin/controller/Config.php index 660ee940..3b01bed7 100644 --- a/app/admin/controller/Config.php +++ b/app/admin/controller/Config.php @@ -2,6 +2,7 @@ namespace app\admin\controller; +use app\admin\service\ConfigService; use think\facade\Filesystem; use app\model\ConfigModel; @@ -55,4 +56,18 @@ class Config extends AdminBaseController return json(['code' => '100500', 'message' => '系统繁忙', 'data' => [$exception->getMessage()]]); } } + + // 获取邮箱模板列表 + public function emailTemplateList() + { + $returnData = (new ConfigService())->emailTemplateList($this->request->param()); + return json($returnData); + } + + // 编辑邮箱模板列表 + public function editEmailTemplate() + { + $returnData = (new ConfigService())->editEmailTemplate($this->request->param()); + return json($returnData); + } } \ No newline at end of file diff --git a/app/admin/route/app.php b/app/admin/route/app.php index eedd5db8..4f8dbae8 100644 --- a/app/admin/route/app.php +++ b/app/admin/route/app.php @@ -14,7 +14,7 @@ $header = [ //Route::get('/test', 'Test/index'); Route::post('/test', 'Test/index'); Route::post('/test_upload', 'Upload/uploadVideo'); -Route::post('test_api', 'User/editUserStage'); +Route::post('test_api', 'Admin/giveVip'); Route::group('/', function () { // 上传图片 Route::post('/upload', 'Upload/upload'); @@ -24,6 +24,9 @@ Route::group('/', function () { Route::post('/set_config', 'Config/setConfig'); Route::post('/get_config', 'Config/getConfig'); + Route::post('config/email_template_list', 'Config/emailTemplateList'); //获取邮箱模板列表 + Route::post('config/edit_email_template', 'Config/editEmailTemplate'); //编辑邮箱模板 + // 渠道列表 Route::post('/channel/list', 'Channel/list'); //渠道列表 Route::post('/channel/add', 'Channel/add')->middleware('admin_log'); //新增渠道 @@ -203,6 +206,9 @@ Route::group('/', function () { Route::post('/user/give_stock', 'setting.GiveStock/add')->middleware('admin_log'); Route::post('/user/give_stock_list', 'setting.GiveStock/index'); + // 送会员 + Route::post('admin/give_vip', 'Admin/giveVip')->middleware('admin_log'); //赠送用户vip + // 配置管理 // 合约插针行情 Route::post('/setting/forex_hq_index', 'setting.Forex/hq_index'); diff --git a/app/admin/service/AdminService.php b/app/admin/service/AdminService.php index 078a184b..347afb9f 100644 --- a/app/admin/service/AdminService.php +++ b/app/admin/service/AdminService.php @@ -8,13 +8,20 @@ use app\home\service\BaseHomeService; use app\model\AdminLogModel; use app\model\AdminModel; use app\model\AuthRoleModel; +use app\model\PurchaseVipLogModel; +use app\model\PurchaseVipModel; use app\model\TranslatorCustomerModel; use app\model\UserAccessLogModel; use app\model\UserChatGroupModel; use app\model\UserChatLinkModel; +use app\model\UserModel; +use app\model\UserStockLogModel; +use app\model\UserStockModel; use phpDocumentor\Reflection\Type; use think\exception\ValidateException; use app\utility\UnqId; +use think\facade\Config; +use think\facade\Db; use think\facade\Log; use function Sodium\compare; use think\facade\Request; @@ -576,4 +583,58 @@ class AdminService extends AdminBaseService } } + // 赠送会员 + public function giveVip($param) + { + try { + if (empty($param['user_id'])) { + return $this->toData('400', '请指定用户ID'); + } + if (empty($param['month']) || $param['month'] <= 0 || $param['month'] > 100) { + return $this->toData('400', '请指定有效的会员月数'); + } + $userId = $param['user_id']; + $giveDay = $param['month'] * 30; + + $info = UserModel::getFieldsByUserId('trade_password,lever_status,gender,last_name,first_name,real_status,country_id,user_no,nick_name,email,phone_number,country_code,agent_id,is_real,head_img_id,invite_code,is_test_user', $param['user_id']); + if (empty($info)) { + return $this->toData('500', 'The user does not exist.'); + } + // 记录购买vip信息, 扣除用户金额 + Db::transaction(function () use ($userId, $giveDay) { + // 查询用户是否开通过vip,更新用户vip到期时间 + $vipLog = PurchaseVipModel::where(['user_id'=>$userId])->find(); + $expireTimestamp = strtotime("+$giveDay day"); + $expireTime = date("Y-m-d H:i:s", $expireTimestamp); + if (!empty($vipLog)) { + if (empty($vipLog->expire)) { + return $this->toData('100400', ' The vip expire error '); + } + if ($vipLog->expire >= date("Y-m-d H:i:s")) { + $expireTimestamp = strtotime("+$giveDay day", strtotime($vipLog->expire)); + $expireTime = date("Y-m-d H:i:s", $expireTimestamp); + } + $vipLog->expire = $expireTime; + $vipLog->save(); + } else { + PurchaseVipModel::create([ + 'user_id' => $userId, + 'expire' => $expireTime + ]); + } + // 添加用户购买VIP的日志 + PurchaseVipLogModel::create([ + 'user_id' => $userId, + 'amount' => 0, + 'stock_id' => "USD", + 'expire' => $expireTime, + 'day' => $giveDay, + ]); + }); + return $this->toData('0', 'successful'); + } catch (\Exception $e) { + return $this->toData('500', 'The system is busy.', [$e->getMessage(), $e->getTrace()]); + } + } + } diff --git a/app/admin/service/ConfigService.php b/app/admin/service/ConfigService.php new file mode 100644 index 00000000..84e65f59 --- /dev/null +++ b/app/admin/service/ConfigService.php @@ -0,0 +1,63 @@ +toData('400', '参错错误'); + } + if (empty($param['limit']) || !is_numeric($param['limit'])) { + return $this->toData('400', '参错错误'); + } + $where = []; + if (isset($param['tpl_type'])) { + $where['tpl_type'] = $param['tpl_type']; + } + $list = EmailTemplateModel::where($where)->order('id', 'desc')->paginate([ + 'list_rows' => $param['limit'], + 'page' => $param['page'], + ]); + return $this->toData('0', 'SUCCESS', [ + 'list' => $list->items(), // 当前页的数据 + 'page' => $list->currentPage(), // 当前页码 + 'total' => $list->total(), // 总记录数 + 'last_page' => $list->lastPage(), // 最后一页页码 + ]); + } catch (\Exception $e) { + return $this->toData('500', 'The system is busy. Please try again later.', [$e->getMessage(), $e->getTrace()]); + } + } + + // 编辑邮箱模板 + public function editEmailTemplate($param) + { + try { + if (empty($param['id']) || !is_numeric($param['id'])) { + return $this->toData('400', '参错错误'); + } + if (empty($param['title']) || empty($param['content'])) { + return $this->toData('400', '参错错误'); + } + + $emailTemplate = EmailTemplateModel::where(['id'=>$param['id']])->find(); + if (empty($emailTemplate)) { + return $this->toData('500', '修改的模板数据不存在'); + } + $emailTemplate->email = $param['email'] ?? ""; + $emailTemplate->title = $param['title'] ?? ""; + $emailTemplate->content = $param['content'] ?? ""; + $emailTemplate->save(); + return $this->toData('0', 'success'); + } catch (\Exception $e) { + return $this->toData('500', 'The system is busy. Please try again later.', [$e->getMessage(), $e->getTrace()]); + } + } +} \ No newline at end of file diff --git a/app/admin/service/setting/StockMarketService.php b/app/admin/service/setting/StockMarketService.php index fb34f0a4..5169cd2a 100644 --- a/app/admin/service/setting/StockMarketService.php +++ b/app/admin/service/setting/StockMarketService.php @@ -329,7 +329,7 @@ class StockMarketService extends AdminBaseService } - $stockMin = ceil($param['stock_min']); + $stockMin = $param['stock_min']; $leverMin = ceil($param['lever_min']); $leverMax = ceil($param['lever_max']); diff --git a/app/home/controller/News.php b/app/home/controller/News.php index 30f6ef10..501bd2da 100644 --- a/app/home/controller/News.php +++ b/app/home/controller/News.php @@ -2,12 +2,14 @@ namespace app\home\controller; +use app\model\EmailTemplateModel; use app\model\PurchaseVipModel; use app\model\UserChatLinkModel; use Goutte\Client; use think\facade\Cache; use think\facade\Config; use think\facade\Log; +use think\facade\Queue; use think\Request; use think\response\Json; @@ -95,18 +97,37 @@ class News extends HomeBaseController */ public function testApi() { - $s3Config = Config::get('common.chat_server.bse_url'); - $uniq = bin2hex(random_bytes(16)); $getEnv = env('ACCOUT_TYPE.ALL_IN_ONE'); return json([ 'code' => '0', 'message' => 'successful', - 'data' => $s3Config, + 'data' => [], 'env' => $getEnv, 'random' => $uniq, ]); } + public function testSendEmail() + { + $emailTemplate = EmailTemplateModel::where('tpl_type', EmailTemplateModel::TPL_TYPE_ONE)->find(); + if (empty($emailTemplate)) { + return json(['code'=>500, 'message'=>'failed']); + } + $emailTemplate = $emailTemplate->toArray(); + $emailTemplate['email'] = '2154243450@qq.com'; + + + $phpEmail = new \app\utility\SendEmail(); + $bool = $phpEmail->sendEmail($emailTemplate['email'], $emailTemplate['title'], $emailTemplate['content']); + var_dump($bool); + + return json([ + 'code' => '0', + 'message' => 'successful', + 'data' => $bool, + ]); + } + } \ No newline at end of file diff --git a/app/home/job/RegDone.php b/app/home/job/RegDone.php new file mode 100644 index 00000000..f41ea8c5 --- /dev/null +++ b/app/home/job/RegDone.php @@ -0,0 +1,34 @@ +sendEmail($data['email'], $data['title'], $data['content']); + if ($bool) { + break; + } + } + Log::info("think-queue 邮箱注册后的队列任务正常结束." ); + } catch (\Exception $e) { + Log::info("think-queue 邮箱注册后的队列任务异常:message=".$e->getMessage().'date='.json_encode($data)); + } + + // 删除任务 + $job->delete(); + } + + // 任务失败后执行的方法 + public function failed($data) + { + Log::info("think-queue 用户注册后的队列任务执行失败:" . json_encode($data)); + } +} \ No newline at end of file diff --git a/app/home/route/app.php b/app/home/route/app.php index 8575cf8f..b4360f0c 100644 --- a/app/home/route/app.php +++ b/app/home/route/app.php @@ -285,8 +285,7 @@ Route::group('/',function (){ Route::post('get_ip', 'Login/getIP'); Route::get('get_news', 'News/index'); - Route::post('test', 'News/testApi'); - Route::post('test_api', 'user/userAccessLog'); + Route::post('test', 'News/testSendEmail'); })->allowCrossDomain($header); diff --git a/app/home/service/BaseHomeService.php b/app/home/service/BaseHomeService.php index 0a5f3dc2..6c1eae2a 100644 --- a/app/home/service/BaseHomeService.php +++ b/app/home/service/BaseHomeService.php @@ -92,6 +92,13 @@ class BaseHomeService return ['title' => $title, 'subject' => $subject, 'code' => $code]; } + public function getEmailTemplateForRegDone(){ + return [ + 'title' => '账号注册成功', + 'content' => '您的账号注册成功.', + ]; + } + /** * 生成13位用户号 * @return string diff --git a/app/home/service/LoginService.php b/app/home/service/LoginService.php index a85d20e2..f23dddcb 100644 --- a/app/home/service/LoginService.php +++ b/app/home/service/LoginService.php @@ -7,6 +7,7 @@ use app\home\validate\LoginValidate; use app\model\AdminModel; use app\model\CountryModel; use app\model\CustomerRelationalModel; +use app\model\EmailTemplateModel; use app\model\UserChatGroupModel; use app\model\UserChatLinkModel; use app\model\UserModel; @@ -99,6 +100,7 @@ class LoginService extends BaseHomeService $param['invite_code'] = $param['invite_code'] ?? ''; $param['agent_code'] = $param['agent_code'] ?? ''; $chCode = $param['ch_code'] ?? ''; // 注册渠道标识码 + $phone = $param['phone']; //p3定制需求-邮箱注册必须传手机号 // 邮件注册参数校验 validate(LoginValidate::class)->scene('emailRegister')->check($param); @@ -167,7 +169,7 @@ class LoginService extends BaseHomeService $password = (new UnqId())->encryptPassword($param['password'], $salt); $userInviteCode = $this->getUniqInviteCode(); // 需要开启事务 - \think\facade\Db::transaction(function () use ($chCode, $email, $userNo, $userInviteCode, $parentUserId, $password, $ip, $salt, $agentId) { + \think\facade\Db::transaction(function () use ($chCode, $phone, $email, $userNo, $userInviteCode, $parentUserId, $password, $ip, $salt, $agentId) { // 截取邮箱@前的部分作为用户名称 $pos = strpos($email, '@'); if ($pos !== false) { @@ -188,6 +190,7 @@ class LoginService extends BaseHomeService 'user_no' => $userNo, 'nick_name' => $userNickName ?? 'user_' . time(), 'email' => $email, + 'phone' => $phone, 'invite_code' => $userInviteCode, 'parent_id' => $parentUserId, 'agent_id' => $agentId, @@ -278,6 +281,18 @@ class LoginService extends BaseHomeService $this->delCache($emailKey); // 累加已经注册的个数 $this->updateHadRegisterNumCache($ipCanRegisterNumPerIpPerDay); + + // 注册后的队列任务 + $emailTemplate = EmailTemplateModel::where('tpl_type', EmailTemplateModel::TPL_TYPE_ONE)->find(); + if (empty($emailTemplate)) { + Log::info("邮箱注册 - 邮箱模板配置为空!"); + $emailTemplate = $this->getEmailTemplateForRegDone(); + } else { + $emailTemplate = $emailTemplate->toArray(); + } + $emailTemplate['email'] = $email; + Queue::push('app\home\job\RegDone', $emailTemplate, 'email_reg_done_queue'); + return $this->toData('0', 'Registration Successful.', []); } catch (ValidateException $validateException) { // 参数校验失败 异常类 diff --git a/app/home/service/UserService.php b/app/home/service/UserService.php index 2234ce95..4201b5f4 100644 --- a/app/home/service/UserService.php +++ b/app/home/service/UserService.php @@ -286,11 +286,11 @@ class UserService extends BaseHomeService // 查询用户美股余额是否足够 【产品确定用美股余额支付】 $userMoney = UserStockModel::where(['user_id'=>$userId,'stock_id'=> $stockId])->find(); if (empty($userMoney)) { - return $this->toData('100400', ' The user USD balance is insufficient ', []); + return $this->toData('100400', ' The user USD balance is insufficient'); } $userMoneyNum = $userMoney->usable_num; if ($userMoneyNum < $vipPrice) { - return $this->toData('100400', ' The user USD balance is insufficient ', []); + return $this->toData('100400', ' The user USD balance is insufficient'); } // 记录购买vip信息, 扣除用户金额 @@ -309,14 +309,14 @@ class UserService extends BaseHomeService ]); // 查询用户是否开通过vip,更新用户vip到期时间 $vipLog = PurchaseVipModel::where(['user_id'=>$userId])->find(); - $expireTimestamp = strtotime('+30 days'); + $expireTimestamp = strtotime('+30 day'); $expireTime = date("Y-m-d H:i:s", $expireTimestamp); if (!empty($vipLog)) { if (empty($vipLog->expire)) { return $this->toData('100400', ' The vip expire error '); } - if ($vipLog->expire >= $expireTime) { - $expireTimestamp = strtotime('+30 days', strtotime($vipLog->expire)); + if ($vipLog->expire >= date("Y-m-d H:i:s")) { + $expireTimestamp = strtotime('+30 day', strtotime($vipLog->expire)); $expireTime = date("Y-m-d H:i:s", $expireTimestamp); } $vipLog->expire = $expireTime; diff --git a/app/home/validate/LoginValidate.php b/app/home/validate/LoginValidate.php index ad51dcb2..bdae2de9 100644 --- a/app/home/validate/LoginValidate.php +++ b/app/home/validate/LoginValidate.php @@ -42,7 +42,7 @@ class LoginValidate extends BaseHomeValidate protected $scene = [ 'sendEmail' => ['email'], - 'emailRegister' => ['email', 'email_code', 'password', 'invite_code'], + 'emailRegister' => ['phone', 'email', 'email_code', 'password', 'invite_code'], 'emailLogin' => ['email', 'password','device'], 'sendSms' => ['phone', 'nation'], 'smsRegister' => ['phone', 'nation','sms_code', 'password', 'invite_code'], diff --git a/app/model/EmailTemplateModel.php b/app/model/EmailTemplateModel.php new file mode 100644 index 00000000..35c8a385 --- /dev/null +++ b/app/model/EmailTemplateModel.php @@ -0,0 +1,16 @@ +phpEmail = new PHPMailer(); - $this->phpEmail->SMTPDebug = 0; // 关闭调试功能 + $this->phpEmail->SMTPDebug = SMTP::DEBUG_OFF; // 关闭调试功能 $this->phpEmail->CharSet = 'UTF-8'; - $this->phpEmail->isSMTP(); // 设定使用SMTP服务 - //$this->phpEmail->Host = 'smtpdm-ap-southeast-1.aliyun.com'; - $this->phpEmail->Host = empty( env('EMAIL.Host')) ? 'smtpdm-ap-southeast-1.aliyun.com': env('EMAIL.Host'); - $this->phpEmail->Port = 465; // SMTP服务器的端口号 - $this->phpEmail->SMTPAuth = true; - $this->phpEmail->Username = env('EMAIL.Username'); // 发件地址 - $this->phpEmail->Password = env('EMAIL.Password'); // SMTP密码 - $this->phpEmail->SMTPSecure = 'ssl'; - $this->phpEmail->From = env('EMAIL.From'); + $this->phpEmail->isSMTP(); // 使用SMTP 协议 + $this->phpEmail->SMTPAuth = true; // 启用SMTP身份验证 + $this->phpEmail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; // 推荐使用tls加密协议,tls协议端口是587; ssl加密协议已经过时,存在严重安全漏洞(如 POODLE 攻击), ssl协议端口是465 + $this->phpEmail->Host = env('EMAIL.HOST'); // SMTP 服务器地址 + $this->phpEmail->Port = env('EMAIL.PORT'); // SMTP 端口 + $this->phpEmail->Username = env('EMAIL.USERNAME'); // SMTP 用户名 + $this->phpEmail->Password = env('EMAIL.PASSWORD'); // SMTP 密码 + $this->phpEmail->From = env('EMAIL.FROM'); // 发件人信息 +// $this->phpEmail->FromName = env('EMAIL.FROM'); // 发件人名称 } /** @@ -34,6 +35,7 @@ class SendEmail public function sendEmail($toAddress, $title, $content): bool { try { +// $this->phpEmail->isHTML(true); $this->phpEmail->addAddress($toAddress); $this->phpEmail->Subject = $title; $this->phpEmail->Body = $content; @@ -41,8 +43,7 @@ class SendEmail if ($status) { return true; } - trace('---异常-----'.$this->phpEmail->ErrorInfo, 'info'); - + trace('---发送邮件异常----- status = '.$status.'|error_info='.$this->phpEmail->ErrorInfo, 'info'); return false; }catch (\Exception $exception) { trace('---异常-----'.$exception->getMessage(), 'info');