加密类文件在参考里,本章未用到三方库。参考里用了三方库,有需要的也可以参考。http/https协议皆可。
header为最终参数串,带入报文即可;postman测试通过。ASCII2UTF_8函数相关调用到参考里查找。
std::string getCurentTime()
{
time_t _t = time(NULL);
char bufTime[64] = { 0 };
struct tm _tt;
//localtime_s(&_tt, &_t);//系统本地时间
gmtime_s(&_tt ,&_t);//格林时间
_tt.tm_year += 1900;
_tt.tm_mon += 1;
sprintf_s(bufTime, 64,"%04d-%02d-%02dT%02d:%02d:%02dZ"
, _tt.tm_year, _tt.tm_mon, _tt.tm_mday, _tt.tm_hour, _tt.tm_min, _tt.tm_sec);
return std::string(bufTime);
}
unsigned char ToHex(unsigned char x)
{
return x > 9 ? x + 55 : x + 48;
}
std::string getUUID() {
#ifdef WIN32
char buffer[BYTE_64] = { 0 };
GUID guid;
if (CoCreateGuid(&guid))
{
fprintf(stderr, "create guid error\n");
return "";
}
_snprintf_s(buffer, BYTE_64,
"%08X%04X%04x%02X%02X%02X%02X%02X%02X%02X%02X",
guid.Data1, guid.Data2, guid.Data3,
guid.Data4[0], guid.Data4[1], guid.Data4[2],
guid.Data4[3], guid.Data4[4], guid.Data4[5],
guid.Data4[6], guid.Data4[7]);
printf("guid: %s\n", buffer);
return std::string(buffer);
#else
uuid_t uuid;
uuid_generate(uuid);
char buf[64] = { 0 };
uuid_unparse(uuid, buf);
return std::string(buf);
#endif
};
std::string specialUrlEncode(const std::string& str)
{
std::string strTemp = "";
size_t length = str.length();
for (size_t i = 0; i < length; i++)
{
if (isalnum((unsigned char)str[i]) ||
(str[i] == '-') ||
(str[i] == '_') ||
(str[i] == '.') ||
(str[i] == '~'))
strTemp += str[i];
else if (str[i] == ' ')
strTemp += "+";
else
{
strTemp += '%';
strTemp += ToHex((unsigned char)str[i] >> 4);
strTemp += ToHex((unsigned char)str[i] % 16);
}
}
return strTemp;
}
//ascii to Utf8
std::string ASCII2UTF_8(std::string& strAsciiCode)
{
#ifdef WIN32
std::string strRet("");
//
std::wstring wstr = Acsi2WideByte(strAsciiCode);
//
strRet = Unicode2Utf8(wstr);
return strRet;
#endif
#ifdef __linux__
char lpszBuf[256] = { 0 };
k2u(const_cast<char*>(strAsciiCode.c_str()), strAsciiCode.size(), lpszBuf, 256);
return std::string(lpszBuf);
// char lpszBuf[256]={0};
// a2u(const_cast<char*>(strAsciiCode.c_str()),strAsciiCode.size(),lpszBuf,256);
// return std::string(lpszBuf);
// return std::string(strAsciiCode);
#endif
};
struct HttpMsgArg
{
HttpMsgArg()
: addr_("dysmsapi.aliyuncs.com")
, AccessKeyId(ACCESS_KEY_ID)
, AccessKeySecret(ACCESS_KEY_SECRET)
, Timestamp("2018-04-13T10:10:10Z")
, Format("JSON")
, SignatureMethod("HMAC-SHA1")
, SignatureVersion("1.0")
, SignatureNonce("1")
, Signature("")
//
, Action("SendSms")
, Version("2017-05-25")
, RegionId("cn-hangzhou")
, PhoneNumbers("17090833800")
, SignName("阿里云短信测试专用")//阿里云短信测试专用
, TemplateCode("SMS_105240742")//SMS_105240742
, TemplateParam("")
//, SmsUpExtendCode("")
//, OutId("123")
{
};
//
std::string addr_; // web 服务器地址
//
std::string AccessKeyId; //
std::string AccessKeySecret; //
std::string Timestamp; //格式为:yyyy-MM-dd’T’HH:mm:ss’Z’;时区为:GMT
std::string Format; //没传默认为JSON,可选填值:XML
std::string SignatureMethod; //建议固定值:HMAC-SHA1
std::string SignatureVersion; //建议固定值:1.0
std::string SignatureNonce; //用于请求的防重放攻击,每次请求唯一,JAVA语言建议用:java.util.UUID.randomUUID()生成即可
std::string Signature; //最终生成的签名结果值
std::string Action; //API的命名,固定值,如发送短信API的值为:SendSms
std::string Version; //API的版本,固定值,如短信API的值为:2017-05-25
std::string RegionId; //API支持的RegionID,如短信API的值为:cn-hangzhou
/*
*短信接收号码,支持以逗号分隔的形式进行批量调用,
*批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,
*验证码类型的短信推荐使用单条调用的方式
*/
std::string PhoneNumbers;
std::string SignName; //短信签名
std::string TemplateCode; //短信模板ID
/*
短信模板变量替换JSON串,友情提示:如果JSON中需要带换行符,请参照标准的JSON协议。
*/
std::string TemplateParam;
//std::string SmsUpExtendCode; //上行短信扩展码,无特殊需要此字段的用户请忽略此字段
//std::string OutId; //外部流水扩展字段
};
HttpMsgArg myArgHttp;
//签名内容缓存
std::string sortQueryStringTmp = "";
sortQueryStringTmp.append("GET&").append(specialUrlEncode("/"));
//签名内容项,参数key的字符串排序
myArgHttp.TemplateParam = "{'customer':'test'}";
std::map<std::string, std::string> coder;
//acl::url_coder coder;//注意中文字段UTF-8表述
coder.insert(pair<std::string, std::string>("AccessKeyId", myArgHttp.AccessKeyId.c_str()));
coder.insert(pair<std::string, std::string>("Action", myArgHttp.Action.c_str()));
coder.insert(pair<std::string, std::string>("Format", myArgHttp.Format.c_str()));
//coder.insert(pair<std::string, std::string>("OutId", myArgHttp.OutId.c_str()));
coder.insert(pair<std::string, std::string>("PhoneNumbers", myArgHttp.PhoneNumbers.c_str()));
coder.insert(pair<std::string, std::string>("RegionId", myArgHttp.RegionId.c_str()));
coder.insert(pair<std::string, std::string>("SignName", ASCII2UTF_8(myArgHttp.SignName).c_str()));
coder.insert(pair<std::string, std::string>("SignatureMethod", myArgHttp.SignatureMethod.c_str()));
coder.insert(pair<std::string, std::string>("SignatureNonce", getUUID().c_str()));
coder.insert(pair<std::string, std::string>("SignatureVersion", myArgHttp.SignatureVersion.c_str()));
coder.insert(pair<std::string, std::string>("TemplateCode", myArgHttp.TemplateCode.c_str()));
coder.insert(pair<std::string, std::string>("TemplateParam", ASCII2UTF_8(myArgHttp.TemplateParam).c_str()));
coder.insert(pair<std::string, std::string>("Timestamp", getCurentTime().c_str()));
coder.insert(pair<std::string, std::string>("Version", myArgHttp.Version.c_str()));
//
int index = 1;
std::string urlcodeadd;
std::map<std::string, std::string>::iterator mapitem = coder.begin();
for (; mapitem != coder.end(); mapitem++, ++index)
{
urlcodeadd.append(mapitem->first).append("=").append(specialUrlEncode(mapitem->second));
if (index != coder.size())
urlcodeadd.append("&");
}
//printf("排序参数集:\r\n%s\r\n", urlcodeadd.c_str());
sortQueryStringTmp.append("&").append(specialUrlEncode(urlcodeadd));
//printf("待签名的请求字符串specialUrlEncode:\r\n%s\r\n", sortQueryStringTmp.c_str());
//生成签名,调用签名算法函数,注意阿里的AccessKeySecret+&才是真正的AccessKeySecret
int hmaclen = 20;
char hmac_buf[32] = { 0 };
std::string KeySecret_ali = (myArgHttp.AccessKeySecret + "&");
hmac_sha((char*)(ASCII2UTF_8(KeySecret_ali)).c_str(), (int)KeySecret_ali.length()
, (char*)ASCII2UTF_8(sortQueryStringTmp).c_str(), (int)sortQueryStringTmp.length(), hmac_buf, hmaclen);
std::string hmac = std::string(hmac_buf, hmaclen);
printf("密钥+HmacSHA1算法:\r\n%s\r\n", hmac.c_str());
//printf("%s\n", get_slip_time_milliseconds());
//base64算法调用,前面签名算法结果作为输入参数,得到最终签名
unsigned char hmacbase64[29] = {0};
//base64_encode((const unsigned char*)hmac.c_str(), static_cast<int>(hmac.length()), hmacbase64);
hmac = Base64::Encode((const unsigned char*)hmac.c_str(), static_cast<int>(hmac.length()));
printf("HmacSHA1算法+Base64:\r\n%s\r\n", hmacbase64);
//将签名加入请求字段
std::string header="?";
header += urlcodeadd;
header += "&Signature=";
header += specialUrlEncode((char*)hmacbase64);
printf("header:\r\n%s\r\n", header.c_str());
有问题请留言。。。