php企业微信会话内容存档,企业微信会话内容存档开发期间遇到的一些坑

作者:Hogan

链接:http://www.588zj.com/article/qywxDev

声明:请尊重原作者的劳动,如需转载请注明出处

前阵子,接手的项目需要实现企业微信会话内容存档(下称企微存档),开发期间,踩得坑一个又一个,悲惨至极~为了避免日后遗忘,来这里记录一下

Java调用企微存档SDK踩到的坑

首先我是从企业微信官方文档那里下载了企微存档的SDK,长这样子:

736071b47fad2a571ff9ecf177184ed8.png

看起来没毛病,调用也走得通.然后我就想直接把Finance.java和所有的.dll文件拿到我接手的项目里,并且放到想放的包或者目录中,然后duang,duang,duang,问题就来了.

问题1:.dll文件放到放的目录中,比如resources下新建的文件夹lib中,程序会提示找不到文件.怎么解决呢,搜索引擎大法走起,

关于.dll文件存放目录,网上说的大概有几种:

①把dll文件丢到java/jdk/bin目录下------------想都不想,直接过掉

②把dll文件丢到C:\Windows\System32下-----------------就更离谱了

③放到项目中自己新建的目录,比如我初衷想要的 resources.lib目录,然后修改 IDEA (我用的是IDEA)运行配置中的 VM option 为:-Djava.library.path=D:\***\lib ----------------好家伙,可以找到,但是加载到的.dll文件却找不到它本身依赖的.dll文件- -

解决:最后,好吧,我屈服了,还是直接把.dll文件放在src同级目录下了.

问题2:我把Finance.java放到项目中的随便一个包下面,调用的时候却报错java.lang.UnsatisfiedLinkError.

这里报错的原因是包的路径和.dll头文件的路径不一致

解决:把Finance.java放到和人家给的SDK同样的包com.tencent.wework下,问题得到解决

企微存档解码踩到的坑

我对解密实在是陌生,再加上企微存档的文档写得实在是不咋样,踩了挺多坑的.查了很多,最后找到了下面这位老哥的博客,完美解决解码的问题

企业微信那边的配置就不多说了,可以参照上面微博所说的,到http://web.chacuo.net/netrsakeypair获取密钥对,把公钥设置到企业微信会话存档设置页面"消息加密公钥"处,把私钥存起来......

2bf769c7c6485a589203a2f59303a1df.png

解密的相关代码如下:

import sun.security.util.DerInputStream;

import sun.security.util.DerValue;

import javax.crypto.BadPaddingException;

import javax.crypto.Cipher;

import javax.crypto.IllegalBlockSizeException;

import javax.crypto.NoSuchPaddingException;

import java.io.IOException;

import java.math.BigInteger;

import java.security.InvalidKeyException;

import java.security.KeyFactory;

import java.security.NoSuchAlgorithmException;

import java.security.PrivateKey;

import java.security.spec.InvalidKeySpecException;

import java.security.spec.RSAPrivateCrtKeySpec;

import java.util.Base64;

public class RSAUtil {

/**

* RSA pkcs1 2048bit 解密工具,

* 获取私钥PrivateKey

* @param privKeyPEM 2048bit pkcs1格式,base64编码后的RSA字符串

* @return PrivateKey,用于解密 decryptRSA

* @throws IOException 异常

* @throws NoSuchAlgorithmException 异常

* @throws InvalidKeySpecException 异常

*/

public static PrivateKey getPrivateKey(String privKeyPEM) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {

String privKeyPEMnew = privKeyPEM.replaceAll("\\r\\n", "")//看看保存到数据库的这个字符是不是有\r,如果没有,那就只需要替换掉"\\n"

.replace("-----BEGIN RSA PRIVATE KEY-----", "")

.replace("-----END RSA PRIVATE KEY-----", "");

byte[] bytes = java.util.Base64.getDecoder().decode(privKeyPEMnew);

DerInputStream derReader = new DerInputStream(bytes);

DerValue[] seq = derReader.getSequence(0);

BigInteger modulus = seq[1].getBigInteger();

BigInteger publicExp = seq[2].getBigInteger();

BigInteger privateExp = seq[3].getBigInteger();

BigInteger prime1 = seq[4].getBigInteger();

BigInteger prime2 = seq[5].getBigInteger();

BigInteger exp1 = seq[6].getBigInteger();

BigInteger exp2 = seq[7].getBigInteger();

BigInteger crtCoef = seq[8].getBigInteger();

RSAPrivateCrtKeySpec keySpec = new RSAPrivateCrtKeySpec(modulus, publicExp, privateExp, prime1, prime2, exp1, exp2, crtCoef);

KeyFactory keyFactory = KeyFactory.getInstance("RSA");

PrivateKey privateKey = keyFactory.generatePrivate(keySpec);

return privateKey;

}

/**

* RSA pkcs1 2048bit 解密工具,

* @param str 被解密的字符串

* @param privateKey 私钥对象 从 getPrivateKey 获取

* @return 解密后数据

* @throws NoSuchPaddingException 异常

* @throws NoSuchAlgorithmException 异常

* @throws InvalidKeyException 异常

* @throws BadPaddingException 异常

* @throws IllegalBlockSizeException 异常

*/

public static String decryptRSA(String str, PrivateKey privateKey) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {

Cipher cipher = Cipher.getInstance("RSA");

cipher.init(Cipher.DECRYPT_MODE, privateKey);

byte[] randomkeybyte = Base64.getDecoder().decode(str);

byte[] finalrandomkeybyte = cipher.doFinal(randomkeybyte);

return new String(finalrandomkeybyte);

}

}

