用戶註冊之短信驗證

一般咱們實名註冊用戶的時候,都會要求輸入手機號,而後獲取手機驗證碼,而後填到頁面,像下面這樣:php

ok,如今來理一下思緒:前端

1.註冊頁面vue

由於這裏要說的是短信驗證,因此只貼出核心代碼,下面是手機號和短信驗證碼這兩部分的前端代碼片斷:ajax

<div data-v-7cf0b24e="" class="lj_input_standard4">
    <span data-v-7cf0b24e="" id="left_span6">手機號</span>
    <span data-v-7cf0b24e="" id="asterisk_span6">*</span>
    <input v-model="phone" data-v-7cf0b24e="" id="myinput6" name="data[phone]" type="tel" maxlength="11" placeholder="請輸入手機號碼">
</div>
<div data-v-7cf0b24e="" class="lj_input_standard4">
    <span data-v-7cf0b24e="" id="left_span7">短信驗證碼</span>
    <span data-v-7cf0b24e="" id="asterisk_span7">*</span>
    <input data-v-7cf0b24e="" id="myinput7" name="data[code]" type="tel" placeholder="請輸入驗證碼">
    <div data-v-7cf0b24e="" class="lj_register_getvcode sendCode" id="sendCode" @click="send" 
:class="{ login_code_gbb: (phone.length!==11 || wait) }">{{time}}</div> </div>

這個頁面使用vue.js寫的,可是你不用先去了解vue.js再來看接下來的內容,so,繼續json

上面就是表單的兩個字段:phone和code,@click=「send」設置了「獲取驗證碼」這個div的單擊事件爲send();api

//send方法
send: function() {
                if(app.phone.length!=11 || app.phone!=parseInt(app.phone) || app.wait) return;
                $.ajax({
                    url: '/?c=api&m=mobilecode&phone='+app.phone,
                    type: 'post',
                    dataType: 'json',
                    success: function(res) {
                        if( res.code ) {
                            app.timer();
                            layer.msg('發送成功');
                        } else {
                            layer.msg('發送失敗');
                        }
                    }
                });
            },

一樣的,你可能不懂vue的語法,可是你應該可以看懂:cookie

獲取phone字段輸入的手機號(通過各類驗證以後),而且發起一個ajax請求,正如你看到的那樣,這個請求攜帶了手機號參數,session

接下來,繼續看請求的接口究竟是怎麼處理的。併發

2.api接口app

public function mobilecode() {
        $phone = $this->input->get("phone") =='' ? $this->input->post("phone") : $this->input->get("phone");
        if(!$phone){
            exit_json(0,'手機號爲空!');
        }
        if($_COOKIE['wait_time'] && $phone == $_SESSION['phone']){
            exit_json(0,'已經發送太短信了,請稍後再試!');
        }

        $randcode = rand('100000','999999');
        $_SESSION['randcode'] = $randcode;
        $_SESSION['phone'] = $phone;
        $this->load->library('mdysms');
        $res = $this->mdysms->sendSms($phone,['code'=>$randcode]);
       if($res->Code === 'OK'){
           //設置cookie
           setcookie("wait_time",1,50);
           $_SESSION['phone'] = $phone;
            //獲取方式
           exit_json(1,'短信發送成功!');
       }else{
           exit_json(0,'短信發送失敗!');
       }
    }

生成隨機驗證碼並存到服務端session中(把手機號也存到session是爲了作校驗防止同一手機號屢次註冊);

加載類文件並執行sendSms方法(自定義類文件,用於將驗證碼和手機號以及必需參數傳給阿里短信服務的SDK方法);

3.自定義類文件

這個類用於收集阿里短信服務SDK方法所需的全部參數,並調用AliSDK中的方法

require_once dirname(__FILE__).'/dysms/SignatureHelper.php';
require_once dirname(__FILE__).'/dysms/conf.inc.php';
use Aliyun\DySDKLite\SignatureHelper;
class Mdysms {
     public $conf;
     
     public function __construct()
     {
         $this->conf['accessKeyId'] = ACCESSKEYID;
         $this->conf['accessKeySecret'] = ACCESSKEYSECRET;
         $this->conf['signName'] = SignName;
         $this->conf['templateCode'] = TemplateCode;
     }

