之前公司用的阿里大于短信服务,后来新注册公司再去注册阿里大于时居然说无法开启,硬是跳转到阿里短信服务去,看了一下短信服务的文档,说直接下载SDK工具包就可以直接调用,还贴了PHP的实例DEMO,心里突然一丝丝小感动,阿里居然这么人性化了,还有DEMO,试着下载然后调用,才发现都是坑~~各种报错,文档还没有说明,居然还说一切都在更新中,我也是醉了,没办法,只能调用原生HTTP接口,按照它说的签名获取方式,搞了两个多小时终于调通了,贴出来供有需要的小伙伴们使用,框架用的是THINKPHP,你们想用的试试看
<?php
namespace Org;
header("Content-type:text/html; charset=UTF-8");
/**
* 阿里云短信验证码发送类
* @author Albert Zhang
*
*/
class Sms {
public function SendSMS($phoneNum,$code){
$target = "http://dysmsapi.aliyuncs.com/?";
$phoneNum = $phoneNum;//手机号码串,以逗号隔开
$mobile_code = $code;//验证码
// 注意使用GMT时间
date_default_timezone_set("GMT");
$dateTimeFormat = 'Y-m-d\TH:i:s\Z'; // ISO8601规范
$accessKeyId = '*****';
$accessKeySecret = '****************';
$ParamString="{\"code\":\"".strval($mobile_code)."\"}";
$data = array(
// 公共参数
'SignatureMethod' => 'HMAC-SHA1',
'SignatureNonce'=> uniqid(),
'Format' => 'XML',
'AccessKeyId' => $accessKeyId,
'SignatureVersion' => '1.0',
'Timestamp' => date($dateTimeFormat),
// 业务参数
'Action' => 'SendSms',
'Version' => '2017-05-25',
'RegionId' => 'cn-hangzhou',
'TemplateCode' => 'SMS_******',
'PhoneNumbers' => $phoneNum,
'SignName' =>'******',
'TemplateParam' => $ParamString,
'OutId' => '123'
);
$data['Signature'] = $this -> getSign($data, $accessKeySecret);
// dump($data);die;
// 发送请求
$result = $this -> xml_to_array($this -> https_request($target.http_build_query($data)));
if($result["SendSmsResponse"]['Message'] == 'OK' && $result['SendSmsResponse']["Code"] == 'OK'){
return true;
}else{
return $result["SendSmsResponse"]["Message"]."和".$result["SendSmsResponse"]["Code"];
}
}
// 接口请求
public function https_request($url){
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$data = curl_exec($curl);
if (curl_errno($curl)) {return 'ERROR '.curl_error($curl);}
curl_close($curl);
return $data;
}
// xml格式转成数组格式
public function xml_to_array($xml){
$reg = "/<(\w+)[^>]*>([\\x00-\\xFF]*)<\\/\\1>/";
if(preg_match_all($reg, $xml, $matches)){
$count = count($matches[0]);
for($i = 0; $i < $count; $i++){
$subxml= $matches[2][$i];
$key = $matches[1][$i];
if(preg_match( $reg, $subxml )){
$arr[$key] = $this -> xml_to_array( $subxml );
}else{
$arr[$key] = $subxml;
}
}
}
return @$arr;
}
// 阿里云POP协议的一个奇葩规定--之前就差在这儿没加
public function percentEncode($str) {
// 使用urlencode编码后,将"+","*","%7E"做替换即满足ECS API规定的编码规范
$res = urlencode($str);
$res = preg_replace('/\+/', '%20', $res);
$res = preg_replace('/\*/', '%2A', $res);
$res = preg_replace('/%7E/', '~', $res);
return $res;
}
//获取签名算法--按照阿里云文档指示一步一步算
public function getSign($parameters, $accessKeySecret) {
// 第一步 将参数Key按字典顺序排序
ksort($parameters);
// 第二步 生成规范化请求字符串
$canonicalizedQueryString = '';
foreach($parameters as $key => $value)
{
$canonicalizedQueryString .= '&' . $this -> percentEncode($key)
. '=' . $this -> percentEncode($value);
}
// 第三步 生成用于计算签名的字符串 stringToSign
$stringToSign = 'GET&%2F&' . $this -> percentEncode(substr($canonicalizedQueryString, 1));
//echo "<br>".$stringToSign."<br>";
// 第四步 计算签名,注意accessKeySecret后面要加上字符'&'
$signature = base64_encode(hash_hmac('sha1', $stringToSign, $accessKeySecret . '&', true));
return $signature;
}
}
?>