完整代码下载地址:https://download.csdn.net/download/lyn5284767/11485236
一,前提
1,企业微信开通了会话内容存档
2,程序运行环境windows平台,VS2017,c++
3,你是企业微信的管理员
二,准备工作
1,获取RSA公私钥对,推荐用http://web.chacuo.net/netrsakeypair这个网址生成。
生成密钥位数:2048位,密钥格式:PKCS1,如下:
2,上传公钥给微信
3,设置可访问IP
三,关键代码
需要用到的第三方库: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;
}