900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > springboot推送微信公众号消息 java推送微信公众号消息

springboot推送微信公众号消息 java推送微信公众号消息

时间:2022-08-13 04:09:43

相关推荐

springboot推送微信公众号消息 java推送微信公众号消息

文章目录

1. 公众号申请和配置首先!!记得设置白名单2. 依赖2.1 父子工程聚合2.2 独立的单独工程3. 工具类3.1 HttpUtil http请求工具类3.2 RestTemplateConfig 配置类3.3 WeChatTemplate 短信模板实体类3.4 WxConstant 微信相关参数封装类3.5 WxGetTokenUtil 生成 access_token3.7 WxMpConfiguration 微信server的配置类,不写这个server就没法用3.8 WxResult 微信返回错误码封装类3.9 WxSendUtill 发送消息工具类4. 调用(controller)

1. 公众号申请和配置

首先!!记得设置白名单

2. 依赖

2.1 父子工程聚合

<!--父工程版本控制--> <properties><weixin-java-mp.version>3.0.0</weixin-java-mp.version></properties><dependencyManagement><dependencies><!--微信公众号--><dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-mp</artifactId><version>${weixin-java-mp.version}</version></dependency><!--json转化的工具依赖--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>${fastjson.version}</version></dependency></dependencies></dependencyManagement><!--子工程中引用--><!--微信公众号--><dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-mp</artifactId></dependency><!--json转化的工具依赖--><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId></dependency>

2.2 独立的单独工程

<!--微信公众号--><dependency><groupId>com.github.binarywang</groupId><artifactId>weixin-java-mp</artifactId><version>3.0.0</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.47</version></dependency>

3. 工具类

目录结构:

util.wx文件夹 HttpUtil.java 类RestTemplateConfig.java 类WeChatTemplate 类WxConstant.java 类WxGetTokenUtil.java 类WxResult.java 类WxSendUtil.java 类

3.1 HttpUtil http请求工具类

