export.cpp
extern "C"
{
#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include "WeWorkFinanceSdk_C.h"
WeWorkFinanceSdk_t* sdk = NewSdk();
__declspec(dllexport) void free_p(void* p)
{
if (p) {
free(p);
p = 0;
}
}
__declspec(dllexport) int init_sdk(char* corpid, char* key)
{
int ret = Init(sdk, corpid, key);
if (ret != 0)
{
DestroySdk(sdk);
printf("Init SDK failed.");
}
return ret;
}
__declspec(dllexport) char* get_chat_data(int seq, int limit, char* proxy, char* passwd, int timeout, int* datalen)
{
char* retData = 0;
*datalen = 0;
Slice_t* chatDatas = NewSlice();
int ret = GetChatData(sdk, seq, limit, proxy, passwd, timeout, chatDatas);
if (ret != 0) {
FreeSlice(chatDatas);
printf("Get data failed, return code: %d.", ret);
return retData;
}
retData = (char*)malloc(chatDatas->len * sizeof(char));
memcpy(retData, chatDatas->buf, chatDatas->len);
*datalen = chatDatas->len;
FreeSlice(chatDatas);
return retData;
}
__declspec(dllexport) char* pull_media_file(char* fileid, char* proxy, char* passwd, int timeout, int datalen)
{
char index[512*1024] = { 0 };
char* file_buff = (char*)malloc(datalen * sizeof(char));
char* fbidx = file_buff;
int total_len = 0;
int isfinish = 0;
while (isfinish == 0) {
//每次使用GetMediaData拉取存档前需要调用NewMediaData获取一个mediaData,在使用完mediaData中数据后,还需要调用FreeMediaData释放。
printf("index:%s\n", index);
MediaData_t* mediaData = NewMediaData();
int ret = GetMediaData(sdk, index, fileid, proxy, passwd, timeout, mediaData);
if (ret != 0) {
//单个分片拉取失败建议重试拉取该分片,避免从头开始拉取。
FreeMediaData(mediaData);
printf("GetMediaData err ret:%d\n", ret);
free_p(file_buff);
return file_buff;
}
memcpy(fbidx, mediaData->data, mediaData->data_len);
fbidx += mediaData->data_len;
total_len += mediaData->data_len;
//获取下次拉取需要使用的indexbuf
memset(index, 0, 512*1024);
memcpy(index, mediaData->outindexbuf, mediaData->out_len);
isfinish = mediaData->is_finish;
FreeMediaData(mediaData);
}
return file_buff;
}
__declspec(dllexport) char* decrypt_data(char* encrypt_key, char* encrypt_chat_msg, int* datalen)
{
char* retData = 0;
*datalen = 0;
Slice_t* msgs = NewSlice();
int ret = DecryptData(encrypt_key, encrypt_chat_msg, msgs);
retData = (char*)malloc(msgs->len * sizeof(char));
memcpy(retData, msgs->buf, msgs->len);
*datalen = msgs->len;
FreeSlice(msgs);
return retData;
}
__declspec(dllexport) void destory_sdk()
{
DestroySdk(sdk);
}
}
使用vs编译此cpp文件为dll
libpywechat.cpp
extern "C"{
#include "WeWorkFinanceSdk_C.h"
#include <dlfcn.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <cstring>
typedef WeWorkFinanceSdk_t* newsdk_t();
typedef int Init_t(WeWorkFinanceSdk_t*, const char*, const char*);
typedef void DestroySdk_t(WeWorkFinanceSdk_t*);
typedef int GetChatData_t(WeWorkFinanceSdk_t*, unsigned long long, unsigned int, const char*, const char*, int, Slice_t*);
typedef Slice_t* NewSlice_t();
typedef void FreeSlice_t(Slice_t*);
typedef int GetMediaData_t(WeWorkFinanceSdk_t*, const char*, const char*, const char*, const char*, int, MediaData_t*);
typedef int DecryptData_t(const char*, const char*, Slice_t*);
typedef MediaData_t* NewMediaData_t();
typedef void FreeMediaData_t(MediaData_t*);
void* so_handle = 0;
WeWorkFinanceSdk_t* sdk = 0;
void free_p(void* p)
{
if (p) {
free(p);
p = 0;
}
}
int init_sdk(char* corpid, char* key)
{
so_handle = dlopen("./libWeWorkFinanceSdk_C.so", RTLD_LAZY);
if (!so_handle) {
printf("load sdk so fail:%s\n", dlerror());
return -1;
}
newsdk_t* newsdk_fn = (newsdk_t*)dlsym(so_handle, "NewSdk");
sdk = newsdk_fn();
Init_t* init_fn = (Init_t*)dlsym(so_handle, "Init");
DestroySdk_t* destroysdk_fn = (DestroySdk_t*)dlsym(so_handle, "DestroySdk");
int ret = init_fn(sdk, corpid, key);
if (ret != 0) {
//sdk¿¿¿¿¿¿
destroysdk_fn(sdk);
printf("init sdk err ret:%d\n", ret);
return -1;
}
return 0;
}
char* get_chat_data(int seq, int limit, char* proxy, char* passwd, int timeout, int* datalen)
{
char* retData = 0;
*datalen = 0;
NewSlice_t* newslice_fn = (NewSlice_t*)dlsym(so_handle, "NewSlice");
FreeSlice_t* freeslice_fn = (FreeSlice_t*)dlsym(so_handle, "FreeSlice");
//¿¿¿¿GetChatData¿¿¿¿¿¿¿¿¿NewSlice¿¿¿¿chatDatas¿¿¿¿¿chatDatas¿¿¿¿¿¿¿¿¿¿FreeSlice¿¿¿
//Slice_t* chatDatas = newslice_fn();
GetChatData_t* getchatdata_fn = (GetChatData_t*)dlsym(so_handle, "GetChatData");
Slice_t* chatDatas = newslice_fn();
int ret =getchatdata_fn(sdk, seq, limit, proxy, passwd, timeout, chatDatas);
if (ret != 0) {
freeslice_fn(chatDatas);
printf("Get data failed, return code: %d.", ret);
return retData;
}
retData = (char*)malloc(chatDatas->len * sizeof(char));
memcpy(retData, chatDatas->buf, chatDatas->len);
*datalen = chatDatas->len;
freeslice_fn(chatDatas);
return retData;
}
char* pull_media_file(char* fileid, char* proxy, char* passwd, int timeout, int datalen)
{
char index[512 * 1024] = { 0 };
char* file_buff = (char*)malloc(datalen * sizeof(char));
char* fbidx = file_buff;
int total_len = 0;
int isfinish = 0;
GetMediaData_t* getmediadata_fn = (GetMediaData_t*)dlsym(so_handle, "GetMediaData");
NewMediaData_t* newmediadata_fn = (NewMediaData_t*)dlsym(so_handle, "NewMediaData");
FreeMediaData_t* freemediadata_fn = (FreeMediaData_t*)dlsym(so_handle, "FreeMediaData");
while (isfinish == 0) {
//¿¿¿¿GetMediaData¿¿¿¿¿¿¿¿¿NewMediaData¿¿¿¿mediaData¿¿¿¿¿mediaData¿¿¿¿¿¿¿¿¿¿FreeMediaData¿¿¿
printf("index:%s\n", index);
MediaData_t* mediaData = newmediadata_fn();
int ret = getmediadata_fn(sdk, index, fileid, proxy, passwd, timeout, mediaData);
if (ret != 0) {
//¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿¿
freemediadata_fn(mediaData);
printf("GetMediaData err ret:%d\n", ret);
free_p(file_buff);
return file_buff;
}
memcpy(fbidx, mediaData->data, mediaData->data_len);
fbidx += mediaData->data_len;
total_len += mediaData->data_len;
//¿¿¿¿¿¿¿¿¿¿¿indexbuf
memset(index, 0, 512 * 1024);
memcpy(index, mediaData->outindexbuf, mediaData->out_len);
isfinish = mediaData->is_finish;
freemediadata_fn(mediaData);
}
return file_buff;
}
char* decrypt_data(char* encrypt_key, char* encrypt_chat_msg, int* datalen)
{
char* retData = 0;
*datalen = 0;
NewSlice_t* newslice_fn = (NewSlice_t*)dlsym(so_handle, "NewSlice");
FreeSlice_t* freeslice_fn = (FreeSlice_t*)dlsym(so_handle, "FreeSlice");
DecryptData_t* decryptdata_fn = (DecryptData_t*)dlsym(so_handle, "DecryptData");
Slice_t* msgs = newslice_fn();
int ret = decryptdata_fn(encrypt_key, encrypt_chat_msg, msgs);
retData = (char*)malloc(msgs->len * sizeof(char));
memcpy(retData, msgs->buf, msgs->len);
*datalen = msgs->len;
freeslice_fn(msgs);
return retData;
}
void destory_sdk()
{
DestroySdk_t* destroysdk_fn = (DestroySdk_t*)dlsym(so_handle, "DestroySdk");
destroysdk_fn(sdk);
}
}
gcc libpywechat.cpp -fPIC -shared -ldl -o libpywechat.so
注释用extern “C” 消除函数开头的_Z (name mangling, name decoratio, 名字修饰)
import base64
from ctypes import *
import json
import sys
from Crypto import Random
from Crypto.Cipher import PKCS1_v1_5 as Cipher_pkcs1_v1_5
from Crypto.PublicKey import RSA
pysdk = cdll.LoadLibrary('./pywechat.dll')
# void free_p(void* p)
# int init_sdk(char* corpid, char* key)
# char* get_chat_data(int seq, int limit, char* proxy, char* passwd, int timeout, int* datalen)
# char* pull_media_file(char* fileid, char* proxy, char* passwd, int timeout, int datalen)
# char* decrypt_data(char* encrypt_key, char* encrypt_chat_msg, int* datalen)
# void destory_sdk()
pysdk.get_chat_data.restype = c_int64
pysdk.pull_media_file.restype = c_int64
pysdk.decrypt_data.restype = c_int64
corpid = b'企业号'
key = b'会话存档密钥'
seq = c_int(0)
limit = c_int(100)
proxy = b''
passwd = b''
timeout = c_int(10)
corpid_buff = create_string_buffer(corpid, len(corpid)+1)
key_buff = create_string_buffer(key, len(key)+1)
proxy_buff = create_string_buffer(proxy, len(proxy)+1)
passwd_buff = create_string_buffer(passwd, len(passwd)+1)
ret_len = c_int(0)
# 初始化sdk
init_status = pysdk.init_sdk(corpid_buff, key_buff)
print("Init sdk ret_code.", init_status)
if init_status != 0:
sys.exit(init_status)
# 获取数据
resp = pysdk.get_chat_data(seq, limit, proxy_buff, passwd_buff, timeout, byref(ret_len))
# ret_data_demo = {
# "errcode": 0,
# "errmsg": "ok",
# "chatdata": [{
# "seq": 1,
# "msgid": "10717693993641340428_1641865486744",
# "publickey_ver": 1,
# "encrypt_random_key": "随机加密码",
# "encrypt_chat_msg": "加密消息内容"
# }, {
# "seq": 2,
# "msgid": "13596831180950397347_1641871046891",
# "publickey_ver": 1,
# "encrypt_random_key": "随机加密码",
# "encrypt_chat_msg": "加密消息内容"
# }]
# }
ret_data = json.loads(string_at(resp, ret_len.value))
# 释放内存空间
# pysdk.free_p(resp)
#
datails_data_demo = {"msgid": "13596831180950397347_1641871046891", "action": "send", "from": "发送方",
"tolist": ["接收方"], "roomid": "", "msgtime": 1641871046713, "msgtype": "file",
"file": {"md5sum": "C328154E2E2D4879443CAF464F1F9E0D", "filename": "Visual Assist X 10.9.2210.rar",
"fileext": "rar", "filesize": 35341717,
"sdkfileid": "文件序号"}}
random_generator = Random.new().read
assert ret_data.get("errcode") == 0
for chat_data in ret_data.get("chatdata"):
if 'external' in chat_data.get("msgid"):
continue
print(chat_data.get("msgid"))
# TODO: 判断 publickey_ver
with open("私钥文件") as f:
key = f.read()
rsakey = RSA.importKey(key)
cipher = Cipher_pkcs1_v1_5.new(rsakey)
encrypt_key = cipher.decrypt(base64.b64decode(chat_data.get("encrypt_random_key")), None)
encrypt_msg = bytes(chat_data.get("encrypt_chat_msg"), encoding='utf-8')
encrypt_key_buff = create_string_buffer(encrypt_key, len(encrypt_key)+1)
encrypt_msg_buff = create_string_buffer(encrypt_msg, len(encrypt_msg)+1)
ret_len = c_int(0)
byte_details = pysdk.decrypt_data(encrypt_key_buff, encrypt_msg_buff, byref(ret_len))
byte_details = string_at(byte_details, ret_len.value)
data_details = json.loads(byte_details)
print(data_details)
if data_details.get("msgtype") is None:
print("invalid type error")
continue
elif data_details.get("msgtype") == "file":
fileid = bytes(data_details.get('file').get("sdkfileid"), encoding='utf-8')
filelen = data_details.get('file').get("filesize")
file_content = pysdk.pull_media_file(create_string_buffer(fileid, len(fileid)+1), proxy_buff, passwd_buff, timeout, c_int(filelen))
filename = data_details.get('file').get("filename")
with open(filename, 'wb') as dstf:
dstf.write(string_at(file_content, filelen))
# pysdk.free_p(file_content)
elif data_details.get("msgtype") == "text":
print("text message")
pysdk.destory_sdk()
print(1)
sys.exit(0)