通过企业微信服务端API接口进行群发应用消息 您所在的位置:网站首页 微信群发助手怎么看有没有发送成功 通过企业微信服务端API接口进行群发应用消息

通过企业微信服务端API接口进行群发应用消息

2024-07-09 09:40| 来源: 网络整理| 查看: 265

最近项目上需要用到企业微信应用进行消息的群发功能,用来将系统产生的告警消息通过企业微信群发的方式通知客户方,来达到及时处理故障的目的,使用了下还是较简单的,这里记录一下过程,备查。文章前面有一点术语的介绍,如果想快速直接看怎么使用,点击这里跳过基本术语介绍,直接开始。

一.基本术语介绍说明 1.corpid

每个企业都拥有唯一的corpid,获取此信息可在管理后台“我的企业”-“企业信息”下查看“企业ID”(需要有管理员权限) 在这里插入图片描述

2.userid

每个成员都有唯一的userid,即所谓“帐号”。在管理后台->“通讯录”->点进某个成员的详情页,可以看到。 在这里插入图片描述

3.部门id

每个部门都有唯一的id,在管理后台->“通讯录”->“组织架构”->点击某个部门右边的小圆点可以看到 在这里插入图片描述

4.tagid

每个标签都有唯一的标签id,在管理后台->“通讯录”->“标签”,选中某个标签,在右上角会有“标签详情”按钮,点击即可看到 在这里插入图片描述 在这里插入图片描述

5.agentid

每个应用都有唯一的agentid。在管理后台->“应用与小程序”->“应用”,点进某个应用,即可看到agentid。 在这里插入图片描述

6.secret

secret是企业应用里面用于保障数据安全的“钥匙”,每一个应用都有一个独立的访问密钥,为了保证数据的安全,secret务必不能泄漏。

自建应用secret。在管理后台->“应用与小程序”->“应用”->“自建”,点进某个应用,即可看到。 基础应用secret。某些基础应用(如“审批”“打卡”应用),支持通过API进行操作。在管理后台->“应用与小程序”->“应用->”“基础”,点进某个应用,点开“API”小按钮,即可看到。 通讯录管理secret。在“管理工具”-“通讯录同步”里面查看(需开启“API接口同步”); 客户联系管理secret。在“客户联系”栏,点开“API”小按钮,即可看到。 7.access_token

access_token是企业后台去企业微信的后台获取信息时的重要票据,由corpid和secret产生。所有接口在通信时都需要携带此信息用于验证接口的访问权限

二.通过企业微信服务端API群发应用消息 1.Http接口调用工具类准备

因为需要用到Http调用,这里提前准备2个Http的调用工具,一个是Java的Jdk自带实现的,不依赖任何jar包,可用于测试,如果你的调用量不多,也可以用于生产。另一个是依赖apache的httpClient,具备连接池功能,建议可用于生产。因为代码占内容太多,因此代码位于文章最后,可直接跳转至代码部署查看,点击即会跳转

2.获取access_token

官方接口文档:https://work.weixin.qq.com/api/doc/90000/90135/91039 请求方式:GET(HTTPS) 请求URL:https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRET 在这里插入图片描述 注:通常正式环境需要自己登陆后自行维护access_token,一般是2小时有效期,在快到期或已过期时需要重新登陆,可以用利用返回结果码为40014和42001分别表示为非法access_token和过期的access_token,可以利用此两个错误码进行判断与更新

测试代码: 使用纯Jdk实现的工具类进行调试:

