C++阿里云短信发送(SendSms)-mongoose方式

1、阿里云短信服务

该服务基于阿里云短信服务平台OpenAPI门户-短信服务-短信发送-发送短信(SendSms)进行开发,已验证,可发送,包含了所有的校验、签名算法。

SendSms_短信服务_API文档-阿里云OpenAPI开发者门户 (aliyun.com)

2、aliyunmsg_service.h(头文件)

#ifndef GATEWAYCONFIGEMBED_ALIYUNMSG_SERVICE_H
#define GATEWAYCONFIGEMBED_ALIYUNMSG_SERVICE_H
#include "../../web/common/common.h"
#include <openssl/hmac.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include "../../web/httpserver/mongoose.h"
#include <ctime>
#include <string>
#include <iostream>

string percentEncode(const std::string& str);
string sha256Hex(const std::string& str);
string hmacSha256(const std::string& key, const std::string& data);
string generateRandomUUID();
string buildCanonicalRequest(const std::string& method, const std::string& uri, const std::string& queryString,
                                  const std::string& canonicalHeaders, const std::string& signedHeaders, const std::string& hashedBody);
string generateTimestamp();

void sendSms(const std::string& accessKeyId, const std::string& accessSecret, const std::string& phoneNumbers,
             const std::string& signName, const std::string& templateCode, const std::string& templateParam, long sendLogId);
#endif //GATEWAYCONFIGEMBED_ALIYUNMSG_SERVICE_H

3、aliyunmsg_service.cpp(源文件)

#include "aliyunmsg_service.h"
#include <openssl/hmac.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <ctime>
#include <iostream>
#include <iomanip>

std::string percentEncode(const std::string& str) {
	std::ostringstream encoded;
	for (const auto& c : str) {
		if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
			encoded << c;
		} else if (c == ' ') {
			encoded << "%20";
		} else if (c == '*') {
			encoded << "%2A";
		} else {
			encoded << '%' << std::uppercase << std::setw(2) << std::setfill('0') << std::hex << (int)(unsigned char)c;
		}
	}

	std::string result = encoded.str();
	std::string::size_type pos = 0;
	while ((pos = result.find("%7E", pos)) != std::string::npos) {
		result.replace(pos, 3, "~");
	}

	return result;
}

std::string hmacSha256(const std::string& key, const std::string& data) {
	unsigned char* digest;
	unsigned int digest_len;
	digest = HMAC(EVP_sha256(), key.c_str(), key.length(),
	              (const unsigned char*)data.c_str(), data.length(), NULL, &digest_len);

	std::ostringstream ss;
	ss << std::hex << std::setfill('0');
	for (unsigned int i = 0; i < digest_len; ++i) {
		ss << std::setw(2) << (int)digest[i];
	}

	return ss.str();
}

std::string sha256Hex(const std::string& str) {
	unsigned char hash[SHA256_DIGEST_LENGTH];
	SHA256(reinterpret_cast<const unsigned char*>(str.c_str()), str.length(), hash);

	std::ostringstream ss;
	ss << std::hex << std::setfill('0');
	for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
		ss << std::setw(2) << static_cast<int>(hash[i]);
	}

	return ss.str();
}

std::string generateRandomUUID() {
	std::srand(std::time(0));
	std::string uuid;
	for (int i = 0; i < 16; ++i) {
		uuid += "0123456789abcdef"[std::rand() % 16];
	}
	return uuid;
}

std::string buildCanonicalRequest(const std::string& method, const std::string& uri, const std::string& queryString,
                                  const std::string& canonicalHeaders, const std::string& signedHeaders, const std::string& hashedBody) {
	return method + "\n" + uri + "\n" + queryString + "\n" + canonicalHeaders + "\n" + signedHeaders + "\n" + hashedBody;
}

string generateTimestamp() {
	std::time_t rawTime;
	std::tm* timeInfo;
	std::ostringstream timestampStream;

	std::time(&rawTime);
	timeInfo = std::gmtime(&rawTime);

	timestampStream << std::put_time(timeInfo, "%Y-%m-%dT%H:%M:%SZ");
	return timestampStream.str();
}

