最近开始写微信公众号了,作为小白的我,有些懵,参考各种大神写的博客,总算实现了第一个功能。写此博客作为记录吧。
第一步:注册登录相应微信公众号信息
微信公众号平台地址:https://mp.weixin.qq.com/
第二步:实现内外网穿透
参考博客:http://blog.csdn.net/xyang81/article/details/52141881
第三步:仔细阅读开发文档,地址:
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432,然后开始进行编码实现。
我要实现的功能,简单来说就是,获取用户向公众号发送的消息,然后依据一定条件进行消息筛选,符合要求的进行入库操作。
话不多说,开始贴代码吧。
package com.weixin.controller;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Date;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.weixin.entity.RequestTextMessage;
import com.weixin.entity.Serial;
import com.weixin.service.SerialService;
import com.weixin.util.ReplyMessage;
import com.weixin.util.SHA1;
@Controller
@RequestMapping
public class RecognitionSerialNumberController {
private static final Logger log =Logger.getLogger(RecognitionSerialNumberController.class);
// 设置一个全局的token,开发者自己设置。api这样解释:Token可由开发者可以任意填写,
// 用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)
private String TOKEN = "guoyou";
@Autowired
private SerialService serialService ;
@RequestMapping(value="/addSerialNumber.html")
public void addSerialNumber(HttpServletRequest request, HttpServletResponse response) throws Exception{
//checkToken(request, response); //仅在认证微信开发者模式时调用一次即可
response.setContentType("text/html;charset=UTF-8");
PrintWriter pw = response.getWriter();
String wxMsgXml =IOUtils.toString(request.getInputStream(), "utf-8");
log.info("获取的数据信息>>>>>"+wxMsgXml);
boolean eventType =wxMsgXml.contains("Event") ;// 如果包含,则是触发事件
RequestTextMessage textMsg =null ;
String returnXml ="";
StringBuffer replyMsg = new StringBuffer();
if(!eventType){ //信息交互事件
textMsg = ReplyMessage.getRequestTextMessage(wxMsgXml);//解析用户输入的信息
String content = textMsg.getContent().trim();//用户发送信息
String openId= textMsg.getFromUserName().trim();//发送方账号(OpenID)
String creattime=textMsg.getCreateTime();
String msgType=textMsg.getMessageType();// 发送类型
String tousername=textMsg.getToUserName();//用户微信号
boolean flag= isContainsNumOrLetter(content);
if(flag) {
//将数据入库
Serial serial = new Serial();
serial.setAddtime(new Date());
serial.setOpen_id(openId);
serial.setName(tousername);
serial.setSn(content);
serial.setBt_mac_addr("");
serial.setWifi_mac_addr("");
serialService.insertSelective(serial);
//serialService.insert(serial);
replyMsg.append("返回信息!");
returnXml = ReplyMessage.getReplyTextMessage(replyMsg.toString(), textMsg.getFromUserName(),textMsg.getToUserName());
}else {
replyMsg.append("输入字符不符合格式!");
returnXml = ReplyMessage.getReplyTextMessage(replyMsg.toString(), textMsg.getFromUserName(),textMsg.getToUserName());
}
}
log.info("wxMsgXml>>>>>>>>>>>>>>"+wxMsgXml);
log.info("returnXml>>>>>>>>>>>>>>"+returnXml);
pw.println(returnXml);
}
/**
*
* @Title: isContainsNumOrLetter
* @Description: TODO(判断字符是否符合要求即包含数字和字母且长度为12)
* @param @param str
* @param @return 参数
* @return boolean 返回类型
* @throws
*/
private boolean isContainsNumOrLetter(String str) {
boolean flag = false;
boolean isDigit = false;//定义一个boolean值,用来表示是否包含数字
boolean isLetter = false;//定义一个boolean值,用来表示是否包含字母
//假设有一个字符串
for (int i=0 ; i<str.length() ; i++){ //循环遍历字符串
if (Character.isDigit(str.charAt(i))){ //用char包装类中的判断数字的方法判断每一个字符
isDigit = true;
}
if (Character.isLetter(str.charAt(i))){ //用char包装类中的判断字母的方法判断每一个字符
isLetter = true;
}
}
/*循环完毕以后
*如果isDigit为true,则代表字符串中包含数字,否则不包含
*如果isLetter为true,则代表字符串中包含字母,否则不包含
*/
//System.out.println(isDigit); //System.out.println(isLetter);
if(isDigit && isLetter) {
//根据字符长度、判断输入是Wifi 还是蓝牙
int len=str.length();
if( len == 12) {
flag = true;
}
}
return flag;
}
/*
* 第一步:验证服务器地址的有效性 开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上,
* GET请求携带四个参数:signature、timestamp、nonce、echostr
* 开发者通过检验signature对请求进行校验(下面有校验方式)。 若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,
* 则接入生效, 成为开发者成功,否则接入失败。
*
* 加密/校验流程如下:
* 1. 将token、timestamp、nonce三个参数进行字典序排序
* 2. 将三个参数字符串拼接成一个字符串进行sha1加密
* 3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
*
* 字典排序(lexicographical order)是一种对于随机变量形成序列的排序方法。其方法是,按照字母顺序,或者数字小大顺序,由小到大的形成序列。
*/
public boolean checkToken(HttpServletRequest request, HttpServletResponse response) throws IOException {
boolean flag = false;
// 微信加密签名
String signature = request.getParameter("signature");
// 随机字符串
String echostr = request.getParameter("echostr");
// 时间戳
String timestamp = request.getParameter("timestamp");
// 随机数
String nonce = request.getParameter("nonce");
String[] str = { TOKEN, timestamp, nonce };
Arrays.sort(str); // 字典序排序
String bigStr = str[0] + str[1] + str[2];
// SHA1加密
String digest = new SHA1().getDigestOfString(bigStr.getBytes()).toLowerCase();
// 确认请求来至微信
if (digest.equals(signature)) {
response.getWriter().print(echostr);
flag = true;
}else {
System.out.println("TAG"+"接入失败");
}
return flag;
}
}
ReplyMessage.java
package com.weixin.util;
import java.util.Date;
import java.util.List;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.weixin.entity.Item;
import com.weixin.entity.ReplyTextMessage;
import com.weixin.entity.ReplyTuwenMessage;
import com.weixin.entity.RequestTextMessage;
public class ReplyMessage {
// 获取关注事件
public static RequestTextMessage getRequestFocus(String xml){
XStream xstream = new XStream(new DomDriver());
xstream.alias("xml", RequestTextMessage.class);
xstream.aliasField("ToUserName", RequestTextMessage.class, "toUserName");
xstream.aliasField("FromUserName", RequestTextMessage.class, "fromUserName");
xstream.aliasField("CreateTime", RequestTextMessage.class, "createTime");
xstream.aliasField("MsgType", RequestTextMessage.class, "messageType");
xstream.aliasField("Event", RequestTextMessage.class, "event");
xstream.aliasField("EventKey", RequestTextMessage.class, "eventKey");
// xstream.aliasField("Content", RequestTextMessage.class, "content");
// xstream.aliasField("MsgId", RequestTextMessage.class, "msgId");
RequestTextMessage requestTextMessage = (RequestTextMessage)xstream.fromXML(xml);
return requestTextMessage;
}
// 获取推送文本消息
public static RequestTextMessage getRequestTextMessage(String xml){
XStream xstream = new XStream(new DomDriver());
xstream.alias("xml", RequestTextMessage.class);
xstream.aliasField("URL", RequestTextMessage.class, "url");
xstream.aliasField("ToUserName", RequestTextMessage.class, "toUserName");
xstream.aliasField("FromUserName", RequestTextMessage.class, "fromUserName");
xstream.aliasField("CreateTime", RequestTextMessage.class, "createTime");
xstream.aliasField("MsgType", RequestTextMessage.class, "messageType");
xstream.aliasField("Content", RequestTextMessage.class, "content");
xstream.aliasField("MsgId", RequestTextMessage.class, "msgId");
RequestTextMessage requestTextMessage = (RequestTextMessage)xstream.fromXML(xml);
return requestTextMessage;
}
// 回复文本消息
public static String getReplyTextMessage(String content, String fromUserName,String toUserName){
ReplyTextMessage we = new ReplyTextMessage();
we.setMessageType("text");
we.setFuncFlag("0");
we.setCreateTime(new Long(new Date().getTime()).toString());
we.setContent(content);
we.setToUserName(fromUserName);
we.setFromUserName(toUserName);
XStream xstream = new XStream(new DomDriver());
xstream.alias("xml", ReplyTextMessage.class);
xstream.aliasField("ToUserName", ReplyTextMessage.class, "toUserName");
xstream.aliasField("FromUserName", ReplyTextMessage.class, "fromUserName");
xstream.aliasField("CreateTime", ReplyTextMessage.class, "createTime");
xstream.aliasField("MsgType", ReplyTextMessage.class, "messageType");
xstream.aliasField("Content", ReplyTextMessage.class, "content");
xstream.aliasField("FuncFlag", ReplyTextMessage.class, "funcFlag");
String xml =xstream.toXML(we);
return xml;
}
// 回复图文消息
public static String getReplyTuwenMessage(String fromUserName,String toUserName,List<Item> articleList){
// NewsMessage newsMessage = new NewsMessage();
// MessageUtil messageUtil = new MessageUtil();
ReplyTuwenMessage we = new ReplyTuwenMessage();
// List<Item> articleList = new ArrayList<>();
// Articles articles = new Articles();
// Item item = new Item();
// Item item2 = new Item();
// Item item3 = new Item();
we.setMessageType("news");
we.setCreateTime(new Long(new Date().getTime()).toString());
we.setToUserName(fromUserName);
we.setFromUserName(toUserName);
we.setFuncFlag("0");
we.setArticleCount(articleList.size());
we.setArticles(articleList);
XStream xstream = new XStream(new DomDriver());
xstream.alias("xml", ReplyTuwenMessage.class);
xstream.aliasField("ToUserName", ReplyTuwenMessage.class, "toUserName");
xstream.aliasField("FromUserName", ReplyTuwenMessage.class, "fromUserName");
xstream.aliasField("CreateTime", ReplyTuwenMessage.class, "createTime");
xstream.aliasField("MsgType", ReplyTuwenMessage.class, "messageType");
xstream.aliasField("Articles", ReplyTuwenMessage.class, "Articles");
xstream.aliasField("ArticleCount", ReplyTuwenMessage.class, "articleCount");
xstream.aliasField("FuncFlag", ReplyTuwenMessage.class, "funcFlag");
//xstream.aliasField("item", Articles.class, "item");
xstream.alias("item", new Item().getClass());
xstream.aliasField("Title", Item.class, "title");
xstream.aliasField("Description", Item.class, "description");
xstream.aliasField("PicUrl", Item.class, "picUrl");
xstream.aliasField("Url", Item.class, "url");
String xml =xstream.toXML(we);
return xml;
}
}
RequestTextMessage.java
package com.weixin.entity;
public class RequestTextMessage {
private String url;
private String toUserName;
private String fromUserName;
private String createTime;
private String messageType;
private String content;
private String msgId;
private String event;
private String eventKey;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getToUserName() {
return toUserName;
}
public void setToUserName(String toUserName) {
this.toUserName = toUserName;
}
public String getFromUserName() {
return fromUserName;
}
public void setFromUserName(String fromUserName) {
this.fromUserName = fromUserName;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
public String getMessageType() {
return messageType;
}
public void setMessageType(String messageType) {
this.messageType = messageType;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getMsgId() {
return msgId;
}
public void setMsgId(String msgId) {
this.msgId = msgId;
}
public String getEvent() {
return event;
}
public void setEvent(String event) {
this.event = event;
}
public String getEventKey() {
return eventKey;
}
public void setEventKey(String eventKey) {
this.eventKey = eventKey;
}
}
获取/回复用户发送的其他类型消息还未实现,有时间整理出来一并贴出来。革命尚未成功,还需努力呀。