一、本节要点
1.回调url
上一节,我们启用服务器配置的时候,填写了一个服务器地址(url),如下图,这个url就是回调url,是开发者用来接收微信消息和事件的接口URL 。也就是说,用户在微信公众号中发送的消息会被推送到这个回调url,而我们可以接收用户的消息,并进行回复。
2.被动回复消息的流程
官方文档:
我们在上一节中设置的消息加解密方式是安全模式。因此在用户发给公众号的消息(接收消息)以及公众号被动回复用户消息(回复消息)都会加密,
流程:
用户发送消息之后,微信服务器将消息传递给 第三方服务器,第三方服务器接收到消息后,再对消息做出相应的回复消息。
接收消息:需先从request请求对象的输入流中获取请求参数和已加密的请求消息,再对已加密的请求消息进行解密操作,即可获得明文。
然后就行对明文消息的业务处理了。
回复消息:封装好回复消息后,需先对回复消息进行加密,获得已已加密消息,然后再通过http请求调用被动回复消息的接口,来发送消息。
3.被动回复消息加解密
3.1接收消息的 解密
(1)从请求的输入流中获取加密的请求消息
//1.获取加密的请求消息:使用输入流获得加密请求消息postData
ServletInputStream in = request.getInputStream();
BufferedReader reader =new BufferedReader(new InputStreamReader(in));
String tempStr=""; //作为输出字符串的临时串,用于判断是否读取完毕
while(null!=(tempStr=reader.readLine())){
postData+=tempStr;
}
logger.info("postData:"+postData);
View Code
(2)对加密的请求消息进行解密获得明文
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(Env.TOKEN,Env.ENCODING_AES_KEY,Env.APP_ID);
result=wxcpt.DecryptMsg(msgSignature, timeStamp, nonce, postData);
View Code
(3)解密算法
直接调用微信官方的 WXBizMsgCrypt 类的 DecryptMsg(String, String, String, String) 方法即可。
3.2 回复消息的加密
直接用官方加解密工具类。
wxcpt = new WXBizMsgCrypt(Env.TOKEN,Env.ENCODING_AES_KEY,Env.APP_ID);
replyMsg=wxcpt.EncryptMsg(replyMsg, timeStamp, nonce);
View Code
4.消息对象的封装
根据官方文档消息的xml传输格式,我们可以将消息封装成对象。请参见后面的代码实现部分
5.数据传输—对象 转成 xml字符串
根据官方文档,数据是以XML数据包的形式进行传输的。因此,我们需要
(1)解析微信发来的请求(xmlStr),从xml字符串中获取需要的信息
(2)回复消息时,将消息对象转成xml字符串。
我们是使用dom4j,xstream来进行这个转换的,因此需要导入jar包,maven依赖如下:
<!-- 7.XML解析 -->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.10</version>
</dependency>
具体请参见代码实现的 MessageUtil 部分。
5.1 解析微信发来的请求(XML),获取请求参数
/**
* @desc :1.解析微信发来的请求(XML),获取请求参数
*
* @param request
* @return
* @throws Exception Map<String,String>
*/
public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
// 将解析结果存储在HashMap中
Map<String, String> map = new HashMap<String, String>();
// 从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;
}
View Code
5.2 将文本消息转成xml字符串
/**
* 2.文本消息对象转换成xml
*
* @param textMessage 文本消息对象
* @return xml
*/
public static String textMessageToXml(TextMessage textMessage) {
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}
View Code
二、代码实现
1.微信配置类—Env.java
微信公众号接入配置类
package com.ray.weixin.gz.config;
/**@desc : 微信公众号接入配置
*
* @author: shirayner
* @date : 2017年9月27日 下午4:57:36
*/
public class Env {
/**
* 1. 企业应用接入秘钥相关
*/
// public static final String APP_ID = "wx4ddse2334debebef2cc";
//public static final String APP_SECRET = "068e2599abf88ba72frrgbfs6f3c56e";
//测试号
public static final String APP_ID = "wxa00642deff56g062";
public static final String APP_SECRET = "fcc96fefdgdhtj1a46af7993784917";
/**
* 2.服务器配置:
* 启用并设置服务器配置后,用户发给公众号的消息以及开发者需要的事件推送,将被微信转发到该URL中
*/
public static final String TOKEN = "weixin";
public static final String ENCODING_AES_KEY = "JvJ1Dww6tjUU2psC3pdewegreHfovfWP3LfX1xrriz1";
}
View Code
2.HTTP请求工具类—HttpHelper.java
package com.ray.weixin.gz.util;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.FileEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.util.EntityUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
/**
* HTTP请求封装,建议直接使用sdk的API
*/
public class HttpHelper {
/**
* @desc :1.发起GET请求
*
* @param url
* @return JSONObject
* @throws Exception
*/
public static JSONObject doGet(String url) throws Exception {
//1.生成一个请求
HttpGet httpGet = new HttpGet(url);
//2.配置请求的属性
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(5000).setConnectTimeout(5000).build();//2000
httpGet.setConfig(requestConfig);
//3.发起请求,获取响应信息
//3.1 创建httpClient
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
try {
//3.2 发起请求,获取响应信息
response = httpClient.execute(httpGet, new BasicHttpContext());
//如果返回结果的code不等于200,说明出错了
if (response.getStatusLine().getStatusCode() != 200) {
System.out.println("request url failed, http code=" + response.getStatusLine().getStatusCode()
+ ", url=" + url);
return null;
}
//4.解析请求结果
HttpEntity entity = response.getEntity(); //reponse返回的数据在entity中
if (entity != null) {
String resultStr = EntityUtils.toString(entity, "utf-8"); //将数据转化为string格式
System.out.println("GET请求结果:"+resultStr);
JSONObject result = JSON.parseObject(resultStr); //将String转换为 JSONObject
if(result.getInteger("errcode")==null) {
return result;
}else if (0 == result.getInteger("errcode")) {
return result;
}else {
System.out.println("request url=" + url + ",return value=");
System.out.println(resultStr);
int errCode = result.getInteger("errcode");
String errMsg = result.getString("errmsg");
throw new Exception("error code:"+errCode+", error message:"+errMsg);
}
}
} catch (IOException e) {
System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
e.printStackTrace();
} finally {
if (response != null) try {
response.close(); //释放资源
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
/** 2.发起POST请求
* @desc :
*
* @param url 请求url
* @param data 请求参数(json)
* @return
* @throws Exception JSONObject
*/
public static JSONObject doPost(String url, Object data) throws Exception {
//1.生成一个请求
HttpPost httpPost = new HttpPost(url);
//2.配置请求属性
//2.1 设置请求超时时间
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(100000).setConnectTimeout(100000).build();
httpPost.setConfig(requestConfig);
//2.2 设置数据传输格式-json
httpPost.addHeader("Content-Type", "application/json");
//2.3 设置请求实体,封装了请求参数
StringEntity requestEntity = new StringEntity(JSON.toJSONString(data), "utf-8");
httpPost.setEntity(requestEntity);
//3.发起请求,获取响应信息
//
公众号给微信服务器响应数据
最新推荐文章于 2024-09-20 08:48:14 发布