1、安装 easy-sms
composer require "overtrue/easy-sms"
image.png
安装成功。
2、配置
在config目录中增加easysms.php配置文件。config/easysms.php添加如下内容,这里我使用的阿里云的短信服务。
<?php
return [
// HTTP 请求的超时时间(秒)
'timeout' => 5.0,
// 默认发送配置
'default' => [
// 网关调用策略,默认:顺序调用
'strategy' => \Overtrue\EasySms\Strategies\OrderStrategy::class,
// 默认可用的发送网关
'gateways' => [
'aliyun','yunpian',
],
],
// 可用的网关配置
'gateways' => [
'errorlog' => [
'file' => '/tmp/easy-sms.log',
],
'aliyun' => [
'access_key_id' => 'LTA*********6',//阿里云短信后台获取
'access_key_secret' => 'VEm***********6kd',//阿里云短信后台获取
'sign_name' => '',//签名名称,阿里云短信后台设置
],
],
];
3.为easy-sms增加一个服务提供者
php artisan make:provider EasySmsServiceProvider
添加内容如下
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Overtrue\EasySms\EasySms;
class EasySmsServiceProvider extends ServiceProvider
{
/**
* Register services.
*
* @return void
*/
public function register()
{
//
$this->app->singleton(EasySms::class,function ($app){
return new EasySms(config('easysms'));
});
$this->app->alias(EasySms::class,'easysms');
}
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
//
}
}
在config/app.php注册服务提供者,在providers中增加
App\Providers\EasySmsServiceProvider::class,
- 修改users表,增加phone字段
php artisan make:migration add_phone_to_users_table --table=users
在新生成的迁移文件中找到 database/migrations/日期前缀_add_phone_to_users_table.php修改如下
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddPhoneToUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
//
$table->string('phone')->nullable()->unique()->after('name');
$table->string('email')->nullable()->change();//因为是手机注册,需要修改 email 字段为 nullable。
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('users', function (Blueprint $table) {
//
$table->dropColumn('phone');
$table->string('email')->nullable(false)->change();
});
}
}
执行php artisan migrate 时报错
image.png
提示修改字段属性需要安装doctrine/dbal。
安装doctrine/dbal组件
composer require doctrine/dbal
image.png
安装成功,重新执行
php artisan migrate
image.png
这次执行成功。
到此基础准备工作完成。
5.短信验证码接口
梳理下最简单的流程,如图所示
image.png
(1)构建api控制器基类
在app/Http/Controllers 目录下新建api目录,并在api目录中创建Controller.php文件。修改内容如下
<?php
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use Dingo\Api\Routing\Helpers;
use App\Http\Controllers\Controller as BaseController;
class Controller extends BaseController
{
use Helpers;
}
api的基类中我们增加了 DingoApi 的 helper,这个 trait 可以帮助我们处理接口响应,后面 Api 控制器都会继承这个基础控制器。
(2)在 app/Http/Controllers/Api 中创建控制器VerificationCodesController,并修改代码如下
<?php
namespace App\Http\Controllers\Api;
class VerificationCodesController extends Controller
{
public function store()
{
return $this->response->array(['info' => 'test info code']);
}
}
我们利用 DingoApi 的 Helpers trait,使用 $this->response->array返回数据。
postman中进行测试
访问正常。
(3)为控制器创建表单请求验证类
php artisan make:request Api/VerificationCodeRequest
修改app/Http/Requests/Api/VerificationCodeRequest.php 内容如下
<?php
namespace App\Http\Requests\Api;
use Dingo\Api\Http\FormRequest;
class VerificationCodeRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'phone' => [
'required',
'regex:/^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199)\d{8}$/',
'unique:users'
]
];
}
}
(4)继续完成控制器
修改app/Http/Controllers/Api/VerificationCodesController.php代码如下
<?php
namespace App\Http\Controllers\Api;
use App\Http\Requests\Api\VerificationCodeRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Overtrue\EasySms\EasySms;
class VerificationCodesController extends Controller
{
public function store(VerificationCodeRequest $request, EasySms $easySms)
{
$phone = $request->phone;
// 生成4位随机数,左侧补0
$code = str_pad(random_int(1, 9999), 4, 0, STR_PAD_LEFT);
try {
$result = $easySms->send($phone, [
//'content' => "尊敬的用户,您的注册会员动态密码为:{$code},请勿泄漏于他人!",
'template' => 'SMS_********3', //我使用的阿里云短信服务,这里是在阿里云后台设置的短信模板ID
'data' => [
'code' => $code //阿里云短信后台模板中的短信验证码变量code,要对应
]
]);
} catch (\Overtrue\EasySms\Exceptions\NoGatewayAvailableException $exception) {
$message = $exception->getException('aliyun')->getMessage();
return $this->response->errorInternal($message ?: '短信发送异常');
}
$key = 'verificationCode_'.str_random(15);
$expiredAt = now()->addMinutes(10);
// 缓存验证码 10分钟过期。
Cache::put($key, ['phone' => $phone, 'code' => $code], $expiredAt);
return $this->response->array([
'key' => $key,
'expired_at' => $expiredAt->toDateTimeString(),
])->setStatusCode(201);
}
}
首先生成 4 位随机码,调用easySms 发送短信到用户手机,此处使用阿里云短信服务,不同短信平台需要传送参数格式不同。
发送成功后,生成一个 key,在缓存中存储这个 key 对应的手机以及验证码,10 分钟过期
将 key 以及 过期时间 返回给客户端,客户端根据获取到的key值请求下一接口。
处理顺序的接口时,常常是第一个接口返回一个随机的 key,利用这个 key 去调用第二个接口,这将为我们接下来要做的注册接口做准备。
关于发送成功后返回的随机 key 这里有几种思路:
使用手机号作为 key,不推荐这样,两个并发请求,如果使用了相同的手机号,无论是什么原因导致的这种情况的发生,都会造成某一个验证不通过;
为了防止上面一种情况,可以使用 手机号 + 几位随机字符串,例如 4 位随机字符串,或者当前时间戳,冲突的概率很小;
使用一个 x 位的随机字符串,一般短时间内的随机字符串,例如 15 位,冲突的概率也很小。
(5)测试接口
在postman中以post方式访问接口 http://你的域名/api/verificationCodes
image.png
成功返回了key,手机很快收到了短信验证码。
到此短信验证码准备成功,下面将进行手机注册接口的开发。
网友评论