一般咱们实名注册用户的时候,都会要求输入手机号,而后获取手机验证码,而后填到页面,像下面这样: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; } }