java 微信公众号文档整理 生成公众号二维码 获取token 发送消息 个人笔记整理 消息回调 域名验证

spring boot整合公众号笔记

1. 域名验证

   1.1 WechatController  与  CheckUtil 验证 

    

@Controller
@RequestMapping("certification/access")
public class WechatController {
    private Logger logger = LoggerFactory.getLogger(WechatController.class);
    /**
     * @Description 这是微信回调的验证接口
     */
    @RequestMapping(method = RequestMethod.GET)
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String signature = req.getParameter("signature");
        String timestamp = req.getParameter("timestamp");
        String nonce = req.getParameter("nonce");
        String echostr = req.getParameter("echostr");

        PrintWriter out = resp.getWriter();
        if(CheckUtil.checkSignature(signature, timestamp, nonce)){
            out.print(echostr);
        }
    }
    /**
     * 消息的接收与响应
     */
    @RequestMapping(method = RequestMethod.POST)
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException{
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");
        PrintWriter out = resp.getWriter();
        try {
            Map<String, String> map = MessageUtil.xmlToMap(req);
            String fromUserName = map.get("FromUserName");//发送者
            String toUserName = map.get("ToUserName");//接收者
            String msgType = map.get("MsgType");//消息类型
            String content = map.get("Content");//消息内容

            String message = null;
            if(MessageUtil.MESSAGE_TEXT.equals(msgType)){//文本消息

            }else if(MessageUtil.MESSAGE_EVNET.equals(msgType)){//事件消息
                String eventType = map.get("Event");
                if(MessageUtil.MESSAGE_SUBSCRIBE.equals(eventType)){//用户未关注时,进行关注后的事件推送

                    String eventKey = map.get("EventKey");
                    if(!StringUtil.isEmpty(eventKey)){
                        eventKey = eventKey.replace("qrscene_","");
                        //自己的逻辑
                    }
                    message = MessageUtil.initText(toUserName, fromUserName, MessageUtil.menuText());
                }else if(MessageUtil.FOLLOW_OFFICIAL_ACCOUNT.equals(eventType)){//用户已关注时的事件推送

                    String eventKey = map.get("EventKey");
                    if(!StringUtil.isEmpty(eventKey)){
                       //自己的逻辑 
                    }
                    message = MessageUtil.initText(toUserName, fromUserName, MessageUtil.menuText());
                }else if(MessageUtil.MESSAGE_CLICK.equals(eventType)){//点击事件
                    message = MessageUtil.initText(toUserName, fromUserName, MessageUtil.menuText());
                }else if(MessageUtil.MESSAGE_VIEW.equals(eventType)){//查看事件
                    
                }else if(MessageUtil.MESSAGE_SCANCODE.equals(eventType)){//扫描码推送
                    
                }
            }else if(MessageUtil.MESSAGE_LOCATION.equals(msgType)){
               
            }
            logger.info(message);
            out.print(message);
        } catch (DocumentException e) {
            e.printStackTrace();
            logger.error("消息与响应失败:"+e);
            out.print("");
        }finally{
            out.close();
        }
    }
}

 1.2 CheckUtil 验证类

 

package com.syx.modules.system.wechat;

import java.security.MessageDigest;
import java.util.Arrays;

public class CheckUtil {
   private static final String token = "imooc";
   public static boolean checkSignature(String signature,String timestamp,String nonce){
      String[] arr = new String[]{token,timestamp,nonce};
      //排序
      Arrays.sort(arr);
      
      //生成字符串
      StringBuffer content = new StringBuffer();
      for(int i=0;i<arr.length;i++){
         content.append(arr[i]);
      }
      
      //sha1加密
      String temp = getSha1(content.toString());
      
      return temp.equals(signature);
   }
   
   /**
    * Sha1加密方法
    * @param str
    * @return
    */
   public static String getSha1(String str) {
      if (str == null || str.length() == 0) {
         return null;
      }
      char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            'a', 'b', 'c', 'd', 'e', 'f' };