     public function sendSms($phoneNumbers, $param, $templateCode = FALSE, $signName = FALSE)
     {
        $params['TemplateParam'] = json_encode($param, JSON_UNESCAPED_UNICODE);
        $params['TemplateCode'] = $templateCode?$templateCode:$this->conf['templateCode'];
        $params['SignName'] = $signName?$signName:$this->conf['signName'];
        $params['PhoneNumbers'] = $phoneNumbers;

        $helper = new SignatureHelper();
$resp
= $helper->request( $this->conf['accessKeyId'], $this->conf['accessKeySecret'], "dysmsapi.aliyuncs.com", array_merge($params, array( "RegionId" => "cn-hangzhou", "Action" => "SendSms", "Version" => "2017-05-25" )) ); return $resp; } }

這些紅字常量是在conf.inc.php中定義的,是購買阿里短信服務時候獲取到的。那麼,這個request方法用到的參數以下:

accessKeyId-------------------購買短信通知服務獲取
accessKeySecret---------------購買短信通知服務獲取
signName----------------------購買短信通知服務獲取
templateCode------------------購買短信通知服務獲取
PhoneNumbers------------------手機號
TemplateParam-----------------在這裏就是隨機驗證碼
domain------------------------dysmsapi.aliyuncs.com
RegionId----------------------cn-hangzhou
Action------------------------SendSms
Version-----------------------2017-05-25

4.阿里雲的SDK(其實這個能夠無視)

<?php

namespace Aliyun\DySDKLite;

/**
 * 簽名助手 2017/11/19
 *
 * Class SignatureHelper
 */
class SignatureHelper {

    /**
     * 生成簽名併發起請求
     *
     * @param $accessKeyId string AccessKeyId (https://ak-console.aliyun.com/)
     * @param $accessKeySecret string AccessKeySecret
     * @param $domain string API接口所在域名
     * @param $params array API具體參數
     * @param $security boolean 使用https
     * @return bool|\stdClass 返回API接口調用結果,當發生錯誤時返回false
     */
    public function request($accessKeyId, $accessKeySecret, $domain, $params, $security=false) {
        $apiParams = array_merge(array (
            "SignatureMethod" => "HMAC-SHA1",
            "SignatureNonce" => uniqid(mt_rand(0,0xffff), true),
            "SignatureVersion" => "1.0",
            "AccessKeyId" => $accessKeyId,
            "Timestamp" => gmdate("Y-m-d\TH:i:s\Z"),
            "Format" => "JSON",
        ), $params);
        ksort($apiParams);

        $sortedQueryStringTmp = "";
        foreach ($apiParams as $key => $value) {
            $sortedQueryStringTmp .= "&" . $this->encode($key) . "=" . $this->encode($value);
        }

        $stringToSign = "GET&%2F&" . $this->encode(substr($sortedQueryStringTmp, 1));

        $sign = base64_encode(hash_hmac("sha1", $stringToSign, $accessKeySecret . "&",true));

        $signature = $this->encode($sign);

        $url = ($security ? 'https' : 'http')."://{$domain}/?Signature={$signature}{$sortedQueryStringTmp}";

        try {
            $content = $this->fetchContent($url);
            return json_decode($content);
        } catch( \Exception $e) {
            return false;
        }
    }

    private function encode($str)
    {
        $res = urlencode($str);
        $res = preg_replace("/\+/", "%20", $res);
        $res = preg_replace("/\*/", "%2A", $res);
        $res = preg_replace("/%7E/", "~", $res);
        return $res;
    }

    private function fetchContent($url) {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_TIMEOUT, 5);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            "x-sdk-client" => "php/2.0.0"
        ));

        if(substr($url, 0,5) == 'https') {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        }

        $rtn = curl_exec($ch);

        if($rtn === false) {
            trigger_error("[CURL_" . curl_errno($ch) . "]: " . curl_error($ch), E_USER_ERROR);
        }
        curl_close($ch);

        return $rtn;
    }
}
相關文章
相關標籤/搜索