1111import me .chanjar .weixin .cp .api .WxCpMsgAuditService ;
1212import me .chanjar .weixin .cp .api .WxCpService ;
1313import me .chanjar .weixin .cp .bean .msgaudit .*;
14+ import me .chanjar .weixin .cp .config .WxCpConfigStorage ;
1415import me .chanjar .weixin .cp .util .crypto .WxCpCryptUtil ;
1516import me .chanjar .weixin .cp .util .json .WxCpGsonBuilder ;
1617import org .apache .commons .lang3 .StringUtils ;
3536public class WxCpMsgAuditServiceImpl implements WxCpMsgAuditService {
3637 private final WxCpService cpService ;
3738
39+ /**
40+ * SDK初始化有效期,根据企微文档为7200秒
41+ */
42+ private static final int SDK_EXPIRES_TIME = 7200 ;
43+
3844 @ Override
3945 public WxCpChatDatas getChatDatas (long seq , @ NonNull long limit , String proxy , String passwd ,
4046 @ NonNull long timeout ) throws Exception {
41- String configPath = cpService .getWxCpConfigStorage ().getMsgAuditLibPath ();
47+ // 获取或初始化SDK
48+ long sdk = this .initSdk ();
49+
50+ long slice = Finance .NewSlice ();
51+ long ret = Finance .GetChatData (sdk , seq , limit , proxy , passwd , timeout , slice );
52+ if (ret != 0 ) {
53+ Finance .FreeSlice (slice );
54+ throw new WxErrorException ("getchatdata err ret " + ret );
55+ }
56+
57+ // 拉取会话存档
58+ String content = Finance .GetContentFromSlice (slice );
59+ Finance .FreeSlice (slice );
60+ WxCpChatDatas chatDatas = WxCpChatDatas .fromJson (content );
61+ if (chatDatas .getErrCode ().intValue () != 0 ) {
62+ throw new WxErrorException (chatDatas .toJson ());
63+ }
64+
65+ chatDatas .setSdk (sdk );
66+ return chatDatas ;
67+ }
68+
69+ /**
70+ * 获取或初始化SDK,如果SDK已过期则重新初始化
71+ *
72+ * @return sdk id
73+ * @throws WxErrorException 初始化失败时抛出异常
74+ */
75+ private synchronized long initSdk () throws WxErrorException {
76+ WxCpConfigStorage configStorage = cpService .getWxCpConfigStorage ();
77+
78+ // 检查SDK是否已缓存且未过期
79+ if (!configStorage .isMsgAuditSdkExpired ()) {
80+ long cachedSdk = configStorage .getMsgAuditSdk ();
81+ if (cachedSdk > 0 ) {
82+ return cachedSdk ;
83+ }
84+ }
85+
86+ // SDK未初始化或已过期,需要重新初始化
87+ String configPath = configStorage .getMsgAuditLibPath ();
4288 if (StringUtils .isEmpty (configPath )) {
4389 throw new WxErrorException ("请配置会话存档sdk文件的路径,不要配错了!!" );
4490 }
4591
46- /**
47- * 完整的文件库路径:
48- *
49- * /www/osfile/libcrypto-1_1-x64.dll,libssl-1_1-x64.dll,libcurl-x64.dll,WeWorkFinanceSdk.dll,
50- * libWeWorkFinanceSdk_Java.so
51- */
5292 // 替换斜杠
5393 String replacePath = configPath .replace ("\\ " , "/" );
5494 // 获取最后一个斜杠的下标,用作分割路径
@@ -79,36 +119,22 @@ public WxCpChatDatas getChatDatas(long seq, @NonNull long limit, String proxy, S
79119
80120 Finance .loadingLibraries (osLib , prefixPath );
81121 long sdk = Finance .NewSdk ();
82- //因为会话存档单独有个secret,优先使用会话存档的secret
83- String msgAuditSecret = cpService . getWxCpConfigStorage () .getMsgAuditSecret ();
122+ // 因为会话存档单独有个secret,优先使用会话存档的secret
123+ String msgAuditSecret = configStorage .getMsgAuditSecret ();
84124 if (StringUtils .isEmpty (msgAuditSecret )) {
85- msgAuditSecret = cpService . getWxCpConfigStorage () .getCorpSecret ();
125+ msgAuditSecret = configStorage .getCorpSecret ();
86126 }
87- long ret = Finance .Init (sdk , cpService . getWxCpConfigStorage () .getCorpId (), msgAuditSecret );
127+ long ret = Finance .Init (sdk , configStorage .getCorpId (), msgAuditSecret );
88128 if (ret != 0 ) {
89129 Finance .DestroySdk (sdk );
90130 throw new WxErrorException ("init sdk err ret " + ret );
91131 }
92132
93- long slice = Finance .NewSlice ();
94- ret = Finance .GetChatData (sdk , seq , limit , proxy , passwd , timeout , slice );
95- if (ret != 0 ) {
96- Finance .FreeSlice (slice );
97- Finance .DestroySdk (sdk );
98- throw new WxErrorException ("getchatdata err ret " + ret );
99- }
100-
101- // 拉取会话存档
102- String content = Finance .GetContentFromSlice (slice );
103- Finance .FreeSlice (slice );
104- WxCpChatDatas chatDatas = WxCpChatDatas .fromJson (content );
105- if (chatDatas .getErrCode ().intValue () != 0 ) {
106- Finance .DestroySdk (sdk );
107- throw new WxErrorException (chatDatas .toJson ());
108- }
133+ // 缓存SDK
134+ configStorage .updateMsgAuditSdk (sdk , SDK_EXPIRES_TIME );
135+ log .debug ("初始化会话存档SDK成功,sdk={}" , sdk );
109136
110- chatDatas .setSdk (sdk );
111- return chatDatas ;
137+ return sdk ;
112138 }
113139
114140 @ Override
@@ -128,36 +154,27 @@ public WxCpChatModel getDecryptData(@NonNull long sdk, @NonNull WxCpChatDatas.Wx
128154 * @throws Exception the exception
129155 */
130156 public String decryptChatData (long sdk , WxCpChatDatas .WxCpChatData chatData , Integer pkcs1 ) throws Exception {
131- /**
132- * 企业获取的会话内容,使用企业自行配置的消息加密公钥进行加密,企业可用自行保存的私钥解开会话内容数据。
133- * msgAuditPriKey 会话存档私钥不能为空
134- */
157+ // 企业获取的会话内容,使用企业自行配置的消息加密公钥进行加密,企业可用自行保存的私钥解开会话内容数据。
158+ // msgAuditPriKey 会话存档私钥不能为空
135159 String priKey = cpService .getWxCpConfigStorage ().getMsgAuditPriKey ();
136160 if (StringUtils .isEmpty (priKey )) {
137161 throw new WxErrorException ("请配置会话存档私钥【msgAuditPriKey】" );
138162 }
139163
140164 String decryptByPriKey = WxCpCryptUtil .decryptPriKey (chatData .getEncryptRandomKey (), priKey , pkcs1 );
141- /**
142- * 每次使用DecryptData解密会话存档前需要调用NewSlice获取一个slice,在使用完slice中数据后,还需要调用FreeSlice释放。
143- */
165+ // 每次使用DecryptData解密会话存档前需要调用NewSlice获取一个slice,在使用完slice中数据后,还需要调用FreeSlice释放。
144166 long msg = Finance .NewSlice ();
145167
146- /**
147- * 解密会话存档内容
148- * sdk不会要求用户传入rsa私钥,保证用户会话存档数据只有自己能够解密。
149- * 此处需要用户先用rsa私钥解密encrypt_random_key后,作为encrypt_key参数传入sdk来解密encrypt_chat_msg获取会话存档明文。
150- */
168+ // 解密会话存档内容
169+ // sdk不会要求用户传入rsa私钥,保证用户会话存档数据只有自己能够解密。
170+ // 此处需要用户先用rsa私钥解密encrypt_random_key后,作为encrypt_key参数传入sdk来解密encrypt_chat_msg获取会话存档明文。
151171 int ret = Finance .DecryptData (sdk , decryptByPriKey , chatData .getEncryptChatMsg (), msg );
152172 if (ret != 0 ) {
153173 Finance .FreeSlice (msg );
154- Finance .DestroySdk (sdk );
155174 throw new WxErrorException ("msg err ret " + ret );
156175 }
157176
158- /**
159- * 明文
160- */
177+ // 明文
161178 String plainText = Finance .GetContentFromSlice (msg );
162179 Finance .FreeSlice (msg );
163180 return plainText ;
@@ -209,7 +226,6 @@ public void getMediaFile(@NonNull long sdk, @NonNull String sdkfileid, String pr
209226 ret = Finance .GetMediaData (sdk , indexbuf , sdkfileid , proxy , passwd , timeout , mediaData );
210227 if (ret != 0 ) {
211228 Finance .FreeMediaData (mediaData );
212- Finance .DestroySdk (sdk );
213229 throw new WxErrorException ("getmediadata err ret " + ret );
214230 }
215231
0 commit comments