最新版本的阿里雲短信,不需要sdk,帶防刷機制【轉】

http://www.thinkphp.cn/code/4414.html

如有疑問,請留言,或者加QQ羣交流:193569204

以下可完美解決阿里雲最新版本的短信通知類發送。還有效的控制刷短信操作。
application/common 下自定義文件:Alisms.php

  1. <?php
  2. /**
  3.  * Dabuba System 大布吧系統
  4.  *
  5.  * ====================================================================
  6.  * @link      http://www.dabuba.com/
  7.  * @copyright Copyright (c) 2016 Dabuba.com All rights reserved.
  8.  * @license   http://www.apache.org/licenses/LICENSE.-2.0
  9.  * ====================================================================
  10.  *
  11.  * @package     阿里雲短信公共類
  12.  *
  13.  * @subpackage  阿里雲短信驗證碼發送類
  14.  *
  15.  * @author      Tggui
  16.  *
  17.  */
  18. namespace app\common;
  19. use think\Controller;
  20.  
  21. class Alisms extends Controller
  22. {
  23.     // 保存錯誤信息
  24.     public $error;
  25.     // Access Key ID
  26.     private $accessKeyId    = '';
  27.     // Access Access Key Secret 
  28.     private $accessKeySecret= '';
  29.     //短信簽名  阿里雲短信服務裏面申請的那個 
  30.     private $aliProduct     = '';
  31.     
  32.     public function __construct() 
  33.     {
  34.         // 配置參數 去阿里雲獲取
  35.         $this -> accessKeyId      = 'xxxx';
  36.         $this -> accessKeySecret  = 'xxxx';
  37.         $this -> aliProduct       = 'xxxx';
  38.     }
  39.     
  40.     private function percentEncode($string) {
  41.         $string = urlencode ( $string );
  42.         $string = preg_replace ( '/\+/', '%20', $string );
  43.         $string = preg_replace ( '/\*/', '%2A', $string );
  44.         $string = preg_replace ( '/%7E/', '~', $string );
  45.         return $string;
  46.     }
  47.     
  48.     /**
  49.      * 簽名
  50.      *
  51.      * @param unknown $parameters            
  52.      * @param unknown $accessKeySecret            
  53.      * @return string
  54.      */
  55.     private function computeSignature($parameters, $accessKeySecret) {
  56.         ksort ( $parameters );
  57.         $canonicalizedQueryString = '';
  58.         foreach ( $parameters as $key => $value ) {
  59.             $canonicalizedQueryString .= '&' . $this->percentEncode ( $key ) . '=' . $this->percentEncode ( $value );
  60.         }
  61.         $stringToSign = 'GET&%2F&' . $this->percentencode ( substr ( $canonicalizedQueryString, 1 ) );
  62.         $signature = base64_encode ( hash_hmac ( 'sha1', $stringToSign, $accessKeySecret . '&', true ) );
  63.         return $signature;
  64.     }
  65.     
  66.     /**
  67.      * 發送短信
  68.      *
  69.      * @param string $mobile 手機號碼
  70.      * @param string $type 類型
  71.      * @param int $create_id 操作人menber_id
  72.      * @return bool 返回狀態
  73.      */
  74.     public function sendSms( $mobile, $type, $create_id = 0 ) 
  75.     {
  76.         $returnArr      = [];
  77.         $returnArr['status']    = 0;
  78.         //判斷是否能發送
  79.         $isSend_time    = model('sms') -> isSend( $mobile );
  80.         //請等待多少秒後才能重新獲取短信驗證碼
  81.         if ( !empty($isSend_time) ) {
  82.             $returnArr['time']  = $isSend_time;
  83.             return $returnArr;
  84.         }
  85.         //獲取短信模板信息
  86.         $tempCodeArr    = $this -> tempCode($type);
  87.         //寫入數據庫
  88.         $addData        = ['create_id' => $create_id, 'mobile' => $mobile, 'code' => $tempCodeArr['sms_code'], 'create_time' => time()];
  89.         $sms_id         = model('sms') -> insertGetId($addData);
  90.         if ($sms_id) {
  91.             $params     = [
  92.                 'SignName'          => $tempCodeArr['signName'],
  93.                 'Format'            => 'JSON',
  94.                 'Version'           => '2017-05-25',
  95.                 'AccessKeyId'       => $this -> accessKeyId,
  96.                 'SignatureVersion'  => '1.0',
  97.                 'SignatureMethod'   => 'HMAC-SHA1',
  98.                 'SignatureNonce'    => uniqid(),
  99.                 'Timestamp'         => gmdate( 'Y-m-d\TH:i:s\Z' ),
  100.                 'Action'            => 'SendSms',
  101.                 'TemplateCode'      => $tempCodeArr['TemplateCode'],
  102.                 'PhoneNumbers'      => $mobile,
  103.                 'TemplateParam'     => '{"code":"' . $tempCodeArr['sms_code'] . '"}'
  104.             ];
  105.             // 計算簽名並把簽名結果加入請求參數
  106.             $params ['Signature']   = $this -> computeSignature ( $params, $this -> accessKeySecret );
  107.             //請求的接口
  108.             $url    = 'http://dysmsapi.aliyuncs.com/?' . http_build_query ( $params );
  109.             //公共方法的curl
  110.             dbb_curl( $url, null, $result );
  111.             //將json轉換數組
  112.             $result = json_decode ( $result, true );
  113.             /**
  114.              * 返回數據的大概格式
  115.              *  [
  116.                   'Message'     => "OK"
  117.                   'RequestId'   => "xxxx"
  118.                   'BizId'       => "xxxxxx"
  119.                   'Code'        => "OK"
  120.                 ]
  121.             */
  122.             //以下自己寫嚴謹點 我大概給個示例
  123.             if ( $result ['Code'] == 'OK' ) {
  124.                 //存在 更新數據庫
  125.                 $rs_update  = model('sms') -> sendUpdate($sms_id, $result['RequestId']);
  126.                 if ($rs_update) {
  127.                     $returnArr['status'] = 1;
  128.                 }
  129.             }
  130.             //錯誤信息
  131. //          return $this->error = $this->getErrorMessage($status)
  132.         }
  133.         return $returnArr;
  134.     }
  135.     
  136.     /**
  137.      * 短信模板
  138.      */
  139.     private function tempCode( $type ) 
  140.     {
  141.         //短信簽名
  142.         $product  = $this -> aliProduct;
  143.         //隨機4位 + 2(66/88)
  144.         $code_arr = array('66','88');
  145.         $sms_code = random('4','2356789').$code_arr[array_rand($code_arr,1)];
  146.         switch ($type) {
  147.             //模板1
  148.             case 1 : 
  149.                 $TemplateCode = "SMS_xxx01";
  150.                 break;
  151.             //模板2
  152.             case 2 : 
  153.                 $TemplateCode = "SMS_xxx02";
  154.                 break;
  155.         }
  156.         return [ 'sms_code' => $sms_code, 'TemplateCode' => $TemplateCode, 'signName' => $product ];
  157.     }
  158.  
  159.     /**
  160.      * 獲取詳細錯誤信息
  161.      *
  162.      * @param unknown $status            
  163.      */
  164.     public function getErrorMessage( $status )
  165.     {
  166.         $message    = [
  167.             'isv.InvalidDayuStatus.Malformed'           => '賬戶短信開通狀態不正確',
  168.             'isv.InvalidSignName.Malformed'             => '短信簽名不正確或簽名狀態不正確',
  169.             'isv.InvalidTemplateCode.MalFormed'         => '短信模板Code不正確或者模板狀態不正確',
  170.             'isv.InvalidRecNum.Malformed'               => '目標手機號不正確,單次發送數量不能超過100',
  171.             'isv.InvalidParamString.MalFormed'          => '短信模板中變量不是json格式',
  172.             'isv.InvalidParamStringTemplate.Malformed'  => '短信模板中變量與模板內容不匹配',
  173.             'isv.InvalidSendSms'                        => '觸發業務流控',
  174.             'isv.InvalidDayu.Malformed'                 => '變量不能是url,可以將變量固化在模板中' 
  175.         ];
  176.         if (isset ( $message [$status] )) {
  177.             return $message [$status];
  178.         }
  179.         return $status;
  180.     }
  181. }

