TP6对接阿里云短信验证,实现简单的登录注册

        一直没机会对接阿里的短信验证,今天自己写一个玩玩,把总结的一些点分享给大家。

        代码亲测好用,直接copy走稍加改动即可。

        前提:

        (1)准备好阿里云短信的签名、模板、accessKeyId、accessKeySecret。签名模板没过审也可以,可以用阿里云的测试签名和模板。在弄代码之前 最好先在阿里的api调试里面先测试一下自己的签名和模板能不能成功的发送出去,具体参考阿里云 OpenAPI 开发者门户https://next.api.aliyun.com/api/Dysmsapi/2017-05-25/SendSms?params=%7B%7D&lang=PHP

        (2)本人开发用的windows搭的环境,如果想用自己的站点 去对接阿里云短信的同学,注意把本地你自己的域名配个https的,不然请求阿里api时会报curl的错误。

        以上准备好后,开始正文:

1.   首先安装一下阿里云的sdk

composer require alibabacloud/dysmsapi-20170525 2.0.9

2.   创建Sample.php,封装阿里云短信api使用

把相关配置项配置在里面,签名和模板没过审的可以先用阿里测试的,具体详情参考阿里的手册

贴一下代码

<?php
namespace app;

use AlibabaCloud\SDK\Dysmsapi\V20170525\Dysmsapi;

use clagiordano\weblibs\configmanager\ArrayConfigManager;
use Darabonba\OpenApi\Models\Config;
use AlibabaCloud\SDK\Dysmsapi\V20170525\Models\SendSmsRequest;


class Sample
{
    /**
     * 使用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);
    }

    /**
     * @param string[] $data
     * @return void
     */
    public static function main($phone, $code)
    {
        $code = ["code" => $code];
        // $client = self::createClient("LTAI5tJhF874FTXC1RnABC1m", "NNdztlLo3SfJGWjsjX2HrLQWEQWslzT");
        $client = self::createClient("LTAI5tFwazjUX3gD3BjLZpVW", "0cHslGgpg2QRlM8Y7R802bici9IEKY"); // 阿里云key和accesecret
        $sendSmsRequest = new SendSmsRequest([
            "phoneNumbers" => $phone, //控制器层的接收的手机号
            "signName" => "阿里云短信测试", //短信签名
            "templateCode" => "SMS_12345678", //短信模板
            "templateParam" => json_encode($code), //验证码
        ]);
        $resp = $client->sendSms($sendSmsRequest);
        if (!$resp) {
            return false;
        }
        return $resp;
    }
}

3.所有东西都配置好之后就在想调用的地方调用这个main方法就可以了,我是自己单独封装了一个http的接口,用来发送短信验证码,同时把接收到的验证码存到redis里做一个三分钟的失效时间,用来处理我的业务逻辑,贴一下代码。

    /**
     * 发送短信验证码
     *
     * @return Json
     */
    public function sendRes(Request $request){
        $data['phone']     = $request->param("phone");
        $data['create_at'] = date('Y-m-d H:i:s',time());
        $data['ip']        = $request->ip();
        if (empty($data['phone']) || !LoginService::checkPhoneNum($data['phone'])){
            return error_code(10003);
        }
        //将生成的验证码放入缓存中 做三分钟失效时间
        $getCode = rand(1000,9999);
        $redis   = new Redis(Config::get('cache.stores.redis'));
        $redis -> setex($data['phone'],180, $getCode);
        //调用阿里api接口 发送验证码
        $sendCode = Sample::main($data['phone'],$getCode);
        if($sendCode -> body -> code === "isv.BUSINESS_LIMIT_CONTROL"){
            return error_code(11103);
        }
        return json(['code' => 0, 'msg' => '发送成功']);
    }

代码里return的error_code是我自己封装的全局错误码,忽略即可。

注:不需要登录注册,只需要对接阿里短信验证的,至此就结束了。

4.注册

 贴一下我的mysql表结构

控制器controller层代码:

接收参数 -> 校验 -> 入库

    /**
     * 注册
     *
     * @return array|Json
     */
    public function register(Request $request)
    {
        $data['phone']      =   $request->post('phone');
        $data['username']   =   $request->post('username');
        $data['pwd']        =   $request->post('pwd');
        $data['sendSms']    =   $request->post('sendSms');
        //校验接收数据 -> 入库
        $result = LoginService::checkRegister($data);
        if($result){
            return $result;
        }
        $sqlData = ['name'       =>  $data['username'],
                    'pwd'        =>  md5($data['pwd']),
                    "phone"      =>  $data['phone'],
                    "lastOpTime" =>  0 ,
                    "regTime"    =>  time()];
        Db::name('jason_user')->insert($sqlData);
        return json(['code' => 0, 'msg' => '注册成功!']);
    }

