1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > java 实现微信公众号消息推送

java 实现微信公众号消息推送

时间:2022-10-13 05:48:13

相关推荐

java 实现微信公众号消息推送

注册微信公众号

这里主要用测试账号来演示:测试账号注册地址正式账号注册地址:微信公众平台

设置消息模板

可参考微信公众号文档:微信公众号文档

模板根据需求设置(注意:参数长度不能超出微信规定,否则将发送失败)

参数要求规则

java代码

依赖

<!--json——jar--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.54</version></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>4.5.6</version></dependency><!-- httpRequest --><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5</version></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpcore</artifactId><version>4.4.1</version></dependency><dependency><groupId>commons-httpclient</groupId><artifactId>commons-httpclient</artifactId><version>3.1</version></dependency>

请求地址、appid、密钥等信息;信息配置到application配置中,方便统一管理;

package com.andon.wxPush.conf;import lombok.Data;import org.springframework.stereotype.Service;import org.springframework.beans.factory.annotation.Value;/*** @Description: 读取 Properties配置信息的类*/@Service("wxConfiguration")@Datapublic class WxConfiguration {//获取微信access_token请求地址@Value("${wxConfig.url.WX_ACCESS_TOKEN_URL}")private String wxAccessTokenUrl;//发送微信公众号模板消息请求地址@Value("${wxConfig.url.SEND_MESSAGE_TEMPLATE_URL}")private String sendMessageTemplateUrl;//小程序唯一凭证,即 AppID@Value("${wxConfig.appid}")private String appId;//小程序唯一凭证密钥,即 AppSecret@Value("${wxConfig.secret}")private String secret;//模板id@Value("${wxConfig.templateId}")private String templateId;}

发送请求工具类

package com.andon.wxPush.utils;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.andon.wxPush.template.HttpResult;import mon.base.Splitter;import lombok.extern.slf4j.Slf4j;import mons.lang.StringEscapeUtils;import mons.lang3.StringUtils;import org.apache.http.HttpEntity;import org.apache.http.HttpResponse;import org.apache.http.NameValuePair;import org.apache.http.client.config.RequestConfig;import org.apache.http.client.entity.UrlEncodedFormEntity;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpGet;import org.apache.http.client.methods.HttpPost;import org.apache.http.entity.ContentType;import org.apache.http.entity.StringEntity;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClientBuilder;import org.apache.http.impl.client.HttpClients;import org.apache.http.impl.client.LaxRedirectStrategy;import org.apache.http.message.BasicNameValuePair;import org.apache.http.util.EntityUtils;import org.ponent;import java.io.IOException;import java.util.Map;import static org.apache.tomcat.util.file.ConfigFileLoader.getURI;@Component@Slf4jpublic class HttpUtils {public HttpResult stringPostJson(String path, String content) throws Exception{return stringPost(path, null, content, "utf-8", "utf-8", "application/json");}public HttpResult stringPost(String path, Map<String,String> headerMap, String content, String contentencode, String encode, String contentType) throws Exception{StringEntity entity = new StringEntity(content, contentencode);entity.setContentType(contentType);return post(path, headerMap, entity, encode);}private HttpResult post(String path, Map<String,String> headerMap, HttpEntity entity, String encode){HttpResult httpResult = new HttpResult();CloseableHttpClient httpClient = null;CloseableHttpResponse response = null;try{HttpPost httpPost = new HttpPost(getURI(path));LaxRedirectStrategy redirectStrategy = new LaxRedirectStrategy();httpClient = HttpClientBuilder.create().setRedirectStrategy(redirectStrategy).build();RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(120000).setConnectTimeout(120000).setConnectionRequestTimeout(120000).setCircularRedirectsAllowed(true).setRedirectsEnabled(true).setMaxRedirects(5).build();httpPost.setConfig(requestConfig);// httpPost.setHeader("User-Agent", header);if(headerMap != null && headerMap.size() > 0){for(String name:headerMap.keySet()) {httpPost.addHeader(name, headerMap.get(name));}}httpPost.setEntity(entity);response = httpClient.execute(httpPost);httpResult.setStatus(response.getStatusLine().getStatusCode());if(httpResult.getStatus() == 200){HttpEntity resEntity = response.getEntity();httpResult.setBody(EntityUtils.toString(resEntity, encode));}}catch(Exception ex){log.error("post请求出错", ex);}finally{try{if(response != null){response.close();}if(httpClient != null){httpClient.close();}}catch(Exception ex) {log.error("post请求关闭资源出错", ex);}}return httpResult;}public JSONObject stringGetJson(String url) {JSONObject jsonObject = null;//通过HttpClients.createDefault()获取到CloseableHttpClient对象CloseableHttpClient httpclient = HttpClients.createDefault();//创建HttpGet 对象,参数为请求的地址HttpGet method = new HttpGet(url);try {//执行方法请求接口得到响应HttpResponse response = httpclient.execute(method);//解析响应数据String content = EntityUtils.toString(response.getEntity(), "UTF-8");//转为json格式jsonObject = JSON.parseObject(content);EntityUtils.consume(response.getEntity());//完全消耗} catch (Exception e) {log.error("get请求出错", e);e.printStackTrace();} finally {try {//释放连接method.releaseConnection();httpclient.close();} catch (IOException e) {e.printStackTrace();}}return jsonObject;}}

json处理工具类

package com.andon.wxPush.utils;import com.fasterxml.jackson.databind.DeserializationFeature;import com.fasterxml.jackson.databind.ObjectMapper;import lombok.extern.slf4j.Slf4j;import mons.lang3.StringUtils;import java.text.SimpleDateFormat;@Slf4jpublic class JsonUtils {private static ObjectMapper json;static {json = new ObjectMapper();json.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));json.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);}/*** 序列化为JSON字符串*/public static String ObjectToString(Object object) {try {return (json.writeValueAsString(object));} catch (Exception e) {log.error("序列化为JSON字符串出错",e);}return null;}public static <T> T getObject(String jsonString, Class<T> clazz) {if (StringUtils.isEmpty(jsonString))return null;try {return json.readValue(jsonString, clazz);} catch (Exception e) {log.error("将JSON字符串转化为Map出错",e);return null;}}}

消息模板

package com.andon.wxPush.template;import lombok.Data;import java.util.Map;import java.util.TreeMap;@Datapublic class WxSendMessageTemplate {/*** 接收者openId*/private String touser;/*** 模板ID*/private String template_id;/*** 模板跳转链接*/private String url;/*** 模板跳转链接*/private Map<String,String> miniprogram;/*** 消息data*/private TreeMap<String, TreeMap<String, String>> data;/*** 参数** @param value 值* @param color 颜色* @return params*/public static TreeMap<String, String> item(String value, String color) {TreeMap<String, String> params = new TreeMap<String, String>();params.put("value", value);params.put("color", color);return params;}}

结果模板

package com.andon.wxPush.template;import lombok.Data;@Datapublic class HttpResult {private Integer status = 601;private String body;}

消息推送

package com.andon.wxPush.service.impl;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONObject;import com.andon.util.DateUtil;import com.andon.wxPush.conf.WxConfiguration;import com.andon.wxPush.service.WxSendMsgService;import com.andon.wxPush.template.HttpResult;import com.andon.wxPush.template.WxSendMessageTemplate;import com.andon.wxPush.utils.HttpUtils;import com.andon.wxPush.utils.JsonUtils;import mon.collect.Maps;import lombok.extern.slf4j.Slf4j;import mons.lang.StringUtils;import org.springframework.beans.factory.annotation.Value;import org.springframework.http.HttpStatus;import org.springframework.http.ResponseEntity;import org.springframework.stereotype.Service;import javax.annotation.Resource;import java.io.UnsupportedEncodingException;import .URLEncoder;import java.text.SimpleDateFormat;import java.time.LocalDate;import java.util.Date;import java.util.Map;import java.util.TreeMap;@Service@Slf4jpublic class WxSendMsgServiceImpl implements WxSendMsgService {//凭证有效时间private static final String KEY_EXPIRES_IN = "expiresIn";//private static final String KEY_TOKEN = "accessToken";//拼接缓存前缀private static final String ACCESS_TOKEN_KEY_PREFIX = "AccessToken_";@Resourceprivate WxConfiguration wxConfiguration;@Resourceprivate HttpUtils httpUtils;/*** accessToken缓存*/private static Map<String, Map<String, Object>> accessTokenMap = Maps.newConcurrentMap();/*** 推送模板* @param templateMsg* @return*/@Overridepublic JSONObject noticeTemplate(JSONObject templateMsg) {// 模版IDString templateId = wxConfiguration.getTemplateId();TreeMap<String, TreeMap<String, String>> params = new TreeMap<>();SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//微信公众号根据具体模板参数组装params.put("keyword4", WxSendMessageTemplate.item(sdf.format(new Date()), "#000000")); //告警时间params.put("keyword3", WxSendMessageTemplate.item(templateMsg.getString("andonName"), "#000000")); //报警类型params.put("keyword1", WxSendMessageTemplate.item(templateMsg.getString("equipmentName"), "#000000"));//设备名称params.put("keyword2", WxSendMessageTemplate.item(templateMsg.getString("installPlace"), "#000000"));//设备位置params.put("first", WxSendMessageTemplate.item(templateMsg.getString("andonContent"), "#000000"));//告警内容WxSendMessageTemplate wxTemplateMsg = new WxSendMessageTemplate();// 模版IDwxTemplateMsg.setTemplate_id(templateId);// openIdwxTemplateMsg.setTouser(templateMsg.getString("openId"));// 关键字赋值wxTemplateMsg.setData(params);String data = JsonUtils.ObjectToString(wxTemplateMsg);System.out.println(data);return this.handleSendMsgLog(data);}//捕获异常private JSONObject handleSendMsgLog(String data) {JSONObject resultDto = new JSONObject();try {resultDto = this.sendTemplateMsg(data);System.out.println("handleSendMsgLog:" + resultDto.toJSONString());} catch (Exception exception) {log.error("发送微信模版失败", exception);}// TODO 可以记录一下发送记录的日志return resultDto;}//发送模板public JSONObject sendTemplateMsg(String data) throws Exception {// 获取tokenJSONObject accessTokenRes = this.getAccessToken();String accessToken = accessTokenRes.getString("access_token");// 发送消息HttpResult httpResult = null;try {httpResult = httpUtils.stringPostJson(wxConfiguration.getSendMessageTemplateUrl() + accessToken, data);} catch (Exception e) {e.printStackTrace();}return JSON.parseObject(httpResult.getBody());}/*** 获取全局access_token*/public JSONObject getAccessToken() {//拼接获取缓存keyString key = ACCESS_TOKEN_KEY_PREFIX.concat(wxConfiguration.getAppId()).concat(wxConfiguration.getSecret());Map<String, Object> accessTokenJson = accessTokenMap.get(key);if (accessTokenJson != null) {long expiresIn = (Long) accessTokenJson.get(KEY_EXPIRES_IN);if (System.currentTimeMillis() < expiresIn) {return (JSONObject) accessTokenJson.get(KEY_TOKEN);}accessTokenMap.remove(key);}synchronized (this) {accessTokenJson = accessTokenMap.get(key);// 多线程环境下,其他线程可能已经获得最新corpAccessToken,直接返回if (accessTokenJson != null) {return (JSONObject) accessTokenJson.get(KEY_TOKEN);}String url = String.format(wxConfiguration.getWxAccessTokenUrl(), wxConfiguration.getAppId(), wxConfiguration.getSecret());JSONObject resJson = httpUtils.stringGetJson(url);if (resJson != null && StringUtils.isNotEmpty(resJson.getString("access_token"))) {accessTokenJson = this.seAccessToken(resJson);}if (accessTokenJson == null) {try {throw new Exception();} catch (Exception e) {log.error("设置access_token缓存失败");e.printStackTrace();}}//放入缓存中accessTokenMap.put(key, accessTokenJson);JSONObject accessTokenJsonRes = (JSONObject) accessTokenJson.get(KEY_TOKEN);if (accessTokenJsonRes == null) {try {throw new Exception();} catch (Exception e) {log.error("获取access_token错误");e.printStackTrace();}}return accessTokenJsonRes;}}//设置access_tokenprivate Map<String, Object> seAccessToken(JSONObject jsonObject) {Map<String, Object> token = Maps.newHashMap();// 减去3分钟,以免过时token.put(KEY_EXPIRES_IN, (jsonObject.getLongValue("expires_in") - 3 * 60) * 1000 + System.currentTimeMillis());token.put(KEY_TOKEN, jsonObject);return token;}}

效果

发送测试

微信公众号接收效果

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。