Java微信公众号开发梳理
Java微信公众号开发梳理
现在微信公众平台的开发已经越来越普遍,这次开发需要用到微信公众平台。因此做一个简单的记录,也算是给那些没踩过坑的童鞋一些启示吧。我将分几块来简单的描述一下,之后会做详细的说明。
功能性说明
微信提供了许许多多的接口供用户使用,开发者可以根据这些接口获取用户的信息。
普遍的有用户的昵称性别地理位置等。
其他我就不一一列举了,总之需要根据你的实际业务需求来进行使用。
你需要什么就去看看微信是否提供了相应的接口供你使用。
微信接口文档地址路径:https://mp.weixin.qq.com/wiki/home/index.html
接口调用说明
微信的接口有几种不同的类型:
1、get请求,微信会提供一个地址,然后你直接在这个地址后面加上参数即可调用接口
2、post请求,微信提供一个地址,你需要向这个接口地址传入相应的参数。
3、回调请求,微信在收到用户消息或者别的触发条件成立时调用用户设置的URL地址。
请求格式包括XML和json,需要根据接口文档来。任何语言均可,JS有微信专门的JS-SDK。
我使用的是JAVA
关键词说明
OpenID:用户在你这个公众号上的唯一标识(我这边的处理是与项目中用户的UserId进行绑定,这样也就实现了用户在你的平台进行绑定)
access_token :注意,这里我把这个名字换一下,“ACCESS_TOKEN”为了和之后的分开。这个东西是一个全局量,当你需要调用特定的微信接口时,微信会验证你是否有权限,你就需要传这个值给微信。注意!!获取access_token是有次数限制的,但是access_token 的过期时间很长,所以在没有过期的情况下请勿重复获取。
access_token:这个和我称作小写的access_token和大写的不一样,这个是用户鉴权时使用,获取这个小写的access_token是没有次数限制的,这个东西能只是用于获取用户openId时使用。(新手千万要区分不同的access_token以免出现问题)
开发者填写的URL:接口文档出现这个的时候一开始我也很懵比,这里的URL是指,当用户如果进行特定的操作,如:发送给公众号消息,进入公众号,等等,微信会把一些参数传入这个URL。举个例子,如果用户发送给公众号一个字符。那么公众号会把这个字符转发给你这个URL,然后你这个URL接到微信给你的发的信息,你就可以返回给用户信息了。
这个URL是在这里设置的:

这里的服务器地址URL就是
其中微信有两个信息比较重要,第一微信会告诉你这是用户的什么事件,第二是哪个用户也就是用户的openId
网页授权域名:

在这里必须设置网页的授权域名,否则用户在微信公众号中对于你的域名下的地址将不信任。
开发三步走
这是建立在你已经做好准备的情况下是三步,如果你连公众号服务器域名都没有的话就不只了。
第一步、网页授权域名

