概述 在做项目的时候,需要用到短信发送验证码功能。不能不说Yii2的牛逼,很容易就搞定了。下面我整理一下具体功能和流程,分享给大家。 主要功能 通过Yii2 rules验证手机号 通过js验证是否为手机号 通过Ajax验证手机是否在数据库存在 通过ajax发送短信验证码 Js倒计时功能(cookie保存信息,防刷新) 通过Yii2 rules 验证手机短信码是否合法。 实现详细步骤和代码 前端表单设计,这里主要定义了手机号码filed和和发送短信的按钮 'id' =>'second' <?php $form = ActiveForm::begin(); ?> <?= $form->field($model, 'loginMode')->hiddenInput(['value' => 'login_sms_code'])->label(false); ?> <div class="form-group has-feedback login-mobile f-left"> <?= $form->field($model, 'mobile')->textInput(['placeholder' => $model->getAttributeLabel('mobile')])->label(false) ?> <span class="glyphicon glyphicon-phone form-control-feedback"></span> </div> <?= Html::buttonInput(Yii::t('app', 'Get SMS Code'), ['class' => 'btn bg-yellow ', 'name' => 'signup-button', 'id' => 'second']) ?> <div class="clear"></div> <div class="form-group has-feedback"> <?= $form->field($model, 'smsCode')->textInput(['placeholder' => $model->getAttributeLabel('smsCode')])->label(false) ?> <span class="glyphicon glyphicon-mobile form-control-feedback"></span> </div> <div class="footer bg-gray"> <?= Html::submitButton(Yii::t('app', 'Login'), ['class' => 'btn bg-blue btn-block']) ?> </div><?php ActiveForm::end(); ?> 当发送短信的按钮 'id'=>'second' 被点击后,会通过js验证手机的合法性,然后发送短信,并进行倒计时。具体js部分代码如下 //发送验证码时添加cookiefunction addCookie(name,value,expiresHours){ var cookieString=name+"="+escape(value); //判断是否设置过期时间,0代表关闭浏览器时失效 if(expiresHours>0){ var date=new Date(); date.setTime(date.getTime()+expiresHours*1000); cookieString=cookieString+";expires=" + date.toUTCString(); } document.cookie=cookieString; }//修改cookie的值function editCookie(name,value,expiresHours){ var cookieString=name+"="+escape(value); if(expiresHours>0){ var date=new Date(); date.setTime(date.getTime()+expiresHours*1000); //单位是毫秒 cookieString=cookieString+";expires=" + date.toGMTString(); } document.cookie=cookieString; }//根据名字获取cookie的值function getCookieValue(name){ var strCookie=document.cookie; var arrCookie=strCookie.split("; "); for(var i=0;i<arrCookie.length;i++){ var arr=arrCookie[i].split("="); if(arr[0]==name){ return unescape(arr[1]); break; } } } $(function(){ $("#second").click(function (){ sendCode($("#second")); }); v = getCookieValue("secondsremained_login") ? getCookieValue("secondsremained_login") : 0;//获取cookie值 if(v>0){ settime($("#second"));//开始倒计时 } })//发送验证码function sendCode(obj){ var site = 'http://yun.ucrm.com.cn/'; var mobile = $("#loginform-mobile").val(); //检查手机是否合法 var result = isPhoneNum(); if(result){ //检查手机号码是否存在 var exists_result = dbCheckMobileExists(site+'site/check-mobile-exists',{"mobile":mobile}); if(exists_result){ doPostBack(site+'sms/send-login-code',{"mobile":mobile}); addCookie("secondsremained_login",60,60);//添加cookie记录,有效时间60s settime(obj);//开始倒计时 } } }//检查手机号码是否存在function dbCheckMobileExists(url,queryParam){ $.ajax({ async : false, cache : false, type : 'POST', url : url,// 请求的action路径 data:queryParam, error : function() {// 请求失败处理函数 }, success:function(result){ if(result=='Success'){ return true; } else{ alert('该手机号码不存在!'); return false; } } }); }//将手机利用ajax提交到后台的发短信接口function doPostBack(url,queryParam) { $.ajax({ async : false, cache : false, type : 'POST', url : url,// 请求的action路径 data:queryParam, error : function() {// 请求失败处理函数 }, success:function(result){ if(result=='Success'){ alert('短信发送成功,验证码10分钟内有效,请注意查看手机短信。如果未收到短信,请在60秒后重试!'); } else{ alert('短信发送失败,请和网站客服联系!'); return false; } } }); }//开始倒计时var countdown;function settime(obj) { countdown=getCookieValue("secondsremained_login") ? getCookieValue("secondsremained_login") : 0; if (countdown ==0) { obj.removeAttr("disabled"); obj.val("获取验证码"); return; } else { obj.attr("disabled", true); obj.val(countdown + "秒后重发"); countdown--; editCookie("secondsremained_login",countdown,countdown+1); } setTimeout(function() { settime(obj) },1000) //每1000毫秒执行一次}//校验手机号是否合法function isPhoneNum(){ var phonenum = $("#loginform-mobile").val(); var myreg = /^(((13[0-9]{1})|(15[0-9]{1})|(18[0-9]{1}))+\d{8})$/; if(!myreg.test(phonenum)){ alert('请输入有效的手机号码!'); $("#loginform-mobile").focus(); return false; }else{ return true; } } 上述代码中有两个方法是通过Ajax交互的,一个为验证手机是否合法的方法dbCheckMobileExists(),另一个是通过ajax发送短信码的方法doPostBack(). 具体每个方法的代码大家上面看就可以了。 dbCheckMobileExists()会提交到CheckMobileExists方法检查手机是否存在: public function actionCheckMobileExists() { $mobile = Yii::$app->request->post('mobile'); if(User::findByMobile($mobile)){ echo 'Success'; }else{ echo 'Failed'; } } doPostBack()会提交到SendLoginCode方法发送登录验证码: public function actionSendLoginCode() { $mobile = Yii::$app->request->post('mobile'); $code = $this->createCode(); $content = "本次验证码为".$code.",您正在登录纽仁云客管理系统,打死也不告诉别人哦"; if($this->send($mobile,$content)===true){ //检查session是否打开 if(!Yii::$app->session->isActive){ Yii::$app->session->open(); } //验证码和短信发送时间存储session Yii::$app->session->set('login_sms_code',$code); Yii::$app->session->set('login_sms_time',time()); echo 'Success'; }else{ echo 'Failed'; } } 在上述发送代码的时候,当发送成功时,会保存两个session,login_sms_code和login_sms_time,分别记录了验证码内容和生成时间。 当发送成功后,用户会收到验证码,然后输入后进行提交,此时我们会进行验证码的校验,这里我们是采用yii2 rules来完成此项任务。 在 LoginForm 表的里面的 rules 里面添加下面校验规则,大家可以看到这里写了关于手机和验证码的诸多验证规则,其实最后一个验证规则即为 验证短信码是否正确,这里我们通过requiredValue验证用户输入的值是否等于 getSmsCode 的值即可。 ['mobile', 'required','on' => ['default','login_sms_code']], ['mobile', 'integer','on' => ['login_sms_code']], ['mobile','match','pattern'=>'/^1[0-9]{10}$/','on' => ['default','login_sms_code'],'message'=>'{attribute}必须为1开头的11位纯数字'], ['mobile', 'string', 'min'=>11,'max' => 11,'on' => ['default','login_sms_code']], ['smsCode', 'required','on' => ['default','login_sms_code']], ['smsCode', 'integer','on' => ['default','login_sms_code']], ['smsCode', 'string', 'min'=>6,'max' => 6,'on' => ['default','login_sms_code']], ['smsCode', 'required','requiredValue'=>$this->getSmsCode(),'on' => ['default','login_sms_code'],'message'=>'手机验证码输入错误'], 上面的getSmsCode()代码如下,这里通过session获取了验证码和生成时间,如果在10分钟内,则返回验证码session的值。 public function getSmsCode() { //检查session是否打开 if(!Yii::$app->session->isActive){ Yii::$app->session->open(); } //取得验证码和短信发送时间session $signup_sms_code = intval(Yii::$app->session->get('login_sms_code')); $signup_sms_time = Yii::$app->session->get('login_sms_time'); if(time()-$signup_sms_time < 600){ return $signup_sms_code; }else{ return 888888; } } 上面为全部代码,大家可以直接使用。大家有什么问题或更好的建议可以直接在后面回帖。后续我会为大家分享更多的代码。