微信开发之模版推送_微信公众号模板消息推送时在微信上提醒 - CSDN
  • 微信模板推送

    2017-08-07 14:26:02
    1.需求:微信服务号模板消息推送 2.流程: 1. 设计模板样式 2. 获得微信的全局调用凭证+接口 3. 设计库 4. 获得关注服务号的用户 5. 填充内容 6. 推送模板 7. 推送成功/失败返回结果设计模板登录公司...

    1.需求:微信服务号模板消息推送
    2.流程:
    1. 设计模板样式
    2. 获得微信的全局调用凭证+接口
    3. 设计库
    4. 获得关注服务号的用户
    5. 填充内容
    6. 推送模板
    7. 推送成功/失败返回结果

    设计模板

    登录公司或个人的微信公众平台-功能模板消息-模板库,这里有微信自己的设计好的模板库的样式,也可以自己设计,
    这里写图片描述
    本人用的是微信模板库的模板
    本人用的是微信模板库的模板

    获得微信的接口调用凭证+接口

    在微信服务号的开发者工具-开发者文档里有一则模板消息接口的文档,里面介绍了推送模板消息的用到的接口信息。
    模型消息接口使用文档
    1. 获取接口调用凭证access_token
    access_token是公众号的全局唯一接口调用凭据,公众号调用各接口时都需使用 access_token。开发者需要进行妥善保存。access_token的存储至少要保留512个字符空间。access_token的有效期目前为2个小时,需定时刷新,重复获取将导致上次获取的access_token失效。
    接口调用请求说明:
    https请求方式: GET
    https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
    参数说明:
    这里写图片描述
    返回说明
    这里写图片描述
    2. 发送模板消息接口
    接口调用请求说明
    http请求方式: POST
    https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN
    3. 获得关注用户id
    公众号可通过本接口来获取帐号的关注者列表,关注者列表由一串OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的)组成。一次拉取调用最多拉取10000个关注者的OpenID,可以通过多次拉取的方式来满足需求。
    接口调用请求说明
    http请求方式: GET(请使用https协议)
    https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID
    参数说明:
    这里写图片描述

    后端操作

    我使用的是idea开发工具+spring boot+mybatis+mysql
    1. 创建项目
    这里写图片描述
    2. pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    
      <modelVersion>4.0.0</modelVersion>
      <packaging>war</packaging>
    
      <name>weixing</name>
      <groupId>com.weixing</groupId>
      <artifactId>weixing</artifactId>
      <version>1.0-SNAPSHOT</version>
    
      <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.2.RELEASE</version>
      </parent>
    
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <shiro.version>1.3.2</shiro.version>
      </properties>
    
      <dependencies>
        <dependency>
          <groupId>org.mybatis.spring.boot</groupId>
          <artifactId>mybatis-spring-boot-starter</artifactId>
          <version>1.2.0</version>
        </dependency>
    
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
    
        <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <scope>runtime</scope>
        </dependency>
    
        <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>1.0.27</version>
        </dependency>
    
        <dependency>
          <groupId>net.sf.json-lib</groupId>
          <artifactId>json-lib</artifactId>
          <version>2.4</version>
          <classifier>jdk15</classifier>
        </dependency>
    
        <dependency>
          <groupId>javax.servlet</groupId>
          <artifactId>javax.servlet-api</artifactId>
          <version>3.1.0</version>
        </dependency>
    
        <dependency>
          <groupId>me.chanjar</groupId>
          <artifactId>weixin-java-tools</artifactId>
          <version>1.0.2</version>
        </dependency>
    
        <dependency>
          <groupId>redis.clients</groupId>
          <artifactId>jedis</artifactId>
          <version>2.1.0</version>
        </dependency>
    
        <dependency>
          <groupId>org.apache.commons</groupId>
          <artifactId>commons-lang3</artifactId>
          <version>3.3.2</version>
        </dependency>
    
        <dependency>
          <groupId>com.jfinal</groupId>
          <artifactId>jfinal-weixin</artifactId>
          <version>1.9</version>
        </dependency>
    
        <dependency>
          <groupId>com.jfinal</groupId>
          <artifactId>jfinal</artifactId>
          <version>3.1</version>
        </dependency>
    
        <dependency>
          <groupId>org.springframework.boot </groupId>
          <artifactId>spring-boot-configuration-processor</artifactId>
          <optional>true </optional>
        </dependency>
    
        <!-- swagger依赖 -->
        <dependency>
          <groupId>io.springfox</groupId>
          <artifactId>springfox-swagger2</artifactId>
          <version>2.6.1</version>
        </dependency>
        <dependency>
          <groupId>io.springfox</groupId>
          <artifactId>springfox-swagger-ui</artifactId>
          <version>2.6.1</version>
        </dependency>
    
    
        <!-- 集成shiro 权限控制-->
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-core</artifactId>
          <version>${shiro.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-web</artifactId>
          <version>${shiro.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-spring</artifactId>
          <version>${shiro.version}</version>
        </dependency>
        <dependency>
          <groupId>org.apache.shiro</groupId>
          <artifactId>shiro-ehcache</artifactId>
          <version>${shiro.version}</version>
        </dependency>
      </dependencies>
      <build>
        <plugins>
          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <dependencies>
              <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>springloaded</artifactId>
                <version>1.2.5.RELEASE</version>
              </dependency>
            </dependencies>
          </plugin>
        </plugins>
    
      </build>
    
    </project>
    
    1. application.properties配置文件
      在配置文件配置端口以及数据库信息
      这里写图片描述
    server.port=8081
    server.tomcat.max-threads=1000
    
    spring.output.ansi.enabled=DETECT
    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/weixing?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&allowMultiQueries=true&useSSL=false
    spring.datasource.username=root
    spring.datasource.password=
    mybatis.mapper-locations=classpath:mybatis/*.xml
    mybatis.type-aliases-package=com.application.pojo
    
    1. 创建pojo
      这里写图片描述
      4.1AccessToken微信通用接口凭证
    package com.application.pojo;
    
    import java.util.Date;
    
    /**
     * 微信通用接口凭证
     * Created by 13592 on 2017/6/26.
     */
    public class AccessToken {
    
        //获取到的凭证
        private String token;
        //凭证有效时间,单位:秒
        private int expiresIn;
        //当前时间
        private Date time;
    
        public String getToken() {
            return token;
        }
    
        public void setToken(String token) {
            this.token = token;
        }
    
        public int getExpiresIn() {
            return expiresIn;
        }
    
        public void setExpiresIn(int expiresIn) {
            this.expiresIn = expiresIn;
        }
    
        public Date getTime() {
            return time;
        }
    
        public void setTime(Date time) {
            this.time = time;
        }
    }
    
    4.2UserList用户列表
    
    package com.application.pojo;
    
    import org.json.JSONArray;
    
    /**
     * 用户列表
     * Created by 13592 on 2017/6/27.
     */
    public class UserList {
        //关注该公众账号的总用户数
        private int total;
        //拉取的OPENID个数,最大值为10000
        private int count;
        //列表数据,OPENID的列表
        private JSONArray data;
        //拉取列表的最后一个用户的OPENID
        private String next_openid;
    
        public int getTotal() {
            return total;
        }
    
        public void setTotal(int total) {
            this.total = total;
        }
    
        public int getCount() {
            return count;
        }
    
        public void setCount(int count) {
            this.count = count;
        }
    
        public JSONArray getData() {
            return data;
        }
    
        public void setData(JSONArray data) {
            this.data = data;
        }
    
        public String getNext_openid() {
            return next_openid;
        }
    
        public void setNext_openid(String next_openid) {
            this.next_openid = next_openid;
        }
    }
    
    1. 常量类,用于配置接口以及一些固定的信息
      这里写图片描述
      5.1WechatApiUrlConstants微信常量API常量类
    package com.application.scheduling;
    
    /**
     * 微信常量API常量类
     * Created by 13592 on 2017/6/27.
     */
    public class WechatApiUrlConstants {
        //凭证获取
        public final static String token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";
        //用户列表
        public final static String user_list_url = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID";
        //用户信息
        public final static String user_data_url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
        //微信接口
        public final static String weixing_url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
        //第三方用户唯一凭证
        public final static String appid = "wx8aae499a2";
        //第三方用户唯一凭证密钥
        public final static String secret = "075c76ea076a8";
        //模板id
        public final static String template_id = "WmDf6MhB6lgUk";
        //详情连接
        public final static String url = "http://www.baidu.com/";
        //测试凭证
        public final static String ce_appid = "wxe50a7d9ecf";
        //测试密钥
        public final static String ce_secret = "33ed74e6e1";
        //测试模板id
        public final static String ce_template_id = "RY2_Ga_Epv7o59pYhpTclXw";
        //预览人员 燕之夜
        public final static String preview_yaner = "ow-b4GR-LyAixQbu1_9pZX-Y";
    
    1. 工具类-htt请求/调用接口/时间计算等
      这里写图片描述
      6.1MyX509TrustManager微信请求-信任管理器
    package com.application.util;
    
    import javax.net.ssl.X509TrustManager;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    
    /**
     * 微信请求-信任管理器
     * Created by 13592 on 2017/6/26.
     */
    public class MyX509TrustManager implements X509TrustManager{
    
        /**
         * 该方法检查客户端的证书,若不信任该证书则抛出异常。由于我们不需要对客户端进行认证,因此我们只需要执行默认的信任管理器的这个方法。
         * JSSE中,默认的信任管理器类为TrustManager。
         * @param x509Certificates
         * @param s
         * @throws CertificateException
         */
        @Override
        public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    
        }
    
        /**
         * 该方法检查服务器的证书,若不信任该证书同样抛出异常。通过自己实现该方法,可以使之信任我们指定的任何证书。
         * 在实现该方法时,也可以简单的不做任何处理,即一个空的函数体,由于不会抛出异常,它就会信任任何证书。
         * @param x509Certificates
         * @param s
         * @throws CertificateException
         */
        @Override
        public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
    
        }
    
        /**
         * 返回受信任的X509证书数组。
         * @return
         */
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }
    
    6.2AccessTokenUtil获取微信APPID和secret工具类
    
    package com.application.util;
    
    
    import com.application.pojo.AccessToken;
    import com.application.pojo.UserData;
    import com.application.pojo.UserList;
    
    /**
     * 获取微信APPID和secret工具类
     * Created by 13592 on 2017/6/27.
     */
    public class AccessTokenUtil {
        public static AccessToken accessToken = new AccessToken();
        public static UserData userData = new UserData();
        public static UserList userList = new UserList();
    
    }
    
    6.3CommonUtil通用工具类/配置类
    
    package com.application.util;
    
    import com.application.from.MessageFrom;
    import com.application.pojo.AccessToken;
    import com.application.pojo.UserData;
    import com.application.pojo.UserList;
    import com.application.scheduling.WechatApiUrlConstants;
    import net.sf.json.JSONObject;
    
    import org.json.JSONArray;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.context.annotation.Configuration;
    
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSocketFactory;
    import javax.net.ssl.TrustManager;
    import java.io.BufferedReader;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.ConnectException;
    import java.net.URL;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;
    
    /**
     * 通用工具类
     * Created by 13592 on 2017/6/26.
     */
    @Configuration
    public class CommonUtil {
    
        private static Logger log = LoggerFactory.getLogger(CommonUtil.class);
        /**
         * 发送https请求
         *
         * @param requestUrl 请求地址
         * @param requestMethod 请求方式(GET、POST)
         * @param outputStr 提交的数据
         * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
         */
        public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
            JSONObject jsonObject = null;
            try {
                // 创建SSLContext对象,并使用我们指定的信任管理器初始化
                TrustManager[] tm = { new MyX509TrustManager() };
                SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
                sslContext.init(null, tm, new java.security.SecureRandom());
                // 从上述SSLContext对象中得到SSLSocketFactory对象
                SSLSocketFactory ssf = sslContext.getSocketFactory();
                URL url = new URL(requestUrl);
                HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
                conn.setSSLSocketFactory(ssf);
    
                conn.setDoOutput(true);
                conn.setDoInput(true);
                conn.setUseCaches(false);
                // 设置请求方式(GET/POST)
                conn.setRequestMethod(requestMethod);
                // 当outputStr不为null时向输出流写数据
                if (null != outputStr) {
                    OutputStream outputStream = conn.getOutputStream();
                    // 注意编码格式
                    outputStream.write(outputStr.getBytes("UTF-8"));
                    outputStream.close();
                }
                // 从输入流读取返回内容
                InputStream inputStream = conn.getInputStream();
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                String str = null;
                StringBuffer buffer = new StringBuffer();
                while ((str = bufferedReader.readLine()) != null) {
                    buffer.append(str);
                }
    
                // 释放资源
                bufferedReader.close();
                inputStreamReader.close();
                inputStream.close();
                inputStream = null;
                conn.disconnect();
                jsonObject = JSONObject.fromObject(buffer.toString());
            } catch (ConnectException ce) {
                log.error("连接超时:{}", ce);
            } catch (Exception e) {
                log.error("https请求异常:{}", e);
            }
            return jsonObject;
            }
    
        /**
         * 获取接口访问凭证
         *
         * @param appid 凭证
         * @param appsecret 密钥
         * @return
         */
        public static AccessToken getToken(String appid, String appsecret) {
            String requestUrl = WechatApiUrlConstants.token_url.replace("APPID", appid).replace("APPSECRET", appsecret);
            // 发起GET请求获取凭证
            JSONObject jsonObject = httpsRequest(requestUrl, "GET", null);
            if (null != jsonObject) {
                try {
                    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    AccessTokenUtil.accessToken.setToken(jsonObject.getString("access_token"));
                    AccessTokenUtil.accessToken.setExpiresIn(jsonObject.getInt("expires_in"));
                    AccessTokenUtil.accessToken.setTime(dateFormat.parse(dateFormat.format(new Date())));
                    if(null != AccessTokenUtil.accessToken){
                        log.info("获取access_token成功,有效时长{}秒 token:{}", AccessTokenUtil.accessToken.getExpiresIn(), AccessTokenUtil.accessToken.getToken());
                    }
                } catch (Exception e) {
                    AccessTokenUtil.accessToken = null;
    
                    log.error("{}", e);
                    log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
                }
            }
            return AccessTokenUtil.accessToken;
        }
    
        /**
         * 获取用户信息
         * @param open 用户id
         * @param token 调用接口凭证
         * @return
         */
        public static UserData getUser(List<String> open, String token){
            for (int i = 0 ; i < open.size() ; i ++){
                String requestUrl = WechatApiUrlConstants.user_data_url.replace("ACCESS_TOKEN",token).replace("OPENID",open.get(i));
                //发起GET请求获取凭证
                JSONObject jsonObject = httpsRequest(requestUrl,"GET",null);
                if (null != jsonObject){
                    try {
                        AccessTokenUtil.userData.setSubscribe(jsonObject.getInt("subscribe"));
                        AccessTokenUtil.userData.setOpenid(jsonObject.getString("openid"));
                        AccessTokenUtil.userData.setNickname(jsonObject.getString("nickname"));
                        AccessTokenUtil.userData.setSex(jsonObject.getInt("sex"));
                        AccessTokenUtil.userData.setLanguage(jsonObject.getString("language"));
                        AccessTokenUtil.userData.setCity(jsonObject.getString("city"));
                        AccessTokenUtil.userData.setProvince(jsonObject.getString("province"));
                        AccessTokenUtil.userData.setCountry(jsonObject.getString("country"));
                        AccessTokenUtil.userData.setHeadimgurl(jsonObject.getString("headimgurl"));
                        AccessTokenUtil.userData.setSubscribe_time(jsonObject.getString("subscribe_time"));
                        AccessTokenUtil.userData.setUnionid(jsonObject.getString("unionid"));
                        AccessTokenUtil.userData.setRemark(jsonObject.getString("remark"));
                        AccessTokenUtil.userData.setGroupid(jsonObject.getInt("groupid"));
                        AccessTokenUtil.userData.setTagid_list(jsonObject.get("tagid_list"));
                        if (null != AccessTokenUtil.userData){
                            log.info("获取用户信息成功, token:{}",open.get(i), jsonObject.getString("nickname"));
                            System.out.println("用户id:"+open.get(i)+"用户姓名:"+jsonObject.getString("nickname"));
                        }else{
                            log.error("获取用户信息失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
                        }
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }
            }
    
            return AccessTokenUtil.userData;
        }
    
        /**
         * 获取关注用户列表
         * @param token 调用接口凭证
         * @param openid 第一个拉取的OPENID
         * @return
         */
        public static UserList getUserList(String token,String openid){
            String requestUrl = WechatApiUrlConstants.user_list_url.replace("ACCESS_TOKEN",token).replace("NEXT_OPENID","");
            //发起GET请求获取凭证
            JSONObject jsonObject = httpsRequest(requestUrl,"GET",null);
            if (null != jsonObject){
                try {
                    AccessTokenUtil.userList.setCount(jsonObject.getInt("count"));
                    AccessTokenUtil.userList.setNext_openid(jsonObject.getString("next_openid"));
                    AccessTokenUtil.userList.setTotal(jsonObject.getInt("total"));
                    JSONObject json1 = jsonObject.getJSONObject("data");
                    JSONArray json2 = new JSONArray(json1.get("openid").toString());
                    AccessTokenUtil.userList.setData(json2);
                    if (null != AccessTokenUtil.userList)
                        log.info("获取用户列表成功, token:{}", AccessTokenUtil.userList.getCount(), AccessTokenUtil.userList.getTotal());
                    else{
                        log.error("获取用户列表失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
    
            }
            return AccessTokenUtil.userList;
        }
    
        /**
         * 获取token的时间差
         * @param time 获取时间
         * @return
         */
        public static Long dateDiff(Date time){
            Date curretTime = new Date(System.currentTimeMillis());
            long nd = 1000 * 24 * 60 * 60;// 一天的毫秒数
            long nh = 1000 * 60 * 60;// 一小时的毫秒数
            long nm = 1000 * 60;// 一分钟的毫秒数
            long ns = 1000;// 一秒钟的毫秒数
            long diff;
            long day = 0;
            long hour = 0;
            long min = 0;
            long sec = 0;
            try {
                diff = curretTime.getTime() - time.getTime();
                day = diff / nd;// 计算差多少天
                hour = diff % nd / nh + day * 24;// 计算差多少小时
                min = diff % nd % nh / nm + day * 24 * 60;// 计算差多少分钟
                sec = diff % nd % nh % nm / ns;// 计算差多少秒
                // 输出结果
                System.out.println("时间相差:" + day + "天" + (hour - day * 24) + "小时"
                        + (min - day * 24 * 60) + "分钟" + sec + "秒。");
                System.out.println("hour=" + hour + ",min=" + min);
            } catch (Exception e) {
                e.printStackTrace();
            }
             return hour;
        }
    
    
        /**
         * 预览推送模板
         * @param mf 模板信息
         * @param openid 预览人员
         * @param url 推送接口
         */
        public static void reviewUser(MessageFrom mf, String openid,String url){
            JSONObject json = new JSONObject();
            json.put("touser", openid);//接收者wxName
            json.put("template_id", WechatApiUrlConstants.ce_template_id);//消息模板
            json.put("url", WechatApiUrlConstants.url);//填写url可查看详情
            JSONObject dd = new JSONObject();
            JSONObject dd2 = new JSONObject();
            dd2.put("value", mf.getTitle_name());//消息提示
            dd2.put("color", "#173177");
            dd.put("first", dd2);
            JSONObject cc2 = new JSONObject();
            cc2.put("value", mf.getVulnerability_levels());//漏洞等级
            cc2.put("color", "#173177");
            dd.put("keyword1", cc2);
            JSONObject ee2 = new JSONObject();
            ee2.put("value", mf.getVulnerability_time());//漏洞时间
            ee2.put("color", "#173177");
            dd.put("keyword2", ee2);
            JSONObject gg2 = new JSONObject();
            gg2.put("value", mf.getVulnerabiliry_Overview());
            gg2.put("color", "#173177");
            dd.put("remark", gg2);
            json.put("data", dd);
            System.out.println(json.toString());
            JSONObject js = CommonUtil.httpsRequest(url, "POST", json.toString());
            System.out.println("js=="+js);
    
        }
    
        /**
         * 全推送模板
         * @param mf 模板信息
         * @param openidList 全关注用户
         * @param url 推送接口
         */
        public static void push(MessageFrom mf,List<String> openidList,String url){
            for (int i = 0 ; i < openidList.size(); i ++){
                JSONObject json = new JSONObject();
                json.put("touser", openidList.get(i));//接收者wxName
                json.put("template_id", WechatApiUrlConstants.ce_template_id);//消息模板
                json.put("url", WechatApiUrlConstants.url);//填写url可查看详情
                JSONObject dd = new JSONObject();
                JSONObject dd2 = new JSONObject();
                dd2.put("value", mf.getTitle_name());//消息提示
                dd2.put("color", "#173177");
                dd.put("first", dd2);
                JSONObject cc2 = new JSONObject();
                cc2.put("value", mf.getVulnerability_levels());//漏洞等级
                cc2.put("color", "#173177");
                dd.put("keyword1", cc2);
                JSONObject ee2 = new JSONObject();
                ee2.put("value", mf.getVulnerability_time());//漏洞时间
                ee2.put("color", "#173177");
                dd.put("keyword2", ee2);
                JSONObject gg2 = new JSONObject();
                gg2.put("value", mf.getVulnerabiliry_Overview());
                gg2.put("color", "#173177");
                dd.put("remark", gg2);
                json.put("data", dd);
                System.out.println(json.toString());
                JSONObject js = CommonUtil.httpsRequest(url, "POST", json.toString());
                System.out.println("js=="+js);
            }
        }
    
    
    
    }
    
    1. service
      这里写图片描述
      7.1AccessTokenService全局调用凭证的操作
    package com.application.service;
    
    import java.util.Date;
    
    /**
     * 全局调用凭证的操作
     * Created by 13592 on 2017/6/27.
     */
    public interface AccessTokenService {
        /**
         * 新增全局调用凭证信息
         * @param token 全局调用凭证id
         */
        void insertToken(String token);
    
        /**
         *  删除表中信息
         *  @return
         */
        void deleteToken();
    
        /**
         * 查询全局调用凭证id
         * @return
         */
        String selectToken();
    
        /**
         * 查询新增时间
         * @return
         */
        Date selectTime();
    }
    
    7.1.1AccessTokenServiceImpl
    
    package com.application.service.impl;
    
    import com.application.mapper.AccessTokenMapper;
    import com.application.pojo.AccessToken;
    import com.application.service.AccessTokenService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.Date;
    
    /**
     * Created by 13592 on 2017/6/27.
     */
    @Service
    public class AccessTokenServiceImpl implements AccessTokenService {
        @Autowired
        private AccessTokenMapper accessTokenMapper;
        @Override
        public void insertToken(String token){
            AccessToken accessToken = new AccessToken();
            Date curretTime = new Date(System.currentTimeMillis());
            accessToken.setToken(token);
            accessToken.setTime(curretTime);
            accessTokenMapper.insertToken(accessToken);
        }
        @Override
        public void deleteToken(){
            accessTokenMapper.deleteToken();
        }
        @Override
        public String selectToken(){
            return accessTokenMapper.selectToken();
        }
        @Override
        public Date selectTime(){return accessTokenMapper.selectTime();}
    }
    
    7.2PreviewService预览人员操作
    
    package com.application.service;
    
    
    import com.application.pojo.PreviewUser;
    
    import java.util.List;
    
    /**
     * 预览人员操作
     * Created by 13592 on 2017/6/29.
     */
    public interface PreviewService {
    
        /**
         * 查询用户id列表
         * @return
         */
        List<String> getOpenid();
    
        /**
         * 新增预览用户信息
         * @param previewUser
         */
        void insertOpenid(PreviewUser previewUser);
    
        /**
         * 查询预览列表
         * @return
         */
        List<PreviewUser> previewList();
    
        /**
         * 通过微信名称查询预览用户id
         * @param opename 微信名称
         * @return
         */
        String selectOpenid(String opename);
    }
    
    7.2.2PreviewServiceImpl
    
    package com.application.service.impl;
    
    import com.application.mapper.PreviewMapper;
    import com.application.pojo.PreviewUser;
    import com.application.service.PreviewService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import java.util.List;
    
    /**
     * Created by 13592 on 2017/6/29.
     */
    @Service
    public class PreviewServiceImpl implements PreviewService{
        @Autowired
        private PreviewMapper previewMapper;
        @Override
        public List<String> getOpenid(){
            List<String> openidList = previewMapper.getOpenid();
            return openidList;
        }
        @Override
        public void insertOpenid(PreviewUser previewUser){
            try {
                previewMapper.insertOpenid(previewUser);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        @Override
        public List<PreviewUser> previewList(){
            return previewMapper.previewList();
        }
        @Override
        public String selectOpenid(String openname){
            String id = "";
            try {
                id = previewMapper.selectOpenid(openname);
            }catch (Exception e){
                e.printStackTrace();
            }
            return id;
        }
    }
    
    1. mapper层-完成持久化DAO层
      使用MyBatis在我们通过xml集中配置SQL,并通过创建接口Mapper文件来完成持久化DAO层(mybatis内部使用的是动态代理,所以我们不需要自己编写实现类)。
      这里写图片描述
      8.1AccessTokenMapper
    package com.application.mapper;
    
    
    
    import com.application.pojo.AccessToken;
    
    import java.util.Date;
    
    /**
     * Created by 13592 on 2017/6/27.
     */
    public interface AccessTokenMapper {
        void insertToken(AccessToken token);
        void deleteToken();
        String selectToken();
        Date selectTime();
    
    }
    
     8.2PreviewMapper
    
    package com.application.mapper;
    
    
    import com.application.pojo.PreviewUser;
    
    import java.util.List;
    
    /**
     * Created by 13592 on 2017/6/29.
     */
    public interface PreviewMapper {
        List<String> getOpenid();
        void insertOpenid(PreviewUser previewUser);
        List<PreviewUser> previewList();
        String selectOpenid(String openname);
    
    }
    
    1. form页面接受参数类
      用于接受页面传过来的数据
      这里写图片描述
      9.1MessageFrom
    package com.application.from;
    
    /**
     * Created by 13592 on 2017/6/28.
     */
    public class MessageFrom {
        //预览用户
        private String preview_user;
        //标题名称
        private String title_name;
        //漏洞等级
        private String Vulnerability_levels;
        //漏洞时间
        private String Vulnerability_time;
        //漏洞概要
        private String Vulnerabiliry_Overview;
    
        public String getPreview_user() {
            return preview_user;
        }
    
        public void setPreview_user(String preview_user) {
            this.preview_user = preview_user;
        }
    
        public String getTitle_name() {
            return title_name;
        }
    
        public void setTitle_name(String title_name) {
            this.title_name = title_name;
        }
    
        public String getVulnerability_levels() {
            return Vulnerability_levels;
        }
    
        public void setVulnerability_levels(String vulnerability_levels) {
            Vulnerability_levels = vulnerability_levels;
        }
    
        public String getVulnerability_time() {
            return Vulnerability_time;
        }
    
        public void setVulnerability_time(String vulnerability_time) {
            Vulnerability_time = vulnerability_time;
        }
    
        public String getVulnerabiliry_Overview() {
            return Vulnerabiliry_Overview;
        }
    
        public void setVulnerabiliry_Overview(String vulnerabiliry_Overview) {
            Vulnerabiliry_Overview = vulnerabiliry_Overview;
        }
    }
    
     9.2PreviewUserForm
    
    package com.application.from;
    
    /**
     * 页面预览人员
     * Created by 13592 on 2017/6/30.
     */
    public class PreviewUserForm {
        //预览用户id
        private String openid;
        //预览用户名
        private String name;
    
        public String getOpenid() {
            return openid;
        }
    
        public void setOpenid(String openid) {
            this.openid = openid;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    
    1. 使用swagger
      这里写图片描述
      10.1Swagger2
    package com.application;
    
    import com.google.common.base.Predicates;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.context.request.async.DeferredResult;
    import springfox.documentation.builders.ApiInfoBuilder;
    import springfox.documentation.builders.PathSelectors;
    import springfox.documentation.service.ApiInfo;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spring.web.plugins.Docket;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;
    
    
    /**
     * 说明:
     * 时间: 2017/3/28 11:32
     *
     * @author wimas
     */
    @Configuration
    @EnableSwagger2
    public class Swagger2 {
    
        @Bean
        public Docket createRestApi() {
            return new Docket(DocumentationType.SWAGGER_2).groupName("access")
                    .genericModelSubstitutes(DeferredResult.class)
                    .useDefaultResponseMessages(false)
                    .forCodeGeneration(true)
                    .pathMapping("/")// base,最终调用接口后会和paths拼接在一起s
                    .select()
                    .paths(Predicates.or(PathSelectors.regex("/access/.*")))//过滤的接口
                    .build()
                    .apiInfo(apiInfo());
        }
    
    
        private ApiInfo apiInfo() {
            return new ApiInfoBuilder()
                    .title("微信模板推送")
                    .description("")
                    .version("1.0")
                    .build();
        }
    }
    
    1. controller控制类
      11.1WechatController
    package com.application.controller;
    
    import com.application.from.MessageFrom;
    import com.application.from.PreviewUserForm;
    import com.application.pojo.AccessToken;
    import com.application.pojo.PreviewUser;
    import com.application.pojo.UserData;
    import com.application.pojo.UserList;
    import com.application.scheduling.WechatApiUrlConstants;
    import com.application.service.AccessTokenService;
    import com.application.service.PreviewService;
    import com.application.util.CommonUtil;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiImplicitParam;
    import io.swagger.annotations.ApiOperation;
    import io.swagger.annotations.ApiParam;
    import org.apache.shiro.authz.annotation.RequiresPermissions;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    import javax.validation.Valid;
    import java.util.*;
    
    /**
     * 微信推送信息
     * Created by 13592 on 2017/6/26.
     */
    @RestController
    @RequestMapping("/access")
    @Api(description = "微信模板推送")
    public class WechatController {
        @Autowired
        private PreviewService previewService;
        @Autowired
        private AccessTokenService accessTokenService;
    
    
        @ApiOperation(value = "模板推送")
        @PostMapping(value = "/token")
        @ApiImplicitParam(name = "mf", value = "模板信息", required = true, dataType = "MessageFrom")
        @RequiresPermissions("access:token")
        public void wxTuisong(@Valid @RequestBody MessageFrom mf){
            AccessToken token = new AccessToken();
            Date date = accessTokenService.selectTime();
            Long time = getDiff(date);
            if(time>=2){//时间间隔大于等于2个小时则重新取接口调用凭证
                accessTokenService.deleteToken();
                token = headtoken (WechatApiUrlConstants.appid,WechatApiUrlConstants.secret);//获取token
                accessTokenService.insertToken(token.getToken());
            }else{
                token.setToken(accessTokenService.selectToken());
            }
            if(token.getToken()!=null){
                UserList userList = getUserList(token.getToken(),"");
                String url = WechatApiUrlConstants.weixing_url.replace("ACCESS_TOKEN", token.getToken());//转换为响应接口模式
                List<String> previewUserList = previewService.getOpenid();//预览用户id列表
                List<String> opeidList = new ArrayList<String>();//所有关注用户列表
                for (int i = 0 ; i < userList.getData().length() ; i ++){
                    opeidList.add(userList.getData().get(i).toString());
                }
                List<String> list = new ArrayList<String>();
                if (mf.getPreview_user()!= "" || !mf.getPreview_user().equals("string")){
                    for (int i = 0 ; i < previewUserList.size(); i ++){
                        if(mf.getPreview_user().equals(previewUserList.get(i))){
                            reviewUser(mf,previewUserList.get(i),url);
                        }
                    }
                }else{
                    push(mf,opeidList,url);
                }
            }
        }
    
        @ApiOperation(value = "新增预览人员")
        @PostMapping(value = "/insert")
        @ApiImplicitParam(name = "puf", value = "模板信息", required = true, dataType = "PreviewUserForm")
        @RequiresPermissions("access:insert")
        public void insert(@Valid @RequestBody PreviewUserForm puf){
            PreviewUser previewUser = new PreviewUser();
            previewUser.setOpenid(puf.getOpenid());
            previewUser.setOpenname(puf.getName());
            previewService.insertOpenid(previewUser);
        }
    
        @ApiOperation(value = "查询预览列表")
        @GetMapping(value = "/selectList")
        @RequiresPermissions("access:selectList")
        public List<PreviewUser> selectList(){
            return previewService.previewList();
        }
    
        @ApiOperation(value = "查询预览id")
        @GetMapping(value = "/selectOpenid/{openname}")
        @RequiresPermissions("access:selectOpenid")
        public String selectOpenid(@ApiParam(name = "openname",value = "用户名称",required = true) @PathVariable String openname){
            return previewService.selectOpenid(openname);
        }
        /**
         * 请求token
         * @Description :
         * @param
         * @return
         * ---------------
         * @Author  : My
         * @CreateData : 2016-1-18
         */
        public static AccessToken headtoken (String appId,String appSrecet){
            AccessToken token = CommonUtil.getToken(appId, appSrecet);
            return token;
        }
    
    
        /**
         * 获取关注用户
         * @param token 接口调用凭证
         * @param openid
         * @return
         */
       public static UserList getUserList(String token,String openid){
            UserList userList = CommonUtil.getUserList(token,openid);
            return userList;
       }
    
        /**
         * 时间获取
         * @param time 获取时间
         * @return
         */
       public static Long getDiff(Date time){
            CommonUtil commonUtil = new CommonUtil();
            return commonUtil.dateDiff(time);
    
       }
    
        /**
         * 获取用户信息
         * @param openid 用户id
         * @param token 接口调用凭证
         * @return
         */
       public static UserData userDate(List<String> openid,String token){
           CommonUtil commonUtil = new CommonUtil();
           return commonUtil.getUser(openid,token);
       }
    
    
        /**
         * 预览推送模板
         * @param mf 模板信息
         * @param openid 用户id
         * @param url 接口
         */
       public static void reviewUser(MessageFrom mf, String openid,String url){
          /* CommonUtil commonUtil = new CommonUtil();
           commonUtil.reviewUser(mf, openid, url);*/
    
       }
    
        /**
         * 全推送模板
         * @param mf 模板信息
         * @param openidList 全关注用户
         * @param url 推送接口
         */
        public static void push(MessageFrom mf,List<String> openidList,String url){
           /* CommonUtil commonUtil = new CommonUtil();
            commonUtil.push(mf, openidList, url);*/
        }
    
        public static void main(String[] args){
            AccessToken token = new AccessToken();
    //        token = CommonUtil.getToken(APP_ID,SECRET);
            WechatController wechatController = new WechatController();
            CommonUtil commonUtil = new CommonUtil();
            MessageFrom massages = new MessageFrom();
            wechatController.wxTuisong(massages);
            System.out.println("==================================================");
    
        }
    }
    
    1. mybatis.xml
      这里写图片描述
      12.1AccessTokenMapper.xml
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.application.mapper.AccessTokenMapper" >
        <resultMap id="BaseResultMap"  type="com.application.pojo.AccessToken">
            <result column="access_token_name" property="token" jdbcType="VARCHAR"/>
            <result column="access_token_time" property="time" jdbcType="TIMESTAMP"/>
        </resultMap>
    
        <insert id="insertToken" parameterType="com.application.pojo.AccessToken">
            INSERT INTO weixing_access_token (
              access_token_name,
              access_token_time
            )
            VALUES
            (
              #{token,jdbcType=VARCHAR},#{time,jdbcType=TIMESTAMP})
    
        </insert>
    
        <delete id="deleteToken">
            DELETE
            FROM
              weixing_access_token
            WHERE
              1 = 1
        </delete>
    
        <select id="selectToken" resultType="String">
            SELECT
              access_token_name
            FROM
              weixing_access_token
        </select>
    
        <select id="selectTime" resultType="Date">
            SELECT
              access_token_time
            FROM
              weixing_access_token
        </select>
    </mapper>
    12.2PreviewMapper.xml
    
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.application.mapper.PreviewMapper" >
        <resultMap id="BaseResultMap"  type="com.application.pojo.PreviewUser">
            <result column="openid" property="openid" jdbcType="VARCHAR"/>
            <result column="openname" property="openname" jdbcType="VARCHAR"/>
        </resultMap>
        <select id="getOpenid" resultType="java.lang.String">
          SELECT openid FROM  review_user
        </select>
        <insert id="insertOpenid" parameterType="com.application.pojo.PreviewUser">
          INSERT INTO review_user (openid, openname)
          VALUES
            (
              #{openid,jdbcType=VARCHAR},#{openname,jdbcType=VARCHAR})
        </insert>
        <select id="previewList" resultMap="BaseResultMap" parameterType="com.application.pojo.PreviewUser">
            SELECT * FROM  review_user
        </select>
        <select id="selectOpenid" resultType="string" parameterType="string">
          SELECT
            openid
          FROM
            review_user
          WHERE
            openname = #{openname,jdbcType=VARCHAR}
        </select>
    
    
    </mapper>
    1. spring boot启动类
      这里写图片描述
      13.1Application
      package com.application;

    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cache.annotation.EnableCaching;

    /**
    * Created by 13592 on 2017/6/27.
    */

    @SpringBootApplication
    @EnableCaching
    @MapperScan(basePackages = “com.application.mapper”)
    public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    
    }
    

    }

    1. 数据库
      这里写图片描述
      14.1review_user预览表
      这里写图片描述
      14.2weixing_access_token全局调用接口凭证信息表
      这里写图片描述
    2. 启动Application
      正常启动的情况
      这里写图片描述
      启动完毕后,在浏览器输入http://localhost:8081/swagger-ui.html
      这里写图片描述
    3. 测试-输入模板消息
      这里写图片描述
      发送之后,因为填写了预览人,所以我会接受到这条推送信息
      微信收到的模板
      这里写图片描述
      后端显示返回结果
      在调用模板消息接口后,会返回JSON数据包。正常时的返回JSON数据包示例:
      {
      “errcode”:0,
      “errmsg”:”ok”,
      “msgid”:200228332
      }
    展开全文
  • java实现微信公众号模版消息推送 准备 登录微信公众号后台(公众号模版消息推送必须为认证后的服务号)获取获取添加模版消息ID 具体实现 java代码 /** * 体脂数据推送信息给微信 * @param access_token ...

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

    准备

    登录微信公众号后台(公众号模版消息推送必须为认证后的服务号)获取获取添加模版消息ID 

    具体实现

    java代码

    /**
    	 * 体脂数据推送信息给微信
    	 * @param access_token
    	 * @param open_id
    	 * @param highPressure
    	 * @param lowPressure
    	 * @param heart
    	 * @param bloodPressureLevel
    	 */
    	public  void sendBodyCompostionInfoToWeChart(final String access_token,final String open_id,final String user_name,final String bodyCompostionText,final String test_time){
    
    			try {
    				String	regUser = "http://wxdemo.xxxx.com/wxdevices/bodycompositionmain?openId="+open_id;
    				String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token="+access_token;
    				Map<String, Object> map = new HashMap<String, Object>();
    				map.put("touser", open_id); //推送用户openid
    				map.put("template_id", WXUtil.TTJK_TEMP_TIZHI_ID); //指定模版ID
    				map.put("url", regUser);  //点击模版跳转地址
    				Map<String, Object> data_map =new HashMap<String, Object>();
    				Map<String, Object> first = new HashMap<String, Object>();
    				first.put("value", "您好,你有一条体脂检测信息");
    				first.put("color", "#000000");
    				Map<String, Object> keynote1 = new HashMap<String, Object>();
    				keynote1.put("value", user_name);
    				keynote1.put("color", "#000000");
    				Map<String, Object> keynote2 = new HashMap<String, Object>();
    				keynote2.put("value", test_time);
    				keynote2.put("color", "#000000");
    				Map<String, Object> keynote3 = new HashMap<String, Object>();
    				keynote3.put("value", bodyCompostionText);
    				keynote3.put("color", "#000000");
    				Map<String, Object> remark = new HashMap<String, Object>();
    				remark.put("value", "点击查看详情");
    				remark.put("color", "#000000");
    				data_map.put("first", first);
    				data_map.put("keyword1", keynote1);
    				data_map.put("keyword2", keynote2);
    				data_map.put("keyword3", keynote3);
    				data_map.put("remark", remark);
    				map.put("data", data_map);
    				JSONObject json = JSONObject.fromObject(map);
    				String result = HttpUtil.sendPost(url, json.toString());
    				System.out.println(result);
    				JSONObject json_arr = JSONObject.fromObject(result);
    				String isOk = String.valueOf(json_arr.get("errmsg"));
    				logger.info(" errmsg >>>>>>>>> "+isOk);
    				if(isOk.equals("ok")){
    					logger.info("体脂据推送成功 , "+open_id );
    				}else{
    					logger.info("体脂据推送失败 , "+open_id );
    				}
    			} catch (Exception e) {
    				logger.error("", e);
    			}
    			
    	}

     成功截图

     

    就是这么简单,如有不明白可以点击博客左边+ wx 帮你解答

    展开全文
  • 写这篇文章之前先给大家看张图片,这种图是不是很熟悉,用过微信关注过某些公众号的用户应该都见过,没错,是微信公众号推送出来的。通过消息推送,可以为用户发送预约服务,购买提醒服务,发货服务,提现提醒服务等...

    写这篇文章之前先给大家看张图片,这种图是不是很熟悉,用过微信关注过某些公众号的用户应该都见过,没错,是微信公众号推送出来的。通过消息推送,可以为用户发送预约服务,购买提醒服务,发货服务,提现提醒服务等消息通知。

    现在,我们也要做这样一件事,不过我的业务场景是这样的:现在有一个公众号,还有一个小程序,我需要给指定的已关注我公众号的用户推送一条模板消息,当用户点击模板消息后可以调到我小程序中的指定页面。(本文以此业务场景记录开发过程)

    不了解微信公众号或者没有相关经验的开发人员可能有点懵,因为不知道怎么下手,究竟该如何推送模板消息呢,其实很简单,我们只需要根据微信公众平台技术文档去仔细阅读接口调用方式并按照规范调用即可完成推送。附:模板消息推送接口

    大致阅读文档后,我们知道需要具备以下条件:

    1. 有一个微信公众号,并且知道公众号的appid和appSecret
    2. 有一个小程序,并且知道小程序的appid
    3. 需要跳转到的小程序的页面(不知道的话可以问前端开发人员要)
    4. 知道就模板消息接受者的openid(接受者已关注微信公众号)

    以下附上我们需要用到的两个官方接口:

    //微信获取ACCESS_TOKEN API
    public static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET";
    
    //微信模板消息推送 API
    public static final String MESSAGE_TEMPLATE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";

    第一个接口为获取access_token,它是调用接口的凭证,在调用其他接口前必须先调用此接口获取access_token(请将自己的微信公众号的appid和appSecret替换接口地址中的APPID和SECRET)。此接口返回示例如下(返回结果是一个json数据包,注意access_token的有效期为7200s,也就是2小时,且此接口的调用频次为日限2000,如果你的推送用户量大,请把返回的access_token放到缓存中缓存一段时间,节约网络资源,从我做起。:)。另外,调用接口时,请登录“微信公众平台-开发-基本配置”提前将服务器IP地址添加到IP白名单中,点击查看设置方法,否则将无法调用成功。

    {
    "access_token":"25_vdgBGnGbfY1bE9e0xOw-mHTROXh6xUXwCANb49jjEQ_Eu4iyhW2MqSmA1UZf7oGelW9AjLGzICvhOJcAqLaxDRVBLmwkeLDEPwQ0YbDN7-wdYza47x-WYDY0lvbFJX3ejIMu6xwnQZGlN2Um1SXHTXSeAD5AHLG",
    "expires_in":7200
    }

    第二个接口即为推送消息模板的关键性接口,模板消息的推送就是依靠此接口完成的,但是注意,需要将第一个接口返回的access_token解析拿出来替换这个接口地址中的ACCESS_TOKEN。(以下为此接口的请求体,封装成一个数据传输对象dto,然后转成json)

    {
               "touser":"OPENID",        // 接收模板消息的用户
               "template_id":"ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY",        //公众号中配置的消息模板对应的模板ID
               "url":"http://weixin.qq.com/download",         //想要跳转的路径 
               "miniprogram":{        //需要跳转的小程序的appid和页面
                 "appid":"xiaochengxuappid12345",
                 "pagepath":"index?foo=bar"
               },          
               "data":{        // 封装模板消息数据
                       "first": {
                           "value":"恭喜你购买成功!",
                           "color":"#173177"
                       },
                       "keyword1":{
                           "value":"巧克力",
                           "color":"#173177"
                       },
                       "keyword2": {
                           "value":"39.8元",
                           "color":"#173177"
                       },
                       "keyword3": {
                           "value":"2014年9月22日",
                           "color":"#173177"
                       },
                       "remark":{
                           "value":"欢迎再次购买!",
                           "color":"#173177"
                       }
               }
           }

    注意:请务必根据微信公众平台的技术文档按照规范封装数据请求体

    注:url和miniprogram都是非必填字段,若都不传则模板无跳转;若都传,会优先跳转至小程序。开发者可根据实际需要选择其中一种跳转方式即可。当用户的微信客户端版本不支持跳小程序时,将会跳转至url。

    å°¼çï¼ç«ç¶ç»æäºï¼ï¼ - èè头è£é¼è¡¨æ_表æ头ç_èè头_éé¦é¿è¡¨æ


    这就结束了?并没有!如果我没有公众号我想练练手怎么办呢?当然有办法,我们可以申请测试号直接测试!nice!

    微信公众平台接口测试帐号申请,点此申请测试号!!!

    现在公众号的appid和appSecret有了!

    关注二维码,相当于关注了上面的测试号,这样我们就拿到了自己的openid!

    增加一个模板消息,现在模板ID也有了!

    根据上面的步骤,一步步来,直接放张结果图吧!大功告成!

    (本文最终推送的结果与实际场景有出入,因为本测试号无法关联我要跳转的小程序,所以...)

    文章最后抛出一些注意点:

    1. 如果要在微信公众号内推送消息,其分为微信消息与小程序消息,微信消息可以主动推送,小程序消息的推送依赖于用户主动点击小程序内产生的formid,两者是有差别的,注意区分。(本文推送的是微信消息,所以跟formid没关系)
    2. 如果要推送消息并且跳转对应小程序,需要小程序已审核发布,并且已关联本公众号,否则推送不出来!
    3. 本文发送http请求依赖了hutool工具包,自行pom文件引入调用即可。
    4. 多看文档介绍,调用接口推送完毕回返回状态码,根据状态码自行检查错误。全局返回码说明

    附上本文demo代码:

    public class WxTemplateMessage {
    
        public static void main(String[] args) {
            final Logger logger = LoggerFactory.getLogger(WxTemplateMessage.class);
            logger.info("========微信模板消息定时推送开始========");
            String appId = "wxf8daaba119674993ae";        // 公众号appid
            String appSecret = "2a996e13386170a817c42d611a8b26ce49";      // 公众号appSecret
            String miniAppId = "wx37e7dd9d2312bfb19d4";        // 要跳转的小程序appid
            String pagePath = "pages/common/Outpatient-pay?type=clinic";     // 要跳转的小程序页面
            String accessToken = JSONObject.fromObject(HttpUtil.get(WeChatMessagePushConstants.ACCESS_TOKEN_URL.replace("APPID", appId).replace("SECRET", appSecret))).getString("access_token");
            WechatTemplate template = new WechatTemplate();
            template.setTemplate_id("a5kTd_SzwgUhwRrh21PF7eYIcouGUNaQ8tdRoHgNTC5GE");     // 模板消息ID
            template.setTouser("olfZfwadJ24NRAm7YS2fESXYuFVqmM");     //  接收者openid
            Miniprogram miniprogram = new Miniprogram();
            miniprogram.setAppid(miniAppId);
            miniprogram.setPagepath(pagePath);
            template.setMiniprogram(miniprogram);
            Map<String, TemplateData> mapdata = new HashMap<>();
            TemplateData first = new TemplateData("您好,您有一笔订单产生!");
            mapdata.put("first", first);
    
            TemplateData keyword1 = new TemplateData("测试用户");       // 用户名
            mapdata.put("keyword1", keyword1);
    
            TemplateData keyword3 = new TemplateData("100.00");           // 订单金额
            mapdata.put("keyword3", keyword3);
    
            TemplateData keyword4 = new TemplateData("小米手机");         // 商品信息
            mapdata.put("keyword4", keyword4);
    
            TemplateData remark = new TemplateData("更多详细内容点击查看");         // 备注
            mapdata.put("remark", remark);
            template.setData(mapdata);
    
            logger.info("推送内容:[{}]", com.alibaba.fastjson.JSONObject.toJSONString(template));
            JSONObject pushResult = JSONObject.fromObject(HttpUtil.post(WeChatMessagePushConstants.MESSAGE_TEMPLATE_URL.replace("ACCESS_TOKEN", accessToken), com.alibaba.fastjson.JSONObject.toJSONString(template)));
            int result = 0;
            if (null != pushResult) {
                if (0 != pushResult.getInt("errcode")) {
                    result = pushResult.getInt("errcode");
                    logger.info("推送结果:[推送失败],错误代码:[{}],错误原因:[{}]。", pushResult.getInt("errcode"), pushResult.getString("errmsg"));
                } else {
                    logger.info("推送结果:[推送成功]。");
                }
            }
            logger.info("========微信模板消息定时推送结束========");
        }
    }
    
    public class WeChatMessagePushConstants {
    
        //微信获取ACCESS_TOKEN API
        public static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET";
    
        //微信模板消息推送 API
        public static final String MESSAGE_TEMPLATE_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";
    
    }
    public class Miniprogram {
    
        private String appid;
    
        private String pagepath;
    
        public String getAppid() {
            return appid;
        }
    
        public void setAppid(String appid) {
            this.appid = appid;
        }
    
        public String getPagepath() {
            return pagepath;
        }
    
        public void setPagepath(String pagepath) {
            this.pagepath = pagepath;
        }
    }
    public class WechatTemplate {
        private String touser;
    
        private String template_id;
    
        private Miniprogram miniprogram;
    
        private String url;
    
        private Map<String, TemplateData> data;
    
        public String getUrl() {
            return url;
        }
    
        public void setUrl(String url) {
            this.url = url;
        }
    
        public Miniprogram getMiniprogram() {
            return miniprogram;
        }
    
        public void setMiniprogram(Miniprogram miniprogram) {
            this.miniprogram = miniprogram;
        }
    
        public String getTouser() {
            return touser;
        }
    
        public void setTouser(String touser) {
            this.touser = touser;
        }
    
        public String getTemplate_id() {
            return template_id;
        }
    
        public void setTemplate_id(String template_id) {
            this.template_id = template_id;
        }
    
        public Map<String, TemplateData> getData() {
            return data;
        }
    
        public void setData(Map<String, TemplateData> data) {
            this.data = data;
        }
    
    }

    å®ç¾_å®ç¾è¡¨æ下期再见!

    展开全文
  • 微信公众号消息模板推送demo,亲测能用,替换下参数就能用
  • 第一步,在微信公众平台添加模板第二步,根据所需JSON创建封装实体类微信模板消息发送APIhttps://mp.weixin.qq.com/wiki?t=resource/res_main&amp;id=mp1433751277所需要的JSON格式,这个要根据自己选中的模板来定...

    第一步,在微信公众平台添加模板

    第二步,根据所需JSON创建封装实体类

    微信模板消息发送API

    https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1433751277

    所需要的JSON格式,这个要根据自己选中的模板来定具体参数

     {
               "touser":"OPENID",
               "template_id":"ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY",
               "url":"http://weixin.qq.com/download",  
               "miniprogram":{
                 "appid":"xiaochengxuappid12345",
                 "pagepath":"index?foo=bar"
               },          
               "data":{
                       "first": {
                           "value":"恭喜你购买成功!",
                           "color":"#173177"
                       },
                       "keyword1":{
                           "value":"巧克力",
                           "color":"#173177"
                       },
                       "keyword2": {
                           "value":"39.8元",
                           "color":"#173177"
                       },
                       "keyword3": {
                           "value":"2014年9月22日",
                           "color":"#173177"
                       },
                       "remark":{
                           "value":"欢迎再次购买!",
                           "color":"#173177"
                       }
               }
           }

    我自己选中的模板样式:

    所以创建了一下实体:

    public class TemplateMessage {
    
        //用户openid
        private String touser;
    
        //模板消息ID
        private String template_id;
    
        //详情跳转页面
        private String url;
    
        //模板数据封装实体
        private Data data;
    
        public String getTouser() {
            return touser;
        }
    
        public void setTouser(String touser) {
            this.touser = touser;
        }
    
        public String getTemplate_id() {
            return template_id;
        }
    
        public void setTemplate_id(String template_id) {
            this.template_id = template_id;
        }
    
        public String getUrl() {
            return url;
        }
    
        public void setUrl(String url) {
            this.url = url;
        }
    
        public Data getData() {
            return data;
        }
    
        public void setData(Data data) {
            this.data = data;
        }
    }
    
    public class Data {
    
        private  Content first;
        private  Content keyword1;
        private  Content keyword2;
        private  Content keyword3;
        private  Content keyword4;
        private  Content remark;
    
        public Content getKeyword4() {
            return keyword4;
        }
    
        public void setKeyword4(Content keyword4) {
            this.keyword4 = keyword4;
        }
    
        public Content getFirst() {
            return first;
        }
    
        public void setFirst(Content first) {
            this.first = first;
        }
    
        public Content getKeyword1() {
            return keyword1;
        }
    
        public void setKeyword1(Content keyword1) {
            this.keyword1 = keyword1;
        }
    
        public Content getKeyword2() {
            return keyword2;
        }
    
        public void setKeyword2(Content keyword2) {
            this.keyword2 = keyword2;
        }
    
        public Content getKeyword3() {
            return keyword3;
        }
    
        public void setKeyword3(Content keyword3) {
            this.keyword3 = keyword3;
        }
    
        public Content getRemark() {
            return remark;
        }
    
        public void setRemark(Content remark) {
            this.remark = remark;
        }
    }
    
    public class Content {
    
        //消息内容
        private String value;
    
        //消息字体颜色
        private String color;
    
        public String getValue() {
            return value;
        }
    
        public void setValue(String value) {
            this.value = value;
        }
    
        public String getColor() {
            return color;
        }
    
        public void setColor(String color) {
            this.color = color;
        }
    }
    

    第三步,配置文件application.properties中配置请求路径,模板ID,跳转路径等

    #模板ID
    Template=ra6vbHS2MY060Zt5VrkGEAySMens4Tpca4I8zE7FNTo
    
    #跳转页面路径
    HaveALook=www.baidu.com

    第四步,开发消息发送业务接口(这是局部代码,其中ResponseVo是自定义返回对象,可以不关注,换成string或你们的自定义返回对象就好):

    /**
     * 发送模板消息
     * @param content
     * @return
     */
     ResponseVO TemplateMessage(String content);


    /**
     * 模板消息请求路径
     */
    private static String  TemplateMessage_Url="https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN";

     /**
         * 模板消息推送
         * @param content   要发送的JSON
         * @return
         */
        public ResponseVO TemplateMessage(String content){
            //获得令牌
            String accessToken = tokenFeignService.getToken();
    
            //创建返回实体对象
            ResponseVO vo = new ResponseVO();
            //获得新的token
            String url=TemplateMessage_Url.replace("ACCESS_TOKEN", accessToken);
    
            //调用接口进行发送
            JSONObject jsonObject = httpRequest(url, "POST", content);
            Integer errcode = jsonObject.getInteger("errcode");
            String errorCodeText = ErrorCodeText.errorMsg(errcode);
    
            if (errcode == 0){
                vo.setSuccess(true);
            }else{
                vo.setSuccess(false);
            }
            vo.setCode(errcode);
            vo.setText(errorCodeText);
            return vo;
    
        }
    

    第五步,前端控制器

    //引入跳转路径
    @Value("${HaveALook}")
    private String HaveALook;
    
    //引入模板ID
    @Value("${Template}")
    private String Template;
    @GetMapping("/test")
     public String test(){
        //创建消息发送实体对象
        TemplateMessage templateMessage=new TemplateMessage();
        templateMessage.setUrl(HaveALook);
        templateMessage.setTouser("oKWFV1K4-88PuhQiw80syHB");
        templateMessage.setTemplate_id(Template);
        //设置模板标题
        Content first=new Content();
        first.setValue("预警");
        first.setColor("#FF0000");
        //设置模板内容
        Content keyword1=new Content();
        keyword1.setValue("测试");
        keyword1.setColor("#FF0000");
        //设置模板位置
        Content keyword2=new Content();
        keyword2.setValue("菇房");
        keyword2.setColor("#FF0000");
        //设置设备
        Content keyword3=new Content();
        keyword3.setValue("传感器设备");
        keyword3.setColor("#FF0000");
        //设置时间
        Content keyword4=new Content();
        SimpleDateFormat format=new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
        String format1 = format.format(new Date());
        keyword4.setValue(format1);
        keyword4.setColor("#FF0000");
        //设置跳转内容
        Content remark=new Content();
        remark.setValue("点此处查看详情");
        remark.setColor("#FF0000");
        //创建模板信息数据对象
        Data data=new Data();
        data.setFirst(first);
        data.setKeyword1(keyword1);
        data.setKeyword2(keyword2);
        data.setKeyword3(keyword3);
        data.setKeyword4(keyword4);
        data.setRemark(remark);
        templateMessage.setData(data);
    
        //将封装的数据转成JSON
        String jsonString = JSON.toJSONString(templateMessage);
        weixinMessageService.TemplateMessage(jsonString);
        return jsonString;
     }

    展开全文
  • 一、开发前准备 需要到微信公众号平台获取几个必要的参数: appId,appSecret,templateId(消息模板id),openId(用户访问时授权获取) ...--微信模版消息推送三方sdk--> <dependency> <groupId...
  • 实现功能:通过微信公众号指定某个用户主动进行推送消息 准备工作:要有认证过的服务号,要有自己的服务器,还需要在公众号后台配置好token验证(需要https) 1、首先需要获取 access_token,需要appid和secret ...
  • java二次开发微信公众号接口,实现根据用户授权,获取用户code,再获取openid,然后向其推送模版消息
  • 微信公众号开发之模板消息推送系统 小程序爬虫接单、app爬虫接单、网页爬虫接单、接口定制、网站开发、小程序开发微信公众号开发> 点击这里联系我们 < 微信请扫描下方二维码 代码仅供学习交流,请勿用于...
  • 微信小程序的消息推送功能简单的说就是发送一条微信通知给用户,用户点开消息可以查看消息内容,也可以通过消息链接进入到小程序的制定页面。 微信小程序消息推送需要用户触发动作才能发送消息,比如用户提交订单、...
  • 微信小程序消息推送需要用户触发动作才能发送消息,比如用户提交订单、支付成功。一次只能发一条。也就是说只有用户点了小程序,操作了form表单提交然后生成一个formid ,才可以通过这条formid可以推送一条模板消息。...
  • 推送微信模板消息,我们需要准备的条件有: 1、有效的access_token 2、微信公众号提供的消息模板的Template_id access_token: 公众平台以access_token为接口调用凭据,来调用接口,所有接口的调用需要先获取...
  • 微信模板消息推送

    2019-03-14 10:32:01
    一、微信公众号或测试号内配置,我这里使用的...二、SpringBoot后台实现微信消息模板推送代码 注意:对于消息测试这类不是特别重要的功能,最好不要抛出异常 @Service @Slf4j public class PushMessageServiceIm...
  • 开发公众号推送消息是十分重要又基础的功能,这里主要记录一下微信公众号推送模板开发的相关流程和代码。 首先:首先去服务号后台选择你要推送的消息模板微信有自己的模板,按照需要选取,没有合适的可以自行申请...
  • 5行代码实现微信模版消息推送,springboot实现微信推送,java微信推送 今天来带大家学习下微信模版消息推送。 先看效果图: 核心代码只有下面几行,即可轻松实现微信模版消息推送 //1,配置 ...
  • 微信公众号开发 调用推送模板消息接口超时,之前一直好好的,今天早上就出现了链接超时的问题,是不是微信的接口出问题了,如果是,怎么把问题反馈给微信,如果不是,请问出现该问题的其他原因是什么?![图片说明]...
  • 微信小程序推送模板消息功能,基于springboot ,包含前端和后端全流程
  • 该demo主要涉及微信模板消息推送功能, 详细 代码下载:http://www.demodashi.com/demo/14627.html 概述 微信公众平台开始支持前端网页,大家可能看到很多网页上都有分享到朋友圈,关注微信等按钮...
  • 微信公众号的配置完了,消息推送就比较简单了。本节主要介绍一下推送的代码。  一、首先需要在公众号平台中新建一个模板(用于推送消息)。下面是测试和正式微信公众号的模板。正式的模板可以设置标题、行业、内容...
1 2 3 4 5 ... 20
收藏数 9,942
精华内容 3,976
关键字:

微信开发之模版推送