之前写了一篇文章,接入网易云信的短信验证码,原文:

网易云信的优点很明显,无论是发送还是验证,都可以请求API进行操作,根本不需要自己写逻辑,直接请求发送和验证就能够实现,非常方便。

缺点也不算是缺点,网易云信从一推出就被人调侃是为财大气粗的企业服务的,小企业人家根本不在乎。

使用完20条,必须进行购买,而购买套餐包是4W条起,有效时间是两年,贵是真的不贵,1800多,这是最低的标准,很多人就望而却步了。

其实在前期,我们更多希望的是按照发送的短信数量进行付费,尽管可能一条短信的价格是在¥0.05左右,后面用的多了,在买套餐包是最好的。

找了很多家,网上的都参差不齐,说说我找的几家吧:

  • 云之讯,服务功能都可以,短信可以按照条数付费,套餐也都可以买少的,但是API文档之烂我也醉了
  • 短信宝,看到他那个平台的界面和体验,我就放弃了
  • 还有一家忘了,根本不说价格,直接让你注册,注册完打电话给你,像是推销。(我就不说出来了)

最后还是别人推荐给我的阿里大于,还是应该选择大公司,网易云信、腾讯云(企业认证)、阿里大于我都觉得可以。

一、thinkphp5接入阿里大于:

给别人的thinkphp5的项目做短信,接入阿里大于进行短信验证码的发送和验证。

安德兔已经很好的实现了发送短信,就不重复,感谢分享:

二、验证码生成、发送、与验证:

1、本地生成验证码:

阿里大于的验证码是需要自己生成的,因此就需要生成一个6位或者4位的随机数字:

顺便需要一个校验手机号的正确性的函数:

/**
 * 生成短信验证码
 *  - 默认长度 6
 * @param int $length
 * @return string
 */
function create_code($length = 6) {
    return str_pad(mt_rand(0, pow(10, $length) - 1), $length, '0', STR_PAD_LEFT);
}
/**
 * 验证手机号是否正确
 * @author honfei
 * @param number $mobile
 */
function is_mobile($mobile) {
    if (!is_numeric($mobile)) {
        return false;
    }
    return preg_match('#^13[\d]{9}$|^14[5,7]{1}\d{8}$|^15[^4]{1}\d{8}$|^17[0,6,7,8]{1}\d{8}$|^18[\d]{9}$#', $mobile) ? true : false;
}

2、发送短信验证码:

已经参照安德兔的方案介入了阿里大于,如果没接入,首先要接入

在发送的时候需要进行几个判断步骤:

  1. 手机号是否正确
  2. 从缓存中查询是否发送过验证码

    • 如果发送过,时间差在1分钟之内,不允许发送
    • 如果超过1分钟,允许再次发送
  3. 发送验证码

    • 如果发送成功,写入缓存,缓存的键是手机号,内容包括生成的验证码和发送的时间戳
 // 获取手机号
        $phone=intval(trim($request->post('phone')));
        // 校验手机号
        if(!is_mobile($phone)){
            return $this->error("手机号格式错误");
        }
        /**
         *  从缓存中查询手机号
         *  如果手机号不存在,则直接生成新的验证码
         *  如果手机号存在,查看上次发送的时间,如果在一分钟之内,不允许发送,超过1分钟才允许发送
         *  验证码验证之后,将删除短信验证码
         *  缓存记录的内容如下:
         *  'phone'=>[
              'phone'=>'',
              'code'=>'code',
                'time'=>'timestamp'
            ];
         */
        // 缓存中获取信息
        $cacheCodeInfo=Cache::get($phone);
        if(NULL!=$cacheCodeInfo){
            // 如果缓存中存在信息
            // 判断时间差在60秒之内的不允许发送
            if(floor(time()-intval($cacheCodeInfo['time']))<=60){
                return $this->error("一分钟内只允许发送一条短信");
            }
        }
        // 缓存中没有信息或者是时间已经超过了60秒
        // 则发送新的验证码
        $code=create_code();
        $Send = new SendModel();
        $result = $Send->sms([
            'param'  => ['code'=>$code],
            'mobile'  => strval($phone),
            'template'  => Config::get('alidayu.template_1'),
        ]);
        // 如果手机号发送成功,则写入缓存中
        $time=time();
        if($result){
            $cacheData=[
                'phone'=>$phone,
                'code'=>$code,
                'time'=>$time
            ];
            Cache::set($phone,$cacheData);
            return $this->success('验证码发送成功,有效时间10分钟');
           
        }else{
            if($result=='isv.BUSINESS_LIMIT_CONTROL'){
                $result="验证码发送次数上限";
            }
           return $this->error($result);
        }

3、验证短信验证码:

短信验证码的验证步骤:

  1. 验证手机号和验证码的格式、
  2. 从缓存中取出手机号
  3. 如果存在并且验证码没有超时,进行验证码的匹配
  4. 匹配或者失败,全部视为失败。
// 获得手机和code
        $code=trim($request->post('code'));
        $phone=trim($request->post('phone'));
        if(strlen($code)==0 || strlen($phone)==0 || !is_mobile($phone)){
            return $this->error('手机号或者验证码格式错误');
        }
        // 从缓存中读取code
        $codeInfo=Cache::get($phone);
        if(NULL == $codeInfo){
            return $this->error('验证码不存在');
        }
        // 存在验证码,进行时间校验 
        $timeDiff=time()-intval($codeInfo['time']);
        if($timeDiff >= 600){
            // 验证码超时删除缓存
            Cache::rm($phone);
            return $this->error('验证码超时');
                }
        // 比较验证码
        if($codeInfo['code']==$code){
            // 校验成功删除缓存
            Cache::rm($phone);
            return $this->success('验证码校验成功');
        }else{
            return $this->error('验证码错误');
        }
    }

三、其他:

缓存中可以加入时间,比如验证码的时间就是20分钟,20分钟后销毁。

QQ截图20170410115153.png