複製代碼

 

以上代碼只需要改三個參數和tempCode的模板就可以了。

相關方法:

common.php

  1. /**
  2.  * 發送短信
  3.  *
  4.  * @param string $mobile 手機號碼
  5.  * @param string $type 類型:1-用戶註冊驗證碼、2-修改密碼驗證碼
  6.  * @param int $create_id 操作人menber_id
  7.  * @return bool 返回狀態
  8.  */
  9. function smsSend($mobile, $type, $create_id, $ParamArr='')
  10. {
  11.     $aliSms = new \app\common\AliSms();
  12.     return $aliSms->sendSms($mobile, $type, $create_id, $ParamArr);
  13. }
  14.  
  15. /**
  16.  * 通過CURL獲取遠程服務器數據
  17.  * @param string $url 遠程服務器URL
  18.  * @param json $data POST數據
  19.  * @param mixed $output 返回值
  20.  * @param array $header 傳遞頭部信息
  21.  * @return mixed
  22.  */
  23. function dbb_curl($curr_url, $data = null, &$output, $header = null)
  24. {
  25.     $ch = curl_init();
  26.     if (!$header) {
  27.         $header = ["Accept-Charset: utf-8"];
  28.     }
  29.     curl_setopt($ch, CURLOPT_URL, $curr_url);
  30.     curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
  31.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  32. //     curl_setopt($ch, CURLOPT_HEADER, true); //獲取頭部信息
  33.     if (1 == strpos("$".$curr_url, "https://")) {
  34.         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  35.         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  36.     }
  37.     curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
  38.     if (!empty($data)){
  39.         curl_setopt($ch, CURLOPT_POST, 1);
  40.         curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  41.     }
  42.     $output     = curl_exec($ch);
  43.     $errorno    = curl_errno($ch);
  44.     curl_close($ch);
  45.     if ($errorno) {
  46.         return $errorno;
  47.     }else{
  48.         return 0;
  49.     }
  50. }

