1.微信公众号测试账号:
找到服务号的开发文档,点击进去。

  1. Java代码:
    准备工作:
    (1)填写JS接口安全域名

    (2)填写接口配置信息:

    (2)java的Token验证接口

@RequestMapping(value = "/verifier",method = {RequestMethod.GET})public void processGet(HttpServletRequest request, HttpServletResponse response) throws Exception{System.out.println("验证接口消息");String signature = request.getParameter("signature");String timestamp = request.getParameter("timestamp");String nonce = request.getParameter("nonce");String echostr = request.getParameter("echostr");//校验证签名boolean check = wxService.check(signature, timestamp, nonce);if (check){System.out.println("接入成功");PrintWriter writerOut = response.getWriter();writerOut.print(echostr);writerOut.flush();writerOut.close();}else {System.out.println("接入失败");}}
 验证签名:
public boolean check(String signature, String timestamp, String nonce){//字典排序String token = "自定义的Token值";String[] wxStrArr = {token, timestamp, nonce};Arrays.sort(wxStrArr);//进行sha1加密String wxString = wxStrArr[0]+wxStrArr[1]+wxStrArr[2];String wxSha1 = sha1(wxString);//加密后的数据和signature进行对比return StringUtils.equalsIgnoreCase(wxSha1,signature);}
private static String sha1(String wxString) {try {//获取加密对象MessageDigest sha1 = MessageDigest.getInstance("sha1");byte[] digest = sha1.digest(wxString.getBytes());StringBuilder sb = new StringBuilder();char[] chars = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};//处理加密结果for (byte b : digest) {sb.append(chars[(b>>4)&15]);sb.append(chars[b&15]);}return sb.toString();} catch (Exception e) {e.printStackTrace();}return null;}

###创建菜单;

(1)抽象的菜单类

public class AbstractButton {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public AbstractButton(String name) {super();this.name = name;}
}

(2)view菜单

public class ViewButton extends AbstractButton {private String type = "view";private String url;public String getType() {return type;}public void setType(String type) {this.type = type;}public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public ViewButton(String name, String url) {super(name);this.url = url;}
}

###获取Token

public void getToken(){String wxTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET";String appId = "微信公众号的APPID值";String appsecret = "微信公众号的APPSECRET值";String url = StringUtils.replace(wxTokenUrl, "APPID", appId).replace("APPSECRET", appsecret);String tokenStr = WechatUtils.get(url);JSONObject tokenjson = JSONObject.fromObject(tokenStr);String accessToken = tokenjson.getString("access_token");String expiresIn = tokenjson.getString("expires_in");//wxAccessToken = new WxAccessToken(accessToken,expiresIn);}
 Token的有效时间为2小时,创建一个保存Token值和判断Token是否过期的类;
public class WxAccessToken {private String accessToken;private long expiresTime;public String getAccessToken() {return accessToken;}public void setAccessToken(String accessToken) {this.accessToken = accessToken;}public long getExpiresTime() {return expiresTime;}public void setExpiresTime(long expiresTime) {this.expiresTime = expiresTime;}public WxAccessToken(String accessToken, String expiresIn) {super();this.accessToken = accessToken;expiresTime = System.currentTimeMillis()+Integer.parseInt(expiresIn)*1000;}/***判断 accessToken是否过期*/public boolean isExpires(){return System.currentTimeMillis()>expiresTime;}
}
向外暴露 获取Token方法
 /***向外暴露 获取Token方法**/public String getAccessToken(){if (wxAccessToken == null || wxAccessToken.isExpires()){getToken();}return wxAccessToken.getAccessToken();}
创建微信公众号菜单的接口:
/***创建微信的自定义菜单*/public void createMenu(){String creatMenuUrl = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN";String appId = "微信公众号的APPID值";String reUrl = "点击菜单需要跳转的路径";int result = 0;String accessToken = getAccessToken();String muenUrlAccessToken = StringUtils.replace(creatMenuUrl, "ACCESS_TOKEN", accessToken);Button button = new Button();//设置url要加https//button.getButton().add(new ViewButton("菜单名称","https://open.weixin.qq.com/connect/oauth2/authorize?appid="+appId+"&redirect_uri="+reUrl+"/login&response_type=code&scope=snsapi_base&#wechat_redirect"));String jsonObjectStr = JSONObject.fromObject(button).toString();JSONObject jsonObject = WechatUtils.httpRequest(muenUrlAccessToken, "POST", jsonObjectStr);if (null != jsonObject) {if (0 != jsonObject.getInt("errcode")) {result = jsonObject.getInt("errcode");System.out.println("创建菜单失败 errcode:{}");System.out.println(jsonObject.getString("errmsg"));System.out.println(jsonObject.getInt("errcode"));}}}

创建微信的工具类:

package cn.kkou.justice.common.utils;import cn.kkou.justice.common.MyX509TrustManager;
import cn.kkou.justice.common.PropertiesLoader;
import net.sf.json.JSONObject;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.ConnectException;
import java.net.URL;
import java.net.URLConnection;
import java.security.SecureRandom;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** @author* @version 1.0.0*/
public class WechatUtils {private static Logger logger = LoggerFactory.getLogger(PropertiesLoader.class);/***向指定的地址发送get请求*/public static String get(String url){try {URL urlObj = new URL(url);//开连接URLConnection urlConnection = urlObj.openConnection();InputStream is = urlConnection.getInputStream();byte[] bytes = new byte[1024];int len;StringBuilder sb = new StringBuilder();while ((len=is.read(bytes))!=-1){sb.append(new String(bytes,0,len));}return sb.toString();} catch (Exception e) {e.printStackTrace();}return null;}/*** 描述:  发起https请求并获取结果* @param requestUrl 请求地址* @param requestMethod 请求方式(GET、POST)* @param outputStr 提交的数据* @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)*/public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) {JSONObject jsonObject = null;StringBuffer buffer = new StringBuffer();try {// 创建SSLContext对象,并使用我们指定的信任管理器初始化TrustManager[] tm = { new MyX509TrustManager() };SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");sslContext.init(null, tm, new SecureRandom());// 从上述SSLContext对象中得到SSLSocketFactory对象SSLSocketFactory ssf = sslContext.getSocketFactory();URL url = new URL(requestUrl);HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection();httpUrlConn.setSSLSocketFactory(ssf);httpUrlConn.setDoOutput(true);httpUrlConn.setDoInput(true);httpUrlConn.setUseCaches(false);// 设置请求方式(GET/POST)httpUrlConn.setRequestMethod(requestMethod);if ("GET".equalsIgnoreCase(requestMethod)){httpUrlConn.connect();}// 当有数据需要提交时if (null != outputStr) {OutputStream outputStream = httpUrlConn.getOutputStream();// 注意编码格式,防止中文乱码outputStream.write(outputStr.getBytes("UTF-8"));outputStream.close();}// 将返回的输入流转换成字符串InputStream inputStream = httpUrlConn.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String str = null;while ((str = bufferedReader.readLine()) != null) {buffer.append(str);}bufferedReader.close();inputStreamReader.close();// 释放资源inputStream.close();inputStream = null;httpUrlConn.disconnect();jsonObject = JSONObject.fromObject(buffer.toString());} catch (ConnectException ce) {logger.info("连接超时:",ce);} catch (Exception e) {logger.info("微信菜单创建请求错误:",e);}return jsonObject;}/** xml转map*/public static Map<String, String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException {HashMap<String, String> map = new HashMap<String,String>();SAXReader reader = new SAXReader();InputStream ins = request.getInputStream();Document doc = reader.read(ins);Element root = doc.getRootElement();@SuppressWarnings("unchecked")List<Element> list = (List<Element>)root.elements();for(Element e:list){map.put(e.getName(), e.getText());}ins.close();return map;}}

推送模板消息给关注的用户:

     //1,推送消息JSONObject templateMessage = disposeTemInfo("用户的openId");//3,如果是正式版发送模版消息,这里需要配置你的信息JSONObject msgJsonObject = disposePushInfoList();JSONObject jsonObject = JSONObject.fromObject(templateMessage);jsonObject.put("data",msgJsonObject);//发起推送try {sendTemplateMsg(jsonObject);System.out.println("推送成功");} catch (Exception e) {System.out.println("推送失败:" + e.getMessage());e.printStackTrace();}
public JSONObject disposeTemInfo(String openId){//openId是用户关注公众号的唯一标识String wxTemplateId = "模板Id";String appId = "APPID";String url = "点击消息跳转的路径";JSONObject templateMessageJson = new JSONObject();templateMessageJson.put("touser",openId);templateMessageJson.put("template_id",wxTemplateId);templateMessageJson.put("url","https://open.weixin.qq.com/connect/oauth2/authorize?appid="+appId+"&redirect_uri="+url+"/login&response_type=code&scope=snsapi_base&#wechat_redirect");return templateMessageJson;}
public JSONObject disposePushInfoList(){//对应微信公众号模板的.DATA 前面的值String wxTemplateFirst = "";String wxTemplateKey1 = "";String wxTemplateKey2 = "";String wxTemplateKey3 = "";String wxTemplateRemark = "";//字体颜色String wxTemplateColor ="";String firstStr = StringUtils.EMPTY;JSONObject first = new JSONObject();first.put("value",firstStr);first.put("color",wxTemplateColor);JSONObject KeyWord1 = new JSONObject();KeyWord1.put("value","");KeyWord1.put("color",wxTemplateColor);JSONObject KeyWord2 = new JSONObject();KeyWord2.put("value","");KeyWord2.put("color",wxTemplateColor);JSONObject KeyWord3 = new JSONObject();KeyWord3.put("value","";KeyWord3.put("color",wxTemplateColor);JSONObject remark = new JSONObject();remark.put("value","");remark.put("color",wxTemplateColor);JSONObject msgJson = new JSONObject();msgJson.put(wxTemplateFirst,first);msgJson.put(wxTemplateKey1,KeyWord1);msgJson.put(wxTemplateKey2,KeyWord2);msgJson.put(wxTemplateKey3,KeyWord3);msgJson.put(wxTemplateRemark,remark);return msgJson;}
public void sendTemplateMsg(JSONObject templateMessage){int result = 0;String accessToken = getAccessToken();String sendMsgUrlStr = StringUtils.replace("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN", "ACCESS_TOKEN", accessToken);String msgJsonStr = templateMessage.toString();JSONObject jsonObject = WechatUtils.httpRequest(sendMsgUrlStr, "POST", msgJsonStr);if (null != jsonObject) {if (0 != jsonObject.getInt("errcode")) {result = jsonObject.getInt("errcode");logger.error("推送消息失败");}}}

微信公众号自定义菜单和推送模板消息相关推荐

  1. 微信公众号开发-菜单事件推送

    菜单事件推送在微信公众号开发中也是属于比较常用的一个功能,就是用户点击菜单之后,微信会将事件推送给接口程序. 不过微信开发到现在也是老生常谈的的东西了,我就简单写一下菜单事件推送的这个过程. 注意:点 ...

  2. 微信公众号如何和Salesforce集成,然后后台给公众号的关注者推送模板消息?

    这个问题其实蛮常见的.[自由侠部落]的学习群里,之前也有人讨论过,Salesforce既然可以和推特集成,那同微信的集成也一样,都是可以通过配置和部署实现的. 目前我所了解到的Salesforce与微 ...

  3. 微信公众号开发之关注推送图文消息

    关注/取消关注事件 用户在关注与取消关注公众号时,微信会把这个事件推送到开发者填写的URL.方便开发者给用户下发欢迎消息或者做帐号的解绑. 微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总 ...

  4. 微信公众号自定义菜单跳转到历史消息页面

    首先声明,这个功能微信已经下架了,从已发表里面搜索已经没有历史记录勾选了. 操作方法: 在页面地址中填写以下地址: https://mp.weixin.qq.com/mp/profile_ext?ac ...

  5. php 微信公众号自定义菜单

    使用php配置微信公众号自定义菜单 注意: 编写发送消息之前需要在微信公众平台后台左边菜单找到基本配置 然后开启服务器配置 一级菜单数组,个数应为1~3个, 二级菜单数组,个数应为1~5个 如果有疑问 ...

  6. springboot微信公众号自定义菜单创建及响应

    微信公众号自定义菜单创建及响应 前言 本篇博客是为了速度开发微信公众号而进行讲解,对于深入的原理性讲解推荐去观看微信公众平台的官方文档. 微信公众号分为订阅号,服务号,小程序,本篇主要是介绍的订阅号开 ...

  7. java 创建自定义菜单_Java实现微信公众号自定义菜单的创建方法示例

    本文实例讲述了Java实现微信公众号自定义菜单的创建方法.分享给大家供大家参考,具体如下: 开发公众号的时候可能需要给一些自定义菜单添加事件,比如点击某菜单然后服务端给用户推送信息. 我们也可以使用微 ...

  8. 微信公众号自定义菜单怎么添加多篇文章?

    本文主要是从个人的经验出发,分享一个主题: 微信公众号自定义菜单如何添加多篇文章(主要通过推文分类.精选 来实现) 不仅仅从微信页面模板.专辑的角度,同时分享一些微信公众号运营人员遇到的共性问题,例如 ...

  9. 微信公众号自定义菜单添加emoji表情图标

    微信公众号自定义菜单添加emoji表情图标 第一步:打开微信公众平台接口调试工具,点击前往接口调试工具: 第二步:把这段代码   {"button":[{"sub_but ...

最新文章

  1. 奖学金申请 | 2019年清华-青岛数据科学研究院​“RONG”奖学金申请通知
  2. 根据文法画出语法树_更多确定子句语法
  3. 浅析Java各种变量线程安全问题
  4. CodeForces - 1058A. In Search of an Easy Problem
  5. ONOS系统架构演进,实现高可用性解决方案
  6. 前端学习(661):逻辑运算符
  7. html中a标签如何设置行宽高
  8. 云场景实践研究第37期:悦跑圈
  9. 盛夏光年——14年暑期总结
  10. ecshop_商品描述远程图片自动本地化插件
  11. TinyWeb:C#中的简单Web服务器
  12. 软件测试基础:自动化测试、安全测试、性能测试
  13. (转载)o(1), o(n), o(logn), o(nlogn) 时间复杂度
  14. Java并发编程基础(一篇入门)
  15. VirtualBox安装Windows和CentOS虚拟机
  16. 数据科学工程篇_AB实验原理与实践
  17. JAVA Swing万年历
  18. 如何确定产品生命周期
  19. Protel99SE添加泪滴焊盘
  20. Oracle操作语句(PL/SQL)创建表空间:第 1 行出现错误: ORA-01119: 创建数据库文件时出错 ORA-27040: 文件创建错误, 无法创建文件OSD-04002: 无法打开文件

热门文章

  1. polplayer下载网址和polplayer直播源
  2. IoT黑板报0207:MU-MIMO技术让网络龟速变神速
  3. 如何让Word 2003识别Docx文件
  4. Word 2003域应用完全手册
  5. 什么是策划?策划的真正含义是什么?
  6. 漫谈并发编程:Actor模型
  7. 雷霆复鸣 决战巅峰 | 第七届XCTF国际网络攻防联赛总决赛即刻启航!
  8. 在fastreport里转换金额大小写
  9. java左手画圆右手画方_左手画圆,右手画方,有两个截然不同的说法,你知道吗?...
  10. 关于搭建一个简易搭建网站的大概步骤