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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37522951/article/details/79235231
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 {
			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.配置域名,如下图:


接下来就可以开始我们的开发了







猜你喜欢

转载自blog.csdn.net/qq_37522951/article/details/79235231