12月份接到一个年度总结的项目。要求总结报告通过企业微信推送给用户,这时候就要用到企业微信的接口了,这时候就要注意了,
1,首先确认Corpid和Corpsecret,AgentId,
企业微信测试要认证,我这边是用户提供的所以不方便透露
2,消息推送有很多种,我接触到的有三种,图文推送,文本推送,其中图文推送有点击图文直接进入页面的,还有一种是点击图片有一篇你可以自定义的文章,文章下有阅读原文才是你程序的页面链接
这个是点击就能进去的图文消息模式
{
"touser" : "UserID1|UserID2|UserID3",
"toparty" : "PartyID1 | PartyID2",
"totag" : "TagID1 | TagID2",
"msgtype" : "news",
"agentid" : 1,
"news" : {
"articles" : [
{
"title" : "中秋节礼品领取",
"description" : "今年中秋节公司有豪礼相送",
"url" : "URL",
"picurl" : "http://res.mail.qq.com/node/ww/wwopenmng/images/independent/doc/test_pic_msg1.png",
"appid": "",
"pagepath": ""
}
]
},
"enable_id_trans": 0,
"enable_duplicate_check": 0,
"duplicate_check_interval": 1800
}
这些是传入参数,url可以直接填写程序的入口,appid可以不填写,图片路径我之前使用本地路径是不可以的,选择网络路径或者项目路径都行,应该是外网要能访问的,至于外网如何访问你的,你可以用内网穿透natapp来测试
注意注意注意 !!!!看官方文档时仔细了,touser要认真填,我当时填的是@all,结果所有人都能收到,没几分钟就挨叼了
3,消息推送 代码展示
public static String sendQyAppMessage(String content, List<String> empCodes, String imageUrl, String media_id) { //获取企业微信的access_token String token = getQyAccessToken(false); // String token = TOKEN; System.out.println(token); StringBuilder stringBuilder = new StringBuilder(); //遍历empCodes,拼接字符串 for (String empCode : empCodes) { stringBuilder.append(empCode).append("|"); } //删除最后一个| stringBuilder.deleteCharAt(stringBuilder.length() - 1); String toUser = stringBuilder.toString(); //TODO 推送消息的内容 String requestBody = "{ \"touser\": \"%s\"," + " \"toparty\": \"\", " + "\"totag\": \"\", " + "\"msgtype\": \"news\", " + "\"agentid\": %s, " + "\"news\": { " + "\"articles\":[ " + "{ \"title\": \"年度工作数字报告\"," + " \"description\": \"用数字报告解锁你的独家故事\"," + " \"url\": \"https://nb.sugh.net/toindex\", " + "\"picurl\": \"%s\", " + "\"appid\": \"\", " + "\"pagepath\": \"\" } ] }," + "\"enable_id_trans\": 0," + " \"enable_duplicate_check\": 0," + " \"duplicate_check_interval\": 1800 }"; requestBody = String.format(requestBody, toUser, ConfKit.entAgentId, imageUrl); System.out.println(requestBody); String url = SEND_APP_MESSAGE_URL.replace("ACCESS_TOKEN", token); // 要发送的 JSON 请求体 try { HttpClient httpClient = HttpClients.createDefault(); // 创建 POST 请求 HttpPost httpPost = new HttpPost(url); // 设置请求头部信息 httpPost.setHeader("Content-Type", "application/json"); // 设置请求体 StringEntity stringEntity = new StringEntity(requestBody, StandardCharsets.UTF_8); httpPost.setEntity(stringEntity); // 发送请求并获取响应 HttpResponse response = httpClient.execute(httpPost); // 处理响应 HttpEntity responseEntity = response.getEntity(); BufferedReader reader = new BufferedReader(new InputStreamReader(responseEntity.getContent())); String line; StringBuilder responseBuilder = new StringBuilder(); while ((line = reader.readLine()) != null) { responseBuilder.append(line); } // 输出响应结果 System.out.println("Response: " + responseBuilder.toString()); } catch (Exception e) { e.printStackTrace(); } return "success"; }
这里我的推送对象不固定,所以传入的要自己用|来分割,各位可以根据业务需求可自己改动
这代码中需要的有access_token ,agentId, 前者需要获取,后者可直接用
获取token的代码为下:
public static String getQyAccessToken(boolean forceGetNew) { //强制获取新的AccessToken if (forceGetNew) { if (qyAccessTokenEntity == null || qyAccessTokenEntity.getAccessToken() == null) { qyAccessTokenEntity = new AccessTokenEntity(); getQyAccessTokenFromWXServer(qyAccessTokenEntity); } else { getQyAccessTokenFromWXServer(qyAccessTokenEntity); } return qyAccessTokenEntity.getAccessToken(); } if (qyAccessTokenEntity == null || qyAccessTokenEntity.getAccessToken() == null) { // LogUtils.audit("qyAccessTokenEntity is null ||accessToken is null 重新获取"); qyAccessTokenEntity = new AccessTokenEntity(); getQyAccessTokenFromWXServer(qyAccessTokenEntity); } else { if (qyAccessTokenEntity.isEnabled()) { // LogUtils.audit("企业accessToken:存活时间:" + qyAccessTokenEntity.getLeaveTime() + "。最大生命值:" + qyAccessTokenEntity.getExpiresIn()); return qyAccessTokenEntity.getAccessToken(); } else { // LogUtils.audit("企业accessToken:过期重新获取"); getQyAccessTokenFromWXServer(qyAccessTokenEntity); } } return qyAccessTokenEntity.getAccessToken(); }
4,消息推送(mpnews)
{
"touser" : "UserID1|UserID2|UserID3",
"toparty" : "PartyID1 | PartyID2",
"totag": "TagID1 | TagID2",
"msgtype" : "mpnews",
"agentid" : 1,
"mpnews" : {
"articles":[
{
"title": "Title",
"thumb_media_id": "MEDIA_ID",
"author": "Author",
"content_source_url": "URL",
"content": "Content",
"digest": "Digest description"
}
]
},
"safe":0,
"enable_id_trans": 0,
"enable_duplicate_check": 0,
"duplicate_check_interval": 1800
}
这是传入参数, thumb_media_id需要临时获取,每个thumb_media_id都只能用三天,所以我当时用一次就推送一次
public static String uploadPic(String filePath, String type) throws Exception { //获得你的access_token String redisToken = getQyAccessToken(false); //地址https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID String urlStr = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE"; String replaceUrl = urlStr.replace("ACCESS_TOKEN", redisToken).replace("TYPE", type); //返回结果 String result = null; File file = new File(filePath); if (!file.exists() || !file.isFile()) { throw new IOException("文件不存在"); } URL url = new URL(replaceUrl); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); conn.setRequestMethod("POST");//以POST方式提交表单 conn.setDoInput(true); conn.setDoOutput(true); conn.setUseCaches(false);//POST方式不能使用缓存 //设置请求头信息 conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("Charset", "UTF-8"); //设置边界 String BOUNDARY = "----------" + System.currentTimeMillis(); conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); //请求正文信息 //第一部分 StringBuilder sb = new StringBuilder(); sb.append("--");//必须多两条道 sb.append(BOUNDARY); sb.append("\r\n"); sb.append("Content-Disposition: form-data;name=\"media\"; filename=\"" + file.getName() + "\"\r\n"); sb.append("Content-Type:application/octet-stream\r\n\r\n"); System.out.println("sb:" + sb); //获得输出流 OutputStream out = new DataOutputStream(conn.getOutputStream()); //输出表头 out.write(sb.toString().getBytes("UTF-8")); //文件正文部分 //把文件以流的方式 推送道URL中 DataInputStream din = new DataInputStream(new FileInputStream(file)); int bytes = 0; byte[] buffer = new byte[1024]; while ((bytes = din.read(buffer)) != -1) { out.write(buffer, 0, bytes); } din.close(); //结尾部分 byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("UTF-8");//定义数据最后分割线 out.write(foot); out.flush(); out.close(); if (HttpsURLConnection.HTTP_OK == conn.getResponseCode()) { StringBuffer strbuffer = null; BufferedReader reader = null; try { strbuffer = new StringBuffer(); reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); String lineString = null; while ((lineString = reader.readLine()) != null) { strbuffer.append(lineString); } if (result == null) { result = strbuffer.toString(); log.debug("result:" + result); } } catch (IOException e) { System.err.println("发送POST请求出现异常!" + e); } finally { if (reader != null) { reader.close(); } } } return result; }
同样需要token和上传的文件类型,如果是图片就填image就行了,图片路径各位根据情况自己填写
这样就会返回
Map<String, String> map = JSONUtil.toBean(image, Map.class);
media_id = map.get("media_id");
来接收,随后传入
public static String sendQyAppMessage1(String content, List<String> empCodes, String media_id) { String token = getQyAccessToken(false); // String token = TOKEN; System.out.println(token); StringBuilder stringBuilder = new StringBuilder(); for (String empCode : empCodes) { stringBuilder.append(empCode).append("|"); } //删除最后一个| stringBuilder.deleteCharAt(stringBuilder.length() - 1); String toUser = stringBuilder.toString(); //TODO 推送消息的内容 String requestBody = "{ \"touser\": \"%s\"," + " \"toparty\": \"\", " + "\"totag\": \"\", " + "\"msgtype\": \"mpnews\", " + "\"agentid\": %s, " + "\"mpnews\": { " + "\"articles\":[ " + "{ \"title\": \"年度工作数字报告\"," + " \"thumb_media_id\": \"%s\"," + " \"author\": \"sihai\", " + "\"content_source_url\": \"https://nb.sugh.net/toindex\", " + "\"content\": \"Content\", " + "\"digest\": \"用数字报告解锁你的独家故事!\" } ] }," + " \"safe\": 2, " + "\"enable_id_trans\": 0," + " \"enable_duplicate_check\": 0," + " \"duplicate_check_interval\": 1800 }"; requestBody = String.format(requestBody, toUser, ConfKit.entAgentId, media_id); System.out.println(requestBody); String url = SEND_APP_MESSAGE_URL.replace("ACCESS_TOKEN", token); /* String result = HttpKit.post(url, format); System.out.println(result); return result; String url = "http://example.com/api/endpoint"; // 替换为你的目标 URL */ // 要发送的 JSON 请求体 try { HttpClient httpClient = HttpClients.createDefault(); // 创建 POST 请求 HttpPost httpPost = new HttpPost(url); // 设置请求头部信息 httpPost.setHeader("Content-Type", "application/json"); // 设置请求体 StringEntity stringEntity = new StringEntity(requestBody, StandardCharsets.UTF_8); httpPost.setEntity(stringEntity); // 发送请求并获取响应 HttpResponse response = httpClient.execute(httpPost); // 处理响应 HttpEntity responseEntity = response.getEntity(); BufferedReader reader = new BufferedReader(new InputStreamReader(responseEntity.getContent())); String line; StringBuilder responseBuilder = new StringBuilder(); while ((line = reader.readLine()) != null) { responseBuilder.append(line); } // 输出响应结果 System.out.println("Response: " + responseBuilder.toString()); } catch (Exception e) { e.printStackTrace(); } return "success"; }
接下展示效果
5.常见错误 
检擦获取的access_token是否是你这个应用的,检查
entCorpID
和entSecret
这个是我推送消息时填写了appid,我去掉后就行了
查看微信配置的可信域ip和你发送这个请求的ip是否一致