企业微信-拉取企业微信聊天记录

完整代码下载地址:https://download.csdn.net/download/lyn5284767/11485236

一,前提

1,企业微信开通了会话内容存档

企业微信-拉取企业微信聊天记录_第1张图片

2,程序运行环境windows平台,VS2017,c++

3,你是企业微信的管理员

二,准备工作

1,获取RSA公私钥对,推荐用http://web.chacuo.net/netrsakeypair这个网址生成。

生成密钥位数:2048位,密钥格式:PKCS1,如下:

企业微信-拉取企业微信聊天记录_第2张图片

2,上传公钥给微信

企业微信-拉取企业微信聊天记录_第3张图片

企业微信-拉取企业微信聊天记录_第4张图片

3,设置可访问IP

企业微信-拉取企业微信聊天记录_第5张图片

三,关键代码

需要用到的第三方库:1,企业微信SDK;2,Openssl;3,jsoncpp;

// 私钥解密,cipherText--待解密字符串;    priKey--私钥
std::string rsa_pri_decrypt(const std::string &cipherText, const std::string &priKey)
{
    std::string strRet;
    RSA *rsa = RSA_new();
    BIO *keybio;
    keybio = BIO_new_mem_buf((void *)priKey.c_str(), -1);

    // 读取私钥成RSA
    rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);

    // 分配大小
    int len = RSA_size(rsa);
    char *decryptedText = (char *)malloc(len + 1);
    memset(decryptedText, 0, len + 1);

    // 解密函数  
    int ret = RSA_private_decrypt(cipherText.length(), (const unsigned char*)cipherText.c_str(), (unsigned char*)decryptedText, rsa, RSA_PKCS1_PADDING);
    unsigned long error = ERR_peek_last_error();
    if (ret >= 0)
        strRet = std::string(decryptedText, ret);

    // 释放内存  
    free(decryptedText);
    BIO_free_all(keybio);
    RSA_free(rsa);

    return strRet;
}

RSA * createRSA(unsigned char* key, int publickey)
{
    RSA *rsa = NULL;
    BIO *keybio;
    keybio = BIO_new_mem_buf(key, -1);
    if (keybio == NULL)
    {
        printf("Failed to create key BIO");
        return 0;
    }
    if (publickey)
    {
        rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);
    }
    else
    {
        rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);
    }
    if (rsa == NULL)
    {
        printf("Failed to create RSA");
    }
    return rsa;
}

int private_decrypt(unsigned char* enc_data, int data_len, unsigned char* key, unsigned char*decrypted)
{
    RSA * rsa = createRSA(key, 0);

    int result = RSA_private_decrypt(data_len, enc_data, decrypted, rsa, RSA_PKCS1_PADDING);

    return result;
}

string StringToUtf(string strValue)
{
    int nwLen = MultiByteToWideChar(CP_UTF8, 0, strValue.c_str(), -1, NULL, 0);
    wchar_t * pwBuf = new wchar_t[nwLen + 1];//加上末尾'\0'
    memset(pwBuf, 0, nwLen * 2 + 2);
    MultiByteToWideChar(CP_UTF8, 0, strValue.c_str(), strValue.length(), pwBuf, nwLen);
    int nLen = WideCharToMultiByte(CP_ACP, 0, pwBuf, -1, NULL, NULL, NULL, NULL);
    char * pBuf = new char[nLen + 1];
    memset(pBuf, 0, nLen + 1);
    WideCharToMultiByte(CP_ACP, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);
    std::string retStr = pBuf;
    delete[]pBuf;
    delete[]pwBuf;
    return retStr;
}