import lombok.extern.slf4j.Slf4j;import mons.io.IOUtils;import mons.lang.StringUtils;import .ssl.*;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import .HttpURLConnection;import .URL;import .URLEncoder;import java.nio.charset.StandardCharsets;import java.security.SecureRandom;import java.security.cert.CertificateException;import java.security.cert.X509Certificate;import java.util.Map;@Slf4jpublic class HttpUtil {protected static final String POST_METHOD = "POST";private static final String GET_METHOD = "GET";static {TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {@Overridepublic void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {log.debug("ClientTrusted");}@Overridepublic void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {log.debug("ServerTrusted");}@Overridepublic X509Certificate[] getAcceptedIssuers() {return new X509Certificate[]{};}}};HostnameVerifier doNotVerify = (s, sslSession) -> true;try {SSLContext sc = SSLContext.getInstance("SSL", "SunJSSE");sc.init(null, trustAllCerts, new SecureRandom());HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());HttpsURLConnection.setDefaultHostnameVerifier(doNotVerify);} catch (Exception e) {log.error("Initialization https impl occur exception : {}", e);}}/*** 默认的http请求执行方法** @param url url 路径* @param method 请求的方法 POST/GET* @param map 请求参数集合* @param data 输入的数据 允许为空* @return result*/private static String HttpDefaultExecute(String url, String method, Map<String, String> map, String data) {String result = "";try {url = setParmas(url, map, null);result = defaultConnection(url, method, data);} catch (Exception e) {log.error("出错参数 {}", map);}return result;}public static String httpGet(String url, Map<String, String> map) {return HttpDefaultExecute(url, GET_METHOD, map, null);}public static String httpPost(String url, Map<String, String> map, String data) {return HttpDefaultExecute(url, POST_METHOD, map, data);}/*** 默认的https执行方法,返回** @param url url 路径* @param method 请求的方法 POST/GET* @param map 请求参数集合* @param data 输入的数据 允许为空* @return result*/private static String HttpsDefaultExecute(String url, String method, Map<String, String> map, String data) {try {url = setParmas(url, map, null);log.info(data);return defaultConnection(url, method, data);} catch (Exception e) {log.error("出错参数 {}", map);}return "";}public static String doGet(String url, Map<String, String> map) {return HttpsDefaultExecute(url, GET_METHOD, map, null);}public static String doPost(String url, Map<String, String> map, String data) {return HttpsDefaultExecute(url, POST_METHOD, map, data);}/*** @param path 请求路径* @param method 方法* @param data 输入的数据 允许为空* @return* @throws Exception*/private static String defaultConnection(String path, String method, String data) throws Exception {if (StringUtils.isBlank(path)) {throw new IOException("url can not be null");}String result = null;URL url = new URL(path);HttpURLConnection conn = getConnection(url, method);if (StringUtils.isNotEmpty(data)) {OutputStream output = conn.getOutputStream();output.write(data.getBytes(StandardCharsets.UTF_8));output.flush();output.close();}if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {InputStream input = conn.getInputStream();result = IOUtils.toString(input, StandardCharsets.UTF_8);input.close();conn.disconnect();}return result;}/*** 根据url的协议选择对应的请求方式* @param url 请求路径* @param method 方法* @return conn* @throws IOException 异常*///待改进protected static HttpURLConnection getConnection(URL url, String method) throws IOException {HttpURLConnection conn;if (StringUtils.equals("https", url.getProtocol())) {conn = (HttpsURLConnection) url.openConnection();} else {conn = (HttpURLConnection) url.openConnection();}if (conn == null) {throw new IOException("connection can not be null");}conn.setRequestProperty("Pragma", "no-cache");// 设置不适用缓存conn.setRequestProperty("Cache-Control", "no-cache");conn.setRequestProperty("Connection", "Close");// 不支持Keep-Aliveconn.setUseCaches(false);conn.setDoOutput(true);conn.setDoInput(true);conn.setInstanceFollowRedirects(true);conn.setRequestMethod(method);conn.setConnectTimeout(8000);conn.setReadTimeout(8000);return conn;}/*** 根据url* @param url 请求路径* @return isFile* @throws IOException 异常*///待改进protected static HttpURLConnection getConnection(URL url, boolean isFile) throws IOException {HttpURLConnection conn = (HttpURLConnection) url.openConnection();if (conn == null) {throw new IOException("connection can not be null");}//设置从httpUrlConnection读入conn.setDoInput(true);conn.setDoOutput(true);conn.setUseCaches(false);//如果是上传文件,则设为POSTif (isFile) {conn.setRequestMethod(POST_METHOD); //GET和 POST都可以 文件略大改成POST}// 设置请求头信息conn.setRequestProperty("Connection", "Keep-Alive");conn.setRequestProperty("Charset", String.valueOf(StandardCharsets.UTF_8));conn.setConnectTimeout(8000);conn.setReadTimeout(8000);return conn;}/*** 拼接参数* @param url 需要拼接参数的url* @param map 参数* @param charset 编码格式* @return 拼接完成后的url*/public static String setParmas(String url, Map<String, String> map, String charset) throws Exception {String result = StringUtils.EMPTY;boolean hasParams = false;if (StringUtils.isNotEmpty(url) && map != null && !map.isEmpty()) {StringBuilder builder = new StringBuilder();for (Map.Entry<String, String> entry : map.entrySet()) {String key = entry.getKey().trim();String value = entry.getValue().trim();if (hasParams) {builder.append("&");} else {hasParams = true;}if (StringUtils.isNotEmpty(charset)) {builder.append(key).append("=").append(URLEncoder.encode(value, charset));} else {builder.append(key).append("=").append(value);}}result = builder.toString();}URL u = new URL(url);if (StringUtils.isEmpty(u.getQuery())) {if (url.endsWith("?")) {url += result;} else {url = url + "?" + result;}} else {if (url.endsWith("&")) {url += result;} else {url = url + "&" + result;}}log.debug("request url is {}", url);return url;}}

3.2 RestTemplateConfig 配置类

import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.http.client.ClientHttpRequestFactory;import org.springframework.http.client.SimpleClientHttpRequestFactory;import org.springframework.web.client.RestTemplate;@Configurationpublic class RestTemplateConfig {@Beanpublic RestTemplate restTemplate(ClientHttpRequestFactory factory) {return new RestTemplate(factory);}@Beanpublic ClientHttpRequestFactory simpleClientHttpRequestFactory() {SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();factory.setConnectTimeout(15*1000);factory.setReadTimeout(60*60*1000);return factory;}}

3.3 WeChatTemplate 短信模板实体类

