企业微信API客户端

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了企业微信API客户端相关的知识,希望对你有一定的参考价值。

参考技术A 企业微信API封装

使用示例

java对接企业微信

java对接企业微信

一、注册企业微信

1.1 简介

  企业微信与微信具有一样的体验,通过企业内部与外部客户的管理,构建出社群生态。企业微信提供丰富的api进行调用获取数据管理,也提供各种回调事件。

1.2 注册

  登录官网,一键注册即可。链接: 企业微信

1.2 填写主要信息

  企业微信中填写相关企业信息和负责人,然后创建。进入即可添加所需要的微信人员。

  之后进行通讯录同步(此步骤为最重要一点),同步过后通讯录的人员根据调用接口接收消息。

1.3 创建应用

  创建自己需要的应用,并根据提示创建应用(也可以不创建,用以前有的应用作为发送消息的主体也可以)

二、企业微信基础信息

  创建完企业微信和自己所需要的应用后,需要记住几处重要的参数,方便后续调用api使用。

  简单介绍几个参数:(需存入数据库)
1.企业id:当前企业微信的固定id;
2.agentid:当前自建应用id;
3.secret:应用秘钥,调用验证秘钥;

注:企业应用的可见范围需添加微信中的人员表。为后续调用查询、发送人员作限定选择。

三、消息接收url机制-回调

  在java集成企业微信的同时,需要一个回调服务。现可以实现:
自定义丰富的服务行为、可以及时获取状态变化。

  通过企业微信服务器向后端服务器发送各种需要消息。
这里只讲配置建立消息接收url机制。


  附录上述两张图,其中包含设置可信ip(开发服务器的ip,为了服务器调用api)、配置接收服务器(通过回调机制+配置,验证url是否能接收到消息,并返回企业微信所需要的信息来校验)。加密解密见附录五。
回调配置

能通过发送来的密文(附录5中具体解密),返回给企业微信端需要的密文。即可通过校验,然后就可以填写认证ip进行开发调用接口。

  简单介绍几个参数:(需存入数据库)
1.url:接收企业微信消息的接口
2.token:计算签名(可在配置中随机生成)
3.encoding_aes_key:加密key(加解密使用)

四、java对接企业微信(自建应用)

  在上几个步骤中,我们已有需求的5个参数配置。根据这5个参数就可以进行与java对接。

4.1 对接前提(获取access_token)


token是调用接口的基础。根据之前的保存参数即可获取。以下展示为项目所需接口调用,其他接口使用token基本都能调用。

4.2 手机号获取userid

4.3 发送应用消息



本文只展示文本方面,其他发送信息方面可参照api接口。api接口

五、附加-校验加密解密方式

5.1 方案说明


5.2 代码实例

/**
 * @Author sprem至尊
 * @Date 2022/10/21 16:43
 * @Version 1.0
 */
package com.example.demo.controller;

import com.example.demo.aes.WXBizJsonMsgCrypt;
import com.example.demo.cache.TokenCache;
import com.example.demo.entity.TestEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController 

    @Autowired
    private TokenCache tokenCache;

    @RequestMapping("/")
    private String home(TestEntity testEntity) //postman的参数放在form-data中 不然特殊符号会变空格
        String sToken = "axBoJ9yw3NeLPffBNUTQlfXiP612Xdpw";//SSrYt12q2KL  QDG6eK
        String sCorpID = "ww1ca8f5fe0f582941e9";//""wwca8f511fe0f58941e9"; wx5823bf96d3bd561c7
        String sEncodingAESKey = "Sb8eDJndNDPjIyzqFzMI2sKtOfgoCYMrIWjqu2m1ql3Vb";// W5UBw9XoqW61HPfL7TUsI4qC2myJrw3MQ9bDrbDsWWQ2
        //jWmYm7qr5nMoAUwZRjGtBxmz3K4A1tkAj3ykkR6q2B2C
        String sVerifyMsgSig = testEntity.getMsg_signature();
        String sVerifyTimeStamp = testEntity.getTimestamp();
        String sVerifyNonce = testEntity.getNonce();
        String sVerifyEchoStr = testEntity.getEchostr();
        String sEchoStr ="";//明文
        try 
            //获取其中 aesKey
            WXBizJsonMsgCrypt wxcpt = new WXBizJsonMsgCrypt(sToken, sEncodingAESKey, sCorpID);
            //获取明文
            sEchoStr = wxcpt.VerifyURL(sVerifyMsgSig,sVerifyTimeStamp,sVerifyNonce,
                    sVerifyEchoStr);
            System.out.println("verifyurl echostr: " + sEchoStr);
        catch (Exception e)
            e.printStackTrace();
        
        return sEchoStr;
    
    @RequestMapping("/testCache")
    private String testCache() 
        String s = TokenCache.getValue("s1111");
        if(s==null)
            System.out.println("时间过期");
            TokenCache.setKey("s12111","1243123123");
            s =TokenCache.getValue("s12111");
        
        System.out.println(s);
        return "sss";
    


