您的位置:首页 > 移动开发 > 微信开发

微信公众号开发001-接入服务器

2018-02-02 09:39 288 查看
1.首先阅读公众号开发API,(这里要说明下微信公众号的API里面有好多坑,在实际项目中遇到在一一介绍)

2.公众号接入服务器:(参考公众号API文档:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319

3.接入服务器的后台实现:(设置服务器地址时微信会注定给服务器发起GET请求,而用户关注,发消息等微信会给服务器发送POST请求)

package com.deshangshidai.wechat.controller;

import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.deshangshidai.exceptions.CreateExceptionMessage;
import com.deshangshidai.wechat.subscribe.util.TopayUtil;
import com.deshangshidai.wechat.subscribe.util.WechatGlobalConfig;

@Controller
public class WechatCallBackApiController {

private static Logger log=LoggerFactory.getLogger(WechatCallBackApiController.class);
private String token=WechatGlobalConfig.SYSTEM_TOKEN;//令牌token
@RequestMapping("/")
public void getSystemToken(HttpServletRequest req, HttpServletResponse resp) throws IOException{
log.info("进入效验系统方法");
req.setCharacterEncoding("UTF-8");  //微信服务器POST消息时用的是UTF-8编码,在接收时也要用同样的编码,否则中文会乱码;
     resp.setCharacterEncoding("UTF-8"); //在响应消息(回复消息给用户)时,也将编码方式设置为UTF-8,原理同上;
     boolean isGet = req.getMethod().toLowerCase().equals("get"); //请求方法是否是get
try {
//验证消息的确来自微信服务器
if(isGet){
log.info("进入get方法");
// 微信加密签名
        String signature = req.getParameter("signature");
        // 随机字符串
        String echostr = req.getParameter("echostr");
        // 时间戳
        String timestamp = req.getParameter("timestamp");
        // 随机数
        String nonce = req.getParameter("nonce");
        String[] str = { token, timestamp, nonce };
        Arrays.sort(str); // 字典序排序
        String bigStr = str[0] + str[1] + str[2];
    	MessageDigest md = null;
    	String result="";
    	try {
md = MessageDigest.getInstance("SHA-1");
byte [] digest=md.digest(bigStr.toString().getBytes());
result = byteTostr(digest);
// 确认请求来至微信
        if (result.equals(signature)) {
            resp.getWriter().print(echostr);
        }
} catch (NoSuchAlgorithmException e) {
CreateExceptionMessage.getMessage(e);
resp.getWriter().print(CreateExceptionMessage.getMessage(e));
}     
}else{//post方法
  log.info("进入post方法");
  String respMessage = "异常消息!";
  //自动回复消息事件
  respMessage = TopayUtil.wxToMessage(req);
  resp.getWriter().print(respMessage);
}

} catch (Exception e) {
CreateExceptionMessage.getMessage(e);
resp.getWriter().print(CreateExceptionMessage.getMessage(e));
}

}

public static String byteTostr(byte[] str){
String strDigest = "";
for (int i = 0; i < str.length; i++) {
strDigest+= byteToHexStr(str[i]);
}
return strDigest;
}
//将一个字节转换成十六进制的字符串
public static String byteToHexStr(byte mByte){
char [] Digest ={'0','1', '2', '3', '4', '5', '6','7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
char[] temp = new char[2];
temp[0] = Digest[(mByte>>4)&0x0f];
temp [1]= Digest[mByte&0x0f];
String s = new String(temp);
return s;
}

}


/**
* 自动回复消息util  
*/
package com.deshangshidai.wechat.subscribe.util;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.deshangshidai.message.ImgPath;
import com.deshangshidai.utils.FtpUtils;
import com.deshangshidai.wechat.subscribe.message.resp.Article;
import com.deshangshidai.wechat.subscribe.message.resp.NewsMessage;
import com.deshangshidai.wechat.subscribe.message.resp.TextMessage;

/**
* <p>Title: </p>
* <p>Description: </p>
* <p>Company: 德商时代</p>
* @author:卫凯强
* @date 2017年11月14日 下午4:37:01
**/
public class TopayUtil {
private static Logger logger=LoggerFactory.getLogger(TopayUtil.class);

public static String wxToMessage(HttpServletRequest req){
logger.info("进入自动回复消息方法");
String respMessage = null;
try {

4000
Map<String, String> requestMap = MessageUtil.parseXml(req);
// 发送方帐号(open_id)
String fromUserName = requestMap.get("FromUserName");
// 公众帐号
String toUserName = requestMap.get("ToUserName");
// 消息类型
String msgType = requestMap.get("MsgType");
// 消息内容
//String content = requestMap.get("Content");
// 记录日志
logger.info("FromUserName is:" + fromUserName + ", ToUserName is:" + toUserName + ", MsgType is:" + msgType);
// 文本消息
if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
logger.info("进入文本回复方法");
//这里根据关键字执行相应的逻辑,只有你想不到的,没有做不到的
TextMessage text = new TextMessage();
text.setContent("欢迎关注《德商掌中城》官方微信!");
text.setToUserName(fromUserName);
text.setFromUserName(toUserName);
text.setCreateTime(new Date().getTime() + "");
text.setMsgType(msgType);
respMessage = MessageUtil.textMessageToXml(text);

}  else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
logger.info("进入关注事件方法");
String eventType = requestMap.get("Event");// 事件类型
// 订阅
if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
logger.info("进入关注回复方法");
NewsMessage newMsg=new NewsMessage();
newMsg.setToUserName(fromUserName);
newMsg.setFromUserName(toUserName);
newMsg.setCreateTime(new Date().getTime() + "");
newMsg.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_NEWS);
Article article=new Article();
article.setDescription("欢迎关注《德商掌中城》官方微信"); //图文消息的描述
article.setPicUrl(FtpUtils.IMG_URL+ImgPath.WxBannerImg+"/"+WechatGlobalConfig.guanzhutu); //图文消息图片地址
article.setTitle("德商掌中城");  //图文消息标题
article.setUrl(FileUtil.getHttp("off_line")+FileUtil.getHttp("domain_name")+FileUtil.get("menuOneUrl"));  //图文url链接
List<Article> list=new ArrayList<Article>();
list.add(article);     //这里发送的是单图文,如果需要发送多图文则在这里list中加入多个Article即可!
newMsg.setArticleCount(list.size());
newMsg.setArticles(list);
respMessage = MessageUtil.newsMessageToXml(newMsg);
}
} else if(msgType.equals(MessageUtil.RESP_MESSAGE_TYPE_VOICE)){
TextMessage text = new TextMessage();
text.setContent("您好,我是德商小管家,请联系我们的客服");
respMessage = MessageUtil.textMessageToXml(text);
}

} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