import lombok.Data;import java.util.TreeMap;@Datapublic class WeChatTemplate {private String touser; //接收者openidprivate String template_id; //模板IDprivate String url; //URL置空,则在发送后,点击模板消息会进入一个空白页面(ios),或无法点击(android)private TreeMap<String, TreeMap<String, String>> data; //data数据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;}@Overridepublic String toString() {return "WechatTemplate" +"{" +"openId='" + touser + "'," +"template_id='" + template_id + "'," +"url='" + url + "'," +"data=" + data +'}';}}

3.4 WxConstant 微信相关参数封装类

public class WxConstant {/*** 开发者appId*/public static final String appId="xxxxxxxxxxxxxxxxx";/*** 开发者密码 appSecret*/public static final String appSecret="xxxxxxxxxxxxxxxxxxxxxxxx";/*** templateId:微信公众号模板id*/public static final String templateId="xxxxxxxxxxxxxxxxxxxx";}

3.5 WxGetTokenUtil 生成 access_token

import com.alibaba.fastjson.JSONObject;import java.util.HashMap;import java.util.Map;public class WxGetTokenUtil {public static String getAccessToken() {String appSecret = WxConstant.appSecret;String appId = WxConstant.appId;String tokenUrl = "https://api./cgi-bin/token";Map<String, String> params = new HashMap<>();params.put("appid", appId);params.put("secret", appSecret);params.put("grant_type", "client_credential");String response = HttpUtil.doGet(tokenUrl, params);System.out.println("WxGetTokenUtil.getAccessToken()返回值:" + response);//此处可注释,调试时解开,防止code出报错找不到原因JSONObject accessTokenObject = JSONObject.parseObject(response);return accessTokenObject.getString("access_token");}}

3.7 WxMpConfiguration 微信server的配置类,不写这个server就没法用

import me.chanjar.weixin.mp.api.WxMpConfigStorage;import me.chanjar.weixin.mp.api.WxMpInMemoryConfigStorage;import me.chanjar.weixin.mp.api.WxMpService;import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/*** wechat mp configuration*/@Configuration@ConditionalOnClass(WxMpService.class)public class WxMpConfiguration {@Bean@ConditionalOnMissingBeanpublic WxMpConfigStorage configStorage() {WxMpInMemoryConfigStorage configStorage = new WxMpInMemoryConfigStorage();configStorage.setAppId(WxConstant.appId);configStorage.setSecret(WxConstant.appSecret);// configStorage.setToken(WxConstant.token);// configStorage.setAesKey(WxConstant.key);return configStorage;}@Bean@ConditionalOnMissingBeanpublic WxMpService wxMpService(WxMpConfigStorage configStorage) {WxMpService wxMpService = new me.chanjar.weixin.mp.api.impl.WxMpServiceImpl();wxMpService.setWxMpConfigStorage(configStorage);return wxMpService;}}

3.8 WxResult 微信返回错误码封装类

import lombok.Data;@Datapublic class WxResult {private String errcode;private String errmsg;private String msgid;@Overridepublic String toString() {return "WxError{errcode='" + errcode + "',errmsg='" + errmsg + "',msgid='" + msgid + "'}";}}

3.9 WxSendUtill 发送消息工具类

注意,参数是根据你自己的模板进行组装的,我的模板有以下参数

{first,keyword1,keyword2,keyword3,keyword4,keyword5,remark}

import com.alibaba.fastjson.JSON;import lombok.extern.slf4j.Slf4j;import me.mon.exception.WxErrorException;import me.chanjar.weixin.mp.api.WxMpService;import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;import net.sf.json.JSONObject;import mons.lang.StringUtils;import org.springframework.beans.factory.annotation.Autowired;import org.ponent;import java.text.SimpleDateFormat;import java.util.Date;import java.util.TreeMap;/*** 推送公众号消息*/@Slf4j@Component //使用方式2,需要用到这个注解,并且需要用到WxMapConfiguration。public class WxSendUtil {/*** 发送消息,方式1* @param openId 用户openId* @param data 数据* @param title 标题*/public static WxResult send(String openId, String data, String title) {String url = "";String templateUrl = "https://api./cgi-bin/message/template/send";String time = parseDate3String(new Date());String accessToken = WxGetTokenUtil.getAccessToken();log.info("获取access_token,微信平台接口返回{}", accessToken);TreeMap<String, TreeMap<String, String>> params = new TreeMap<String, TreeMap<String, String>>();//根据具体模板参数的 添加数据params.put("first", WeChatTemplate.item(title, "#000000"));//一般是标题params.put("keyword1", WeChatTemplate.item("项目名称", "#ff0000"));//项目名称,字体颜色params.put("keyword2", WeChatTemplate.item(time, "#000000"));params.put("keyword3", WeChatTemplate.item(time, "#000000"));params.put("keyword4", WeChatTemplate.item(time, "#000000"));params.put("keyword5", WeChatTemplate.item(time, "#000000"));params.put("remark", WeChatTemplate.item(data, "#000000"));WeChatTemplate wechatTemplate = new WeChatTemplate();wechatTemplate.setTemplate_id(WxConstant.templateId);//模板idwechatTemplate.setTouser(openId);// 接收者openidwechatTemplate.setUrl(url); // 模板跳转链接wechatTemplate.setData(params);JSONObject json = JSONObject.fromObject(wechatTemplate);//将java对象转换为json对象String sendData = json.toString();//将json对象转换为字符串log.info("板参数组装{}", sendData);TreeMap<String, String> treeMap = new TreeMap<String, String>();treeMap.put("access_token", accessToken);String retInfo = HttpUtil.doPost(templateUrl, treeMap, sendData);if (!StringUtils.isBlank(retInfo)) {return JSON.parseObject(retInfo, WxResult.class);}log.info("消息模板返回{}", retInfo);return null;}@Autowiredprivate WxMpService wxService;/*** 发送消息,方式2* 发送微信模板信息* @param openId openId* @param url 跳转地址* @param title 标题*/public Boolean sendWxMsg(String openId, String url, String title) {String time = parseDate3String(new Date());// 发送模板消息接口WxMpTemplateMessage templateMessage = WxMpTemplateMessage.builder()// 接收者openid.toUser(openId)// 模板id.templateId(WxConstant.templateId)// 模板跳转链接.url(url).build();// 添加模板数据templateMessage.addData(new WxMpTemplateData("first", title, "#FF00FF")).addData(new WxMpTemplateData("keyword1", "紧急", "#A9A9A9")).addData(new WxMpTemplateData("keyword2", time, "#A9A9A9")).addData(new WxMpTemplateData("remark", url, "#FF00FF"));String msgId = null;try {// 发送模板消息msgId = this.wxService.getTemplateMsgService().sendTemplateMsg(templateMessage);} catch (WxErrorException e) {e.printStackTrace();}log.warn("·==++--·推送微信模板信息:{}·--++==·", msgId != null ? "成功" : "失败");return msgId != null;}//时间转化成字符串,格式 yyyy-MM-dd HH:mm:ssprivate static String parseDate3String(Date date) {SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");return sdf.format(date);}}

4. 调用(controller)

发消息得有发送对象—用户,,要获取到用户的openId,然后才能进行发送

import com.alibaba.fastjson.JSONObject;import com.sq.statistics.utils.wx.WxGetTokenUtil;import com.sq.statistics.utils.wx.WxSendUtil;import io.swagger.v3.oas.annotations.tags.Tag;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.HttpEntity;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpMethod;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.*;import org.springframework.web.client.RestTemplate;import java.util.HashMap;import java.util.List;import java.util.Map;@RestController@RequestMapping("/wx")public class WXController {@Autowiredprivate RestTemplate restTemplate;/*** 获取关注者的openid*/@GetMapping("/open-id/list")public Map<String, Object> getOpenIdList(@RequestParam(required = false) String next_openid) {String url = "https://api./cgi-bin/user/get?access_token={access_token}";Map<String, Object> param = new HashMap<>();param.put("next_openid", next_openid);param.put("access_token", WxGetTokenUtil.getAccessToken());HttpHeaders headers = new HttpHeaders();ResponseEntity<String> entity =restTemplate.exchange(url,HttpMethod.GET,new HttpEntity<String>(headers),String.class,param);String result = entity.getBody();System.out.println("WXController.getOpenIdList()返回值:" + result);//此处可注释,调试时解开,防止code出报错if (result != null && result.contains("count")) {//返回值可能有两种,一种是报错的,一种是正常返回Map<String, Object> resultData = JSONObject.parseObject(result, Map.class);// return resultData;//可以直接返回,也可以自己抽取,,我只需要openId和next_openIdString next_openId = resultData.get("next_openid").toString(); //这个是下一组数据需要的传参Map<String, Object> data = JSONObject.parseObject(resultData.get("data").toString(), Map.class);List<String> openidList = JSONObject.parseArray(data.get("openid").toString(), String.class);Map<String, Object> map = new HashMap<>();map.put("next_openId", next_openId);map.put("openidList", openidList);return map;}return null;//返回的是tokenList,如果想要下一组数据,最后传的/*** 正确返回* {"total":2,"count":2,"data":{"openid":["111111","222222"]},"next_openid":"222222"}** 错误返回,下边这个是白名单没开* {"errcode":40164,"errmsg":"invalid ip 180.0.0.0 ipv6 ::ffff:180.0.0.0, not in whitelist rid: 6268e703-5bc5bc49-4d17363f"}*/}/*** 发送消息*/@PostMapping("/send/message")public void sendMessage(String message, String title, String openId) {WxSendUtil.send(openId, message, title);}}

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