// Callback function to handle response from server
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data, void *fn_data) {
	if (ev == MG_EV_HTTP_MSG) {
		struct mg_http_message *hm = (struct mg_http_message *) ev_data;
		std::cout << "Response: " << std::string(hm->message.ptr, hm->message.len) << std::endl;
		*(bool *) fn_data = true;  // Mark response as received
	}
}

// Function to send SMS
void sendSms(const std::string& accessKeyId, const std::string& accessSecret, const std::string& phoneNumbers,
             const std::string& signName, const std::string& templateCode, const std::string& templateParam, long sendLogId) {

	std::string url = "https://dysmsapi.aliyuncs.com/";
	std::string host = "dysmsapi.aliyuncs.com";
	std::string version = "2017-05-25";

	// Step 1: Build query parameters
	std::map<std::string, std::string> queryParams = {
			{"PhoneNumbers", phoneNumbers},
			{"SignName", signName},
			{"TemplateCode", templateCode},
			{"TemplateParam", templateParam},
			{"OutId", std::to_string(sendLogId)}
	};

	std::string queryString;
	for (const auto& param : queryParams) {
		if (!queryString.empty()) queryString += "&";
		queryString += percentEncode(param.first) + "=" + percentEncode(param.second);
	}

	std::string timestamp = generateTimestamp();

	// Step 2.1: Build headers
	std::map<std::string, std::string> headers = {
			{"host", host},
			{"x-acs-version", version},
			{"x-acs-action", "SendSms"},
			{"x-acs-date", timestamp},
			{"x-acs-signature-nonce", generateRandomUUID()}
	};

	// Step 2.2: Build canonical headers
	std::string canonicalHeaders;
	std::string signedHeaders;
	for (const auto& header : headers) {
		canonicalHeaders += header.first + ":" + header.second + "\n";
		signedHeaders += header.first + ";";
	}
	if (!signedHeaders.empty()) {
		signedHeaders.pop_back(); // Remove trailing semicolon
	}

	// Step 3: Build body and hashed body
	std::string requestBody;  // Empty for this case
	std::string hashedBody = sha256Hex(requestBody);

	// Step 4: Build canonical request
	std::string canonicalRequest = buildCanonicalRequest("POST", "/", queryString, canonicalHeaders, signedHeaders, hashedBody);
	std::string hashedCanonicalRequest = sha256Hex(canonicalRequest);

	// Use HMAC-SHA256 to sign the hashed canonical request
	std::string stringToSign = "ACS3-HMAC-SHA256\n" + hashedCanonicalRequest;
	std::string signature = hmacSha256(accessSecret, stringToSign);

	headers["Authorization"] = "ACS3-HMAC-SHA256 Credential=" + accessKeyId + ", SignedHeaders=" + signedHeaders + ", Signature=" + signature;

	// Step 5: Send request using Mongoose
	struct mg_mgr mgr;
	struct mg_connection *nc;
	bool done = false;

	mg_mgr_init(&mgr);
	nc = mg_http_connect(&mgr, url.c_str(), ev_handler, &done);

	if (nc != NULL) {
		// Add headers
		mg_printf(nc, "POST /?%s HTTP/1.1\r\n", queryString.c_str());
		for (const auto& header : headers) {
			mg_printf(nc, "%s: %s\r\n", header.first.c_str(), header.second.c_str());
		}
		mg_printf(nc, "Content-Length: %d\r\n\r\n%s", (int)requestBody.length(), requestBody.c_str());

		// Wait for the response
		while (!done) {
			mg_mgr_poll(&mgr, 1000);
		}
	} else {
		std::cerr << "Failed to connect to " << url << std::endl;
	}

	mg_mgr_free(&mgr);
}

4、服务调用

std::string accessKeyId = "xxxxx";
std::string accessSecret = "xxxxx";
std::string phoneNumbers = reinterpret_cast<const char *>(PhoneNumber);
std::string signName = "xxxxx";
std::string templateCode = "xxxxx";
std::string templateParam ="xxxxx";
int OutId=xxx;

sendSms(accessKeyId, accessSecret, phoneNumbers, signName, templateCode,templateParam, OutId);
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值