林夕笔记林夕笔记
首页
关于我
首页
关于我
  • 后台笔记

    • Java

      • Java语法
    • MySQL

      • MySQL基础
      • MySQL高级
    • 企业微信开发

      • 开发环境搭建
        • 1. 应用的回调配置【验证有效性】
        • 2.调用会话内容存档SDK
        • 2.获取取客户群列表

企业微信开发环境搭建

1. 应用的回调配置【验证有效性】

application.properties 配置文件
#企业id
qixin.qiYeId=*************
#应用回调Token
qixin.app.callbackToken=*************
#应用回调EncodingAESKey
qixin.app.callbackEncodingAESKey=****************************************************
java代码
import com.bhne.qixin.qixin.util.WXBizJsonMsgCrypt;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;



@Value("${qixin.qiYeId}")
private String qiYeId;
@Value("${qixin.app.callbackToken}")
private String callbackToken;
@Value("${qixin.app.callbackEncodingAESKey}")
private String callbackEncodingAESKey;


/**
 * @Description 企信Get回调接口
 * @Param [msg_signature, nonce, echostr, timestamp][消息体签名, 随机数字串, 企业微信推送过来的随机加密字符串,时间戳]
 * @Return java.lang.String
 * @Author linxi
 * @Date 2025/3/12 13:56
 **/
@GetMapping(produces = "text/plain")
public String qxCallbackGet(@RequestParam String msg_signature, @RequestParam String nonce, @RequestParam String echostr, @RequestParam String timestamp) {
    log.info("CallbackController.qxCallbackGet-->微信回调认证消息 msg_signature={}, nonce={}, echostr={}, timestamp={}",msg_signature, nonce, echostr, timestamp);
    if (StringUtils.isAnyBlank(msg_signature, timestamp, nonce, echostr)) {
        throw new IllegalArgumentException("CallbackController.qxCallbackGet-->请求参数非法,请核实!");
    }
    try {
        //参数为 回调设置的Token 回调设置的Key 企业ID
        WXBizJsonMsgCrypt wxcpt = new WXBizJsonMsgCrypt(callbackToken, callbackEncodingAESKey, qiYeId);
        // 验证URL成功,将sEchoStr返回
        return wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr);
    } catch (Exception e) {
        log.error("CallbackController.qxCallbackGet-->回调验证处理败", e);
    }
    return "";
}   
pom.xml
<!-- 企信依赖 -->
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>20231013</version>
</dependency>

<!-- https://mvnrepository.com/artifact/commons-codec/commons-codec -->
<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.16.0</version>
</dependency> 

注意

@GetMapping(produces = "text/plain") 中 produces = "text/plain" 是为了返回时候返回的为纯文本,否则会返回为json格式。企信需要返回纯文本,所以需要设置。

2.调用会话内容存档SDK

步骤

a. 把SDK v3.0中 libcrypto-3-x64.dll, libcurl-x64.dll, WeWorkFinanceSdk.dll 放到 C:\Windows\system32 路径下
b. 进入企信管理后台 高级功能 --> 会话内容存档
在 会话内容存档 中 选择服务范围, 可信IP地址[服务器地址], 消息加密公钥[RSA使用PKCS1模值为2048bit] 三项必填不然返回为空 c. 获取会话内容存档的 Secret d. 点击 开启

application.properties 配置文件
#企业id
qixin.qiYeId=*************
#会话存档secret
qixin.huihuacundang.secret=***************************************
#会话存档私钥
qixin.huihuacundang.privateKey=******************************************************************************************************************
java代码
import cn.hutool.http.HttpException;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.tencent.wework.Finance;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import javax.crypto.Cipher;
import java.util.Base64;


@Value("${qixin.qiYeId}")
private String qiYeId;
@Value("${qixin.huihuacundang.secret}")
private String hhcdSecret;
@Value("${qixin.huihuacundang.privateKey}")
private String privateKey;

/**
 * @Description 获取会话内容
 * @Param []
 * @Return void
 * @Author linxi
 * @Date 2025/3/13 10:04
 **/