说说怎么用吧.首先我们拿到的是这种格式的数据

{"errcode":0,"chatdata":[{"publickey_ver":2,"encrypt_chat_msg":"1LrkVikw/PxL+FYraimNB+7yEZ9mkOB2Yae7X6pow+wToQb/rYHnHEN3sDIUUuLX7wENOjuRo2yk7VIDq4Bb7j8q3Vfwb5BqGa/hkUYJZj96OJiPLgMJN8+adAFWLVXdVX2MZTVV8qrpDlkYqvHY6ImVj6jDueRVGCd7q0nOetkujEsZCH82ZsggQ2JehJrJ9ROOf/tJBRkIGT2nHkhUlpqK3BvIQ5ZLMNQM51sZXpFt1h4nYxsY/rD+Vwa+HE0ahXGh3a6Eyb9SHOUlzeEadwqPBZD5sORESOXVXG3Gr1imhpxrDE51IfRSFY5iPqOhwFEtMkhZD5xNl/pjE7gJKZLVMZp82GpTn9TBZM=Ia4NqYo4WhZ+C9u","msgid":"13000540326617473990_1589764124","encrypt_random_key":"bGCT7X4LmQTEGpHkXDWRwDwbibeGDvk+INbrW+/T5N23VZWA8iwrlmIcWqM1SlsGDfkELbAg0dpurVsTGuS1p1LLY0kB+ZZvF8qjbJk56BETXiBevgrPwCfukcv0VDkAAjGX+BysQBvScLwN8k/fpfs9ydYDLPaDzQXHVLJRxkM=","seq":4}],"errmsg":"ok"}

如下图,一定要用对应版本的私钥解密,不然会解密失败

c77a4012e14c131c40b355694e23aafe.png

我是这样封装的方法,亲测有效,需要的可以参考或者直接拿去使用(tips:RSAUtil在上面已经给出,包括import的包,Finance是人家企微存档的SDK,JSON用的com.alibaba.fastjson)

/**

* @param sdk 初始化时候获取到的值

* @param ncrypt_random_key 企业微信返回的随机密钥

* @param encrypt_chat_msg 企业微信返回的单条记录的密文消息

* @param privateKey 企业微信管理后台设置的私钥,!!!版本记得对应上!!!

* @return JSONObject 返回不同格式的聊天数据,格式有二十来种

* 详情请看官网 https://open.work.weixin.qq.com/api/doc/90000/90135/91774#%E6%B6%88%E6%81%AF%E6%A0%BC%E5%BC%8F

*/

public static JSONObject decryptChatRecord(Long sdk, String ncrypt_random_key, String encrypt_chat_msg, String privateKey){

Long msg = null;

try {

//获取私钥

PrivateKey privateKeyObj = RSAUtil.getPrivateKey(privateKey);

String str = RSAUtil.decryptRSA(ncrypt_random_key, privateKeyObj);

//初始化参数slice

msg = Finance.NewSlice();

//解密

Finance.DecryptData(sdk, str, encrypt_chat_msg, msg);

String jsonDataStr = Finance.GetContentFromSlice(msg);

logger.info("解析数据:------------" + jsonDataStr);

JSONObject realJsonData = (JSONObject) JSON.parseObject(jsonDataStr);

return realJsonData;

} catch (Exception e) {

logger.error("解析密文失败");

return null;

} finally {

if(msg != null){

//释放参数slice

Finance.FreeSlice(msg);

}

}

}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值