c++ 实现阿里云短信服务接口不使用第三方库

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

阿里短信签名算法

 有问题请留言。。。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bug狂人

让我们和小姐姐唠嗑可以肢愣起来

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值