PHP短信验证

一、前言

现在很多网站的注册和登录都是用了短信验证的原理,例如在输入框中输入自己的手机号,然后手机就收入了4个数字,在界面上的验证框上输入收到的数字,就登录成功了,错误的话则让你重新输入(接收验证码之后会有倒计时)。

二、实现原理

其实现原理很简单,如下图所示:


短信验证实现原理.png

三、连接短信第三方验证接口发送短信

1.申请短信发送平台,获得API接口

本文使用的是五指CMS短信通短信验证平台,网址为:
http://sms.phpip.com/
当然国内还有很多别的平台,某度搜一下就能搜到。

2.了解短信接口基本知识

在平台内,通常都会有接口文档,叫你怎样调用短信平台的API来发送短信。
此API就是一个URL,通过访问此URL,并传输平台要求传入的参数,即可发送短信,根据参数的不同可发送不同类型的短信。
例如美联软通的短信调用API为:
http://sms.phpip.com/api.php?op=sms_service_vip&sms_uid=【$sms_uid】&sms_pid=【$sms_pid】&sms_passwd=【$sms_passwd】&charset=gbk&send_txt=12334&mobile=18900000000&tplid=1
其中的【】就是需要替换的参数,根据中文提示替换完参数之后,即可发送短信成功,并返回一条返回值。

3.简单发送一条短信

如果返回0,就说明短信发送成功了。
关于短信平台的使用方法,详见各平台的接口文档,本文不做重点讲解。

四、实现一个简单的短信注册功能

1.编写短信发送的核心功能

(1)使用file函数接收url的返回值(跨域获取)

php中有一个函数是file_get_contents(),这是一个用于读取文件内容的函数,但是当他的参数为一个url的时候,也能够获取访问此url时接受到的流。下面我们就通过实验证明一下:

<?php
class Sms{
    public function sendSms(){
        $file = file_get_contents("http://www.baidu.com");
        echo $file;
    } 
}

$sms = new Sms();
$sms->sendSms();

当我们通过访问这个文件的时候,其效果如下(注意浏览器的地址栏):


使用file函数获得的流.png

(2)使用file_get_contents()函数调用短信平台发送接口并在本地记录

我们直接使用该函数调用短信平带api接口即可,同时在本地的数据库中记录发送记录,代码如下所示,本代码中的数据库操作使用的是PHP的PDO操作,若对其不了解的朋友可以去看我关于PHP的PDO操作的文章。
首先我们新建一个数据库sms,新建一个sms_message表,具体属性如下图所示:

sms_message表的属性.png

编写一个调用接口发送短信的方法并调用,代码如下:

<?php
class Sms{
    public function sendSms(){
        $sms_uid="301903";
        $sms_pid="6699";
        $sms_passwd="65b6fb60cee529a11e6e55e3ed30cd9d";
        $mobile_phone="18610062316";
        $code = urlencode(rand(1000,9999));
        $sms_url="http://sms.phpip.com/api.php?op=sms_service_vip&sms_uid=".$sms_uid."&sms_pid=".$sms_pid."&sms_passwd=".$sms_passwd."&mobile=".$mobile_phone."&send_txt=".$code."&tplid=1";
        $file = file_get_contents($sms_url);
        //将结果转换为数组
        
        $data = explode("#",$file);
        //如果返回0(#前的数字),则说明调用成功,将记录存入数据库
         if($data[0]==0 || $data[0]==12){
            //获取当前时间戳
            $time = time();
            //使用PDO数据库操作。
            //1. 创建PDO
            try{ //捕获异常
                $pdo = new PDO("mysql:host=localhost;dbname=sms;charset=utf8","root","123456");
            }catch(PDOException $pe){
                //异常处理
                die("数据库连接失败!原因:".$pe->getMessage());
            }

            //2. 插入发送记录
            $sql = "insert into sms_message( phone, code, time) values( {$mobile_phone}, {$code}, {$time})";
            $stmt = $pdo->exec($sql); //执行插入语句

            //3. 解析结果(以关联数组解析)
            if($stmt==1){
                echo "短信发送并记录成功";
            }else{
                echo "PDO出错,错误代码:";
                print_r($stmt);
            }

            //4. 释放结果
            $stmt=null;
            $pdo=null;
        }else{
            echo "调取接口出错,代码:";
            print_r($data);
        }
    } 
}
//调用接口
$sms = new Sms();
$sms->sendSms();

调用完之后的结果为:

短信发送并记录成功

数据库记录为:
数据库记录的短信.png

2.与前端对接

(1)前端页面

首先我们只做一个注册的前端操作界面,代码如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <style type="text/css">
            * {
                margin:0px;
                padding:0px;
            }
            #main_body{
                margin:0px auto;
                width:100%;
                height:2048px;
            }
            #main_gui{
                position:relative;
                top:100px;
                margin:0px auto;
                padding-top:30px;
                width:600px;
                height:370px;
                background-color:#DDD;
            }
            #phone{
                width:170px;
            }
            #sms_code{
                width:100px;
            }
            h3{
                text-align:center
            }
        </style>
        <script src="./jquery/jquery-1.8.3.js"></script>
        <script src="./jquery/jquery-1.8.3.min.js"></script>
    </head>
    <body>
        <div id="main_body">
            <div id="main_gui">
                <form method="post" action="verifySms.php" />
                <center>
                    <h3>会员注册</h3><br/><br/>
                    <p>手&nbsp; 机:<input type="text" id="phone" /></p><br/><br/>
                    <p>验证码:<input type="text" id="sms_code" /><input type="button" id="btn" value="点击获取验证码" /></p><br/><br/>
                    <p><input type="submit" value="点击注册" /></p>
                </center>
                </form>
            </div>
        </div>
    </body>
