您的当前位置:首页>全部文章>文章详情

ThinkPHP6接入阿里云短信实战:阿里云短信验证码登录

发表于:2023-02-12 00:02:49浏览:635次TAG: #ThinkPHP6 #阿里云短信 #验证码登录

最近做的项目需要用手机号注册账号,之前没有对接过发送短信,今天研究了一下, 写下一贴以做记录。项目框架用ThinkPHP6,短信选择阿里云的短信服务。
1、首先开通阿里云短信包,之后申请短信包签名,这里大家自行去阿里云申请。

2、安装阿里云sdk,阿里云提供了两种方式安装sdk,这里选择用composer。

composer require alibabacloud/dysmsapi-20170525 2.0.9

首先创建Sample类方便调用,我们需要有短信签名,签名模板,阿里云keyId和accessKeySecret,阿里云key在阿里云首页,右上角有个acesskey管理就可以看到。
业务逻辑层生成随机验证码方法:

public static function code(){
    //生成一个随机的6位数字验证码
    $code = rand(11111,999999);
    return $code;
}

创建验证手机号码方法:

/**
 * 校验手机号码
 * @param $phone
 * @return bool
 */
function validatePhone ($phone) {
    if(!preg_match("/^1[34578]\d{9}$/", $phone)){
        return false;
    }
    return true;
}

控制器层验证登录

<?php 
declare (strict_types = 1);

namespace app\home\controller;

use app\home\validate\UserCheck;
use avatars\MDAvatars;
use think\exception\ValidateException;
use think\facade\Db;
use think\facade\Session;
use AlibabaCloud\SDK\Dysmsapi\V20170525\Dysmsapi;
use Darabonba\OpenApi\Models\Config;
use AlibabaCloud\SDK\Dysmsapi\V20170525\Models\SendSmsRequest;

class Login
{

    /**
     *发送短信验证码
     * @return \think\Response
     */
    public function send_code()
    {
        $param = get_params();
        $type= $param['code_type'];
        try {
            validate(UserCheck::class)->scene($type.'code')->check($param);
        } catch (ValidateException $e) {
            // 验证失败 输出错误信息
            return to_assign(1, $e->getError());
        }
        //接收手机号参数
        $phone= $param['mobile'];
        if($type == 'reg'){
            $user = Db::name('User')->where(['mobile' => $phone])->find();
            if (!empty($user)) {
                return to_assign(1, '该手机号已经存在');
            }
        }

        if($type == 'forget'){
            $user = Db::name('User')->where(['mobile' => $param['mobile']])->find();
            if (empty($user)) {
                return to_assign(1, '用户不存在');
            }
            if ($user['status'] == -1) {
                return to_assign(1, '该用户禁止登录,请与平台联系');
            }
        }    

        //这个是验证码
        $code = ['code'=>rand(111111,999999)];
        $accessKeyId = get_system_config('aliyun_sms','accesskey_id');
        $accessKeySecret = get_system_config('aliyun_sms','accesskey_secret');
        //发短信
        $client = self::createClient($accessKeyId, $accessKeySecret);
        $sendSmsRequest = new SendSmsRequest([
            "phoneNumbers" => $phone,
            "signName" => "你的签名名称",
            "templateCode" => "你的模板代号",
            "templateParam" => json_encode($code)
        ]);
        // 复制代码运行请自行打印 API 的返回值
        $result =  $client->sendSms($sendSmsRequest);
        // var_dump($result);die;
        if ($result->body->code == 'OK') {
            //发送成功操作
            set_cache($type.$phone, $code, 600);
            return to_assign(0, '短信验证码已发送,请注意查收');
        }else {
            //发送失败操作
            return to_assign(1, '发送失败:'.$result->body->message);
        }
    }
    /**
     * 使用AK&SK初始化账号Client
     * @param string $accessKeyId
     * @param string $accessKeySecret
     * @return Dysmsapi Client
     */
    public static function createClient($accessKeyId, $accessKeySecret){
        $config = new Config([
            // 您的AccessKey ID
            "accessKeyId" => $accessKeyId,
            // 您的AccessKey Secret
            "accessKeySecret" => $accessKeySecret
        ]);
        // 访问的域名
        $config->endpoint = "dysmsapi.aliyuncs.com";
        return new Dysmsapi($config);
    }

    //提交登录
    public function login_code()
    {
        $param = get_params();
        try {
            validate(UserCheck::class)->scene('loginmobile')->check($param);
        } catch (ValidateException $e) {
            // 验证失败 输出错误信息
            return to_assign(1, $e->getError());
        }
        $user = Db::name('User')->where(['mobile' => $param['mobile']])->find();
        if (empty($user)) {
            return to_assign(1, '用户不存在');
        }
        $code = get_cache('login'.$param['mobile']);
        if(empty($code)){
            return to_assign(1, '验证码已过期,请重新获取');
        }
        else{
            if($code['code'] != $param['code']){
                return to_assign(1, '验证码错误');
            }
            if ($user['status'] == -1) {
                return to_assign(1, '该用户禁止登录,请与平台联系');
            }
            $data = [
                'last_login_time' => time(),
                'last_login_ip' => request()->ip(),
                'login_num' => $user['login_num'] + 1,
            ];
            Db::name('user')->where(['id' => $user['id']])->update($data);
            $userInfo = [
                'id' => $user['id'],
                'username' => $user['username'],
                'nickname' => $user['nickname'],
                'headimgurl' => $user['headimgurl'],
            ];
            $session_user = get_config('app.session_user');
            Session::set($session_user, $userInfo);
            $token = make_token();
            set_cache($token, $userInfo, 7200);
            $userInfo['token'] = $token;
            //清楚验证码缓存
            clear_cache('login'.$param['mobile']);
            add_user_log('login', '', $user['id']);
            return to_assign(0, '登录成功', $userInfo);
        }
    }
}

至此短信验证登录完结束

注意 最好这个代码上传到服务器验证,而且请求协议要https,否则可能会出现问题,宝塔面板可以免费申请ssl

官方文档:

SDK及DEMO下载

PHP-SDK快速开始

OpenAPI Explorer

短信发送状态回执错误码

获取状态的:

$result =  $client->sendSms($sendSmsRequest);
// var_dump($result);die;
if ($result->body->code == 'OK') {
    //发送成功操作
    return to_assign(0, '发送成功');
}else {
    //发送失败操作
    return to_assign(1, '发送失败:'.$result->body->message);
}