日常划水:短訊驗證碼開發實例

  • 2019 年 11 月 7 日
  • 筆記

前言

我一生的文章都會放在這裡,我的博客,我希望每一行代碼,每一段文字都能幫助你。https://github.com/CrazyCodes/Blog

大家好,我是CrazyCodes,在日常開發中有沒有遇到過發送短訊驗證碼的接口需要開發?你是如何處理短訊驗證碼發送的呢?本篇我分享下短訊驗證碼發送的設計。

初學者

以聚合數據為例,初學者會醬紫做

百度

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

//初始化  $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);

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

<?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;  }

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

接口

那麼我就開始自己的表演了。首先看本篇你需要了解 – 設計模式中的策略模式 – 依賴注入 – 接口 (interface) 否則,你看的會很懵 (大佬請略過)

首先我們要寫一個interface用於規範發短訊這個動作

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

要求所有發短訊的動作都必須繼承這個接口,並且實現insert方法。

短訊類

接口設定好,我們需要設定一個父類,既發短訊的類,具體實現如下

namespace AppApiCommon;    use GuzzleHttpClient;    class Message  {      /**       * @param $mobile       * @param $tpl       * @param $code       * @param MessageUseInterface $use       * @return mixed       * @throws GuzzleHttpExceptionGuzzleException       */      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 AppApiCommonMessage;      use AppApiCommonMessageUseInterface;  use AppApiCommonRedis;    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的驗證碼類,即完成支付驗證碼的功能。

致謝

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

感謝你看到這裡,希望本篇文章可以幫到你。謝謝。