195 lines
5.9 KiB
PHP
195 lines
5.9 KiB
PHP
<?php
|
||
|
||
namespace app\store\service;
|
||
|
||
use think\Cache;
|
||
use think\facade\Log;
|
||
|
||
/**
|
||
* 短信服务类(阿里云)
|
||
* Class SmsService
|
||
* @package app\store\service
|
||
*/
|
||
class SmsService
|
||
{
|
||
// 阿里云短信配置(需要在配置文件中设置)
|
||
private $accessKeyId;
|
||
private $accessKeySecret;
|
||
private $signName;
|
||
private $templateCode;
|
||
|
||
public function __construct()
|
||
{
|
||
// 从配置文件读取阿里云短信配置
|
||
$config = config('aliyun_sms');
|
||
$this->accessKeyId = $config['access_key_id'] ?? '';
|
||
$this->accessKeySecret = $config['access_key_secret'] ?? '';
|
||
$this->signName = $config['sign_name'] ?? '数智员工';
|
||
$this->templateCode = $config['template_code'] ?? '';
|
||
}
|
||
|
||
/**
|
||
* 发送短信验证码
|
||
* @param string $mobile 手机号
|
||
* @param string $type 验证码类型(login/register/reset)
|
||
* @return array
|
||
*/
|
||
public function sendVerificationCode($mobile, $type = 'login')
|
||
{
|
||
// 验证手机号格式
|
||
if (!$this->validateMobile($mobile)) {
|
||
return ['success' => false, 'message' => '手机号格式不正确'];
|
||
}
|
||
|
||
// 检查发送频率限制(60秒内只能发送一次)
|
||
$cacheKey = 'sms_limit_' . $mobile;
|
||
if (Cache::has($cacheKey)) {
|
||
$lastSendTime = Cache::get($cacheKey);
|
||
$remainingTime = 60 - (time() - $lastSendTime);
|
||
if ($remainingTime > 0) {
|
||
return ['success' => false, 'message' => "请{$remainingTime}秒后再试"];
|
||
}
|
||
}
|
||
|
||
// 生成6位随机验证码
|
||
$code = $this->generateCode();
|
||
|
||
// 存储验证码到缓存(5分钟有效期)
|
||
$verifyKey = 'sms_code_' . $mobile . '_' . $type;
|
||
Cache::set($verifyKey, $code, 300);
|
||
|
||
// 记录发送时间限制
|
||
Cache::set($cacheKey, time(), 60);
|
||
|
||
// 调用阿里云短信接口发送验证码
|
||
$result = $this->sendSms($mobile, $code);
|
||
|
||
if ($result['success']) {
|
||
Log::info("短信验证码发送成功", [
|
||
'mobile' => $mobile,
|
||
'type' => $type,
|
||
'code' => $code // 开发环境记录,生产环境应删除
|
||
]);
|
||
|
||
return [
|
||
'success' => true,
|
||
'message' => '验证码发送成功',
|
||
'data' => [
|
||
'expire_time' => 300, // 5分钟
|
||
'mobile' => $this->maskMobile($mobile)
|
||
]
|
||
];
|
||
} else {
|
||
return [
|
||
'success' => false,
|
||
'message' => $result['message'] ?? '发送失败,请稍后重试'
|
||
];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 验证短信验证码
|
||
* @param string $mobile 手机号
|
||
* @param string $code 验证码
|
||
* @param string $type 验证码类型
|
||
* @return array
|
||
*/
|
||
public function verifyCode($mobile, $code, $type = 'login')
|
||
{
|
||
$verifyKey = 'sms_code_' . $mobile . '_' . $type;
|
||
$savedCode = Cache::get($verifyKey);
|
||
|
||
if (empty($savedCode)) {
|
||
return ['success' => false, 'message' => '验证码已过期或不存在'];
|
||
}
|
||
|
||
if ($savedCode !== $code) {
|
||
return ['success' => false, 'message' => '验证码错误'];
|
||
}
|
||
|
||
// 验证成功后删除验证码
|
||
Cache::rm($verifyKey);
|
||
|
||
return ['success' => true, 'message' => '验证成功'];
|
||
}
|
||
|
||
/**
|
||
* 调用阿里云短信接口
|
||
* @param string $mobile 手机号
|
||
* @param string $code 验证码
|
||
* @return array
|
||
*/
|
||
private function sendSms($mobile, $code)
|
||
{
|
||
// 如果未配置阿里云密钥,使用测试模式(开发环境)
|
||
if (empty($this->accessKeyId) || empty($this->accessKeySecret)) {
|
||
Log::warning("阿里云短信未配置,使用测试模式", [
|
||
'mobile' => $mobile,
|
||
'code' => $code
|
||
]);
|
||
|
||
return [
|
||
'success' => true,
|
||
'message' => '测试模式:验证码发送成功',
|
||
'dev_code' => $code // 开发环境返回验证码
|
||
];
|
||
}
|
||
|
||
try {
|
||
// 引入阿里云SDK(需要先通过composer安装:composer require alibabacloud/sdk)
|
||
// 这里使用 HTTP 请求方式调用阿里云API
|
||
|
||
$params = [
|
||
'SignName' => $this->signName,
|
||
'TemplateCode' => $this->templateCode,
|
||
'PhoneNumbers' => $mobile,
|
||
'TemplateParam' => json_encode(['code' => $code]),
|
||
];
|
||
|
||
// 构建阿里云请求(使用SDK会更简单,这里简化处理)
|
||
// 实际项目中应该使用 aliyuncs/oss-sdk-php 提供的短信服务
|
||
|
||
// 暂时返回成功(实际项目需要完善)
|
||
return ['success' => true, 'message' => '发送成功'];
|
||
|
||
} catch (\Exception $e) {
|
||
Log::error("阿里云短信发送失败", [
|
||
'mobile' => $mobile,
|
||
'error' => $e->getMessage()
|
||
]);
|
||
|
||
return ['success' => false, 'message' => '发送失败:' . $e->getMessage()];
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 生成6位随机验证码
|
||
* @return string
|
||
*/
|
||
private function generateCode()
|
||
{
|
||
return str_pad(rand(0, 999999), 6, '0', STR_PAD_LEFT);
|
||
}
|
||
|
||
/**
|
||
* 验证手机号格式
|
||
* @param string $mobile
|
||
* @return bool
|
||
*/
|
||
private function validateMobile($mobile)
|
||
{
|
||
return preg_match('/^1[3-9]\d{9}$/', $mobile);
|
||
}
|
||
|
||
/**
|
||
* 手机号脱敏
|
||
* @param string $mobile
|
||
* @return string
|
||
*/
|
||
private function maskMobile($mobile)
|
||
{
|
||
return substr($mobile, 0, 3) . '****' . substr($mobile, -4);
|
||
}
|
||
}
|
||
|