public void getHuiHuaNeiRong() {
    // TODO 获取newSwq
    //使用sdk前需要初始化,初始化时请填入自己企业的corpid与secrectkey。
    long sdkIndex = Finance.NewSdk();
    long ret = Finance.Init(sdkIndex, qiYeId, hhcdSecret);
    if (ret != 0) {
        Finance.DestroySdk(sdkIndex);
        log.error("QxBaseApi.getHuiHuaNeiRong-->获取会话内容时初始化SDK失败,返回结果: {}", ret);
    }
    //每次使用GetChatData拉取存档前需要调用NewSlice获取一个slice,在使用完slice中数据后,还需要调用FreeSlice释放。
    long slice = Finance.NewSlice();
    // 参数说明:sdk句柄, 首次拉取时seq传0 拉取序号建议设置为上次拉取返回结果中最大序号, 拉取的最大消息条数, 代理参数1, 代理参数2, 超时时间,单位为秒,建议超时时间设置为5s, NewSlice获取的slice,
    ret = Finance.GetChatData(sdkIndex, 12, 1000, null, null, 5, slice); // 返回是否调用成功 0:成功 !=0失败
    // 返回是否调用成功 0:成功 !=0失败
    if (ret == 0) {
        String dataStr = Finance.GetContentFromSlice(slice);
        JSONObject data = JSONUtil.parseObj(dataStr);
        // 0表示成功,错误返回非0错误码
        if (data.getInt("errcode") == 0) {
            JSONArray chatdataJo = data.getJSONArray("chatdata");
            long maxSeq = 0;
            for (int i = 0; i < chatdataJo.size(); i++) {
                JSONObject jo = chatdataJo.getJSONObject(i);
                // 处理最大seq
                maxSeq = Math.max(jo.getLong("seq"), maxSeq);
                String encrypt_key = decryptEncrypt(jo.getStr("encrypt_random_key"));
                // 加密成功
                if (!"".equals(encrypt_key)) {
                    //每次使用DecryptData解密会话存档前需要调用NewSlice获取一个slice,在使用完slice中数据后,还需要调用FreeSlice释放。
                    long msg = Finance.NewSlice();
                    // 参数说明:sdk句柄, 拉取会话存档返回的encrypt_random_key,使用配置在企业微信管理台的rsa公钥对应的私钥解密后得到encrypt_key, 拉取会话存档返回的encrypt_chat_msg
                    ret = Finance.DecryptData(sdkIndex, encrypt_key, jo.getStr("encrypt_chat_msg"), msg);
                    // 解密成功
                    if (ret == 0) {
                        String infoDataStr = Finance.GetContentFromSlice(msg);
                        JSONObject infoJo = JSONUtil.parseObj(infoDataStr);
                        // 判断是文本消息
                        if ("text".equals(infoJo.getStr("msgtype"))) {
                            // TODO 解析数据用于下一步存储
                            log.info("QxBaseApi.getHuiHuaNeiRong-->解密后消息: {}", infoDataStr);
                        }
                    } else {
                        log.warn("QxBaseApi.getHuiHuaNeiRong-->解密消息密文失败状态码: {}", ret);
                    }
                    // 销毁slice
                    Finance.FreeSlice(msg);
                } else {
                    log.warn("QxBaseApi.getHuiHuaNeiRong-->encrypt_random_key解密到encrypt_key失败: {}", data.getInt("errcode"));
                }
            }
            // TODO 存储newSwq和解析的数据
        } else {
            log.warn("QxBaseApi.getHuiHuaNeiRong-->获取到会话数据失败: {}", data.getInt("errcode"));
        }
    } else {
        log.error("QxBaseApi.getHuiHuaNeiRong-->获取到会话数据失败,返回结果: {}", ret);
    }
    // 销毁slice
    Finance.FreeSlice(slice);
    // 销毁sdk
    Finance.DestroySdk(sdkIndex);
}

/**
 * @Description encrypt_random_key解密到encrypt_key
 * @Param [encryptedData] encrypt_random_key
 * @Return java.lang.String encrypt_key
 * @Author linxi
 * @Date 2025/3/13 15:40
 **/
private String decryptEncrypt(String encryptedData){
    String decryptedData = null;
    try {
        // 将私钥字符串转换为PrivateKey对象
        byte[] keyBytes = Base64.getDecoder().decode(privateKey);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        // 解密数据
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedData);
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        decryptedData = new String(decryptedBytes);
    } catch (Exception e) {
        log.error("QxBaseApi.decrypt-->encrypt_random_key解密到encrypt_key失败",e);
    }
    return decryptedData;
}
pom.xml
<!-- 相关依赖 -->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.26</version>
</dependency>

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.12.0</version>
</dependency>

限制说明

群成员人数不可超过管理端配置的“群成员人数上限”,且最大不可超过2000人(含应用)。 每企业创建群数不可超过1000/天。

2.获取取客户群列表