jAVA接入微信公众号提供服务
前言
本文章控制层基于SpringMVC开发。
将JAVA项目与微信服务器对接
微信相关配置
真实公众号账号配置
进入公众账号平台,登录公众账号后,拉到最下方的开发选项,对开发配置进行启用。
首次对接接口时,需要对域名进行验证,验证方式可以遵循微信提供的步骤进行。
验证完成后,开始配置服务器配置
如图:
测试号配置
进入测试号申请页面,申请完成后配置如下:
配置完成后,即可对接口代码进行编写
代码
首先要明确的是,微信服务器在对接接口,及后续的业务事件的处理请求,都会发送到以上所配置的接口中,区别在于,接入为get请求,业务请求为post请求
所以编写接口时,可以对接口的两种请求方式进行区分
可参考[微信对接文档]进行接口编写(https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html)
pom
<dependency>//用于对XML数据的处理
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6</version>
</dependency>
util
XmlUtil
public class XmlUtil<T> {
/*将xml格式转化为map */
public static Map<String, String> xmlToMap(HttpServletRequest request) {
Map<String, String> map = null;
try (InputStream inputStream = request.getInputStream()){
map=new HashMap<>();
SAXReader reader = new SAXReader();
Document doc = reader.read(inputStream);
Element root = doc.getRootElement();//得到根节点
List<Element> list = root.elements();//根节点下的所有的节点
for (Element e : list) {
if ("ScanCodeInfo".equals(e.getName())){//对公众号菜单扫码事件的做处理
List<Element> elements = e.elements();
for (Element scan:elements){
if ("ScanResult".equals(scan.getName())){
map.put("ScanCodeInfo",scan.getText());
}
}
}else {
map.put(e.getName(), e.getText());
}
}
} catch (Exception e){
e.printStackTrace();
map=null;
}
return map;
}
//对回复的消息进行处理
public static<T> String textMessageToXml(T textMessage) {
XStream xStream = new XStream();
//将根节点替换为xml
xStream.alias("xml",textMessage.getClass());
return xStream.toXML(textMessage);
}
}
EncryptUtil
public class EncryptUtil {
public static String Sha1(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;
}
}
}
controller
这里使用了springMVC进行开发
@ResponseBody
@GetMapping("/wx/auth")//处理接入请求,验证请求是否来自微信服务器
public String auth(@RequestParam(required = true) String echostr,
@RequestParam(required = true) String timestamp,
@RequestParam(required = true) String nonce,
@RequestParam(required = true) String signature
) {
return wxService.auth(echostr, timestamp, nonce, signature);
}
@ResponseBody
@PostMapping("/wx/auth")//处理业务请求
public String service(HttpServletRequest request) throws Exception {
//request 中携带微信服务器发送过来的消息,消息为XML格式,需要自行解析
return wxService.service(XmlUtil.xmlToMap(request););//若要回复用户消息,则需要将回复内容封装成XML格式
}
service
/**
* 验证消息的确来自微信服务器
*/
@Override
public String auth(String echostr, String timestamp, String nonce, String signature) {
if (!StringUtils.isBlank(timestamp) && !StringUtils.isBlank(nonce)) {
//排序
String token = Constant.WX_TOKEN;//公众号配置的token
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 tmp = EncryptUtil.Sha1(content.toString());
if (tmp.equals(signature)) {//比对此次携带的密文是否与自己解析的一致
return echostr;//根据文档所描述,返回此次携带的随机字符串
}
}
return null;
}
public String service(Map<String, String> map ){
if(map==null){
(throw error ) or (return errorMsg)
}
// 之后根据map中的消息类型进行后续处理,返回相应的处理结果
T msg = process(map);
return XmlUtil.textMessageToXml(msg);
}
T为消息实体类,最终需要转换为XML格式的的字符串进行放回
收发消息可参考微信消息处理文档
总结
服务器与公众号的对接,重点在于确认对接请求是否来自微信服务器,且通知微信服务器对接确认的方式
同时要清楚微信服务器在进行对接,及后续业务请求时,访问的是同一个接口,只已请求方式区分,我们只需要对不同的请求方式进行不同的业务处理即可。
业务请求的处理过程后续会再写文章进行详细讲解,这里仅说明了对接的过程