sadiqsalau / laravel-otp
Laravel OTP 包
Requires
- php: ^8.0
- hi-folks/rando-php: ^0.2.0
- laravel/framework: ^9|^10|^11
README
介绍
基于类的系统实现的 Laravel OTP 包。每个 OTP 都是一个执行特定操作的类。例如,EmailVerificationOtp
将标记账户为已验证。
安装
通过 composer 安装
composer require sadiqsalau/laravel-otp
发布配置文件
php artisan vendor:publish --provider="SadiqSalau\LaravelOtp\OtpServiceProvider"
使用方法
生成 OTP
php artisan make:otp {name}
新的 OTP 类将被生成到 app/Otp
目录中。例如
php artisan make:otp UserRegistrationOtp
每个 OTP 必须实现一个 process
方法,该方法在验证后将被调用。在那里 OTP 可以执行必要的操作并返回任何结果。
<?php namespace App\Otp; use SadiqSalau\LaravelOtp\Contracts\OtpInterface as Otp; use Illuminate\Auth\Events\Registered; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use App\Models\User; class UserRegistrationOtp implements Otp { /** * Constructs Otp class */ public function __construct( public string $name, public string $email, public string $password ) { // } /** * Processes the Otp * * @return User */ public function process() { /** @var User */ $user = User::unguarded(function () { return User::create([ 'name' => $this->name, 'email' => $this->email, 'password' => Hash::make($this->password), 'email_verified_at' => now(), ]); }); event(new Registered($user)); Auth::login($user); return $user; } }
发送 OTP
<?php use SadiqSalau\LaravelOtp\Facades\Otp; Otp::identifier($identifier)->send($otp, $notifiable);
$otp
: 要发送的 OTP。$notifiable
: 匿名通知或通知实例。
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Notification; use Illuminate\Http\Request; use Illuminate\Validation\Rules; use SadiqSalau\LaravelOtp\Facades\Otp; use App\Models\User; use App\Otp\UserRegistrationOtp; Route::post('/register', function(Request $request){ $request->validate([ 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'string', 'email', 'max:255', 'unique:' . User::class], 'password' => ['required', Rules\Password::defaults()], ]); $otp = Otp::identifier($request->email)->send( new UserRegistrationOtp( name: $request->name, email: $request->email, password: $request->password ), Notification::route('mail', $request->email) ); return __($otp['status']); });
返回值
['status' => Otp::OTP_SENT] // Success: otp.sent
验证 OTP
<?php use SadiqSalau\LaravelOtp\Facades\Otp; Otp::identifier($identifier)->attempt($code);
$code
: 要比较的 OTP 代码。
返回值
['status' => Otp::OTP_EMPTY] // Error: otp.empty ['status' => Otp::OTP_MISMATCHED] // Error: otp.mismatched ['status' => Otp::OTP_PROCESSED, 'result'=>[]] // Success: otp.processed
result
键包含 OTP 类的 process
方法的返回值
<?php use Illuminate\Support\Facades\Route; use Illuminate\Http\Request; use SadiqSalau\LaravelOtp\Facades\Otp; Route::post('/otp/verify', function (Request $request) { $request->validate([ 'email' => ['required', 'string', 'email', 'max:255'], 'code' => ['required', 'string'] ]); $otp = Otp::identifier($request->email)->attempt($request->code); if($otp['status'] != Otp::OTP_PROCESSED) { abort(403, __($otp['status'])); } return $otp['result']; });
不清理缓存验证 OTP
<?php use SadiqSalau\LaravelOtp\Facades\Otp; Otp::identifier($identifier)->check($code);
$code
: 要比较的 OTP 代码。
返回值
['status' => Otp::OTP_EMPTY] // Error: otp.empty ['status' => Otp::OTP_MISMATCHED] // Error: otp.mismatched ['status' => Otp::OTP_MATCHED] // Success: otp.matched
重新发送 OTP
<?php use SadiqSalau\LaravelOtp\Facades\Otp; Otp::identifier($identifier)->update();
返回值
['status' => Otp::OTP_EMPTY] // Error: otp.empty ['status' => Otp::OTP_SENT] // Success: otp.sent
<?php use Illuminate\Support\Facades\Route; use Illuminate\Http\Request; use SadiqSalau\LaravelOtp\Facades\Otp; Route::post('/otp/resend', function (Request $request) { $request->validate([ 'email' => ['required', 'string', 'email', 'max:255'] ]); $otp = Otp::identifier($request->email)->update(); if($otp['status'] != Otp::OTP_SENT) { abort(403, __($otp['status'])); } return __($otp['status']); });
设置标识符
OTP 类的每个方法都需要设置一个标识符以唯一标识 OTP。
<?php use SadiqSalau\LaravelOtp\Facades\Otp; Otp::identifier($request->email)->send(...);
<?php use SadiqSalau\LaravelOtp\Facades\Otp; Otp::identifier($identifier)->send(...); Otp::identifier($identifier)->attempt(...); Otp::identifier($identifier)->update(); Otp::identifier($identifier)->check(...);
配置
发布包后,配置文件可在 config/otp.php
中找到
format
- 生成的 OTP 代码的格式 (numeric
|alphanumeric
|alpha
)length
- 生成的 OTP 代码的长度expires
- OTP 过期前的分钟数notification
- 要使用的自定义通知类,默认为SadiqSalau\LaravelOtp\OtpNotification
翻译
该包不提供开箱即用的翻译,但这里有一个示例。创建一个新的翻译文件:lang/en/otp.php
<?php return [ /* |-------------------------------------------------------------------------- | OTP Language Lines |-------------------------------------------------------------------------- | | The following language lines are used by the OTP broker | */ 'sent' => 'We have sent your OTP code!', 'empty' => 'No OTP!', 'matched' => 'OTP code verified!', 'mismatched' => 'Mismatched OTP code!', 'processed' => 'OTP was successfully processed!' ];
然后翻译状态
return __($otp['status'])
API
-
Otp::identifier(mixed $identifier)
- 设置 OTP 标识符 -
Otp::send(OtpInterface $otp, mixed $notifiable)
- 向通知发送 OTP -
Otp::attempt(string $code)
- 尝试 OTP 代码,返回调用 OTP 的process
方法的结果 -
Otp::check(string $code)
- 将代码与当前 OTP 进行比较,这不会处理或清除 OTP -
Otp::update()
- 重新发送并更新当前 OTP -
Otp::clear()
- 删除 OTP -
Otp::useGenerator(callable $callback)
- 设置要使用的自定义生成器,生成器将使用$format
和$length
调用 -
Otp::generateOtpCode($format, $length)
- 生成 OTP 代码
贡献
欢迎贡献。