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

这篇具有很好参考价值的文章主要介绍了java 实现微信公众号消息推送。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

注册微信公众号

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

设置消息模板

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

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

java实现微信公众号消息推送,Java,java,微信,开发语言
参数要求规则
java实现微信公众号消息推送,Java,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")
@Data
public 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 com.google.common.base.Splitter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.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.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Map;

import static org.apache.tomcat.util.file.ConfigFileLoader.getURI;

@Component
@Slf4j
public 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 org.apache.commons.lang3.StringUtils;

import java.text.SimpleDateFormat;


@Slf4j
public 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;

@Data
public 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;

@Data
public 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 com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.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 java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.Date;
import java.util.Map;
import java.util.TreeMap;

@Service
@Slf4j
public 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_";

    @Resource
    private WxConfiguration wxConfiguration;

    @Resource
    private HttpUtils httpUtils;

    /**
     * accessToken缓存
     */
    private static Map<String, Map<String, Object>> accessTokenMap = Maps.newConcurrentMap();

    /**
     * 推送模板
     * @param templateMsg
     * @return
     */
    @Override
    public JSONObject noticeTemplate(JSONObject templateMsg) {
        // 模版ID
        String 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();
        // 模版ID
        wxTemplateMsg.setTemplate_id(templateId);
        // openId
        wxTemplateMsg.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 {
        // 获取token
        JSONObject 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() {
        //拼接获取缓存key
        String 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_token
    private 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;
    }

}

效果

发送测试
java实现微信公众号消息推送,Java,java,微信,开发语言
微信公众号接收效果
java实现微信公众号消息推送,Java,java,微信,开发语言文章来源地址https://www.toymoban.com/news/detail-742334.html

到了这里,关于java 实现微信公众号消息推送的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信公众号推送天气教程,自动定时推送【Java版】开发者和小白详细教程

    久违的大更新: 建议先打开,因为GitHub在国内加载很慢。 点击打开 Java版本,教程最近一次更新时间为: 2023-08-23 重大更新: 1: 谚语功能修复。 2: 新增农历生日。 已经部署的伙伴,务必在公众号后台更新新的模块以及applicantion.yml配置文件中的模板ID,新的模板在本教程当中

    2024年01月23日
    浏览(45)
  • 微信公众号模板消息源码实现,打破服务号群发推送次数限制

    公众号服务号每个月只能群发推送四次文章,我们可以使用模板消息为公众号粉丝推送信息 下面是使用golang实现的模板消息发送类库封装,轻松实现模板消息发送 wechat.go 我们的使用方式 推送的效果如图所示,点击模板就能跳转到我们自定义的url上 我在自己客服系统中也是

    2024年02月15日
    浏览(32)
  • spring boot +微信小程序项目,通过微信公众号实现指定用户消息长期推送

    用户登录小程序,后台记录用户的小程序openId和用户唯一的UnionId。然后用户触发公众号事件(关注公众号或者发送指定消息),后台获取到用户公众号的openId,再调用接口通过公众号的openId查询用户的UnionId,再和数据库里的UnionId进行匹配,将用户的公众号openId存入数据库。此

    2024年02月03日
    浏览(36)
  • Java代码 微信公众号推送(代码详细)

    用的是idea, 需要修改的地方在于这些地方改了     然后吧账号密码填写进去就好了  运行类是   Yi   这个类 非常简单 祝大家成功 ,不会的关注私聊   微信公众号测试注册地址:微信公众平台 (qq.com)  我用的模板是这个只有一个数据 ,当然这个可以自己添加  做出来的效果

    2024年02月12日
    浏览(34)
  • 微信小程序生态8-基于weixin-java-mp实现微信公众号被动回复消息

    微信小程序生态1-初识小程序 微信小程序生态2-创建一个微信小程序 微信小程序生态3-微信小程序登录流程设计 微信小程序生态4-扫普通二维码进入小程序、打开短链接进入小程序 微信小程序生态5-微信公众号扫码登录PC端网页 微信小程序生态6-微信公众号授权登录(适用于H

    2024年02月10日
    浏览(33)
  • 微信公众号推送模板消息给用户

    前置条件: 1.公众号为服务号,而非订阅号 2.认证(300元) 3.进入公众号申请模板推送功能 4.添加模板(注意:推送的消息只能使用微信提供的模板,不可自定义,但也是比较全的) 4.2 获取accessToken时,需要将开发环境的电脑ip添加到微信后台的ip白名单(线上环境亦是如此

    2024年02月12日
    浏览(47)
  • 微信小程序向公众号推送消息模板

    由于微信小程序长期订阅的消息模板全部失效以后,对于小程序的消息推送可以改成往公众号推。 这里将介绍如何使用小程序向公众号推送消息,并且消息可以跳转到小程序 1、微信公众平台注册 服务号 (订阅号是不可以推送的)与小程序,两者都需要认证并且 认证主体是

    2024年02月06日
    浏览(36)
  • 微信小程序向公众号推送消息超详细教程

    官方教程 官方教程 开通一下服务号公众号 超级管理员登录服务号公众号后台 登录地址 开通模板消息 申请一个模板消息,获取模板ID 注意此处的参数,后续接口需要使用 绑定公众号与小程序 官方教程 1.登录微信公众号后台 2.点击小程序管理 3.关联小程序 获取微信公众号

    2024年02月11日
    浏览(49)
  • 微信公众号配置 Token 认证以及消息推送功能

    🔭 嗨,您好 👋 我是 vnjohn,在互联网企业担任 Java 开发,CSDN 优质创作者 📖 推荐专栏:Spring、MySQL、Nacos、Java,后续其他专栏会持续优化更新迭代 🌲文章所在专栏:业务设计 🤔 我当前正在学习微服务领域、云原生领域、消息中间件等架构、原理知识 💬 向我询问任何您

    2024年02月09日
    浏览(35)
  • 【小程序】微信小程序关联公众号(服务号)推送通知消息

    最近开发的一个小程序项目需要通过服务号来推送通知。但是在最开始开发小程序的时候并没有考虑到这个功能。 预备知识 : 小程序openid:小程序用户的唯一id 公众号openid:公众号用户的唯一id unionid:同一用户,对同一个微信开放平台下的不同应用,unionid是相同的 准备

    2024年01月18日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包