轉http://www.thinkphp.cn/code/4414.html
如有疑問,請留言,或者加QQ羣交流:193569204
以下可完美解決阿里雲最新版本的短信通知類發送。還有效的控制刷短信操作。
application/common 下自定義文件:Alisms.php
<?php
/**
* Dabuba System 大布吧系統
*
* ====================================================================
* @link http://www.dabuba.com/
* @copyright Copyright (c) 2016 Dabuba.com All rights reserved.
* @license http://www.apache.org/licenses/LICENSE.-2.0
* ====================================================================
*
* @package 阿里雲短信公共類
*
* @subpackage 阿里雲短信驗證碼發送類
*
* @author Tggui
*
*/
namespace app\common;
use think\Controller;
class Alisms extends Controller
{
// 保存錯誤信息
public $error;
// Access Key ID
private $accessKeyId = '';
// Access Access Key Secret
private $accessKeySecret= '';
//短信簽名 阿里雲短信服務裏面申請的那個
private $aliProduct = '';
public function __construct()
{
// 配置參數 去阿里雲獲取
$this -> accessKeyId = 'xxxx';
$this -> accessKeySecret = 'xxxx';
$this -> aliProduct = 'xxxx';
}
private function percentEncode($string) {
$string = urlencode ( $string );
$string = preg_replace ( '/\+/', '%20', $string );
$string = preg_replace ( '/\*/', '%2A', $string );
$string = preg_replace ( '/%7E/', '~', $string );
return $string;
}
/**
* 簽名
*
* @param unknown $parameters
* @param unknown $accessKeySecret
* @return string
*/
private function computeSignature($parameters, $accessKeySecret) {
ksort ( $parameters );
$canonicalizedQueryString = '';
foreach ( $parameters as $key => $value ) {
$canonicalizedQueryString .= '&' . $this->percentEncode ( $key ) . '=' . $this->percentEncode ( $value );
}
$stringToSign = 'GET&%2F&' . $this->percentencode ( substr ( $canonicalizedQueryString, 1 ) );
$signature = base64_encode ( hash_hmac ( 'sha1', $stringToSign, $accessKeySecret . '&', true ) );
return $signature;
}
/**
* 發送短信
*
* @param string $mobile 手機號碼
* @param string $type 類型
* @param int $create_id 操作人menber_id
* @return bool 返回狀態
*/
public function sendSms( $mobile, $type, $create_id = 0 )
{
$returnArr = [];
$returnArr['status'] = 0;
//判斷是否能發送
$isSend_time = model('sms') -> isSend( $mobile );
//請等待多少秒後才能重新獲取短信驗證碼
if ( !empty($isSend_time) ) {
$returnArr['time'] = $isSend_time;
return $returnArr;
}
//獲取短信模板信息
$tempCodeArr = $this -> tempCode($type);
//寫入數據庫
$addData = ['create_id' => $create_id, 'mobile' => $mobile, 'code' => $tempCodeArr['sms_code'], 'create_time' => time()];
$sms_id = model('sms') -> insertGetId($addData);
if ($sms_id) {
$params = [
'SignName' => $tempCodeArr['signName'],
'Format' => 'JSON',
'Version' => '2017-05-25',
'AccessKeyId' => $this -> accessKeyId,
'SignatureVersion' => '1.0',
'SignatureMethod' => 'HMAC-SHA1',
'SignatureNonce' => uniqid(),
'Timestamp' => gmdate( 'Y-m-d\TH:i:s\Z' ),
'Action' => 'SendSms',
'TemplateCode' => $tempCodeArr['TemplateCode'],
'PhoneNumbers' => $mobile,
'TemplateParam' => '{"code":"' . $tempCodeArr['sms_code'] . '"}'
];
// 計算簽名並把簽名結果加入請求參數
$params ['Signature'] = $this -> computeSignature ( $params, $this -> accessKeySecret );
//請求的接口
$url = 'http://dysmsapi.aliyuncs.com/?' . http_build_query ( $params );
//公共方法的curl
dbb_curl( $url, null, $result );
//將json轉換數組
$result = json_decode ( $result, true );
/**
* 返回數據的大概格式
* [
'Message' => "OK"
'RequestId' => "xxxx"
'BizId' => "xxxxxx"
'Code' => "OK"
]
*/
//以下自己寫嚴謹點 我大概給個示例
if ( $result ['Code'] == 'OK' ) {
//存在 更新數據庫
$rs_update = model('sms') -> sendUpdate($sms_id, $result['RequestId']);
if ($rs_update) {
$returnArr['status'] = 1;
}
}
//錯誤信息
// return $this->error = $this->getErrorMessage($status)
}
return $returnArr;
}
/**
* 短信模板
*/
private function tempCode( $type )
{
//短信簽名
$product = $this -> aliProduct;
//隨機4位 + 2(66/88)
$code_arr = array('66','88');
$sms_code = random('4','2356789').$code_arr[array_rand($code_arr,1)];
switch ($type) {
//模板1
case 1 :
$TemplateCode = "SMS_xxx01";
break;
//模板2
case 2 :
$TemplateCode = "SMS_xxx02";
break;
}
return [ 'sms_code' => $sms_code, 'TemplateCode' => $TemplateCode, 'signName' => $product ];
}
/**
* 獲取詳細錯誤信息
*
* @param unknown $status
*/
public function getErrorMessage( $status )
{
$message = [
'isv.InvalidDayuStatus.Malformed' => '賬戶短信開通狀態不正確',
'isv.InvalidSignName.Malformed' => '短信簽名不正確或簽名狀態不正確',
'isv.InvalidTemplateCode.MalFormed' => '短信模板Code不正確或者模板狀態不正確',
'isv.InvalidRecNum.Malformed' => '目標手機號不正確,單次發送數量不能超過100',
'isv.InvalidParamString.MalFormed' => '短信模板中變量不是json格式',
'isv.InvalidParamStringTemplate.Malformed' => '短信模板中變量與模板內容不匹配',
'isv.InvalidSendSms' => '觸發業務流控',
'isv.InvalidDayu.Malformed' => '變量不能是url,可以將變量固化在模板中'
];
if (isset ( $message [$status] )) {
return $message [$status];
}
return $status;
}
}
複製代碼
以上代碼只需要改三個參數和tempCode的模板就可以了。
相關方法:
common.php
/**
* 發送短信
*
* @param string $mobile 手機號碼
* @param string $type 類型:1-用戶註冊驗證碼、2-修改密碼驗證碼
* @param int $create_id 操作人menber_id
* @return bool 返回狀態
*/
function smsSend($mobile, $type, $create_id, $ParamArr='')
{
$aliSms = new \app\common\AliSms();
return $aliSms->sendSms($mobile, $type, $create_id, $ParamArr);
}
/**
* 通過CURL獲取遠程服務器數據
* @param string $url 遠程服務器URL
* @param json $data POST數據
* @param mixed $output 返回值
* @param array $header 傳遞頭部信息
* @return mixed
*/
function dbb_curl($curr_url, $data = null, &$output, $header = null)
{
$ch = curl_init();
if (!$header) {
$header = ["Accept-Charset: utf-8"];
}
curl_setopt($ch, CURLOPT_URL, $curr_url);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// curl_setopt($ch, CURLOPT_HEADER, true); //獲取頭部信息
if (1 == strpos("$".$curr_url, "https://")) {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
}
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
if (!empty($data)){
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
$output = curl_exec($ch);
$errorno = curl_errno($ch);
curl_close($ch);
if ($errorno) {
return $errorno;
}else{
return 0;
}
}
複製代碼
sms的model類相關方法:
/**
* 判斷是否能發送
*
* @param array $data 創建人ID、手機號碼、驗證碼
* @return int 下次獲取等待時間
*/
public function isSend($mobile)
{
$last_create_time = $this->where("mobile='$mobile'")->order('id DESC')->value('create_time');
if (empty($last_create_time)) {
return 0;
}
$curr_time = time();
$interval_time = getConfig('interval_time')?getConfig('interval_time'):60;//間隔時間
$surplus = $curr_time - $last_create_time;
if ( $surplus > $interval_time ) {
return 0;
} else {
return intval(($interval_time - $surplus));
}
}
/**
* 發送結果更新
*
* @param array $data 創建人ID、手機號碼、驗證碼
* @return int 下次獲取等待時間
*/
public function sendUpdate($id, $requestid)
{
$updata_arr = array('status'=>1, 'requestid'=>$requestid, 'update_time'=>time());
return $this->where("id=$id")->update($updata_arr);
}
//============== 以下兩個方法本文沒使用到,可參考 ==============
/**
* 驗證碼校驗
*
* @param string $mobile 手機號碼
* @param string $code 驗證碼
* @return array 校驗結果
*/
public function check_code($mobile, $code)
{
$return_arr = array('status'=>0,'msg'=>'');
$rs = $this->field('id,is_use,create_time')->where("status=1 AND mobile=$mobile AND code=$code")->order('id DESC')->find();
if ($rs) {
if ($rs['is_use']==1) {
$return_arr['msg'] = '該驗證碼已經被使用';
}
$invalidTime = getConfig('code_invalid_time') ? getConfig('code_invalid_time') : 600;
if ( (time() - $rs['create_time']) > $invalidTime ) {
$return_arr['msg'] = '該驗證碼已經失效';
}
if (empty($return_arr['msg'])) {
$return_arr['status'] = 1;
$return_arr['msg'] = '驗證通過';
$return_arr['id'] = $rs['id'];
}
} else {
$return_arr['msg'] = '驗證碼錯誤';
}
return $return_arr;
}
/**
* 標記驗證碼已經被使用
*
* @param int $id 驗證碼ID
* @return bool
*/
public function code_use($id)
{
$data = array('is_use'=>1, 'update_time'=>time());
return $this->where('id',$id)->update($data);
}
複製代碼
表結構:
-- ----------------------------
-- Table structure for dbb_sms
-- ----------------------------
DROP TABLE IF EXISTS `dbb_sms`;
CREATE TABLE `dbb_sms` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '短信ID',
`status` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '發送狀態:0-發送中、1-發送成功',
`mobile` char(15) NOT NULL DEFAULT '' COMMENT '手機號碼',
`code` char(6) NOT NULL DEFAULT '' COMMENT '驗證碼',
`requestid` char(40) NOT NULL DEFAULT '' COMMENT '返回請求id',
`is_use` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '使用狀態:0-未使用、1-已經使用',
`create_id` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '創建人ID',
`create_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '創建時間',
`update_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '更新時間',
PRIMARY KEY (`id`),
KEY `mobile` (`id`,`code`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=632 DEFAULT CHARSET=utf8 COMMENT='短信發送記錄表';
複製代碼
在任意一個控制器直接使用:
//根據方法來填參數即可 sendSms( $mobile, $type, $create_id )
$returnArr = smsSend('手機號', 1, 8);
halt($returnArr);
複製代碼
其他流程看自己需求來寫。