public static void main(String[] args) throws Exception { String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ww160d****&corpsecret=BAtr2B***************"; HttpRestUtils util = new HttpRestUtils(); String result = util.doGet(url); System.out.println(result); }

或者使用apache的httpClient的工具类调试:

public static void main(String[] args) throws InterruptedException { //这里把你的corpid和corpsecret替换成正确的 String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ww160d****&corpsecret=BAtr2B***************"; System.out.println(HttpsKit.get(url)); //关闭连接池,正式环境中这个不要关闭 HttpsKit.closeConnectionPool(); }

响应接果:

{"errcode":0,"errmsg":"ok","access_token":"vMpg1HNU8PHf0qqNSfVGMXw2Gg0HN16LnvMH3J4LXeoY5MMA25PiO2ZabcdHJ6bRi5PqUuyLf94aRBb3yTKs344h5eU35doprLeIKtuf9xfKOk8VQ6F_GeTuxmcV_qQH0CLOrc5y9cXT9SCEi7LpQCiS4F4ssdff0zu-jyGmlEtUBplqSF8xDQBJ3aj6-hfg","expires_in":7200} 3.调用群应用消息发送接口即可

群应用消息发送接口官方文档:https://work.weixin.qq.com/api/doc/90000/90135/90236 应用支持推送文本、图片、视频、文件、图文等类型。 请求方式:POST(HTTPS) 请求地址: https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=ACCESS_TOKEN

以文本消息为例,access_token在请求地址里面,其他的参数就是以json方式封装,其他的参数可参看详情的上面的文档获取。比如以下截图即从官方文档中获取到的 在这里插入图片描述 测试代码如下: 使用纯Jdk实现的工具类进行调试:

public static void main(String[] args) throws Exception { String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=JhLKJB2cZssssssssssssssssssssssssssssssssssssU2HHQ"; HttpRestUtils util = new HttpRestUtils(); String paramStr = "{\"touser\":\"@all\",\"msgtype\":\"text\",\"agentid\":1000001,\"text\":{\"content\":\"测试下应用群发告警消息,打扰了,请忽略。\"}}"; String result = util.doPost(url, paramStr); System.out.println(result); }

或者使用apache的httpClient的工具类调试:

public static void main(String[] args) throws InterruptedException { String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=JhLKJB2cZssssssssssssssssssssssssssssssssssssU2HHQ"; String data = "{\"touser\":\"@all\",\"msgtype\":\"text\",\"agentid\":1000001,\"text\":{\"content\":\"测试下应用群发告警消息,打扰了,请忽略。\"}}"; System.out.println(HttpsKit.postJson(url, data)); //关闭连接池,正式环境中这个不要关闭 HttpsKit.closeConnectionPool(); } 4.Http接口调用工具类代码提供如下

工具类1:使用纯jdk自带的URLConnection实现的

package cn.gzsendi.system.utils; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; public class HttpRestUtils { private final String GET = "GET"; private final String POST = "POST"; private final String CharacterSet = "UTF-8"; public String doGet(String url) throws Exception{ String method = this.GET; return load(url,null,method); } public String doPost(String url, String params) throws Exception{ String method = this.POST; return load(url,params,method); } /** * @param url * @param params * @param method * @return * @throws Exception */ public String load(String url,String params,String method) throws Exception { HttpURLConnection conn = null; try { boolean isHttps = url.startsWith("https"); URL restURL = new URL(url); conn = (HttpURLConnection) restURL.openConnection(); //https请求需要格外处理下 if(isHttps) { TrustManager[] tm = { new MyX509TrustManager() }; SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); sslContext.init(null, tm, new java.security.SecureRandom()); SSLSocketFactory ssf = sslContext.getSocketFactory(); ((HttpsURLConnection)conn).setSSLSocketFactory(ssf); ((HttpsURLConnection)conn).setHostnameVerifier(new TrustAnyHostnameVerifier()); } conn.setDoOutput(true); conn.setAllowUserInteraction(false); conn.setUseCaches(false); conn.setRequestMethod(method); conn.connect(); OutputStreamWriter out = null; OutputStream outputStream = null; if(this.POST.equals(method) && params != null){ outputStream = conn.getOutputStream(); out = new OutputStreamWriter(outputStream, this.CharacterSet); out.write(params); out.close(); } InputStream inputStream = conn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, this.CharacterSet); BufferedReader bReader = new BufferedReader(inputStreamReader); String line = ""; StringBuffer resultStr = new StringBuffer(); while (null != (line = bReader.readLine())) { resultStr.append(line); } // 释放资源 bReader.close(); inputStreamReader.close(); inputStream.close(); inputStream = null; if(out!=null) out.close(); if(outputStream!=null)outputStream.close(); return resultStr.toString(); } catch (Exception e) { e.printStackTrace(); } finally { if(conn != null) conn.disconnect(); } return null; } private class TrustAnyHostnameVerifier implements HostnameVerifier { public boolean verify(String hostname, SSLSession session) { // 直接返回true return true; } } private class MyX509TrustManager implements X509TrustManager { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } } }

工具类2:使用apache的httpclient进行编写实现类 注:pom依赖,我的工具类里面用到了common-io,httpclient,和log4j,其中log4j如果你不想要,可以根据代码进行调整删除,common-io也是一样,也可以采用其他方法,修改点代码就可。

org.apache.httpcomponents httpclient 4.5.12 org.apache.httpcomponents httpmime 4.5.12 commons-io commons-io 2.7 org.slf4j slf4j-api 1.7.25 ch.qos.logback logback-core 1.2.3 ch.qos.logback logback-classic 1.2.3 package cn.gzsendi.system.utils; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TimerTask; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLException; import javax.net.ssl.SSLHandshakeException; import org.apache.commons.codec.CharEncoding; import org.apache.commons.io.IOUtils; import org.apache.http.Consts; import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpRequest; import org.apache.http.NameValuePair; import org.apache.http.NoHttpResponseException; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.clienthods.CloseableHttpResponse; import org.apache.http.clienthods.HttpGet; import org.apache.http.clienthods.HttpPost; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.LayeredConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.NoopHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.TrustStrategy; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.message.BasicNameValuePair; import org.apache.http.protocol.HttpContext; import org.apache.http.ssl.SSLContextBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class HttpsKit { private static Logger logger = LoggerFactory.getLogger(HttpsKit.class); private static final int CONNECT_TIMEOUT = 10000;// 设置连接建立的超时时间为10000ms private static final int SOCKET_TIMEOUT = 30000; // 多少时间没有数据传输 private static final int HttpIdelTimeout = 30000;//空闲时间 private static final int HttpMonitorInterval = 10000;//多久检查一次 private static final int MAX_CONN = 200; // 最大连接数 private static final int Max_PRE_ROUTE = 200; //设置到路由的最大连接数, private static CloseableHttpClient httpClient; // 发送请求的客户端单例 private static PoolingHttpClientConnectionManager manager; // 连接池管理类 private static ScheduledExecutorService monitorExecutor; private static final String APPLICATION_FORM_URLENCODED = "application/x-www-form-urlencoded"; private static final String APPLICATION_JSON = "application/json"; private final static Object syncLock = new Object(); // 相当于线程锁,用于线程安全 private static RequestConfig requestConfig = RequestConfig.custom() .setConnectionRequestTimeout(CONNECT_TIMEOUT) .setConnectTimeout(CONNECT_TIMEOUT) .setSocketTimeout(SOCKET_TIMEOUT).build(); private static CloseableHttpClient getHttpClient() { if (httpClient == null) { // 多线程下多个线程同时调用getHttpClient容易导致重复创建httpClient对象的问题,所以加上了同步锁 synchronized (syncLock) { if (httpClient == null) { try { httpClient = createHttpClient(); } catch (KeyManagementException e) { logger.error("error",e); } catch (NoSuchAlgorithmException e) { logger.error("error",e); } catch (KeyStoreException e) { logger.error("error",e); } // 开启监控线程,对异常和空闲线程进行关闭 monitorExecutor = Executors.newScheduledThreadPool(1); monitorExecutor.scheduleAtFixedRate(new TimerTask() { @Override public void run() { // 关闭异常连接 manager.closeExpiredConnections(); // 关闭5s空闲的连接 manager.closeIdleConnections(HttpIdelTimeout,TimeUnit.MILLISECONDS); logger.info(manager.getTotalStats().toString()); //logger.info("close expired and idle for over "+HttpIdelTimeout+"ms connection"); } }, HttpMonitorInterval, HttpMonitorInterval, TimeUnit.MILLISECONDS); } } } return httpClient; } /** * 构建httpclient实例 * @return * @throws KeyStoreException * @throws NoSuchAlgorithmException * @throws KeyManagementException */ private static CloseableHttpClient createHttpClient() throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException { SSLContextBuilder builder = new SSLContextBuilder(); // 全部信任 不做身份鉴定 builder.loadTrustMaterial(null, new TrustStrategy() { @Override public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { return true; } }); ConnectionSocketFactory plainSocketFactory = PlainConnectionSocketFactory.getSocketFactory(); LayeredConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory(builder.build(), NoopHostnameVerifier.INSTANCE); Registry registry = RegistryBuilder . create() .register("http", plainSocketFactory) .register("https", sslSocketFactory).build(); manager = new PoolingHttpClientConnectionManager(registry); // 设置连接参数 manager.setMaxTotal(MAX_CONN); // 最大连接数 manager.setDefaultMaxPerRoute(Max_PRE_ROUTE); // 路由最大连接数 // 请求失败时,进行请求重试 HttpRequestRetryHandler handler = new HttpRequestRetryHandler() { @Override public boolean retryRequest(IOException e, int i, HttpContext httpContext) { if (i > 3) { // 重试超过3次,放弃请求 logger.error("retry has more than 3 time, give up request"); return false; } if (e instanceof NoHttpResponseException) { // 服务器没有响应,可能是服务器断开了连接,应该重试 logger.error("receive no response from server, retry"); return true; } if (e instanceof SSLHandshakeException) { // SSL握手异常 logger.error("SSL hand shake exception"); return false; } if (e instanceof InterruptedIOException) { // 超时 logger.error("InterruptedIOException"); return false; } if (e instanceof UnknownHostException) { // 服务器不可达 logger.error("server host unknown"); return false; } if (e instanceof ConnectTimeoutException) { // 连接超时 logger.error("Connection Time out"); return false; } if (e instanceof SSLException) { logger.error("SSLException"); return false; } HttpClientContext context = HttpClientContext.adapt(httpContext); HttpRequest request = context.getRequest(); if (!(request instanceof HttpEntityEnclosingRequest)) { // 如果请求不是关闭连接的请求 return true; } return false; } }; CloseableHttpClient client = HttpClients.custom().setConnectionManager(manager).setRetryHandler(handler).build(); return client; } public static String get(String url) { HttpGet httpGet = new HttpGet(url); httpGet.setHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"); httpGet.setConfig(requestConfig); CloseableHttpResponse response = null; InputStream in = null; String result = null; try { response = getHttpClient().execute(httpGet,HttpClientContext.create()); HttpEntity entity = response.getEntity(); if (entity != null) { in = entity.getContent(); result = IOUtils.toString(in, "utf-8"); } } catch (IOException e) { logger.error("error",e); } finally { try { if (in != null) in.close(); } catch (IOException e) { logger.error("error",e); } try { if (response != null) response.close(); } catch (IOException e) { logger.error("error",e); } } return result; } public static String postJson(String url,Map requestParams) { return postJson(url, JsonUtil.toJSONString(requestParams)); } public static String postJson(String url,Map requestParams,Map headerParams) { return postJson(url, JsonUtil.toJSONString(requestParams),headerParams); } public static String postJson(String url,String requestParamStr) { return postJson(url, requestParamStr, null); } public static String postJson(String url,String requestParamStr,Map headerParams) { HttpPost httppost = new HttpPost(url); httppost.setHeader("Content-Type", APPLICATION_JSON+";charset=" + CharEncoding.UTF_8); httppost.setHeader("Accept",APPLICATION_JSON+";charset=" +CharEncoding.UTF_8); httppost.setHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"); if(headerParams != null && headerParams.size()>0){ for(String headerName : headerParams.keySet()) { httppost.setHeader(headerName,headerParams.get(headerName)+""); } } StringEntity se = new StringEntity(requestParamStr,CharEncoding.UTF_8); se.setContentType(APPLICATION_JSON+";charset=" +CharEncoding.UTF_8); httppost.setEntity(se); httppost.setConfig(requestConfig); CloseableHttpResponse response = null; InputStream in = null; String result = null; try { response = getHttpClient().execute(httppost,HttpClientContext.create()); HttpEntity entity = response.getEntity(); if (entity != null) { in = entity.getContent(); result = IOUtils.toString(in, "utf-8"); } } catch (IOException e) { logger.error("error",e); } finally { try { if (in != null) in.close(); } catch (IOException e) { logger.error("error",e); } try { if (response != null) response.close(); } catch (IOException e) { logger.error("error",e); } } return result; } //requestParamStr---------->>> name=test&age=12 public static String postFormUrlencoded(String url,String requestParamStr) { return postFormUrlencoded(url, requestParamStr ,null); } public static String postFormUrlencoded(String url,String requestParamStr,Map headerParams) { Map requestParams = new HashMap(); String[] strs = requestParamStr.split("&"); for(String str : strs) { String[] keyValues = str.split("="); if(keyValues.length == 2) { requestParams.put(keyValues[0], keyValues[1]); } } return postFormUrlencoded(url, requestParams,headerParams); } public static String postFormUrlencoded(String url,Map requestParams) { return postFormUrlencoded(url,requestParams,null); } public static String postFormUrlencoded(String url,Map requestParams,Map headerParams) { HttpPost httppost = new HttpPost(url); //application/json httppost.setHeader("Content-Type", APPLICATION_FORM_URLENCODED+";charset=" + CharEncoding.UTF_8); httppost.setHeader("Accept",APPLICATION_FORM_URLENCODED+";charset=" +CharEncoding.UTF_8); httppost.setHeader("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36"); if(headerParams != null && headerParams.size()>0){ for(String headerName : headerParams.keySet()) { httppost.setHeader(headerName,headerParams.get(headerName)+""); } } List formparams = new ArrayList(); for(String keyStr : requestParams.keySet()) { formparams.add(new BasicNameValuePair(keyStr, requestParams.get(keyStr))); } UrlEncodedFormEntity uefe = new UrlEncodedFormEntity(formparams, Consts.UTF_8); httppost.setEntity(uefe); httppost.setConfig(requestConfig); CloseableHttpResponse response = null; InputStream in = null; String result = null; try { response = getHttpClient().execute(httppost,HttpClientContext.create()); HttpEntity entity = response.getEntity(); if (entity != null) { in = entity.getContent(); result = IOUtils.toString(in, "utf-8"); } } catch (IOException e) { logger.error("error",e); } finally { try { if (in != null) in.close(); if (response != null) response.close(); } catch (IOException e) { logger.error("error",e); } } return result; } /** * 关闭连接池 */ public static void closeConnectionPool() { try { if(httpClient != null) httpClient.close(); if(manager != null) manager.close(); if(monitorExecutor != null) monitorExecutor.shutdown(); } catch (IOException e) { logger.error("error",e); } } }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有