</html>

以上代码显示出来是这个样子的↓:

短信注册界面.png

注意:代码的<head>里必须引用Jquery文件<script src="./jquery/jquery.js"></script><script src="./jquery/jquery.min.js"></script>,否则后面无法实现按钮的功能。

(2)倒计时功能

接下来对“获取验证码”按钮做倒计时功能,本功能采用Jquery来实现,如果对Jquery不熟悉,可以到我JS的课程中学习Jquery。
我们在上面文档的最后增加<script>标签,在其中使用Jquery对第一个按钮做方法绑定,代码如下:

<script>
    $(function(){
        $("#btn").click(function(){
            $.getSMSCode();
        });
    });
    $.getSMSCode=function(){
        $.setTime=60;
        $.minusSecond=setInterval(function(){
            $("#btn").attr("disabled",true);
            $("#btn").attr("value",$.setTime+"s后获取验证码");
            $.setTime--;
            if($.setTime==-2){
            clearInterval($.minusSecond);
            $("#btn").attr("disabled",false);
            $("#btn").attr("value","点击获取验证码");
            }
        },1000);
    };
</script>

(3)发送验证码

在点击获取验证码的时候,先使用AJAX调用后台接口发送短信验证码,当接口调用成功并发送了短信验证码的时候,才调用上面的方法。因为原生AJAX很麻烦,所以这里还是使用Jquery来写实现AJAX,还是在<script>标签内,给“获取验证码”按钮中绑定的函数中在增加一个新的方法,代码如下:

<script>
    $(function(){
        $("#btn").click(function(){
            $.askSMSCode();
        });
    });
    $.getSMSCode=function(){
        $.setTime=60;
        $.minusSecond=setInterval(function(){
            $("#btn").attr("disabled",true);
            $("#btn").attr("value",$.setTime+"s后获取验证码");
            $.setTime--;
            if($.setTime==-2){
            clearInterval($.minusSecond);
            $("#btn").attr("disabled",false);
            $("#btn").attr("value","点击获取验证码");
            }
        },1000);
    };
    $.askSMSCode=function(){
        $.phone_number=$("#phone").val(); //获取表单中填写的电话号码
        $.post("askSms.php",{phone:$.phone_number},function(data){
                    if(data=="OK"){
                        $.getSMSCode();
                    }
                });
        
    };
</script>

此时点击前端界面的“获取验证码”按钮之后,如不出现错误,即可实现按钮倒计时,同时手机收到验证码。

3.接收验证码并验证

手机收到验证码之后,要对提交的验证码进行验证,验证通过则注册成功,验证失败则跳回注册页面重新获取。

(1)前端页面

我们先制作两个前端页面,第一个是成功页面registSuccess.html,代码如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
    </head>
    <body>
        <h1>:) 注册成功</h1>
    </body>
</html>

运行起来是这个样子:


注册成功页面.png

第二个是成功页面registFail.html,代码如下:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <script>
        window.onload=setTimeout(function(){window.location.href="sms_tpl.html";},5000);
        </script>
    </head>
    <body>
        <h1>:( 注册失败</h1><br/>
        <h2>请填写正确的验证码</h2>
    </body>
</html>

运行起来是这个样子:
注册失败页面.png

因为里面写了定时调转的JS代码,所以5秒后会跳回注册页面。

(2)后端注册程序

提交表单后,系统会根据表单中的action提交到verifySms.php中去,然后做相应的验证和处理,代码如下:

<?php
class VerifySms{
    public $phone="";
    public $smsCode="";
    public function verify(){
        $this->phone = $_POST["phone"];
        $this->smsCode = $_POST["smsCode"];
        //使用PDO数据库操作。
        //1. 创建PDO
        try{ //捕获异常
            $pdo = new PDO("mysql:host=localhost;dbname=sms;charset=utf8","root","");
        }catch(PDOException $pe){
            //异常处理
            die("数据库连接失败!原因:".$pe->getMessage());
        }

        //2. 插入发送记录
        $sql = "select code from sms_message where phone={$this->phone} and time=(select MAX(time) from sms_message)";
        $stmt = $pdo->query($sql); //执行插入语句

        //3. 解析结果(以关联数组解析)
        if($stmt->rowCount()==1){
            $row = $stmt->fetch(PDO::FETCH_ASSOC);
            if($row['code']==$this->smsCode){
                header("Location:registSuccess.html");
            }else{
                header("Location:registFail.html");
            }
        }else{
            header("Location:registfail.html");
        }

        //4. 释放结果
        $stmt=null;
        $pdo=null;
    }
}

$verifySms = new VerifySms();
$verifySms->verify();

最后该脚本会根据调用短信接口和数据库操作的结果来返回不同的页面。

五、其他功能

除了以上的手机短信注册功能致之外,还有其他用途,例如登录功能和密码找回功能。

1.登录功能实现思路

登录功能的实现和注册功能很类似。如果用户选择手机号加验证码登录,那么在输入手机号之后,点击获取验证码,会受到验证码,在点击提交验证码之后,系统后台先核对该手机号是否已经注册,若注册则核对提交的验证码和系统记录的验证码是否一致,一致则登录成功,不一致则再跳转到登录页面。

2.密码找回实现思路

实现密码找回有个前提,前提就是用户在注册的时候已经填写并确定了密码,或者在短信验证码注册之后完善了自己的密码。
当用户忘记密码之后,点击相应按钮进入找回密码页面,同样输入注册的手机号并获取验证码,然后提交。若手机号和验证码都验证成功后,则跳转到修改密码的页面,在两次输入的密码一样后,修改密码成功。

以上两个功能在本文中不做演示,各位看官可以自己试验并实现。

禁止转载,如需转载请通过简信或评论联系作者。