SpringBoot多环境+docker集成企业微信会话存档sdk

2023/11/28
发布

## SpringBoot多环境+docker集成企业微信会话存档sdk


顺便吐槽一下,腾讯这个开发者社区的编辑器也太烂了,md都不支持,好歹也算是技术社区啊。。。样式看着不爽的,也可以去这里看


https://gitee.com/insky/doc/blob/master/%E6%8A%80%E6%9C%AF%E6%96%87%E7%AB%A0/%E8%85%BE%E8%AE%AF%E6%8E%A5%E5%8F%A3/%E4%BC%81%E4%B8%9A%E5%BE%AE%E4%BF%A1/SpringBoot%E5%A4%9A%E7%8E%AF%E5%A2%83+docker%E9%9B%86%E6%88%90%E4%BC%81%E4%B8%9A%E5%BE%AE%E4%BF%A1%E4%BC%9A%E8%AF%9D%E5%AD%98%E6%A1%A3sdk.md




对于现在基本流行的springboot环境,官方文档真是比较坑的,基本都要自己摸索。


以下代码大家根据自己项目调整,无需生搬硬套,代码不重要,主要了解到其中的思路和坑点。




### 一. 主要目录结构


hell
├─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │   ├─ft
│ │ │   │ └─qb
│ │ │   │   └─job
│ │ │   │     └─biz
│ │ │   │       └─employee
│ │ │   │        └─qywx
│ │ │   │          └─QywxMessageWinJob.java		# 业务主入口,定时任务执行入口
│ │ │   └─tencent
│ │ │     └─wework
│ │ │       └─Finance.java								# 企业微信sdk中的Finance.java文件copy过来(切记,包名不能错)
│ │ └─resources
│ │   ├─config
│ │   └─lib
│ │     └─qywx
│ │       └─linux
│ │       	 └─libWeWorkFinanceSdk_Java.so				# 企业微信linux sdk中的同名文件
│ │       	 └─libWeWorkFinanceSdk.so				# copy自libWeWorkFinanceSdk_Java.so,改名
│ │       └─win
│ │       	 └─libcrypto-1_1-x64.dll				# 企业微信linux sdk中的同名文件
│ │       	 └─libcurl-x64.dll						# 企业微信linux sdk中的同名文件
│ │       	 └─libssl-1_1-x64.dll					# 企业微信linux sdk中的同名文件
│ │       	 └─WeWorkFinanceSdk.dll					# 企业微信linux sdk中的同名文件



注意:


  • Finance.java文件的包名千万不能错,一定要是com.tencent.wework。

-   linux下的sdk中libWeWorkFinanceSdk_Java.so要改名为libWeWorkFinanceSdk.so,后面都是使用这个libWeWorkFinanceSdk.so。别TM问为什么,我也想知道为什么,腾讯的程序员不出来解释一下么?文档中没有提及,完全的大坑,我也是看了某个老兄的帖子才改的。




实际项目截图:


!image-20231128154354561


### 二. 改造Finance.java文件


因为sdk是分win和linux环境的,所以我们需要对Finance.java进行一些改造,使之可以判断win和linux环境,自动切换加载的dll或so文件。




修改static部分的代码:


ava
  static {
    if (isWindows()) {
      // win。获取4个dll的实际位置,下边使用System.load来加载dll。
      String path = System.getProperty("user.dir") + "\\src\\main\\resources\\lib\\qywx\\win\\";
      path = path.replaceAll("%20", " ").replaceFirst("/", "").replace("/", "\\\\");

      //加载顺序不能变
      System.load(path.concat("libcrypto-1_1-x64.dll"));
      System.load(path.concat("libssl-1_1-x64.dll"));
      System.load(path.concat("libcurl-x64.dll"));
      System.load(path.concat("WeWorkFinanceSdk.dll"));

    } else {
      // linux。加载指定so文件在linux系统下的位置。
      // docker的话这行也可以不要。这里有点小坑,后文会讲。
      System.load("/usr/lib/libWeWorkFinanceSdk.so");

    }
     
    //这行是本身Finance.java就有的,别丢掉。
    System.loadLibrary("WeWorkFinanceSdk");
  }

  public static boolean isWindows() {
    String osName = System.getProperties().getProperty("os.name");
    return osName.toUpperCase().indexOf("WINDOWS") != -1;
  }



自建一个isWindows()方法来判断当前的运行环境。然后在static中根据环境加载不同的dll和so就可以了。




### 三、win & linux


在win或linux运行,看一下主程序调用入口文件QywxMessageWinJob.java。


ava
package com.ft.qb.job.biz.employee.job;

import com.tencent.wework.Finance;

import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.File;
import java.lang.reflect.Field;

/**
 * 用于调用企业微信接口,获取会话存到内容,持久化到数据库
 */
@Component
@Slf4j
public class QywxMessageWinJob {

