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 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
讨论数量: 2

这跟laravel版本没啥关系吧

10个月前 评论
Elves (楼主) 10个月前

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