/**
 * @Author sprem至尊
 * @Date 2022/10/21 17:00
 * @Version 1.0
 */
package com.example.demo.entity;
import lombok.Data;
@Data
public class TestEntity 
    private String msg_signature;
    private String timestamp;
    private String nonce;
    private String echostr;


package com.example.demo.aes;

@SuppressWarnings("serial")
public class AesException extends Exception 

	public final static int OK = 0;
	public final static int ValidateSignatureError = -40001;
	public final static int ParseJsonError = -40002;
	public final static int ComputeSignatureError = -40003;
	public final static int IllegalAesKey = -40004;
	public final static int ValidateCorpidError = -40005;
	public final static int EncryptAESError = -40006;
	public final static int DecryptAESError = -40007;
	public final static int IllegalBuffer = -40008;
	public final static int EncodeBase64Error = -40009;
	public final static int DecodeBase64Error = -40010;
	public final static int GenReturnJsonError = -40011;

	private int code;

	private static String getMessage(int code) 
		switch (code) 
		case ValidateSignatureError:
			return "签名验证错误";
		case ParseJsonError:
			return "json解析失败";
		case ComputeSignatureError:
			return "sha加密生成签名失败";
		case IllegalAesKey:
			return "SymmetricKey非法";
		case ValidateCorpidError:
			return "corpid校验失败";
		case EncryptAESError:
			return "aes加密失败";
		case DecryptAESError:
			return "aes解密失败";
		case IllegalBuffer:
			return "解密后得到的buffer非法";
		case EncodeBase64Error:
			return "base64加密错误";
		case DecodeBase64Error:
			return "base64解密错误";
		case GenReturnJsonError:
			return "josn生成失败";
		default:
			return null; // cannot be
		
	

	public int getCode() 
		return code;
	

	AesException(int code) 
		super(getMessage(code));
		this.code = code;
	



package com.example.demo.aes;

import java.util.ArrayList;

class ByteGroup 
	ArrayList<Byte> byteContainer = new ArrayList<Byte>();

	public byte[] toBytes() 
		byte[] bytes = new byte[byteContainer.size()];
		for (int i = 0; i < byteContainer.size(); i++) 
			bytes[i] = byteContainer.get(i);
		
		return bytes;
	

	public ByteGroup addBytes(byte[] bytes) 
		for (byte b : bytes) 
			byteContainer.add(b);
		
		return this;
	

	public int size() 
		return byteContainer.size();
	


/**
 * 对企业微信发送给企业后台的消息加解密示例代码.
 * 
 * @copyright Copyright (c) 1998-2020 Tencent Inc.
 */

// ------------------------------------------------------------------------

package com.example.demo.aes;

/**
 * 针对 org.json.JSONObject,
 * 要编译打包架包json
 * 官方源码下载地址 : https://github.com/stleary/JSON-java, jar包下载地址 : https://mvnrepository.com/artifact/org.json/json
 */
import org.json.JSONObject;


/**
 * JsonParse class
 *
 * 提供提取消息格式中的密文及生成回复消息格式的接口.
 */
class JsonParse 

	/**
	 * 提取出 JSON 包中的加密消息
	 * @param jsontext 待提取的json字符串
	 * @return 提取出的加密消息字符串
	 * @throws AesException 
	 */
	public static Object[] extract(String jsontext) throws AesException     
		Object[] result = new Object[3];
		try 

			JSONObject json = new JSONObject(jsontext);    
        	String encrypt_msg = json.getString("encrypt");
			String tousername  = json.getString("tousername");
			String agentid     = json.getString("agentid");

			result[0] = tousername;
			result[1] = encrypt_msg;
			result[2] = agentid;
			return result;
		 catch (Exception e) 
			e.printStackTrace();
			throw new AesException(AesException.ParseJsonError);
		
	

	/**
	 * 生成json消息
	 * @param encrypt 加密后的消息密文
	 * @param signature 安全签名
	 * @param timestamp 时间戳
	 * @param nonce 随机字符串
	 * @return 生成的json字符串
	 */
	public static String generate(String encrypt, String signature, String timestamp, String nonce) 

		String format = "\\"encrypt\\":\\"%1$s\\",\\"msgsignature\\":\\"%2$s\\",\\"timestamp\\":\\"%3$s\\",\\"nonce\\":\\"%4$s\\"";
		return String.format(format, encrypt, signature, timestamp, nonce);

	


/**
 * 对企业微信发送给企业后台的消息加解密示例代码.
 * 
 * @copyright Copyright (c) 1998-2014 Tencent Inc.
 */

// ------------------------------------------------------------------------

package com.example.demo.aes;

import java.nio.charset.Charset;
import java.util.Arrays;

/**
 * 提供基于PKCS7算法的加解密接口.
 */
