Files
2026-08-31 11:33:59 +08:00

125 lines
3.6 KiB
PHP

<?php
declare(strict_types=1);
namespace app\service\api\system;
use app\model\system\Config;
use core\base\BaseService;
use support\Redis;
use Webman\Http\Request;
/**
* 验证码服务
*/
class CaptchaService extends BaseService
{
/**
* 获取验证码图片
*/
public function getCaptchaImage(): array
{
// 生成验证码
$captcha = $this->generateCaptcha();
// 存储验证码到Redis,5分钟过期
Redis::setex('captcha:' . $captcha['key'], 300, $captcha['code']);
return [
'code' => 200,
'msg' => '获取成功',
'data' => [
'captcha_key' => $captcha['key'],
'captcha_image' => $captcha['image'],
'expire_time' => 300
]
];
}
/**
* 发送短信验证码
*/
public function sendSmsCode(string $type): array
{
$request = \request();
$mobile = $request->post('mobile');
if (empty($mobile)) {
throw new \Exception('手机号不能为空', 400);
}
// 验证手机号格式
if (!preg_match('/^1[3-9]\\d{9}$/', $mobile)) {
throw new \Exception('手机号格式不正确', 400);
}
// 检查发送频率
$lastSendTime = Redis::get('sms_last_send:' . $mobile);
if ($lastSendTime && time() - $lastSendTime < 60) {
throw new \Exception('发送过于频繁,请稍后再试', 429);
}
// 生成验证码
$code = sprintf('%06d', mt_rand(0, 999999));
// 存储验证码到Redis,10分钟过期
$cacheKey = 'sms_code:' . $mobile;
Redis::setex($cacheKey, 600, $code);
// 记录发送时间
Redis::setex('sms_last_send:' . $mobile, 60, time());
// 发送短信(这里应该调用短信服务商API)
$this->sendSms($mobile, $code, $type);
return [
'code' => 200,
'msg' => '验证码发送成功'
];
}
/**
* 生成验证码
*/
private function generateCaptcha(): array
{
// 生成随机验证码
$chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
$code = '';
for ($i = 0; $i < 4; $i++) {
$code .= $chars[mt_rand(0, strlen($chars) - 1)];
}
// 生成唯一key
$key = md5(uniqid() . microtime(true));
// 这里应该生成验证码图片,暂时返回模拟数据
$image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChwGA60e6kgAAAABJRU5ErkJggg==';
return [
'key' => $key,
'code' => $code,
'image' => $image
];
}
/**
* 发送短信
*/
private function sendSms(string $mobile, string $code, string $type): void
{
// 这里应该调用短信服务商API
// 暂时模拟发送成功
$templates = [
'login' => '您的登录验证码是:{code},有效期10分钟',
'register' => '您的注册验证码是:{code},有效期10分钟',
'bind' => '您的绑定验证码是:{code},有效期10分钟',
'reset' => '您的密码重置验证码是:{code},有效期10分钟'
];
$template = $templates[$type] ?? '您的验证码是:{code},有效期10分钟';
$content = str_replace('{code}', $code, $template);
// 记录发送日志
\Log::info("短信发送: {$mobile} - {$content}");
}
}