複製代碼

 

sms的model類相關方法:

  1.     /**
  2.      * 判斷是否能發送
  3.      *
  4.      * @param array $data 創建人ID、手機號碼、驗證碼
  5.      * @return int 下次獲取等待時間
  6.      */
  7.     public function isSend($mobile)
  8.     {
  9.         $last_create_time = $this->where("mobile='$mobile'")->order('id DESC')->value('create_time');
  10.         if (empty($last_create_time)) {
  11.             return 0;
  12.         }
  13.         $curr_time = time();
  14.         $interval_time = getConfig('interval_time')?getConfig('interval_time'):60;//間隔時間
  15.         $surplus = $curr_time - $last_create_time;
  16.         if ( $surplus > $interval_time ) {
  17.             return 0;
  18.         } else {
  19.             return intval(($interval_time - $surplus));
  20.         }
  21.     }
  22.  
  23.     /**
  24.      * 發送結果更新
  25.      *
  26.      * @param array $data 創建人ID、手機號碼、驗證碼
  27.      * @return int 下次獲取等待時間
  28.      */
  29.     public function sendUpdate($id, $requestid)
  30.     {
  31.         $updata_arr = array('status'=>1, 'requestid'=>$requestid, 'update_time'=>time());
  32.         return $this->where("id=$id")->update($updata_arr);
  33.     }
  34.  
  35.     //============== 以下兩個方法本文沒使用到,可參考 ==============
  36.     /**
  37.      * 驗證碼校驗
  38.      *
  39.      * @param string $mobile 手機號碼
  40.      * @param string $code 驗證碼
  41.      * @return array 校驗結果
  42.      */
  43.     public function check_code($mobile, $code)
  44.     {
  45.         $return_arr = array('status'=>0,'msg'=>'');
  46.         $rs = $this->field('id,is_use,create_time')->where("status=1 AND mobile=$mobile AND code=$code")->order('id DESC')->find();
  47.         if ($rs) {
  48.             if ($rs['is_use']==1) {
  49.                 $return_arr['msg'] = '該驗證碼已經被使用';
  50.             }
  51.             $invalidTime    =    getConfig('code_invalid_time') ? getConfig('code_invalid_time') : 600;
  52.             if ( (time() - $rs['create_time']) > $invalidTime ) {
  53.                 $return_arr['msg'] = '該驗證碼已經失效';
  54.             }
  55.             if (empty($return_arr['msg'])) {
  56.                 $return_arr['status'] = 1;
  57.                 $return_arr['msg'] = '驗證通過';
  58.                 $return_arr['id'] = $rs['id'];
  59.             }
  60.         } else {
  61.             $return_arr['msg'] = '驗證碼錯誤';
  62.         }
  63.         return $return_arr;
  64.     }
  65.     
  66.     /**
  67.      * 標記驗證碼已經被使用
  68.      *
  69.      * @param int $id 驗證碼ID
  70.      * @return bool
  71.      */
  72.     public function code_use($id)
  73.     {
  74.         $data = array('is_use'=>1, 'update_time'=>time());
  75.         return $this->where('id',$id)->update($data);
  76.     }

複製代碼

 

表結構:

  1. -- ----------------------------
  2. -- Table structure for dbb_sms
  3. -- ----------------------------
  4. DROP TABLE IF EXISTS `dbb_sms`;
  5. CREATE TABLE `dbb_sms` (
  6.   `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '短信ID',
  7.   `status` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '發送狀態:0-發送中、1-發送成功',
  8.   `mobile` char(15) NOT NULL DEFAULT '' COMMENT '手機號碼',
  9.   `code` char(6) NOT NULL DEFAULT '' COMMENT '驗證碼',
  10.   `requestid` char(40) NOT NULL DEFAULT '' COMMENT '返回請求id',
  11.   `is_use` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '使用狀態:0-未使用、1-已經使用',
  12.   `create_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '創建人ID',
  13.   `create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '創建時間',
  14.   `update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新時間',
  15.   PRIMARY KEY (`id`),
  16.   KEY `mobile` (`id`,`code`) USING BTREE
  17. ) ENGINE=MyISAM AUTO_INCREMENT=632 DEFAULT CHARSET=utf8 COMMENT='短信發送記錄表';

複製代碼

 

在任意一個控制器直接使用:

  1. //根據方法來填參數即可 sendSms( $mobile, $type, $create_id ) 
  2. $returnArr = smsSend('手機號', 1, 8);
  3. halt($returnArr);

複製代碼

 

其他流程看自己需求來寫。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章