华为云c++短信


#include "stdafx.h"
#include "rapidjson/rapidjson.h"
#include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include "crypto.h"
#include <locale>
#include <codecvt>
#include <iomanip>


void replaceall(std::string& str,const std::string& old_value,const std::string& new_value)
{
    while(true){     
        std::string::size_type  pos(0);     
        if((pos = str.find(old_value)) != std::string::npos)     
            str.replace(pos,old_value.length(),new_value);     
        else
            break;     
    }     
}

std::string getUUID() {
#ifdef WIN32
    char buffer[GUID_LEN] = { 0 };
    GUID guid;

    if (CoCreateGuid(&guid))
    {
        fprintf(stderr, "create guid error\n");
        return "";
    }
    _snprintf(buffer, sizeof(buffer),
        "%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 base64Encode(const unsigned char* Data,int DataByte)
{
    //编码表
    const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    //返回值
    std::string strEncode;
    unsigned char Tmp[4]={0};
    int LineLength=0;
    for(int i=0;i<(int)(DataByte / 3);i++)
    {
        Tmp[1] = *Data++;
        Tmp[2] = *Data++;
        Tmp[3] = *Data++;
        strEncode+= EncodeTable[Tmp[1] >> 2];
        strEncode+= EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F];
        strEncode+= EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F];
        strEncode+= EncodeTable[Tmp[3] & 0x3F];
        if(LineLength+=4,LineLength==76) {LineLength=0;}
    }
    //对剩余数据进行编码
    int Mod=DataByte % 3;
    if(Mod==1)
    {
        Tmp[1] = *Data++;
        strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
        strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4)];
        strEncode+= "==";
    }
    else if(Mod==2)
    {
        Tmp[1] = *Data++;
        Tmp[2] = *Data++;
        strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
        strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)];
        strEncode+= EncodeTable[((Tmp[2] & 0x0F) << 2)];
        strEncode+= "=";
    }

    return strEncode;
}

std::string sha256(const std::string& str)
{
    BYTE hash[SHA256_BLOCK_SIZE];
    _SHA256_CTX sha;
    sha256_init(&sha);
    sha256_update(&sha, (unsigned char*)str.c_str(), str.size());
    sha256_final(&sha, hash);
    std::stringstream ss;
    for(int i = 0; i < SHA256_BLOCK_SIZE; i++)
        ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash[i];
    return ss.str();
}

std::string buildWSSEHeader(const std::string& appKey, const std::string& appSecret)
{
    time_t _t = time(NULL);
    char bufTime[64] = { 0 };
    struct tm _tt;
    localtime_s(&_tt, &_t);
    sprintf(bufTime, "%04d-%02d-%02dT%02d:%02d:%02dZ",_tt.tm_year+1900,_tt.tm_mon+1,_tt.tm_mday,_tt.tm_hour,_tt.tm_min,_tt.tm_sec);

    std::string now(bufTime);
    std::string nonce = getUUID();
    replaceall(nonce,"-", "");
    std::string sum_data = StringHelper::AnsiiToUtf8(nonce + now + appSecret);
    std::string hexdigest = sha256(sum_data);
    replaceall(hexdigest,"-", "");
    std::string base64 = base64Encode((unsigned char*)hexdigest.c_str(), hexdigest.size());

    char szHeadParams[1024];
    _snprintf(szHeadParams, CountArray(szHeadParams), "X-WSSE: UsernameToken Username=\"%s\",PasswordDigest=\"%s\",Nonce=\"%s\",Created=\"%s\"",
        appKey.c_str(), base64.c_str(), nonce.c_str(), now.c_str());
    std::string strParams = StringHelper::AnsiiToUtf8(szHeadParams);
    return strParams;
}