      try {
         MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
         mdTemp.update(str.getBytes("UTF-8"));

         byte[] md = mdTemp.digest();
         int j = md.length;
         char buf[] = new char[j * 2];
         int k = 0;
         for (int i = 0; i < j; i++) {
            byte byte0 = md[i];
            buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
            buf[k++] = hexDigits[byte0 & 0xf];
         }
         return new String(buf);
      } catch (Exception e) {
         return null;
      }
   }
}

1.3 微信配置

 

1.4 如果配置验证就能通过  

2. 获取access_token  方法getAccess_token()

现在缓存中获取token 没有在去重新获取,获取到放到缓存中设置过期时间

@Service
public class WechatService {
    private Logger logger = LoggerFactory.getLogger(WechatService.class);
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private RestTemplate restTemplate;
    @Value("${wechat.w_appid}")
    private String appid;
    @Value("${wechat.w_appsecret}")
    String appsecret;
    @Value("${wechat.w_access_token_url}")
    String access_toekn_url;
    @Value("${wechat.w_template_url}")
    private String template_url;
    @Value("${wechat.w_ticket}")
    private String ticket_url;
    @Value("${wechat.w_qrcode}")
    private String w_qrcode;
    /**
     * @Description 获取token
     */
    public  String getAccess_token(){
       // 这个是在redis中取token 如果没有 重新获取
        String token = (String) redisUtil.get("access_token_app");
        if (token==null||"".equals(token)) {
            String acc_token = access_toekn_url;
            String appId = appid;
            acc_token = acc_token.replace("APPID",appId).replace("APPSECRET",appsecret);
            System.out.println(acc_token);
            try {
                /*
                 * 这里用的是RestTemplate 方式发送http请求
                 */
                WechatResponseEntity wechatResponseEntity = restTemplate.getForObject(acc_token, WechatResponseEntity.class);
                System.out.println(wechatResponseEntity.toString());
                token = wechatResponseEntity.getAccess_token();
                redisUtil.set("access_token_app",token,7100);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return token;
    }

    /**
     * @Description  推送的模板消息公共接口
     * @param appid 接收人的appid
     * @param template_id 使用过的公众号的模板id
    * @param mapD 组装的推送数据 (包含key:模板配置的{{xxx.DATA}}的xxx,value:是的对应的内容)
     */
    public boolean pushMessageWechat(String appid,String template_id,Map<String,String> mapD){
        String token = getAccess_token();
        Map<String,Object> map = assembleTemplateMap(appid,template_id,mapD);
        String temp_url = template_url.replace("ACCESS_TOKEN",token);
        /*
         * 这里用的是RestTemplate 方式发送http请求
         */
        WechatResponseEntity wechatResponseEntity = restTemplate.postForObject(temp_url,map, WechatResponseEntity.class);
        if ("0".equals(wechatResponseEntity.getErrcode())){
            return true;
        }else {
            logger.error("***** 公众号模板消息发送异常 *****",wechatResponseEntity.toString());
        }
        return false;
    }
    /**
     * @Description 组装发送消息内容
     */
    public Map<String,Object> assembleTemplateMap(String appid,String template_id,Map<String,String> mapData){
        Map<String,Object> map = new HashMap<>();
        map.put("touser",appid);
        map.put("template_id",template_id);
        Map<String,Object> map1 = new HashMap<>();
        /*
         *遍历mapDATA 组装模板消息的data
         */
        for(String key:mapData.keySet()){
            Map<String,String> mapNew = new HashMap<>();
            mapNew.put("value",mapData.get(key));
            mapNew.put("color","#173177");
            map1.put(key,mapNew);
        }
        map.put("data",map1);
        return  map;
    }
    /**
     * @Description 获取公众号的临时二维码,带参数当前用户的userId
     */
    public String getQRCodeURL (String userId){
        String token = getAccess_token();
        String url = ticket_url.replace("TOKEN",token);
        Map<String,Object> map = new HashMap<>();
        map.put("expire_seconds",86400);
        //字符串的参数类型
        map.put("action_name","QR_STR_SCENE");
        Map<String,Object> map2 = new HashMap<>();
        //字符串的参数类型
        map2.put("scene_str",userId);
        Map<String,Object> map1 = new HashMap<>();
        map1.put("scene",map2);
        map.put("action_info",map1);
        WechatResponseEntity we = restTemplate.postForObject(url,map, WechatResponseEntity.class);
        System.out.println(we);
        return w_qrcode.replace("TICKET", URLEncoder.encode(we.getTicket()));
    }

}

接收实体类

@Data
public class WechatResponseEntity {
    private String access_token;
    private String expires_in;
    private String errcode;
    private String errmsg;
    private String msgid;
    private String ticket;
    private Integer expire_seconds;
    private String url;
}

 3.生成公众号二维码url 调用 getQRCodeURL() 方法可以获取去二维码url

微信公众号文档:https://developers.weixin.qq.com/doc/offiaccount/Account_Management/Generating_a_Parametric_QR_Code.html

4.关注成功会有WechatController.dopsot()方法回调,回调还需要增加几个基础方法

添加的jar包 一个是RestTemplate 的包 一个转xml的包

<dependency>
   <groupId>org.apache.httpcomponents</groupId>
   <artifactId>httpclient</artifactId>
   <version>4.5.13</version>
</dependency>

<dependency>
   <groupId>com.thoughtworks.xstream</groupId>
   <artifactId>xstream</artifactId>
   <version>1.4.10</version>
</dependency>
/**
 * 消息封装类
 * @author Stephen
 *
 */
public class MessageUtil { 
   
   public static final String MESSAGE_TEXT = "text";
   public static final String MESSAGE_NEWS = "news";
   public static final String MESSAGE_IMAGE = "image";
   public static final String MESSAGE_VOICE = "voice";
   public static final String MESSAGE_MUSIC = "music";
   public static final String MESSAGE_VIDEO = "video";
   public static final String MESSAGE_LINK = "link";
   public static final String MESSAGE_LOCATION = "location";
   public static final String MESSAGE_EVNET = "event";
   public static final String MESSAGE_SUBSCRIBE = "subscribe";//用户未关注时,进行关注后的事件推送
   public static final String MESSAGE_UNSUBSCRIBE = "unsubscribe";
   public static final String MESSAGE_CLICK = "CLICK";
   public static final String MESSAGE_VIEW = "VIEW";
   public static final String MESSAGE_SCANCODE= "scancode_push";
   public static final String FOLLOW_OFFICIAL_ACCOUNT = "SCAN";//用户已关注时的事件推送
   
   /**
    * xml转为map集合
    * @param request
    * @return
    * @throws IOException
    * @throws DocumentException
    */
   public static Map<String, String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException{
      Map<String, String> map = new HashMap<String, String>();
      SAXReader reader = new SAXReader();
      
      InputStream ins = request.getInputStream();
      Document doc = reader.read(ins);
      
      Element root = doc.getRootElement();
      
      List<Element> list = root.elements();
      
      for(Element e : list){
         map.put(e.getName(), e.getText());
      }
      ins.close();
      return map;
   }
   
   /**
    * 将文本消息对象转为xml
    * @param textMessage
    * @return
    */
   public static String textMessageToXml(TextMessage textMessage){
      XStream xstream = new XStream();
      xstream.alias("xml", textMessage.getClass());
      return xstream.toXML(textMessage);
   }

   /**
    * 组装文本消息
    * @param toUserName
    * @param fromUserName
    * @param content
    * @return
    */
   public static String initText(String toUserName,String fromUserName,String content){
      TextMessage text = new TextMessage();
      text.setFromUserName(toUserName);
      text.setToUserName(fromUserName);
      text.setMsgType(MessageUtil.MESSAGE_TEXT);
      text.setCreateTime(System.currentTimeMillis());
      text.setContent(content);
      return textMessageToXml(text);
   }
   
   /**
    * 主菜单
    * @return
    */
   public static String menuText(){
      StringBuffer sb = new StringBuffer();
      sb.append("欢迎您的关注,你已经可以正常接收到消息提醒");
      return sb.toString();
   }

   public static String firstMenu(){
      StringBuffer sb = new StringBuffer();
      sb.append("本套课程介绍微信公众号开发,主要涉及公众号介绍、编辑模式介绍、开发模式介绍等");
      return sb.toString();
   }
   
   public static String secondMenu(){
      StringBuffer sb = new StringBuffer();
      sb.append("慕课网是垂直的互联网IT技能免费学习网站。以独家视频教程、在线编程工具、学习计划、问答社区为核心特色。在这里,你可以找到最好的互联网技术牛人,也可以通过免费的在线公开视频课程学习国内领先的互联网IT技术。");
      sb.append("慕课网课程涵盖前端开发、PHP、Html5、Android、iOS、Swift等IT前沿技术语言,包括基础课程、实用案例、高级分享三大类型,适合不同阶段的学习人群。以纯干货、短视频的形式为平台特点,为在校学生、职场白领提供了一个迅速提升技能、共同分享进步的学习平台。");
      return sb.toString();
   }
   
   public static String threeMenu(){
      StringBuffer sb = new StringBuffer();
      sb.append("词组翻译使用指南\n\n");
      sb.append("使用示例:\n");
      sb.append("翻译足球\n");
      sb.append("翻译中国足球\n");
      sb.append("翻译football\n\n");
      sb.append("回复?显示主菜单。");
      return sb.toString();
   }
// /**
//  * 图文消息转为xml
//  * @param newsMessage
//  * @return
//  */
// public static String newsMessageToXml(NewsMessage newsMessage){
//    XStream xstream = new XStream();
//    xstream.alias("xml", newsMessage.getClass());
//    xstream.alias("item", new News().getClass());
//    return xstream.toXML(newsMessage);
// }
   
// /**
//  * 图片消息转为xml
//  * @param imageMessage
//  * @return
//  */
// public static String imageMessageToXml(ImageMessage imageMessage){
//    XStream xstream = new XStream();
//    xstream.alias("xml", imageMessage.getClass());
//    return xstream.toXML(imageMessage);
// }
   
// /**
//  * 音乐消息转为xml
//  * @param musicMessage
//  * @return
//  */
// public static String musicMessageToXml(MusicMessage musicMessage){
//    XStream xstream = new XStream();
//    xstream.alias("xml", musicMessage.getClass());
//    return xstream.toXML(musicMessage);
// }
// /**
//  * 图文消息的组装
//  * @param toUserName
//  * @param fromUserName
//  * @return
//  */
// public static String initNewsMessage(String toUserName,String fromUserName){
//    String message = null;
//    List<News> newsList = new ArrayList<News>();
//    NewsMessage newsMessage = new NewsMessage();
//
//    News news = new News();
//    news.setTitle("慕课网介绍");
//    news.setDescription("慕课网是垂直的互联网IT技能免费学习网站。以独家视频教程、在线编程工具、学习计划、问答社区为核心特色。在这里,你可以找到最好的互联网技术牛人,也可以通过免费的在线公开视频课程学习国内领先的互联网IT技术。慕课网课程涵盖前端开发、PHP、Html5、Android、iOS、Swift等IT前沿技术语言,包括基础课程、实用案例、高级分享三大类型,适合不同阶段的学习人群。");
//    news.setPicUrl("http://zapper.tunnel.mobi/Weixin/image/imooc.jpg");
//    news.setUrl("www.imooc.com");
//
//    newsList.add(news);
//
//    newsMessage.setToUserName(fromUserName);
//    newsMessage.setFromUserName(toUserName);
//    newsMessage.setCreateTime(System.currentTimeMillis());
//    newsMessage.setMsgType(MESSAGE_NEWS);
//    newsMessage.setArticles(newsList);
//    newsMessage.setArticleCount(newsList.size());
//
//    message = newsMessageToXml(newsMessage);
//    return message;
// }
   
// /**
//  * 组装图片消息
//  * @param toUserName
//  * @param fromUserName
//  * @return
//  */
// public static String initImageMessage(String toUserName,String fromUserName){
//    String message = null;
//    Image image = new Image();
//    image.setMediaId("JTH8vBl0zDRlrrn2bBnMleySuHjVbMhyAo0U2x7kQyd1ciydhhsVPONbnRrKGp8m");
//    ImageMessage imageMessage = new ImageMessage();
//    imageMessage.setFromUserName(toUserName);
//    imageMessage.setToUserName(fromUserName);
//    imageMessage.setMsgType(MESSAGE_IMAGE);
//    imageMessage.setCreateTime(System.currentTimeMillis());
//    imageMessage.setImage(image);
//    message = imageMessageToXml(imageMessage);
//    return message;
// }
   
// /**
//  * 组装音乐消息
//  * @param toUserName
//  * @param fromUserName
//  * @return
//  */
// public static String initMusicMessage(String toUserName,String fromUserName){
//    String message = null;
//    Music music = new Music();
//    music.setThumbMediaId("WsHCQr1ftJQwmGUGhCP8gZ13a77XVg5Ah_uHPHVEAQuRE5FEjn-DsZJzFZqZFeFk");
//    music.setTitle("see you again");
//    music.setDescription("速7片尾曲");
//    music.setMusicUrl("http://zapper.tunnel.mobi/Weixin/resource/See You Again.mp3");
//    music.setHQMusicUrl("http://zapper.tunnel.mobi/Weixin/resource/See You Again.mp3");
//
//    MusicMessage musicMessage = new MusicMessage();
//    musicMessage.setFromUserName(toUserName);
//    musicMessage.setToUserName(fromUserName);
//    musicMessage.setMsgType(MESSAGE_MUSIC);
//    musicMessage.setCreateTime(System.currentTimeMillis());
//    musicMessage.setMusic(music);
//    message = musicMessageToXml(musicMessage);
//    return message;
// }
}
public class TextMessage extends BaseMessage {
   private String Content;
   private String MsgId;
   
   public String getContent() {
      return Content;
   }
   public void setContent(String content) {
      Content = content;
   }
   public String getMsgId() {
      return MsgId;
   }
   public void setMsgId(String msgId) {
      MsgId = msgId;
   }
}

 

/**
 * 消息父类
 * @author Stephen
 *
 */
public class BaseMessage {
   //接收方微信号
   private String ToUserName;
   //发送方微信号
   private String FromUserName;
   //创建时间
   private long CreateTime;
   //消息类型
   private String MsgType;
   public String getToUserName() {
      return ToUserName;
   }
   public void setToUserName(String toUserName) {
      ToUserName = toUserName;
   }
   public String getFromUserName() {
      return FromUserName;
   }
   public void setFromUserName(String fromUserName) {
      FromUserName = fromUserName;
   }
   public long getCreateTime() {
      return CreateTime;
   }
   public void setCreateTime(long createTime) {
      CreateTime = createTime;
   }
   public String getMsgType() {
      return MsgType;
   }
   public void setMsgType(String msgType) {
      MsgType = msgType;
   }
}

 applicat.yml配置文件

wechat:
  #公众号的appid
  w_appid:
  # 公众号的appsecret
  w_appsecret: 
  #获取token的url
  w_access_token_url: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
  #模板id
  w_template_id: 
  #推送消息的接口url
  w_template_url: https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN
  #获取二维码ticket的url
  w_ticket: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN
  #通过ticket换取二维码 的url(TICKET记得进行UrlEncode)
  w_qrcode: https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=TICKET





http:
  #最大连接数
  maxTotal: 100
  #并发数
  defaultMaxPerRoute: 20
  #创建连接的最长时间
  connectTimeout: 3000
  #从连接池中获取到连接的最长时间
  connectionRequestTimeout: 1000
  #数据传输的最长时间
  socketTimeout: 10000
  #提交请求前测试连接是否可用
  staleConnectionCheckEnabled: true
  #可用空闲连接过期时间,重用空闲连接时会先检查是否空闲时间超过这个时间,如果超过,释放socket重新建立
  validateAfterInactivity: 3000000

 5.推送模板消息 WechatService.pushMessageWechat()方法发送模板消息

微信模板配置

{{first.DATA}}

 

工单类型:{{typeName.DATA}}

工单标题:{{typeTitle.DATA}}

流程编号:{{orderNO.DATA}}

操作时间:  {{updateTime.DATA}}

{{remark.DATA}}

6.RestTemplate 集成

博客地址:https://blog.csdn.net/yu1xue1fei/article/details/111610455

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值