TAY
笔记 · · 阅读 97

laravel 手机短信注册登录(阿里云)

一、下载官方sdk

composer require alibabacloud/sdk

二、创建短信配置文件

config/sms.php

<?php
/**
* 短信相关配置
*/
return [
   // 阿里云秘钥ID
   'access_key_id'     =>  '',
   // 阿里云秘钥secret
   'access_secret'     =>  '',
   // 短信模板签名
   'sign_name'         =>  '',
   // 短信模板代码
   'template_code'     =>  ''
];

三、创建路由与控制器

1. 路由

Route ::match(['post', 'get'], 'mobile_login', [App\Http\Controllers\Auth\MobileController::class, 'login'])->name('app.oauth.mobile_login');
Route ::post('auth/mobile_code', [App\Http\Controllers\Auth\MobileController::class, 'getMobileCode'])->name('app.oauth.mobile_code');

2. 控制器

Auth/MobileController.php

<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use AlibabaCloud\Client\AlibabaCloud;
use AlibabaCloud\Client\Exception\ClientException;
use AlibabaCloud\Client\Exception\ServerException;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Http\Request;
use App\Models\User;
use Cache;

class MobileController extends Controller
{
    public function __construct()
    {
        $this->middleware('guest');
    }
    
    public function login(Request $request)
    {
        if($request->isMethod('POST')){
            if(Cache::has('mobile_code_'.$request->mobile)){
                if($request->code == json_decode(Cache::get('mobile_code_'.$request->mobile))->code){
                    // 注册或登录
                    $user = User::where(['mobile'=>$request->mobile])->first();
                    if($user){
                        Auth::login($user);
                    }else{
                        $new_user = User::create([
                            'name' => 'u_'.$request->code,
                            'email' => 'u_'.$request->code.'@email.com',
                            'mobile' => $request->mobile,
                            'password' => Hash::make($request->code.time()),
                        ]);
                        Auth::login($new_user);
                    }
                    return redirect()->route('index')->with(['msg'=>__('登录成功'), 'alert'=>'success']);
               }else{
                   return redirect()->back()->with(['msg'=>__('验证码错误1'), 'alert'=>'error']);
               }
           }else{
               return redirect()->back()->with(['msg'=>__('验证码错误1'), 'alert'=>'error']);
           }
       }else{
           return view('auth.mobile_login');
       }
   }
   // 获取短信
   public function getMobileCode(Request $request)
   {
       $mobile = $request->get('mobile');
       if(!$mobile){
           return ['status'=>'error', 'message'=>__('手机号码格式不正确')];
       }
       $authCode = json_encode(['code'=>mt_rand(100000,999999), 'dateline'=>time()]);
       $successCode = $this->sendMobileCode($mobile, $authCode);
       if($successCode){
           Cache::put('mobile_code_'.$mobile, $authCode, 180);
           return ['status'=>'success', 'message'=>__('发送成功,请注意查收,3分钟内有效')];
       }else{
           return ['status'=>'error', 'message'=>__('发送失败')];
       }
   }
   
   public function sendMobileCode($mobile, $authCode)
   {
       AlibabaCloud::accessKeyClient(config('sms.access_key_id'),config('sms.access_secret'))->regionId('cn-hangzhou')->asDefaultClient();
       try {
           $result = AlibabaCloud::rpc()
               ->product('Dysmsapi')
               ->version('2017-05-25')
               ->action('SendSms')
               ->method('POST')
               ->host('dysmsapi.aliyuncs.com')
               ->options([
                   'query' => [
                       'RegionId' => "cn-hangzhou",
                       'PhoneNumbers' => $mobile,
                       'SignName' => config('sms.sign_name'),
                       'TemplateCode' => config('sms.template_code'),
                       'TemplateParam' => $authCode,
                   ],
               ])
               ->request();
           // 成功发送后的结果集
           //print_r($result->toArray());
           // 短信发送成功可以这里进行相关业务逻辑处理
           if ($result['Code'] == 'OK') {
               return true;
           } else {
               return false;
           }
       } catch (ClientException $e) {
           //echo $e->getErrorMessage() . PHP_EOL;
       } catch (ServerException $e) {
           //echo $e->getErrorMessage() . PHP_EOL;
       }
   }
}

四、blade模板

需要 jquery

@extends('layouts.app')

@section('content')
<div class="container py-4">
    <div class="row justify-content-center">
        <div class="col-lg-4 col-md-6">
            <div class="card shadow-xs stacked">
                <div class="pt-3 border-0">
                    <ul class="nav nav-tabs px-3">
                        <a href="{{ route('app.oauth.mobile_login') }}" class="nav-link active">{{ __('Mobile') }}{{ __('Login') }}</a>
                        <a href="{{ route('login') }}" class="nav-link">{{ __('Email') }}{{ __('Login') }}</a>
                        @if (Route::has('register'))
                        <a href="{{ route('register') }}" class="nav-link">{{ __('Register') }}</a>
                        @endif
                    </ul>
                </div>
                <div class="card-body">
                    <form method="POST" action="{{ route('app.oauth.mobile_login') }}">
                        @csrf
                        <div class="mb-3">
                            <label for="mobile" class="form-label">{{ __('手机号') }}</label>
                            <input id="mobile" type="text" class="form-control @error('mobile') is-invalid @enderror" name="mobile" value="{{ old('mobile') }}" required autocomplete="mobile">
                            @error('mobile')<span class="invalid-feedback" role="alert"><strong>{{ $message }}</strong></span>@enderror
                        </div>
                        <div class="mb-3">
                            <label for="code" class="form-label">{{ __('验证码') }}</label>
                            <div class="input-group mb-3">
                                <input id="code" type="code" class="form-control @error('code') is-invalid @enderror" name="code" required autocomplete="current-code">
                                @error('code')<span class="invalid-feedback" role="alert"><strong>{{ $message }}</strong></span>@enderror
                                <button type="button" class="input-group-text" id="postcode" role="button">{{ __('获取验证码') }}</button>
                            </div>
                        </div>
                        <div class="row mb-3">
                            <div class="col-md-6">
                                <div class="form-check">
                                    <input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}>
                                    <label class="form-check-label" for="remember">{{ __('Remember Me') }}</label>
                                </div>
                            </div>
                            @if (Route::has('password.request'))
                            <div class="col-md-6 text-end">
                                <a href="{{ route('password.request') }}" class="link-primary text-decoration-none">{{ __('Forgot Your Password?') }}</a>
                            </div>
                            @endif
                        </div>
                        <div class="mb-3">
                            <button type="submit" class="btn btn-primary px-4">{{ __('Login') }}</button>
                        </div>
                        <div class="mb-0">
                            <a href="{{ route('app.oauth.redirect', 'qq') }}"><img src="/uploads/system/icon/login-qq.png"></a>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
<script type="module">
$(document).on("click", "#postcode",function () {
    var mobile_number = $('[name="mobile"]').val();
    var wait = 60;
    $.ajax({
        headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
        url: "/auth/mobile_code",
        type: "post",
        dataType: "json",
        data: {"mobile": mobile_number},
        success: function (data) {
            console.log(data);
            if(data.status == 'success'){
                var _set = setInterval(function(){
                    $("#postcode").attr("disabled", true);
                    $('#postcode').text(wait + '秒后重新发送');
                    wait-=1;
                    if(wait <= 0){
                        $("#postcode").removeAttr("disabled");
                        $('#postcode').text('获取验证码');
                        clearInterval(_set);
                    }
                },1000);
            }else{
                alert(data.message);
            }
        }
    })
})
</script>
@endsection

目录