return respMessage;
}

}


/**
* 消息类型util
*/
package com.deshangshidai.wechat.subscribe.util;

import java.io.InputStream;
import java.io.Writer;
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;

import com.deshangshidai.wechat.subscribe.message.resp.Article;
import com.deshangshidai.wechat.subscribe.message.resp.ImageMessage;
import com.deshangshidai.wechat.subscribe.message.resp.MusicMessage;
import com.deshangshidai.wechat.subscribe.message.resp.NewsMessage;
import com.deshangshidai.wechat.subscribe.message.resp.TextMessage;
import com.deshangshidai.wechat.subscribe.message.resp.VideoMessage;
import com.deshangshidai.wechat.subscribe.message.resp.VoiceMessage;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;

public class MessageUtil {
/**
* 会员openId
*/
public static final String _USER_="openId";

/**
* 返回消息类型:文本
*/
public static final String RESP_MESSAGE_TYPE_TEXT = "text";

/**
* 返回消息类型:音乐
*/
public static final String RESP_MESSAGE_TYPE_MUSIC = "music";

/**
* 返回消息类型:图文
*/
public static final String RESP_MESSAGE_TYPE_NEWS = "news";

/**
* 返回消息类型:图片
*/
public static final String RESP_MESSAGE_TYPE_IMAGE = "image";

/**
* 返回消息类型:语音
*/
public static final String RESP_MESSAGE_TYPE_VOICE = "voice";

/**
* 返回消息类型:视频
*/
public static final String RESP_MESSAGE_TYPE_VIDEO = "video";

/**
* 请求消息类型:文本
*/
public static final String REQ_MESSAGE_TYPE_TEXT = "text";

/**
* 请求消息类型:图片
*/
public static final String REQ_MESSAGE_TYPE_IMAGE = "image";

/**
* 请求消息类型:链接
*/
public static final String REQ_MESSAGE_TYPE_LINK = "link";

/**
* 请求消息类型:地理位置
*/
public static final String REQ_MESSAGE_TYPE_LOCATION = "location";

/**
* 请求消息类型:音频
*/
public static final String REQ_MESSAGE_TYPE_VOICE = "voice";

/**
* 请求消息类型:视频
*/
public static final String REQ_MESSAGE_TYPE_VIDEO = "video";

/**
* 请求消息类型:推送
*/
public static final String REQ_MESSAGE_TYPE_EVENT = "event";

/**
* 事件类型:subscribe(订阅)
*/
public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";

/**
* 事件类型:unsubscribe(取消订阅)
*/
public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";

/**
* 事件类型:CLICK(自定义菜单点击事件)
*/
public static final String EVENT_TYPE_CLICK = "CLICK";

/**
* 事件类型:VIEW(自定义菜单URl视图)
*/
public static final String EVENT_TYPE_VIEW = "VIEW";

/**
* 事件类型:LOCATION(上报地理位置事件)
*/
public static final String EVENT_TYPE_LOCATION = "LOCATION";
/**
* 事件类型:SCAN(二维码扫描事件)
*/
public static final String EVENT_TYPE_SCAN = "SCAN";
/**
*菜单view类型
*/
public static final String MENU_TYPE_VIEW="2";
/**
* 菜单click类型
*/
public static final String MENU_TYPE_CLICK="1";

/**
* @Description: 解析微信发来的请求(XML)
* @param @param request
* @param @return
* @param @throws Exception
*/
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;
}

