105 lines
2.6 KiB
PHP
105 lines
2.6 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Exceptions\BizException;
|
|
use App\Models\SmsCode;
|
|
use App\Models\User;
|
|
use Illuminate\Contracts\Cache\Repository as Cache;
|
|
|
|
class SmsCodeService
|
|
{
|
|
/**
|
|
* @var int
|
|
*/
|
|
protected $expires = 300;
|
|
|
|
/**
|
|
* @param \Illuminate\Contracts\Cache\Repository $cache
|
|
*/
|
|
public function __construct(
|
|
protected Cache $cache,
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* 发送短信验证码
|
|
*
|
|
* @param string $phone
|
|
* @param int $type
|
|
* @param string $code
|
|
* @param int $decaySeconds
|
|
* @return \App\Models\SmsCode
|
|
*
|
|
* @throws \App\Exceptions\BizException
|
|
*/
|
|
public function send(
|
|
string $phone,
|
|
int $type,
|
|
string $code,
|
|
int $decaySeconds = 60,
|
|
): SmsCode {
|
|
if (! in_array($type, SmsCode::$allowedTypes)) {
|
|
throw new BizException(__('Invalid verification code type'));
|
|
}
|
|
|
|
$user = User::where('phone', $phone)->first();
|
|
|
|
switch ($type) {
|
|
case SmsCode::TYPE_REGISTER:
|
|
if ($user) {
|
|
throw new BizException(__('The phone number is already registered'));
|
|
}
|
|
|
|
break;
|
|
|
|
case SmsCode::TYPE_LOGIN:
|
|
case SmsCode::TYPE_RESET_PASSWORD:
|
|
case SmsCode::TYPE_SET_WALLET_PASSWORD:
|
|
if ($user === null) {
|
|
throw new BizException('手机号未注册');
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (! $this->cache->add("sms_lock_{$type}_{$phone}", 1, $decaySeconds)) {
|
|
throw new BizException(__('Sending too frequently, please try again later'));
|
|
}
|
|
|
|
return SmsCode::create([
|
|
'phone' => $phone,
|
|
'code' => $code,
|
|
'type' => $type,
|
|
'expires_at' => now()->addSeconds($this->expires),
|
|
'user_id' => $user?->id,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 校验验证码是否正确
|
|
*
|
|
* @param string $phone
|
|
* @param int $type
|
|
* @param string $code
|
|
* @return void
|
|
*
|
|
* @throws \App\Exceptions\BizException
|
|
*/
|
|
public function validate(string $phone, int $type, string $code): void
|
|
{
|
|
$smsCode = SmsCode::where('phone', $phone)
|
|
->where('type', $type)
|
|
->latest('id')
|
|
->first();
|
|
|
|
if ($smsCode === null || $smsCode->code !== $code || $smsCode->isInvalid()) {
|
|
throw new BizException(__('Invalid verification code'));
|
|
}
|
|
|
|
$smsCode->update([
|
|
'is_use' => true,
|
|
]);
|
|
}
|
|
}
|