平常划水:短信驗證碼開發實例

clipboard.png

前言

我一輩子的文章都會放在這裏,個人博客,我但願每一行代碼,每一段文字都能幫助你。 https://github.com/CrazyCodes...

你們好,我是CrazyCodes,在平常開發中有沒有遇到過發送短信驗證碼的接口須要開發?你是如何處理短信驗證碼發送的呢?本篇我分享下短信驗證碼發送的設計。php

初學者

以聚合數據爲例,初學者會醬紫作html

百度git

clipboard.png

找到一串既熟悉又陌生的代碼 (咋整也記不住的代碼)github

//初始化
$curl = curl_init();
//設置抓取的url
curl_setopt($curl, CURLOPT_URL, 'http://www.baidu.com');
//設置頭文件的信息做爲數據流輸出
curl_setopt($curl, CURLOPT_HEADER, 1);
//設置獲取的信息以文件流的形式返回,而不是直接輸出。
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
//設置post方式提交
curl_setopt($curl, CURLOPT_POST, 1);
//設置post數據
$post_data = array(
    "username" => "coder",
    "password" => "12345"
    );
curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
//執行命令
$data = curl_exec($curl);
//關閉URL請求
curl_close($curl);
//顯示得到的數據
print_r($data);

官方也給出了一段維護性略差的代碼redis

<?php
/*
    ***聚合數據(JUHE.CN)短信API服務接口PHP請求示例源碼
    ***DATE:2015-05-25
*/
header('content-type:text/html;charset=utf-8');
  
$sendUrl = 'http://v.juhe.cn/sms/send'; //短信接口的URL
  
$smsConf = array(
    'key'   => '*****************', //您申請的APPKEY
    'mobile'    => '1891351****', //接受短信的用戶手機號碼
    'tpl_id'    => '111', //您申請的短信模板ID,根據實際狀況修改
    'tpl_value' =>'#code#=1234&#company#=聚合數據' //您設置的模板變量,根據實際狀況修改
);
 
$content = juhecurl($sendUrl,$smsConf,1); //請求發送短信
 
if($content){
    $result = json_decode($content,true);
    $error_code = $result['error_code'];
    if($error_code == 0){
        //狀態爲0,說明短信發送成功
        echo "短信發送成功,短信ID:".$result['result']['sid'];
    }else{
        //狀態非0,說明失敗
        $msg = $result['reason'];
        echo "短信發送失敗(".$error_code."):".$msg;
    }
}else{
    //返回內容異常,如下可根據業務邏輯自行修改
    echo "請求發送短信失敗";
}
 
/**
 * 請求接口返回內容
 * @param  string $url [請求的URL地址]
 * @param  string $params [請求的參數]
 * @param  int $ipost [是否採用POST形式]
 * @return  string
 */
function juhecurl($url,$params=false,$ispost=0){
    $httpInfo = array();
    $ch = curl_init();
    curl_setopt( $ch, CURLOPT_HTTP_VERSION , CURL_HTTP_VERSION_1_1 );
    curl_setopt( $ch, CURLOPT_USERAGENT , 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.172 Safari/537.22' );
    curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT , 30 );
    curl_setopt( $ch, CURLOPT_TIMEOUT , 30);
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER , true );
    if( $ispost )
    {
        curl_setopt( $ch , CURLOPT_POST , true );
        curl_setopt( $ch , CURLOPT_POSTFIELDS , $params );
        curl_setopt( $ch , CURLOPT_URL , $url );
    }
    else
    {
        if($params){
            curl_setopt( $ch , CURLOPT_URL , $url.'?'.$params );
        }else{
            curl_setopt( $ch , CURLOPT_URL , $url);
        }
    }
    $response = curl_exec( $ch );
    if ($response === FALSE) {
        //echo "cURL Error: " . curl_error($ch);
        return false;
    }
    $httpCode = curl_getinfo( $ch , CURLINFO_HTTP_CODE );
    $httpInfo = array_merge( $httpInfo , curl_getinfo( $ch ) );
    curl_close( $ch );
    return $response;
}

這樣看,「也不是很差,就是想再改改,至於改什麼,不知道,就是想再改改」json

接口

那麼我就開始本身的表演了。首先看本篇你須要瞭解設計模式

  • 設計模式中的策略模式
  • 依賴注入
  • 接口 (interface)

不然,你看的會很懵 (大佬請略過)curl

首先咱們要寫一個interface用於規範發短信這個動做post

namespace App\Api\Common;

interface MessageUseInterface
{
    public function insert($mobile, $code);
}

要求全部發短信的動做都必須繼承這個接口,而且實現insert方法。編碼

短信類

接口設定好,咱們須要設定一個父類,既發短信的類,具體實現以下

namespace App\Api\Common;

use GuzzleHttp\Client;

class Message
{
    /**
     * @param $mobile
     * @param $tpl
     * @param $code
     * @param MessageUseInterface $use
     * @return mixed
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function send($mobile, $tpl, $code, MessageUseInterface $use)
    {
        $client = new Client();
        $response = $client->request('POST', 'http://v.juhe.cn/sms/send', [
            'form_params' => [
                'mobile' => $mobile,
                'tpl_id' => $tpl,
                'tpl_value' => sprintf('#code#=%s', $code),
                'key' => 'xxxxxxxxxxxx'
            ]
        ]);

        $use->insert($mobile, $code);

        return json_decode($response->getBody(), true);
    }
}

這個類建立了send方法,參數分別爲

  • mobile 既接收短信驗證碼的手機號碼
  • tpl_id 聚合數據提供的模板編碼
  • code 發送的驗證碼
  • MessageUseInterface 上面建立的接口interface

具體實現則是使用GuzzleHttp去實現POST請求,並按聚合數據規定發送驗證碼。

$use->insert($mobile, $code);

則是調用經過MessageUseInterface傳進來的實體類

實體類

以後咱們建立實體類,這裏以手機號+驗證碼登陸爲例

namespace App\Api\Common\Message;


use App\Api\Common\MessageUseInterface;
use App\Api\Common\Redis;

class Login implements MessageUseInterface
{
    public function insert($mobile, $code)
    {
        $redis = Redis::init();
        $key = sprintf('login_code:%s', $mobile);
        $redis->setex($key, 600, $code);
    }
}

Login繼承接口MessageUseInterface 並實現insert方法。這裏redis設定的規範爲

module:手機號 -> value(須要發送的驗證碼)

至此,咱們的短信驗證碼發送的例子就結束了。

使用

咱們能夠下列方式調用,或者使用Laravel的服務提供者

(new Message())->send($tel, 141345, mt_rand(100000, 999999), new Register());

這樣既解決了亂七八糟的各類驗證碼,還提升了代碼的可維護性,若是老闆有新的需求,例如,支付驗證碼什麼的,你只須要新建一個Pay的驗證碼類,即完成支付驗證碼的功能。

致謝

上述只是一個簡單的例子,實體類並未作更多的延伸,請自行發揮創造力。

感謝你看到這裏,但願本篇文章能夠幫到你。謝謝。

相關文章
相關標籤/搜索