class PKCS7Encoder 
	static Charset CHARSET = Charset.forName("utf-8");
	static int BLOCK_SIZE = 32;

	/**
	 * 获得对明文进行补位填充的字节.
	 * 
	 * @param count 需要进行填充补位操作的明文字节个数
	 * @return 补齐用的字节数组
	 */
	static byte[] encode(int count) 
		// 计算需要填充的位数
		int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
		if (amountToPad == 0) 
			amountToPad = BLOCK_SIZE;
		
		// 获得补位所用的字符
		char padChr = chr(amountToPad);
		String tmp = new String();
		for (int index = 0; index < amountToPad; index++) 
			tmp += padChr;
		
		return tmp.getBytes(CHARSET);
	

	/**
	 * 删除解密后明文的补位字符
	 * 
	 * @param decrypted 解密后的明文
	 * @return 删除补位字符后的明文
	 */
	static byte[] decode(byte[] decrypted) 
		int pad = (int) decrypted[decrypted.length - 1];
		if (pad < 1 || pad > 32) 
			pad = 0;
		
		return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
	

	/**
	 * 将数字转化成ASCII码对应的字符,用于对明文进行补码
	 * 
	 * @param a 需要转化的数字
	 * @return 转化得到的字符
	 */
	static char chr(int a) 
		byte target = (byte) (a & 0xFF);
		return (char) target;
	



/**
 * 对企业微信发送给企业后台的消息加解密示例代码.
 * 
 * @copyright Copyright (c) 1998-2014 Tencent Inc.
 */

// ------------------------------------------------------------------------

package com.example.demo.aes;

import java.security.MessageDigest;
import java.util.Arrays;

/**
 * SHA1 class
 *
 * 计算消息签名接口.
 */
class SHA1 

	/**
	 * 用SHA1算法生成安全签名
	 * @param token 票据
	 * @param timestamp 时间戳
	 * @param nonce 随机字符串
	 * @param encrypt 密文
	 * @return 安全签名
	 * @throws AesException 
	 */
	public static String getSHA1(String token, String timestamp, String nonce, String encrypt) throws AesException
			  
		try 
			String[] array = new String[]  token, timestamp, nonce, encrypt ;
			StringBuffer sb = new StringBuffer();
			// 字符串排序
			Arrays.sort(array);
			for (int i = 0; i < 4; i++) 
				sb.append(array[i]);
			
			String str = sb.toString();
			// SHA1签名生成
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			md.update(str.getBytes());
			byte[] digest = md.digest();

			StringBuffer hexstr = new StringBuffer();
			String shaHex = "";
			for (int i = 0; i < digest.length; i++) 
				shaHex = Integer.toHexString(digest[i] & 0xFF);
				if (shaHex.length() < 2) 
					hexstr.append(0);
				
				hexstr.append(shaHex);
			
			return hexstr.toString();
		 catch (Exception e) 
			e.printStackTrace();
			throw new AesException(AesException.ComputeSignatureError);
		
	


/**
 * 对企业微信发送给企业后台的消息加解密示例代码.
 * 
 * @copyright Copyright (c) 1998-2014 Tencent Inc.
 */

// ------------------------------------------------------------------------

/**
 * 针对org.apache.commons.codec.binary.Base64,
 * 需要导入架包commons-codec-1.9(或commons-codec-1.8等其他版本)
 * 官方下载地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi
 */
package com.example.demo.aes;

import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Random;

/**
 * 提供接收和推送给企业微信消息的加解密接口(UTF8编码的字符串).
 * <ol>
 * 	<li>第三方回复加密消息给企业微信</li>
 * 	<li>第三方收到企业微信发送的消息,验证消息的安全性,并对消息进行解密。</li>
 * </ol>
 * 说明:异常java.security.InvalidKeyException:illegal Key Size的解决方案
 * <ol>
 * 	<li>在官方网站下载JCE无限制权限策略文件(JDK7的下载地址:
 *      http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html</li>
 * 	<li>下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt</li>
 * 	<li>如果安装了JRE,将两个jar文件放到%JRE_HOME%\\lib\\security目录下覆盖原来的文件</li>
 * 	<li>如果安装了JDK,将两个jar文件放到%JDK_HOME%\\jre\\lib\\security目录下覆盖原来文件</li>
 * </ol>
 */
public class WXBizJsonMsgCrypt 
	static Charset CHARSET = Charset.forName("utf-8");
	Base64 base64 = new Base64();
	byte[] aesKey;
	String token;
	String receiveid;

	/**
	 * 构造函数
	 * @param token 企业微信后台,开发者设置的token
	 * @param encodingAesKey 企业微信后台,开发者设置的EncodingAESKey

以上是关于企业微信API客户端的主要内容,如果未能解决你的问题,请参考以下文章

企业微信侧边栏功能/微信企业授权

企业微信自定义客户画像

企业微信标签和个人标签,是不是可以根据部门之间设置可见,如果有,请问是不是有提供对应api接口?

java对接企业微信

微信企业号 JS-SDK:上传图片

微信企业号办公系统-图片预览放大功能-previewImage