|
1 | 1 | package WeWorkFinanceSDK |
2 | 2 |
|
3 | | -// #cgo LDFLAGS: -L${SRCDIR}/lib -lWeWorkFinanceSdk_C |
4 | | -// #cgo CFLAGS: -I ./lib/ |
5 | | -// #include <stdlib.h> |
6 | | -// #include "WeWorkFinanceSdk_C.h" |
7 | | -import "C" |
8 | | -import ( |
9 | | - "encoding/json" |
10 | | - "unsafe" |
11 | | -) |
12 | | - |
13 | | -type Client struct { |
14 | | - ptr *C.WeWorkFinanceSdk_t |
15 | | - privateKey string |
16 | | -} |
17 | | - |
18 | | -/** |
19 | | -* 初始化函数 |
20 | | -* Return值=0表示该API调用成功 |
21 | | -* |
22 | | -* @param [in] sdk NewSdk返回的sdk指针 |
23 | | -* @param [in] corpid 调用企业的企业id,例如:wwd08c8exxxx5ab44d,可以在企业微信管理端--我的企业--企业信息查看 |
24 | | -* @param [in] secret 聊天内容存档的Secret,可以在企业微信管理端--管理工具--聊天内容存档查看 |
25 | | -* @param [in] privateKey 消息加密私钥,可以在企业微信管理端--管理工具--消息加密公钥查看对用公钥,私钥一般由自己保存 |
26 | | -* |
27 | | -* |
28 | | -* @return 返回是否初始化成功 |
29 | | -* 0 - 成功 |
30 | | -* !=0 - 失败 |
31 | | - */ |
32 | | -func NewClient(corpId string, corpSecret string, rsaPrivateKey string) (*Client, error) { |
33 | | - ptr := C.NewSdk() |
34 | | - corpIdC := C.CString(corpId) |
35 | | - corpSecretC := C.CString(corpSecret) |
36 | | - defer func() { |
37 | | - C.free(unsafe.Pointer(corpIdC)) |
38 | | - C.free(unsafe.Pointer(corpSecretC)) |
39 | | - }() |
40 | | - retC := C.Init(ptr, corpIdC, corpSecretC) |
41 | | - ret := int(retC) |
42 | | - if ret != 0 { |
43 | | - return nil, NewSDKErr(ret) |
44 | | - } |
45 | | - return &Client{ |
46 | | - ptr: ptr, |
47 | | - privateKey: rsaPrivateKey, |
48 | | - }, nil |
49 | | -} |
50 | | - |
51 | | -func (s *Client) Free() { |
52 | | - if s.ptr == nil { |
53 | | - return |
54 | | - } |
55 | | - C.DestroySdk(s.ptr) |
56 | | - s.ptr = nil |
57 | | -} |
58 | | - |
59 | | -/** |
60 | | -* 拉取聊天记录函数 |
61 | | -* |
62 | | -* |
63 | | -* @param [in] seq 从指定的seq开始拉取消息,注意的是返回的消息从seq+1开始返回,seq为之前接口返回的最大seq值。首次使用请使用seq:0 |
64 | | -* @param [in] limit 一次拉取的消息条数,最大值1000条,超过1000条会返回错误 |
65 | | -* @param [in] proxy 使用代理的请求,需要传入代理的链接。如:socks5://10.0.0.1:8081 或者 http://10.0.0.1:8081 |
66 | | -* @param [in] passwd 代理账号密码,需要传入代理的账号密码。如 user_name:passwd_123 |
67 | | -* @param [in] timeout 超时时间,单位秒 |
68 | | -* @return chatDatas 返回本次拉取消息的数据,slice结构体.内容包括errcode/errmsg,以及每条消息内容。示例如下: |
69 | | -
|
70 | | -{"errcode":0,"errmsg":"ok","chatdata":[{"seq":196,"msgid":"CAQQ2fbb4QUY0On2rYSAgAMgip/yzgs=","publickey_ver":3,"encrypt_random_key":"ftJ+uz3n/z1DsxlkwxNgE+mL38H42/KCvN8T60gbbtPD+Rta1hKTuQPzUzO6Hzne97MgKs7FfdDxDck/v8cDT6gUVjA2tZ/M7euSD0L66opJ/IUeBtpAtvgVSD5qhlaQjvfKJc/zPMGNK2xCLFYqwmQBZXbNT7uA69Fflm512nZKW/piK2RKdYJhRyvQnA1ISxK097sp9WlEgDg250fM5tgwMjujdzr7ehK6gtVBUFldNSJS7ndtIf6aSBfaLktZgwHZ57ONewWq8GJe7WwQf1hwcDbCh7YMG8nsweEwhDfUz+u8rz9an+0lgrYMZFRHnmzjgmLwrR7B/32Qxqd79A==","encrypt_chat_msg":"898WSfGMnIeytTsea7Rc0WsOocs0bIAerF6de0v2cFwqo9uOxrW9wYe5rCjCHHH5bDrNvLxBE/xOoFfcwOTYX0HQxTJaH0ES9OHDZ61p8gcbfGdJKnq2UU4tAEgGb8H+Q9n8syRXIjaI3KuVCqGIi4QGHFmxWenPFfjF/vRuPd0EpzUNwmqfUxLBWLpGhv+dLnqiEOBW41Zdc0OO0St6E+JeIeHlRZAR+E13Isv9eS09xNbF0qQXWIyNUi+ucLr5VuZnPGXBrSfvwX8f0QebTwpy1tT2zvQiMM2MBugKH6NuMzzuvEsXeD+6+3VRqL"}]} |
71 | | -*/ |
72 | | -func (s *Client) GetChatData(seq uint64, limit uint64, proxy string, passwd string, timeout int) ([]ChatData, error) { |
73 | | - proxyC := C.CString(proxy) |
74 | | - passwdC := C.CString(passwd) |
75 | | - chatSlice := C.NewSlice() |
76 | | - defer func() { |
77 | | - C.free(unsafe.Pointer(proxyC)) |
78 | | - C.free(unsafe.Pointer(passwdC)) |
79 | | - C.FreeSlice(chatSlice) |
80 | | - }() |
81 | | - |
82 | | - if s.ptr == nil { |
83 | | - return nil, NewSDKErr(10002) |
84 | | - } |
85 | | - |
86 | | - retC := C.GetChatData(s.ptr, C.ulonglong(seq), C.uint(limit), proxyC, passwdC, C.int(timeout), chatSlice) |
87 | | - ret := int(retC) |
88 | | - if ret != 0 { |
89 | | - return nil, NewSDKErr(ret) |
90 | | - } |
91 | | - buf := s.GetContentFromSlice(chatSlice) |
92 | | - |
93 | | - var data ChatDataResponse |
94 | | - err := json.Unmarshal(buf, &data) |
95 | | - if err != nil { |
96 | | - return nil, err |
97 | | - } |
98 | | - if data.ErrCode != 0 { |
99 | | - return nil, data.Error |
100 | | - } |
101 | | - return data.ChatDataList, nil |
102 | | -} |
103 | | - |
104 | | -/** |
105 | | -* 拉取聊天记录函数 |
106 | | -* |
107 | | -* |
108 | | -* @param [in] seq 从指定的seq开始拉取消息,注意的是返回的消息从seq+1开始返回,seq为之前接口返回的最大seq值。首次使用请使用seq:0 |
109 | | -* @param [in] limit 一次拉取的消息条数,最大值1000条,超过1000条会返回错误 |
110 | | -* @param [in] proxy 使用代理的请求,需要传入代理的链接。如:socks5://10.0.0.1:8081 或者 http://10.0.0.1:8081 |
111 | | -* @param [in] passwd 代理账号密码,需要传入代理的账号密码。如 user_name:passwd_123 |
112 | | -* @param [in] timeout 超时时间,单位秒 |
113 | | -* @return chatDatas 返回本次拉取消息的数据,slice结构体.内容包括errcode/errmsg,以及每条消息内容。示例如下: |
114 | | -
|
115 | | -{"errcode":0,"errmsg":"ok","chatdata":[{"seq":196,"msgid":"CAQQ2fbb4QUY0On2rYSAgAMgip/yzgs=","publickey_ver":3,"encrypt_random_key":"ftJ+uz3n/z1DsxlkwxNgE+mL38H42/KCvN8T60gbbtPD+Rta1hKTuQPzUzO6Hzne97MgKs7FfdDxDck/v8cDT6gUVjA2tZ/M7euSD0L66opJ/IUeBtpAtvgVSD5qhlaQjvfKJc/zPMGNK2xCLFYqwmQBZXbNT7uA69Fflm512nZKW/piK2RKdYJhRyvQnA1ISxK097sp9WlEgDg250fM5tgwMjujdzr7ehK6gtVBUFldNSJS7ndtIf6aSBfaLktZgwHZ57ONewWq8GJe7WwQf1hwcDbCh7YMG8nsweEwhDfUz+u8rz9an+0lgrYMZFRHnmzjgmLwrR7B/32Qxqd79A==","encrypt_chat_msg":"898WSfGMnIeytTsea7Rc0WsOocs0bIAerF6de0v2cFwqo9uOxrW9wYe5rCjCHHH5bDrNvLxBE/xOoFfcwOTYX0HQxTJaH0ES9OHDZ61p8gcbfGdJKnq2UU4tAEgGb8H+Q9n8syRXIjaI3KuVCqGIi4QGHFmxWenPFfjF/vRuPd0EpzUNwmqfUxLBWLpGhv+dLnqiEOBW41Zdc0OO0St6E+JeIeHlRZAR+E13Isv9eS09xNbF0qQXWIyNUi+ucLr5VuZnPGXBrSfvwX8f0QebTwpy1tT2zvQiMM2MBugKH6NuMzzuvEsXeD+6+3VRqL"}]} |
116 | | -*/ |
117 | | -func (s *Client) GetRawChatData(seq uint64, limit uint64, proxy string, passwd string, timeout int) (ChatDataResponse, error) { |
118 | | - proxyC := C.CString(proxy) |
119 | | - passwdC := C.CString(passwd) |
120 | | - chatSlice := C.NewSlice() |
121 | | - defer func() { |
122 | | - C.free(unsafe.Pointer(proxyC)) |
123 | | - C.free(unsafe.Pointer(passwdC)) |
124 | | - C.FreeSlice(chatSlice) |
125 | | - }() |
126 | | - |
127 | | - if s.ptr == nil { |
128 | | - return ChatDataResponse{}, NewSDKErr(10002) |
129 | | - } |
130 | | - |
131 | | - retC := C.GetChatData(s.ptr, C.ulonglong(seq), C.uint(limit), proxyC, passwdC, C.int(timeout), chatSlice) |
132 | | - ret := int(retC) |
133 | | - if ret != 0 { |
134 | | - return ChatDataResponse{}, NewSDKErr(ret) |
135 | | - } |
136 | | - buf := s.GetContentFromSlice(chatSlice) |
137 | | - |
138 | | - var data ChatDataResponse |
139 | | - err := json.Unmarshal(buf, &data) |
140 | | - if err != nil { |
141 | | - return ChatDataResponse{}, err |
142 | | - } |
143 | | - return data, nil |
144 | | -} |
145 | | - |
146 | | -/** |
147 | | -* @brief 解析密文.企业微信自有解密内容 |
148 | | -* @param [in] encrypt_key, getchatdata返回的encrypt_random_key,使用企业自持对应版本秘钥RSA解密后的内容 |
149 | | -* @param [in] encrypt_msg, getchatdata返回的encrypt_chat_msg |
150 | | -* @param [out] msg, 解密的消息明文 |
151 | | -* @return 返回是否调用成功 |
152 | | -* 0 - 成功 |
153 | | -* !=0 - 失败 |
154 | | - */ |
155 | | -func (s *Client) DecryptData(encrypt_random_key string, encryptMsg string) (msg ChatMessage, err error) { |
156 | | - encryptKey, err := RSADecryptBase64(s.privateKey, encrypt_random_key) |
157 | | - if err != nil { |
158 | | - return msg, err |
159 | | - } |
160 | | - encryptKeyC := C.CString(string(encryptKey)) |
161 | | - encryptMsgC := C.CString(encryptMsg) |
162 | | - msgSlice := C.NewSlice() |
163 | | - defer func() { |
164 | | - C.free(unsafe.Pointer(encryptKeyC)) |
165 | | - C.free(unsafe.Pointer(encryptMsgC)) |
166 | | - C.FreeSlice(msgSlice) |
167 | | - }() |
168 | | - |
169 | | - retC := C.DecryptData(encryptKeyC, encryptMsgC, msgSlice) |
170 | | - ret := int(retC) |
171 | | - if ret != 0 { |
172 | | - return msg, NewSDKErr(ret) |
173 | | - } |
174 | | - buf := s.GetContentFromSlice(msgSlice) |
175 | | - |
176 | | - // handle illegal escape character in text |
177 | | - for i := 0; i < len(buf); { |
178 | | - if buf[i] < 0x20 { |
179 | | - buf = append(buf[:i], buf[i+1:]...) |
180 | | - continue |
181 | | - } |
182 | | - i++ |
183 | | - } |
184 | | - |
185 | | - var baseMessage BaseMessage |
186 | | - err = json.Unmarshal(buf, &baseMessage) |
187 | | - if err != nil { |
188 | | - return msg, err |
189 | | - } |
190 | | - |
191 | | - msg.Id = baseMessage.MsgId |
192 | | - msg.From = baseMessage.From |
193 | | - msg.ToList = baseMessage.ToList |
194 | | - msg.Action = baseMessage.Action |
195 | | - msg.Type = baseMessage.MsgType |
196 | | - msg.originData = buf |
197 | | - return msg, err |
198 | | -} |
199 | | - |
200 | | -/** |
201 | | - * 拉取媒体消息函数 |
202 | | - * Return值=0表示该API调用成功 |
203 | | - * |
204 | | - * |
205 | | - * @param [in] sdk NewSdk返回的sdk指针 |
206 | | - * @param [in] sdkFileid 从GetChatData返回的聊天消息中,媒体消息包括的sdkfileid |
207 | | - * @param [in] proxy 使用代理的请求,需要传入代理的链接。如:socks5://10.0.0.1:8081 或者 http://10.0.0.1:8081 |
208 | | - * @param [in] passwd 代理账号密码,需要传入代理的账号密码。如 user_name:passwd_123 |
209 | | - * @param [in] indexbuf 媒体消息分片拉取,需要填入每次拉取的索引信息。首次不需要填写,默认拉取512k,后续每次调用只需要将上次调用返回的outindexbuf填入即可。 |
210 | | - * @param [in] timeout 超时时间,单位秒 |
211 | | - * @param [out] media_data 返回本次拉取的媒体数据.MediaData结构体.内容包括data(数据内容)/outindexbuf(下次索引)/is_finish(拉取完成标记) |
212 | | -
|
213 | | - * |
214 | | - * @return 返回是否调用成功 |
215 | | - * 0 - 成功 |
216 | | - * !=0 - 失败 |
217 | | - */ |
218 | | - |
219 | | -func (s *Client) GetMediaData(indexBuf string, sdkFileId string, proxy string, passwd string, timeout int) (*MediaData, error) { |
220 | | - indexBufC := C.CString(indexBuf) |
221 | | - sdkFileIdC := C.CString(sdkFileId) |
222 | | - proxyC := C.CString(proxy) |
223 | | - passwdC := C.CString(passwd) |
224 | | - mediaDataC := C.NewMediaData() |
225 | | - defer func() { |
226 | | - C.free(unsafe.Pointer(indexBufC)) |
227 | | - C.free(unsafe.Pointer(sdkFileIdC)) |
228 | | - C.free(unsafe.Pointer(proxyC)) |
229 | | - C.free(unsafe.Pointer(passwdC)) |
230 | | - C.FreeMediaData(mediaDataC) |
231 | | - }() |
232 | | - |
233 | | - if s.ptr == nil { |
234 | | - return nil, NewSDKErr(10002) |
235 | | - } |
236 | | - |
237 | | - retC := C.GetMediaData(s.ptr, indexBufC, sdkFileIdC, proxyC, passwdC, C.int(timeout), mediaDataC) |
238 | | - ret := int(retC) |
239 | | - if ret != 0 { |
240 | | - return nil, NewSDKErr(ret) |
241 | | - } |
242 | | - return &MediaData{ |
243 | | - OutIndexBuf: C.GoString(C.GetOutIndexBuf(mediaDataC)), |
244 | | - Data: C.GoBytes(unsafe.Pointer(C.GetData(mediaDataC)), C.int(C.GetDataLen(mediaDataC))), |
245 | | - IsFinish: int(C.IsMediaDataFinish(mediaDataC)) == 1, |
246 | | - }, nil |
247 | | -} |
248 | | - |
249 | | -func (s *Client) GetContentFromSlice(slice *C.struct_Slice_t) []byte { |
250 | | - return C.GoBytes(unsafe.Pointer(C.GetContentFromSlice(slice)), C.int(C.GetSliceLen(slice))) |
| 3 | +type Client interface { |
| 4 | + // GetChatData 拉取聊天记录 |
| 5 | + // |
| 6 | + // @param [in] seq 从指定的seq开始拉取消息,注意的是返回的消息从seq+1开始返回,seq为之前接口返回的最大seq值。首次使用请使用seq:0 |
| 7 | + // @param [in] limit 一次拉取的消息条数,最大值1000条,超过1000条会返回错误 |
| 8 | + // @param [in] proxy 使用代理的请求,需要传入代理的链接。如:socks5://10.0.0.1:8081 或者 http://10.0.0.1:8081 |
| 9 | + // @param [in] passwd 代理账号密码,需要传入代理的账号密码。如 user_name:passwd_123 |
| 10 | + // @param [in] timeout 超时时间,单位秒 |
| 11 | + // |
| 12 | + // @return chatDatas 返回本次拉取消息的数据,slice结构体.内容包括errcode/errmsg,以及每条消息内容。示例如下: |
| 13 | + // {"errcode":0,"errmsg":"ok","chatdata":[{"seq":196,"msgid":"CAQQ2fbb4QUY0On2rYSAgAMgip/yzgs=","publickey_ver":3,"encrypt_random_key":"ftJ+uz3n/z1DsxlkwxNgE+mL38H42/KCvN8T60gbbtPD+Rta1hKTuQPzUzO6Hzne97MgKs7FfdDxDck/v8cDT6gUVjA2tZ/M7euSD0L66opJ/IUeBtpAtvgVSD5qhlaQjvfKJc/zPMGNK2xCLFYqwmQBZXbNT7uA69Fflm512nZKW/piK2RKdYJhRyvQnA1ISxK097sp9WlEgDg250fM5tgwMjujdzr7ehK6gtVBUFldNSJS7ndtIf6aSBfaLktZgwHZ57ONewWq8GJe7WwQf1hwcDbCh7YMG8nsweEwhDfUz+u8rz9an+0lgrYMZFRHnmzjgmLwrR7B/32Qxqd79A==","encrypt_chat_msg":"898WSfGMnIeytTsea7Rc0WsOocs0bIAerF6de0v2cFwqo9uOxrW9wYe5rCjCHHH5bDrNvLxBE/xOoFfcwOTYX0HQxTJaH0ES9OHDZ61p8gcbfGdJKnq2UU4tAEgGb8H+Q9n8syRXIjaI3KuVCqGIi4QGHFmxWenPFfjF/vRuPd0EpzUNwmqfUxLBWLpGhv+dLnqiEOBW41Zdc0OO0St6E+JeIeHlRZAR+E13Isv9eS09xNbF0qQXWIyNUi+ucLr5VuZnPGXBrSfvwX8f0QebTwpy1tT2zvQiMM2MBugKH6NuMzzuvEsXeD+6+3VRqL"}]} |
| 14 | + // |
| 15 | + GetChatData(seq uint64, limit uint64, proxy string, passwd string, timeout int) ([]ChatData, error) |
| 16 | + |
| 17 | + // DecryptData 解析密文.企业微信自有解密内容 |
| 18 | + // |
| 19 | + // @param [in] encrypt_key, getchatdata返回的encrypt_random_key,使用企业自持对应版本秘钥RSA解密后的内容 |
| 20 | + // @param [in] encrypt_msg, getchatdata返回的encrypt_chat_msg |
| 21 | + // @param [out] msg, 解密的消息明文 |
| 22 | + // |
| 23 | + // @return 返回是否调用成功 |
| 24 | + // 0 - 成功 |
| 25 | + // !=0 - 失败 |
| 26 | + // |
| 27 | + DecryptData(encryptRandomKey string, encryptMsg string) (msg ChatMessage, err error) |
| 28 | + |
| 29 | + // GetMediaData 拉取媒体消息函数 |
| 30 | + // |
| 31 | + // Return值=0表示该API调用成功 |
| 32 | + // @param [in] sdk NewSdk返回的sdk指针 |
| 33 | + // @param [in] sdkFileid 从GetChatData返回的聊天消息中,媒体消息包括的sdkfileid |
| 34 | + // @param [in] proxy 使用代理的请求,需要传入代理的链接。如:socks5://10.0.0.1:8081 或者 http://10.0.0.1:8081 |
| 35 | + // @param [in] passwd 代理账号密码,需要传入代理的账号密码。如 user_name:passwd_123 |
| 36 | + // @param [in] indexbuf 媒体消息分片拉取,需要填入每次拉取的索引信息。首次不需要填写,默认拉取512k,后续每次调用只需要将上次调用返回的outindexbuf填入即可。 |
| 37 | + // @param [in] timeout 超时时间,单位秒 |
| 38 | + // @param [out] media_data 返回本次拉取的媒体数据.MediaData结构体.内容包括data(数据内容)/outindexbuf(下次索引)/is_finish(拉取完成标记) |
| 39 | + // |
| 40 | + // @return 返回是否调用成功 |
| 41 | + // 0 - 成功 |
| 42 | + // !=0 - 失败 |
| 43 | + // |
| 44 | + GetMediaData(indexBuf string, sdkFileId string, proxy string, passwd string, timeout int) (*MediaData, error) |
251 | 45 | } |
0 commit comments