下载对应文件,配置在tomcat你的项目的根目录下。
保证:域名/下载的文件名。这个地址能访问到,能在浏览器中显示文字即可。
第二步、获取openId
文档中在:https://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html
1、生成地址
https://open.weixin.qq.com/connect/oauth2/authorize?(这个是不动的)
appid=xxxxxxxxxx(这个是你的appid)
&redirect_uri=http%3a%2f%2fwww.xxxxxxx.com%xxxxxxxx%2fweixxxxxit%2fxxxxx(这个是你的回调地址,需要URL编码)
&response_type=code(不动)
&scope=snsapi_base(如果只要获取openId就不动,需要别的参考文档)
#wechat_redirect(不动)
最终地址类似:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=xxxxxxxxxx&redirect_uri=http%3a%2f%2fwww.xxxxxxx.com%xxxxxxxx%2fweixxxxxit%2fxxxxx&response_type=code&scope=snsapi_base#wechat_redirect
用户访问这个地址,微信就会回调你的回调地址,你在回调地址中就可以获取到openId了
回调地址中springMVC的写法:
/**
* 微信获取openId
*/
@RequestMapping(value="/weiXin", method=RequestMethod.GET)
public String weiXin(HttpServletRequest request)
{
//获取用户openId
String openId = ""; //用户同意授权,获取返回值code和state
String code = request.getParameter("code");
//如果code为空则(请自己实现判断,这里是简写)
if(code == null){
return "index";
} //获取openid的地址
String getOpenidUri = "https://api.weixin.qq.com/sns/oauth2/access_token"
+ "?appid=" + AppID
+ "&secret=" + AppSecret
+ "&code=" + code
+ "&grant_type=authorization_code";
try{
//发送请求获取返回参数,使用java原生实现,可以使用httpclient或者第三方库实现
URL getOpenidUrl = new URL(getOpenidUri);
HttpURLConnection openidConnection = (HttpURLConnection) getOpenidUrl.openConnection();
openidConnection.connect(); BufferedReader openidReader = new BufferedReader(new InputStreamReader(openidConnection.getInputStream()));
StringBuffer openidStringBuffer = new StringBuffer();
String openidLines;
while ((openidLines = openidReader.readLine()) != null) {
openidStringBuffer.append(openidLines);
}
openidReader.close();
openidConnection.disconnect(); //返回的参数是json格式
JSONObject openidJson = JSONObject.parseObject(openidStringBuffer.toString());
if(openidJson.containsKey("openid")){
openId = openidJson.getString("openid");
}
}catch(Exception e){
//连接异常,请求异常,或者json返回值异常均需要处理
} //需要对openId判空,请自行处理
System.out.println(openId);
return "index";
}
当微信回调你这个地址之后按照上述代码执行后即可获取到openId,上述代码只是参考,实际中需要改进很多判断以及对很多错误情况的预判。你也可以根据接口文档详细书写。
第三步、微信调用接口设计
checkoutURL
之前说过,在设置URL的时候会有一个核对的过程,你需要给出你的接口地址,然后返回一个参数验证过后微信才会同意你修改这个URL
下面是checkout的代码,因为涉及到加密所以需要多多注意
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
//工具类,之后会被调用
public class CheckoutUtil {
// 与接口配置信息中的Token要一致
private static String token = "xxxxxxxxxxx"; /**
* 验证签名
*
* @param signature
* @param timestamp
* @param nonce
* @return
*/
public static boolean checkSignature(String signature, String timestamp, String nonce) {
String[] arr = new String[] { token, timestamp, nonce };
// 将token、timestamp、nonce三个参数进行字典序排序
// Arrays.sort(arr);
sort(arr);
StringBuilder content = new StringBuilder();
for (int i = 0; i < arr.length; i++) {
content.append(arr[i]);
}
MessageDigest md = null;
String tmpStr = null; try {
md = MessageDigest.getInstance("SHA-1");
// 将三个参数字符串拼接成一个字符串进行sha1加密
byte[] digest = md.digest(content.toString().getBytes());
tmpStr = byteToStr(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
content = null;
// 将sha1加密后的字符串可与signature对比,标识该请求来源于微信
return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
} /**
* 将字节数组转换为十六进制字符串
*
* @param byteArray
* @return
*/
private static String byteToStr(byte[] byteArray) {
String strDigest = "";
for (int i = 0; i < byteArray.length; i++) {
strDigest += byteToHexStr(byteArray[i]);
}
return strDigest;
} /**
* 将字节转换为十六进制字符串
*
* @param mByte
* @return
*/
private static String byteToHexStr(byte mByte) {
char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
char[] tempArr = new char[2];
tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
tempArr[1] = Digit[mByte & 0X0F];
String s = new String(tempArr);
return s;
}
public static void sort(String a[]) {
for (int i = 0; i < a.length - 1; i++) {
for (int j = i + 1; j < a.length; j++) {
if (a[j].compareTo(a[i]) < 0) {
String temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
}
}
@RequestMapping(value="/weixinTest")
public void weixinTest(HttpServletRequest request) throws Exception{
boolean isGet = request.getMethod().toLowerCase().equals("get");
PrintWriter print;
if (isGet) {
// 微信加密签名
String signature = request.getParameter("signature");
// 时间戳
String timestamp = request.getParameter("timestamp");
// 随机数
String nonce = request.getParameter("nonce");
// 随机字符串
String echostr = request.getParameter("echostr");
// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
if (signature != null && CheckoutUtil.checkSignature(signature, timestamp, nonce)) {
try {
print = response.getWriter();
print.write(echostr);
print.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
URL:http://www.xxxxxxxx.com/weixinTest/
Token:xxxxxxxxxxxx
类似上面
测试时使用兼容模式,等测试完成后使用安全模式,微信提供了AES的加密解密工具类
https://mp.weixin.qq.com/wiki/1/5dc395cdeb98e9d23a8541cf0bab38ad.html
最后微信调用URL
需要解析XML,也就顺带加个工具类需要使用相应dom4j的jar
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader; public class MessageUtil {
public static Map parseXml(HttpServletRequest request) throws Exception {
// 将解析结果存储在HashMap中
Map map = new HashMap(); // 从request中取得输入流
InputStream inputStream = request.getInputStream(); // 读取输入流
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子节点
List<Element> elementList = root.elements(); // 遍历所有子节点
for (Element e : elementList)
map.put(e.getName(), e.getText()); // 释放资源
inputStream.close();
inputStream = null; return map;
}
}
这边以获取地理位置为例(需要在微信后台手动开启这个功能哦)
@RequestMapping(value="/weixinTest")
public void weixinTest(HttpServletRequest request) throws Exception{
// 调用parseXml方法解析请求消息
Map<String, String> requestMap = MessageUtil.parseXml(request);
// 发送方帐号
String fromUserName = requestMap.get("FromUserName");
log.error("----------------------------------------------" + fromUserName);
// 开发者微信号
String toUserName = requestMap.get("ToUserName");
// 消息类型
String msgType = requestMap.get("MsgType"); if ("event".equals(msgType)){
log.error("----------------------------------------------" +msgType);
String Latitude = requestMap.get("Latitude");
log.error("----------------------------------------------" +Latitude);
String Longitude = requestMap.get("Longitude");
log.error("----------------------------------------------" +Longitude); }
}
需要注意的点
1、看清接口文档,仔细理解
2、checkout不要删除,修改地址时需要使用,当地址稳定后项目上线之后直接删除。
3、微信调用URL会被用户平凡访问,向我这样写肯定是不对的,如果你的用户量大负载均衡肯定是必须的。
4、微信接口虽然稳定,但是还是要注意处理意外请求,处理一些可能会出现的错误情况。否则当出现没有这个参数而你去取,很容易导致异常。
5、所有测试均需要在服务器上完成,也就需要外网可以被访问的域名和地址。
6、微信给的权限很多,需要自己看清楚,有的权限是有次数限制的。
7、尽可能把一些参数封装一下,避免代码冗长。
8、所有测试完成后请换成密文形式,不然用户的信息可能泄露。
9、以上所有代码仅供参考,实际中还需要添砖加瓦,大改特改。
10、服务器上调试日志很重要。
Java微信公众号开发梳理的更多相关文章
- Java微信公众号开发
微信公众平台是腾讯为了让用户申请和管理微信公众账号而推出的一个web平台.微信公众账号的种类可以分为3种,并且一旦选定不可更改.按照功能的限制从小到大依次为:订阅号.服务号.企业号.个人只能注册订阅号 ...
- Java微信公众号开发----关键字自动回复消息
在配置好开发者配置后,本人第一个想要实现的是自动回复消息的功能,说明以下几点: 1. url 仍然不变,还是开发配置里的url 2. 微信采用 xml 格式传输数据 3.微信服务器传给我们的参数主要有 ...
- Java 微信公众号开发--- 接入微信
开发微信公众号在没有正式的公众平台账号时,我们可以使用测试平台账号--- 测试平台申请地址:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandb ...
- Java微信公众号开发-外网映射工具配置
一.开发环境准备 1.一个微信公众号 2.外网映射工具(开发调试)如花生壳.ngrok工具 注:与微信对接的URL要具备以下条件a:在公网上能够访问 b:端口只支持80端口 这里使用ngrok.cc: ...
- 初识Java微信公众号开发
选定类型后不可更改 企业号与服务号,订阅号的区别 公众号微信注册流程: 个人就选择订阅号 外网映射 必须要使用映射工具将本地的地址映射到公网上去 介绍一个ngrok 首先下载ngork,例如保存在D盘 ...
- Java微信公众号开发----定时获取access_token并保存到redis中
本人原本是想做微信公众号菜单的创建修改删除等操作的,但是发现需要access_token,通过阅读文档,发现文档要求有以下几点: 1.access_token 获取后有效期是2小时 2.access_ ...
- java微信公众号开发token验证失败的问题及解决办法
本文引自http://m.blog.csdn.net/qq_32331997/article/details/72885424 微信公众平台服务器配置时,需要引入token,但是提交的时候总是提示to ...
- java微信公众号开发----搭建ngrok环境
下载ngrok,一个能够在公网安全访问内网Web主机的工具 下载地址:http://download.csdn.net/download/u014252425/9389847,亲测可用 下载完成后,进 ...
- 微信公众号开发(一)--验证服务器地址的Java实现
现在主流上都用php写微信公众号后台,其实作为后端语言之一的java也可以实现. 这篇文章将对验证服务器地址这一步做出实现. 参考资料:1.慕课网-<初识java微信公众号开发>,2.微信 ...
随机推荐
- Python练习_初识函数_day9
1. 1.作业 1,写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者. 2,写函数,判断用户传入的对象(字符串.列表.元组)长度是否大于5. 3,写函数,检查 ...
- springboot启动流程(七)ioc容器refresh过程(上篇)
所有文章 https://www.cnblogs.com/lay2017/p/11478237.html 正文 在前面的几篇文章中,我们看到Environment创建.application配置文件的 ...
- SpringCloud之Config配置中心+BUS消息总线原理及其配置
一.配置中心作用 在常规的开发中,每个微服务都包含代码和配置.其配置包含服务配置.各类开关和业务配置.如果系统结构中的微服务节点较少,那么常规的代码+配置的开发方式足以解决问题.当系统逐步迭代,其微服 ...
- linux:# vi /etc/profile -bash: vi: command not found 的解决办法
/bin/vi /etc/profile 直接用全路径vi,linux下一切皆文件,进去把profile文件内容改一下,一定是profile出了问题 export JAVA_HOME=/usr/jav ...
- 使用url_for()时,会自动调用转换器的to_url()方法
视图反推url,在动态url(转换器)反推中的应用 # -*- coding: utf-8 -*- from flask import Flask, url_for, redirect from we ...
- element-ui组件,全选树节点,新增数据子节点数据,出现回填问题
案情分析:全选后父节点被选中保存,在这个树节点下新增数据时,就会出现,也被选中,事实上数据是没有被选中,也就意味着权限未被配置,而显示是已经配置了,显然这个是一个bug 1.处理前,直接用下面的方法很 ...
- 分布式爬虫-bilibili评论
实属课程需要,不然早就放弃在半路了.维持了断续半个多月的 bug 调试,突然就实现了.很是欣慰.网上关于分布式爬虫的都是一些介绍,实战的不多并且都很相似,说的云来雾去的,只是项目的流程.可能是项目一路 ...
- Flutter——Card组件
Card 是卡片组件块,内容可以由大多数类型的 Widget 构成,Card 具有圆角和阴影,这让它看起来有立体感. Card组件的常用属性: 属性 说明 margin 外边距 child 子组件 ...
- Data truncation: Incorrect datetime value: 'May 15, 2019 4:15:37 PM
因为系统在windows下测试过是正常的 windows下的jdk+ windows下安装的mysql 全部cases通过 linux下的jdk + windows下安装的mysql 新增和更新,影响 ...
- 用js刷剑指offer(调整数组顺序使奇数位于偶数前面)
题目描述 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变. 牛客网链接 js代码 ...