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
export.cpp
tofix
gcc export.cpp -fPIC -shared -ldl -o libpywechat.so
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)