微信模板推送

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
    }
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值