/**
* @Description: 文本消息对象转换成xml
* @param @param textMessage
* @param @return
*/
public static String textMessageToXml(TextMessage textMessage) {
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}

/**
* @Description: 图文消息对象转换成xml
* @param @param newsMessage
* @param @return
*/
public static String newsMessageToXml(NewsMessage newsMessage) {
xstream.alias("xml", newsMessage.getClass());
xstream.alias("item", new Article().getClass());
return xstream.toXML(newsMessage);
}

/**
* @Description: 图片消息对象转换成xml
* @param @param imageMessage
* @param @return
*/
public static String imageMessageToXml(ImageMessage imageMessage) {
xstream.alias("xml", imageMessage.getClass());
return xstream.toXML(imageMessage);
}

/**
* @Description: 语音消息对象转换成xml
* @param @param voiceMessage
* @param @return
*/
public static String voiceMessageToXml(VoiceMessage voiceMessage) {
xstream.alias("xml", voiceMessage.getClass());
return xstream.toXML(voiceMessage);
}

/**
* @Description: 视频消息对象转换成xml
* @param @param videoMessage
* @param @return
*/
public static String videoMessageToXml(VideoMessage videoMessage) {
xstream.alias("xml", videoMessage.getClass());
return xstream.toXML(videoMessage);
}

/**
* @Description: 音乐消息对象转换成xml
* @param @param musicMessage
* @param @return
*/
public static String musicMessageToXml(MusicMessage musicMessage) {
xstream.alias("xml", musicMessage.getClass());
return xstream.toXML(musicMessage);
}

/**
* 对象到xml的处理
*/
private static XStream xstream = new XStream(new XppDriver() {
public HierarchicalStreamWriter createWriter(Writer out) {
return new PrettyPrintWriter(out) {
// 对所有的xml节点的转换都增加CDATA标记
boolean cdata = true;
@SuppressWarnings("rawtypes")
public void startNode(String name, Class clzz) {
super.startNode(name, clzz);
}

protected void writeText(QuickWriter writer, String text) {
if (cdata) {
writer.write("<![CDATA[");
writer.write(text);
writer.write("]]>");
} else {
writer.write(text);
}
}
};
}
});
}

4.将MP_verify_HwltXWk6Drzcw66N.txt文件放置根目录下(如果放置位置不正确域名将无法设置成功),如下图位置:



5.配置域名,如下图:



接下来就可以开始我们的开发了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: