转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);
复制代码
其他流程看自己需求来写。