int main(void)
{
    CURL *curl;
    CURLcode res;

    std::wstring wstrParams = TEXT("");
    std::string strParams = "";

    TCHAR szpostParams[1024] = {0}; 
    //主要配置在下面有5个,都可以从华为云上获取,不过都要审核
    std::string appKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
    std::string appSecret= "YYYYYYYYYYYYYYYYYYYYYYYYYYYY";
    TCHAR templateId[64] = TEXT("AAAAAAAAAAAAAAAAAA");
    TCHAR sender[64] = TEXT("1256856");
    TCHAR signature[64] = TEXT("模板名字");

    TCHAR szMobile[64] = TEXT("13500000000");
    TCHAR szVerifyCode[64] = TEXT("1233456"); //注意这里的位数一定要和模板里面的位数是一样的,不然会报错
    
    SYSTEMTIME systime;
    std::string strResponseUTF8="";
    std::string strResponse="";
        
    _sntprintf(szpostParams, CountArray(szpostParams), TEXT("from=%s&to=%s&templateId=%s&templateParas=[\"%s\"]&statusCallback=%s&signature=%s"),
        sender, szMobile, templateId, szVerifyCode, TEXT(""),signature);
    //字符集转换
    static std::wstring_convert<std::codecvt_utf8<wchar_t>> wsc;
    //strParams = StringHelper::UnicodeToUtf8(szpostParams);
    strParams = wsc.to_bytes(szpostParams) ;
    curl = curl_easy_init();
    if(curl) 
    {
        struct  curl_slist* header_  = curl_slist_append(NULL,"Content-Type: application/x-www-form-urlencoded");
        curl_slist_append(header_, "Authorization:WSSE realm=\"SDP\",profile=\"UsernameToken\",type=\"Appkey\"");
        curl_slist_append(header_, buildWSSEHeader(appKey, appSecret).c_str());

        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
        curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
        curl_easy_setopt(curl, CURLOPT_URL, "https://rtcsms.cn-north-1.myhuaweicloud.com:10743/sms/batchSendSms/v1");
        curl_easy_setopt(curl, CURLOPT_NOBODY, 0L);    
        curl_easy_setopt(curl, CURLOPT_NOSIGNAL,1L);
        curl_easy_setopt(curl, CURLOPT_POST, 1);  
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, strParams.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &CSMSManager::cbFuncWrite);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, (VOID*)&strResponseUTF8);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
        curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
        curl_easy_setopt(curl, CURLOPT_MAXREDIRS,10);
        curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 2000); 
        curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT_MS, 1000);
        curl_easy_setopt(curl, CURLOPT_DNS_CACHE_TIMEOUT, 600);

        //执行连接
        res = curl_easy_perform(curl);
        /* Check for errors */
        if(res != CURLE_OK)
        {
            fprintf(stderr, "PostVerifyCodeRequest() failed: %s\n", curl_easy_strerror(res));
        }

        //释放由curl_slist_append构建的curl_slist
        //curl_slist_free_all(headers);

        /* always cleanup */
        curl_easy_cleanup(curl);

        //字符集转换
        std::wstring wstrResponse = wsc.from_bytes(strResponseUTF8);
        typedef std::codecvt_byname<wchar_t, char, std::mbstate_t> cb;
        static std::wstring_convert<cb> strCnv(new cb("Chinese"));
        strResponse = strCnv.to_bytes(wstrResponse);

        Document docResponse;
        docResponse.Parse(strResponse.c_str());

        TCHAR szMessage[256]=TEXT("");
        if (docResponse.HasMember("code")==true)
        {
            Value& valError=docResponse["code"];
            Value& valErrorMsg=docResponse["description"];

            //错误信息
            int ErrorCode = -1;
            std::string strError = "";
            std::string strErrorMsg = "";
            if(valError.IsString()) strError = valError.GetString();
            if(valErrorMsg.IsString()) strErrorMsg = valErrorMsg.GetString();

            //结果判断
            if(strError != std::string("000000")) 
            {
                //输出错误
                std::string strStatus;
                if (docResponse.HasMember("result")==true)
                {
                    Value& valData=docResponse["result"][0];
                    if (valData.HasMember("status")==true) 
                    {
                        Value& valStatus=valData["status"];
                        if(valStatus.IsString()) strStatus = valStatus.GetString();
                    }
                }
                _sntprintf(szMessage,CountArray(szMessage),TEXT("短信发送失败 User %d message=%s code=%s status=%s"),
                    pUserVerifyCodeInfo->dwUserID, strCnv.from_bytes(strErrorMsg).c_str(),strCnv.from_bytes(strError).c_str(),strCnv.from_bytes(strStatus).c_str());
                
                Log(LogLevel_Error, szMessage);
                return 1;
            }
            else
            {
                Log(TraceLevel_Info, TEXT("短信发送成功【%s】:【%s】"), pUserVerifyCodeInfo->szMobile, pUserVerifyCodeInfo->szVerifyCode);
            }
        }
        else
        {
            return 0;
        }

    }
    
    return true;
}

 

//主要代码在上面,不保证能编译通过,但是关键代码都有,有些接口是从网上找的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值