腾讯云短信(Short Message Service,SMS)接口自定义API写法 PHPdemo
问题1. 调试时,参数必须是真实的,这样才能一次到位。
比如我,故意短信签名 填个错的(这样不扣量),,提示个 FailedOperation.SignatureIncorrectOrUnapproved
官方说明:签名格式错误或者签名未审批,签名只能由中英文、数字组成,要求2 - 12个字。如果符合签名格式规范,请核查签名是否已审批。
签名和签名 傻傻分不清。
我以为是 请求参数'Signature' 封装有问题。,结果是 Sign 短信签名内容不正确。。。。。。。。。浪费我半小时。。。。。
一般都是 Ctrl +F 快速定位SignatureIncorrectOrUnapproved,,哪知道上面有个 以下仅列出了接口业务逻辑相关的错误码,
--------------------------------------------------吐槽分割线--------------------------------------------------------------
附PHP API3.0 V1 demo
<?php
// API3.0 V1
// 仅供单个手机号发送 单个参数短信 示例.。2个参数的自己变通
// (PHP 5 >= 5.1.2, PHP 7, PECL hash >= 1.1)
date_default_timezone_set("PRC");
// 参数
$uid = '';//在 云API密钥 上申请的标识身份 SecretId 入口https://console.cloud.tencent.com/capi
$pwd =''; //在 云API密钥 上申请的标识身份 SecretKey
$Sign=''; //短信签名内容,使用 UTF-8 编码,必须填写已审核通过的签名
$TemplateParamSet = '500789'; //模板参数, 比如验证码的 数字
$mobile='';//例如:+8610011112222, 其中前面有一个+号 ,86为国家码,
$TemplateID='';// 模板 ID,必须填写已审核通过的模板 ID
$SmsSdkAppid='';//短信SdkAppid在 [短信控制台](https://console.cloud.tencent.com/smsv2) 添加应用后生成的实际SdkAppid,示例如1400006666。
$Timestamp = time();
$Nonce = mt_rand(111111,999999);
$data = array(
'Action' => 'SendSms',
'PhoneNumberSet.0'=> $mobile,
'TemplateID'=> $TemplateID,
'Sign'=> $Sign,
'TemplateParamSet.0'=> $TemplateParamSet,
'SmsSdkAppid'=> $SmsSdkAppid,
'Nonce'=> $Nonce,
'Region' => 'ap-shanghai',
'SecretId'=> $uid,
'Timestamp'=> $Timestamp,
'Version'=> '2019-07-11',
);
// -------------------
$qsign=tosign('POST',$data,$pwd);
$data['Signature']=$qsign;
$target = "https://sms.tencentcloudapi.com/";
//$result = _sendRequest($target,$data,'GET');
$result = _sendRequest($target,$data,'POST');
$result = json_decode($result,true); // json转array
var_dump($result); //查看发送状态
$req =$result['Response']['SendStatusSet'][0]['Code'];
if($req == 'Ok')
{
// 发送成功
return true;
}
function _sendRequest($url, $paramArray, $method = 'POST')
{
$ch = curl_init();
if ($method == 'POST')
{
$paramArray = is_array( $paramArray ) ? http_build_query( $paramArray, null, '&', PHP_QUERY_RFC3986) : $paramArray;
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $paramArray);
}
else
{
$url .= '?' . http_build_query( $paramArray, null, '&', PHP_QUERY_RFC3986);
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT,30);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if (false !== strpos($url, "https")) {
// 证书
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
}
$resultStr = curl_exec($ch);
$result = json_decode($resultStr, true);
if (!$result)
{
return $resultStr;
}
return $result;
}
function tosign($pa,$param,$pwd){
ksort($param);
$signStr = $pa."sms.tencentcloudapi.com/?";
foreach ($param as $key => $value ) {
$signStr = $signStr . $key . "=" . $value . "&";
}
$signStr = substr($signStr, 0, -1);
$signature = base64_encode(hash_hmac("sha1", $signStr, $pwd, true));
return $signature;
}
?>
PHP API3.0 V3
V3签名复杂点了,主要多了几个请求头。
- SendSms(发送短信)
- 输入参数:SmsSdkAppid变更为SmsSdkAppId; TemplateID变更为TemplateId; Sign变更为SignName;
- 输出参数:未变更;
可以看官方发布版本差异。
附官方demo,还是简单明了的。
注意 :
官方demo中 $curl = "curl -X POST......可以改成 PHP CURL写法,这里就不示例。大家百度下。
<?php
// 密钥参数,云API密匙查询: https://console.cloud.tencent.com/cam/capi
$secretId = "AKIDz8krbsJ5yKBZQpn74WFkmLPx3*******";
$secretKey = "Gu5t9xGARNpq86cd98joQYCN3*******";
$host = "sms.tencentcloudapi.com";
$service = "sms";
$version = "2021-01-11";
$action = "SendSms";
$region = "ap-guangzhou";
$timestamp = time();
$algorithm = "TC3-HMAC-SHA256";
// step 1: build canonical request string
$httpRequestMethod = "POST";
$canonicalUri = "/";
$canonicalQueryString = "";
$canonicalHeaders = "content-type:application/json; charset=utf-8\n"."host:".$host."\n";
$signedHeaders = "content-type;host";
// 实际调用需要更新参数,这里仅作为演示签名验证通过的例子
$payloadObj = array(
"SmsSdkAppId" => "1400006666",
"SignName" => "腾讯云",
"TemplateId" => "1234",
"TemplateParamSet" => array("12345"),
"PhoneNumberSet" => array("+8618511122266"),
"SessionContext" => "test",
);
$payload = json_encode($payloadObj);
$hashedRequestPayload = hash("SHA256", $payload);
$canonicalRequest = $httpRequestMethod."\n"
.$canonicalUri."\n"
.$canonicalQueryString."\n"
.$canonicalHeaders."\n"
.$signedHeaders."\n"
.$hashedRequestPayload;
echo $canonicalRequest.PHP_EOL;
// step 2: build string to sign
$date = gmdate("Y-m-d", $timestamp);
$credentialScope = $date."/".$service."/tc3_request";
$hashedCanonicalRequest = hash("SHA256", $canonicalRequest);
$stringToSign = $algorithm."\n"
.$timestamp."\n"
.$credentialScope."\n"
.$hashedCanonicalRequest;
echo $stringToSign.PHP_EOL;
// step 3: sign string
$secretDate = hash_hmac("SHA256", $date, "TC3".$secretKey, true);
$secretService = hash_hmac("SHA256", $service, $secretDate, true);
$secretSigning = hash_hmac("SHA256", "tc3_request", $secretService, true);
$signature = hash_hmac("SHA256", $stringToSign, $secretSigning);
echo $signature.PHP_EOL;
// step 4: build authorization
$authorization = $algorithm
." Credential=".$secretId."/".$credentialScope
.", SignedHeaders=content-type;host, Signature=".$signature;
echo $authorization.PHP_EOL;
$curl = "curl -X POST https://".$host
.' -H "Authorization: '.$authorization.'"'
.' -H "Content-Type: application/json; charset=utf-8"'
.' -H "Host: '.$host.'"'
.' -H "X-TC-Action: '.$action.'"'
.' -H "X-TC-Timestamp: '.$timestamp.'"'
.' -H "X-TC-Version: '.$version.'"'
.' -H "X-TC-Region: '.$region.'"'
." -d '".$payload."'";
echo $curl.PHP_EOL;