一般咱們實名註冊用戶的時候,都會要求輸入手機號,而後獲取手機驗證碼,而後填到頁面,像下面這樣: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; } }