laravel9快速实现发送短信验证码

第一次写文章大佬们不喜勿喷。基于超哥 laravel-easy-sms 实现

一. 环境要求

  • PHP8.0
  • Laravel9
  • Laravel Framework 9.52.16

二. 安装 laravel

composer create-project laravel/laravel 项目名称 9.*

注:如遇无法安装可尝试切换composer官方源。

composer config -g repo.packagist composer https://repo.packagist.org

三. 安装 laravel-easy-sms

composer require overtrue/laravel-easy-sms
  1. 如何配置和使用请前往 laravel-easy-sms
  2. 完整使用文档 laravel-sms

可能会有同学疑问为何配置会放置 services.php 您可以详细阅读 laravel-notifications
您也可以自定义配置文件。项目目录下执行 touch config/文件名.php 后修改 vendor\overtrue\laravel-easy-sms\src\EasySmsServiceProvider.php 源码文件

编写路由测试

  // 使用阿里云测试短信发送接口。
  Route::get('sms-send-code', function () {

    app('easy-sms')->send(158********, [
        'template' => 'SMS_*********',
        'data' => [
            'code' => 6379
        ],
    ]);

    return response()->noContent();
});

laravel9快速实现发送短信验证码

laravel9快速实现发送短信验证码

到这里一个基础的发送短信验证码功能就实现啦

以下是代码段示例

  • 控制器示例
<?php

namespace App\Http\Controllers;

use App\Http\Requests\SmsSendCodeRequest;
use Illuminate\Http\Response;
use Illuminate\Validation\ValidationException;
use Overtrue\EasySms\Exceptions\InvalidArgumentException;

class SmsController extends Controller
{
    /**
     * Create a new controller instance.
     */
    public function __construct()
    {
        //$this->middleware('auth:api');
    }

    /**
     * @throws ValidationException
     * @throws InvalidArgumentException
     */
    public function sendCode(SmsSendCodeRequest $request): Response
    {
        $request->authenticate();

        return response()->noContent();
    }
}
  • 表单验证示例
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\ValidationException;
use Overtrue\EasySms\EasySms;
use Overtrue\EasySms\Exceptions\InvalidArgumentException;
use Overtrue\EasySms\Exceptions\NoGatewayAvailableException;
use RateLimiter;
use Str;

class SmsSendCodeRequest extends FormRequest
{
    /**
     * 表示验证器是否应在第一个规则失败时停止。
     *
     * @var bool
     */
    protected $stopOnFirstFailure = true;

    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize(): bool
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array<string, mixed>
     */
    public function rules(): array
    {
        return [
            'mobile'   => [
                'required',
                'numeric',
                'regex:/^((\+|00)86[-]?)?((1[3-9]\d{9})|((0\d{2,3})?[-]?\d{7,8}))$/'
            ],
        ];
    }

    /**
     * Attempt to authenticate the request's credentials.
     * @return void
     * @throws ValidationException
     * @throws InvalidArgumentException
     */
    public function authenticate(): void
    {
        $this->ensureIsNotRateLimited();

        RateLimiter::hit($this->throttleKey());

        try {
            /* @var EasySms $easySms */
            $easySms = app('easy-sms');

            $easySms->send($this->input('mobile'), [
                'template' => 'SMS_*********',
                'data'     => [
                    'code' => get_sms_code($this->input('mobile')),
                ],
            ]);
        } catch (NoGatewayAvailableException $noGatewayAvailableException) {
            $message = $noGatewayAvailableException->getException('aliyun')->getMessage();

            throw ValidationException::withMessages([
                'mobile' => $message,
            ]);
        }

//        RateLimiter::clear($this->throttleKey());
    }

    /**
     * Ensure the login request is not rate limited.
     *
     * @throws ValidationException
     */
    public function ensureIsNotRateLimited(): void
    {
        if (!RateLimiter::tooManyAttempts($this->throttleKey(), 1)) {
            return;
        }

        $seconds = RateLimiter::availableIn($this->throttleKey());

        throw ValidationException::withMessages([
            'mobile' => trans('auth.throttle', [
                'seconds' => $seconds,
                'minutes' => ceil($seconds / 60),
            ]),
        ]);
    }

    /**
     * Get the rate limiting throttle key for the request.
     */
    public function throttleKey(): string
    {
        return $this->input('mobile') . '|' . $this->ip();
    }
}
  • 辅助函数示例
if (!function_exists('get_sms_code')) {
    function get_sms_code(string|int $mobile): int
    {
        $code = rand(1000, 9999); // 生成四位随机验证码

        // 存储验证码到缓存,有效期为15分钟
        cache()->put('sms_verification_code_' . $mobile, $code, 900);

        return $code;
    }
}

if (!function_exists('verify_sms_code')) {
    function verify_sms_code(string|int $mobile, int $code): bool
    {
        $cacheCode = (int)cache()->pull('sms_verification_code_' . $mobile);

        return $cacheCode === $code;
    }
}

表单验证代码段 请前往 laravel breeze 查看明细
RateLimiter 请前往 laravel 限流 阅读文档

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 2

这跟laravel版本没啥关系吧

1年前 评论
Elves (楼主) 1年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!