  @Value("${project.qywx.session-message.corpid}")
  private String corpid;
  @Value("${project.qywx.session-message.secret}")
  private String secret;


  @XxlJob("QywxMessageJob_syncMessage")
  public void syncMessage() {

    try {
      long ret = 0;

      //使用sdk前需要初始化,初始化成功后的sdk可以一直使用。
      //如需并发调用sdk,建议每个线程持有一个sdk实例。
      //初始化时请填入自己企业的corpid与secrectkey。
      long sdk = Finance.NewSdk();

      ret = Finance.Init(sdk, this.corpid, this.secret);


    }catch(Exception e){
      log.error("企业微信会话sdk初始化失败:", e);
      throw e;
    }

    log.info("sdk加载成功了,继续!!!");
  }

}



只要上一步Finance.java别改错,基本上就run通了。




### 四、docker


docker环境比较特殊。


  1. 一定要注意不要使用alpine版本的java镜像做基础镜像,会丢失一些基础的so文件,导致sdk加载失败。


 ```shell

 # 基础镜像

 FROM openjdk:17-jdk-alpine

 ```


 比如我一开始是openjdk:17-jdk-alpine镜像,当Finance.java执行到System.loadLibrary("WeWorkFinanceSdk")的时候,会报错找不到ld-linux-x86-64.so.2


 ```shell

 java.lang.UnsatisfiedLinkError: /usr/lib/libWeWorkFinanceSdk.so: Error loading shared library ld-linux-x86-64.so.2: No such file or directory (needed by /usr/lib/libWeWorkFinanceSdk.so)

 ```


  1. 将libWeWorkFinanceSdk.so放入docker镜像中。在DockerFile中加一行copy libWeWorkFinanceSdk_Java.so


 ```shell

 # 基础镜像

 FROM openjdk:17-jdk

  

 # copy libWeWorkFinanceSdk_Java.so

 COPY src/main/resources/lib/qywx/linux/libWeWorkFinanceSdk.so /usr/lib/libWeWorkFinanceSdk.so

  

 ADD target/app.jar app.jar

  

 # 更改为中国时区

 RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

 RUN echo 'Asia/Shanghai' >/etc/timezone

  

 # 启动容器时执行

 ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-Ddruid.mysql.usePingMethod=false","-jar","app.jar"]

 # 使用端口80

 EXPOSE 29202 29203

 ```

  

 这里如果加了这行copy,因为jdk容器中,/usr/lib属于java的运行时目录,所以Finance.java文件中的System.load("/usr/lib/libWeWorkFinanceSdk.so");这行加不加是无所谓的。

  

 下边执行的System.loadLibrary("WeWorkFinanceSdk");会自动在/usr/lib目录中加载到WeWorkFinanceSdk的。




如上,根据自己的项目改改,基本都是可以run通的。


评论·3
2024/03/29

源码地址没有吗

赞同 1
评论
2023/12/06
        long ret = 0;
        long sdk = Finance.NewSdk();


        ret = Finance.Init(sdk, this.corpid, this.secret);


        if (ret != 0) {
            Finance.DestroySdk(sdk);
            log.error("企业微信会话存档sdk异常[err ret]:ret=" + ret);
            return;
        }


        int startSeq = 0;
        int limit = 1000;
        int timeout = 1000;


        
        long slice = Finance.NewSlice();
        ret = Finance.GetChatData(sdk, startSeq, limit, "", "", timeout, slice);
赞同
评论 3
2023/12/06
嗯呢,没有传错,除了代理参数我传的数null,timeout我传的是50,其他都没区别,T_T
赞同
回复
2023/12/06
我没有用容器启动,直接在linux上用java命令启动,so文件在/usr/lib,也配置了环境变量
赞同
回复
2023/12/06
参数改成和我一样试试。感觉应该是你的corpid和secret有问题
赞同
回复
你还未登录,请先登录
2023/12/06

你好,我部署在linux上,加载System.loadLibrary("WeWorkFinanceSdk");就卡住,一直加载不成功,是什么原因呢,加载so文件没问题


赞同
评论 5
2023/12/06
这里卡主的话会报错:java.lang.UnsatisfiedLinkError: no WeWorkFinanceSdk in java.library.path: D:\Program Files\Java\jdk-17\bin;C:\WINDOWS\Sun\Java\bin;
确保你的so文件在这些目录里存在
赞同 1
回复
回复 2023/12/06
谢谢了,已经解决了,但是企微一直返回41001,corpId用的也是明文,secret用的是会话存档的secret,ip也在白名单,不知道为啥
赞同
回复
2023/12/06
你是哪一行报错的?
赞同
回复
回复 2023/12/06
Finance.getChatData,就会返回41001,sdk的初始化都是正常的,没有异常
赞同
回复
2023/12/06
我的代码发下边,你参考下,参数别传错了
赞同
回复
你还未登录,请先登录