c++ 实现阿里云短信服务接口不使用第三方库
发布日期:2021-05-10 05:47:03 浏览次数:30 分类:原创文章

本文共 6897 字,大约阅读时间需要 22 分钟。

加密类文件在里,本章未用到三方库。参考里用了三方库,有需要的也可以参考。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());

 有问题请留言。。。

上一篇:邮件发送失败原因分析
下一篇:c++ 内存泄漏崩溃精髓

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2025年03月30日 22时39分17秒