nt main(int argc, char* argv[]) {
    // 初始化SDK
    auto sdk = NewSdk();
    int ret = Init(sdk, "ww7a7bad72f50751ad", "DVXpWlp1MSkOjhvbfApIF43OQ5OHReuC3IQNGynJc7I"); 
    if (ret != 0) {
           printf("init sdk err ret:%d\n", ret);
    }
    // 获取数据
    std::ifstream readFile;
    readFile.open("data.txt");   //将文件流对象与文件连接起来 
    assert(readFile.is_open());   //若失败,则输出错误消息,并终止程序运行 
    std::string s; 
    getline(readFile, s);
    readFile.close();
    unsigned long long seq;

    std::string dt = getTime();
    if (s.empty())
    {
        seq = 0;
    }
    else
    {
        seq = std::stoll(s);
    }
    Slice_t sli;
    ret = GetChatData(sdk, seq, 1000, nullptr, nullptr, 100, &sli);
    if (ret != 0) {
        printf("GetChatData err ret:%d\n", ret);
        return -1;
    }
    // 解析字符串
    std::string strJsonContent = sli.buf;
    Json::Reader reader;
    Json::Value root;
    if (reader.parse(strJsonContent.c_str(), root)) {
        if (root["errcode"].asInt()== 0) {
            if (root["chatdata"].isArray()) {
                int nArraySize = root["chatdata"].size();
                for (int i = 0; i < nArraySize; i++)
                {
                    unsigned char decrypted[4098] = {};
                    int seq= root["chatdata"][i]["seq"].asInt();
                    std::string msgid = root["chatdata"][i]["msgid"].asString();
                    int publickey_ver = root["chatdata"][i]["publickey_ver"].asInt();
                    std::string encrypt_random_key = root["chatdata"][i]["encrypt_random_key"].asString();
                    std::string encrypt_chat_msg = root["chatdata"][i]["encrypt_chat_msg"].asString();
                    std::string base_decode = decode_base64(encrypt_random_key,false);
                    int ret = private_decrypt((unsigned char *)base_decode.c_str(),256, priKey, decrypted);
                    // RSA解密成功
                    if (ret > 0)
                    {
                        ret = DecryptData((const char*)(char*)decrypted, encrypt_chat_msg.c_str(), &sli);
                        // 微信SDK解密成功
                        if (ret == 0) {
                            std::string chardata = GetContentFromSlice(&sli);
                            Json::Reader datareader;
                            Json::Value dataroot;
                            // 解析json数据
                            if (datareader.parse(chardata.c_str(), dataroot)) {
                                std::string msgid = dataroot["msgid"].asString();
                                std::string from = dataroot["from"].asString();
                                double msgtime = dataroot["msgtime"].asDouble();
                                std::string msgtype = dataroot["msgtype"].asString();
                                if (msgtype == "text")// 文本类型
                                {
                                    Json::Value  &text = dataroot["text"];
                                    std::string content = text["content"].asString();
                                    content = StringToUtf(content);
                                }
                                else if(msgtype == "image") //图片
                                {
                                    Json::Value  &image = dataroot["image"];
                                    int filesize = image["filesize"].asInt();
                                    std::string sdkfileid = image["sdkfileid"].asString();
                                    std::string index = "";
                                    while (true) {
                                        MediaData_t* media = NewMediaData();
                                        int mediaret = GetMediaData(sdk, index.c_str(), sdkfileid.c_str(), nullptr, nullptr, 50, media);
                                        if (mediaret != 0) {
                                            printf("GetMediaData err ret:%d\n", ret);
                                            FreeMediaData(media);
                                            return -1;
                                        }
                                        GetData(media);
                                        GetOutIndexBuf(media);
                                        IsMediaDataFinish(media);
                                        char file[200];
                                        snprintf(file, sizeof(file), "%s%d.jpg", "upload/", seq);
                                        FILE *fp = fopen(file, "ab+");
                                        fwrite(GetData(media), GetDataLen(media), 1, fp);
                                        fclose(fp);
                                        if (IsMediaDataFinish(media) == 1)
                                        {
                                            FreeMediaData(media);
                                            break;
                                        }
                                        else {
                                            // assign index value if not finish
                                            index.assign(GetOutIndexBuf(media));
                                            // need free media 
                                            FreeMediaData(media);
                                        }
                                    }
                                }
                            }
                        }
                    }
                    seq= root["chatdata"][i]["seq"].asInt();
                    std::fstream file("data.txt", std::ios::out);
                    file << seq << std::endl;
                    file.close();
                }
            }
        }
        else
        {
            printf("PraseChatData err ret:%s\n", root["errcode"].asString());
            return -1;
        }
    }
    DestroySdk(sdk);
    return 0;
}

你可能感兴趣的:(其他)