业务逻辑层service代码:

    /**
     * 校验用户注册
     *
     * @return mixed
     */
    public static function checkRegister($data)
    {
        //TODO:注册:手机号为唯一标识,需通过短信验证获得的验证码
        $phone      =   $data['phone'];
        $username   =   $data['username'];
        $pwd        =   $data['pwd'];
        $ckSendSms  =   $data['sendSms'];
        $redis      =   new Redis(Config::get('cache.stores.redis'));
        //校验接收到的数据,如果过不了正则,就不必往下继续查mango和redis
        if (empty($phone) || empty($username) || empty($pwd) || empty($ckSendSms)){
            return error_code(11092);
        }
        if(!LoginService::checkPhoneNum($phone) ||!LoginService::checkUserName($username) || !LoginService::rexCheckPassword($pwd)){
            return error_code(10003);
        }
        //校验数据库里是否有该手机号
        $phoneStatus = Db::table('jason_user')->where('phone', $phone)->find();
        if($phoneStatus){
            return error_code(11001);
        }
        //校验短信验证码是否正确
        $sendSms = $redis -> get($phone);
        if(!$sendSms || $sendSms !== $ckSendSms){
            return error_code(11102);
        }
        return false;
    }

5.登录

登录的话我这里采用两种组合方式去登陆,用传过来的操作符operational去区分

operational(1.手机号+密码登录  2.手机号+验证码登录)

控制器controller层代码:

    /**
     * 登录
     *
     * @return array|Json
     */
    public function login(Request $request){
        //TODO:登录两种方式登录
        // 用操作符区分 1:密码登录  2:验证码登录
        $data['operational'] =   $request->post("operational");
        $data['phone']       =   $request->post("phone");
        $data['pwd']         =   $request->post("pwd");
        $data['sendSms']     =   $request->post("sendSms");
        $result = LoginService::checkLogin($data);
        if($result){
            return $result;
        }
        return json(['code' => 0, 'msg' => '登录成功!']);
    }

业务逻辑层service代码:

    /**
     * 校验用户登录
     *
     * @return mixed
     */
    public static function checkLogin($data)
    {
        $operational    =   $data['operational'];
        $phone          =   $data['phone'];
        $pwd            =   $data['pwd'];
        $ckSendSms      =   $data['sendSms'];
        $redis          =   new Redis(Config::get('cache.stores.redis'));
        //校验数据库里是否有该手机号
        $sqlData = Db::table('jason_user')->where('phone', $phone)->find();
        if(!$sqlData){
            return error_code(11000);
        }
        //校验手机号和 密码或验证码
        if($operational == 1){
            if (empty($phone) || empty($pwd) || !LoginService::checkPhoneNum($phone) || !LoginService::rexCheckPassword($pwd)){
                return error_code(10003);
            }
            //校验密码是否正确
            if($sqlData['pwd'] !== md5($pwd)){
                return error_code(11002);
            }
        }else{
            if (empty($phone) || empty($ckSendSms) || !LoginService::checkPhoneNum($phone)){
                return error_code(10003);
            }
            //校验短信验证码是否正确
            $sendSms = $redis -> get($phone);
            if(!$sendSms || $sendSms !== $ckSendSms){
                return error_code(11102);
            }
        }
        return false;
    }

6.注册和登录 结束。下面贴一下用来校验用户名、手机号、密码的三个正则表达式的方法。

注释写的比较全,如果不符合你的业务场景,请不要copy。

    /**
     * 验证手机号
     *
     * @return bool
     */
    public static function checkPhoneNum($phone)
    {
        $isMob = "/^1[3456789]{1}\d{9}$/";
        $isTel = "/^([0-9]{3,4}-)?[0-9]{7,8}$/";
        if (!preg_match($isMob, $phone) && !preg_match($isTel, $phone)) {
            return false;
        } else {
            return true;
        }
    }


    /**
     * 验证密码长度至少为8,且必须包含大小写字母/数字/符号任意三者组合
     *
     * @return bool
     */
    public static function rexCheckPassword($pwd)
    {
        $regStr = "/^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\W_]+$)(?![a-z0-9]+$)(?![a-z\\W_]+$)(?![0-9\\W_]+$)[a-zA-Z0-9\\W_]{8,20}$/";
//        $regStr = "/^(?![0-9]+$)(?![a-z]+$)(?![A-Z]+$)(?!([^(0-9a-zA-Z)]|[\(\)])+$)([^(0-9a-zA-Z)]|[\(\)]|[a-z]|[A-Z]|[0-9]){8,}$/";
        if(preg_match($regStr, $pwd)){
            return true;
        }else{
            return false;
        }
    }


    /**
     * 验证用户名
     * [a-zA-Zxa0-xff_]小写大写英文,或者中文,或者下划线开头
     * [0-9a-zA-Zxa0-xff_]后面的内容可以是小写大写中文数字下划线
     * [0-9a-zA-Zxa0-xff_]{3,15}后面的内容重复3-15次
     * @return bool
     */
    public static function checkUserName($str)
    {
        if (preg_match('/^[a-zA-Zxa0-xff_][0-9a-zA-Zxa0-xff_]{3,15}$/', $str)) {
            return true;
        } else {
            return false;
        }
    }
}

7.至此,发送验证码、注册、登录就结束了,自己随便写的,业务逻辑比较简单。

总结一下就是 先搞定阿里短信验证的对接,然后以手机号作为数据表的唯一标识,去搞注册和登录。

有遇到问题可以评论区dd我,看到会及时回复。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值