微信服务器配置的一点点经验(内含:验证服务器出现token验证失败的处理,接收事件出现XML格式错误,微信网页授权获取 access token 报错40125)

首先需要多些网上的大神
链接:https://bbs.csdn.net/topics/390991193 ;
https://blog.csdn.net/sinat_22878395/article/details/69258165 ;
https://blog.csdn.net/hanghangde/article/details/51028755 ;
https://bbs.csdn.net/topics/391878796
微信服务器配置的一点点经验(内含:验证服务器出现token验证失败的处理,接收事件出现XML格式错误,微信网页授权获取 access token 报错40125)_第1张图片
微信服务器配置的一点点经验(内含:验证服务器出现token验证失败的处理,接收事件出现XML格式错误,微信网页授权获取 access token 报错40125)_第2张图片
微信服务器配置的一点点经验(内含:验证服务器出现token验证失败的处理,接收事件出现XML格式错误,微信网页授权获取 access token 报错40125)_第3张图片
微信服务器配置的一点点经验(内含:验证服务器出现token验证失败的处理,接收事件出现XML格式错误,微信网页授权获取 access token 报错40125)_第4张图片
本文只是将这几个大神的攻略进行排列组合。
Controller类

/**
	*@author TEDYYAN
    * @throws DocumentException 
    * @throws IOException 
    * @throws AesException 
	*@注释:公众号用户互动
*/
@RequestMapping(value="/extensionInsurance/weiXinInteraction",produces = {"text/plain;charset=UTF-8"})
@ResponseBody
public String weiXinInteraction(HttpServletRequest request) throws IOException, DocumentException, AesException{
	String msgSignature = request.getParameter("signature");
       String msgTimestamp = request.getParameter("timestamp");
       String msgNonce = request.getParameter("nonce");
       String echostr = request.getParameter("echostr");
       if (WXPublicUtils.verifyUrl(msgSignature, msgTimestamp, msgNonce,sysConfigService.getValue("sacon.app.token"))) {
       	LOG.info("---------------------------------------------公众号成功连接!");
       	LOG.info("msgNonce"+msgNonce+"   msgTimestamp"+msgTimestamp+"  msgNonce"+msgNonce+"   echostr"+echostr);
           return echostr;
       }
       LOG.info("msgNonce"+msgNonce+"   msgTimestamp"+msgTimestamp+"  msgNonce"+msgNonce+"   echostr"+echostr+"公众号成功失败!");
       return null;
}

WXPublicUtils 类

package com.dido.common.util;

import com.dido.common.payment.weixin.WeiXinConfig;

public class WXPublicUtils {

    /**
     * 验证Token
     * @param msgSignature 签名串,对应URL参数的signature
     * @param timeStamp 时间戳,对应URL参数的timestamp
     * @param nonce 随机串,对应URL参数的nonce
     *
     * @return 是否为安全签名
     * @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息
     */
    public static boolean verifyUrl(String msgSignature, String timeStamp, String nonce,String token)
            throws AesException {
        // 这里的 WXPublicConstants.TOKEN 填写你自己设置的Token就可以了
        String signature = SHA1.getSHA1(token, timeStamp, nonce);
        if (!signature.equals(msgSignature)) {
            throw new AesException(AesException.ValidateSignatureError);
        }
        return true;
    }
}

AesException 类

package com.dido.common.util;

@SuppressWarnings("serial")
public class AesException extends Exception {

	public final static int OK = 0;
	public final static int ValidateSignatureError = -40001;
	public final static int ParseXmlError = -40002;
	public final static int ComputeSignatureError = -40003;
	public final static int IllegalAesKey = -40004;
	public final static int ValidateAppidError = -40005;
	public final static int EncryptAESError = -40006;
	public final static int DecryptAESError = -40007;
	public final static int IllegalBuffer = -40008;
	//public final static int EncodeBase64Error = -40009;
	//public final static int DecodeBase64Error = -40010;
	//public final static int GenReturnXmlError = -40011;

	private int code;

	private static String getMessage(int code) {
		switch (code) {
		case ValidateSignatureError:
			return "签名验证错误";
		case ParseXmlError:
			return "xml解析失败";
		case ComputeSignatureError:
			return "sha加密生成签名失败";
		case IllegalAesKey:
			return "SymmetricKey非法";
		case ValidateAppidError:
			return "appid校验失败";
		case EncryptAESError:
			return "aes加密失败";
		case DecryptAESError:
			return "aes解密失败";
		case IllegalBuffer:
			return "解密后得到的buffer非法";
//		case EncodeBase64Error:
//			return "base64加密错误";
//		case DecodeBase64Error:
//			return "base64解密错误";
//		case GenReturnXmlError:
//			return "xml生成失败";
		default:
			return null; // cannot be
		}
	}

	public int getCode() {
		return code;
	}

	AesException(int code) {
		super(getMessage(code));
		this.code = code;
	}

}

SHA1 类

/**
 * 对公众平台发送给公众账号的消息加解密示例代码.
 * 
 * @copyright Copyright (c) 1998-2014 Tencent Inc.
 */

// ------------------------------------------------------------------------

package com.dido.common.util;

import java.security.MessageDigest;
import java.util.Arrays;

/**
 * SHA1 class
 *
 * 计算公众平台的消息签名接口.
 */
class SHA1 {

	/**
	 * 用SHA1算法生成安全签名
	 * 
	 * @param token
	 *            票据
	 * @param timestamp
	 *            时间戳
	 * @param nonce
	 *            随机字符串
	 * @param encrypt
	 *            密文
	 * @return 安全签名
	 * @throws AesException
	 */
	public static String getSHA1(String token, String timestamp, String nonce, String encrypt) throws AesException {
		try {
			String[] array = new String[] { token, timestamp, nonce, encrypt };
			StringBuffer sb = new StringBuffer();
			// 字符串排序
			Arrays.sort(array);
			for (int i = 0; i < 4; i++) {
				sb.append(array[i]);
			}
			String str = sb.toString();
			// SHA1签名生成
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			md.update(str.getBytes());
			byte[] digest = md.digest();

			StringBuffer hexstr = new StringBuffer();
			String shaHex = "";
			for (int i = 0; i < digest.length; i++) {
				shaHex = Integer.toHexString(digest[i] & 0xFF);
				if (shaHex.length() < 2) {
					hexstr.append(0);
				}
				hexstr.append(shaHex);
			}
			return hexstr.toString();
		} catch (Exception e) {
			e.printStackTrace();
			throw new AesException(AesException.ComputeSignatureError);
		}
	}

	/**
	 * 用SHA1算法验证Token
	 *
	 * @param token
	 *            票据
	 * @param timestamp
	 *            时间戳
	 * @param nonce
	 *            随机字符串
	 * @return 安全签名
	 * @throws AesException
	 */
	public static String getSHA1(String token, String timestamp, String nonce) throws AesException {
		try {
			String[] array = new String[] { token, timestamp, nonce };
			StringBuffer sb = new StringBuffer();
			// 字符串排序
			Arrays.sort(array);
			for (int i = 0; i < 3; i++) {
				sb.append(array[i]);
			}
			String str = sb.toString();
			// SHA1签名生成
			MessageDigest md = MessageDigest.getInstance("SHA-1");
			md.update(str.getBytes());
			byte[] digest = md.digest();

			StringBuffer hexstr = new StringBuffer();
			String shaHex = "";
			for (int i = 0; i < digest.length; i++) {
				shaHex = Integer.toHexString(digest[i] & 0xFF);
				if (shaHex.length() < 2) {
					hexstr.append(0);
				}
				hexstr.append(shaHex);
			}
			return hexstr.toString();
		} catch (Exception e) {
			e.printStackTrace();
			throw new AesException(AesException.ComputeSignatureError);
		}
	}
}

接收xml变为map

/**
	 * 根据request将XML流解析成MAP
	 * 
	 * @param request
	 * @return
	 * @throws IOException
	 * @throws DocumentException
	 */
	public static Map xmlToMap(HttpServletRequest request) throws IOException, DocumentException {
		// 将解析结果存储在HashMap中
		Map map = new HashMap();
		// 从request中取得输入流
		InputStream inputStream = request.getInputStream();
		// 一定要utf-8
		InputStreamReader inputReader = new InputStreamReader(inputStream, "UTF-8");
		BufferedReader buffer = new BufferedReader(inputReader);
		String message = "";
		String s = "";
		while ((s = buffer.readLine()) != null) {
			message += s;
		}
		System.out.println(message);
		LOG.info("WechatSendMessage---------------------------------------------" + message);
		System.out.println("获取输入流");
		// // 读取输入流
		SAXReader reader = new SAXReader();
		// Document document = reader.read(inputStream);
		// 将字符串转化为XML文档对象
		Document document = DocumentHelper.parseText(message);
		Element root = document.getRootElement();
		List elements = root.elements();
		// 遍历根节点下所有子节点
		Iterator iter = root.elementIterator();

		// // 遍历所有子节点
		// for (Element e : elementList) {
		// System.out.println(e.getName() + "|" + e.getText());
		// map.put(e.getName(), e.getText());
		// }
		while (iter.hasNext()) {
			Element ele = (Element) iter.next();
			map.put(ele.getName(), ele.getText());

		}
		// 释放资源
		inputStream.close();
		return map;
	}

处理事件代码

LOG.info("---------------------------------------------进入扫码事件!");
com.alibaba.fastjson.JSONObject jsonObject = HttpClientUtils.httpGet("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + sysConfigService.getValue("sacon.app.id") + "&secret=" + sysConfigService.getValue("sacon.app.secret"));
String access_token = jsonObject.getString("access_token");
Map receivedMap = xmlToMap(request);
String msgType = receivedMap.get("MsgType").replaceAll("\\s*", "");
// 普通消息
if ("text".equals(msgType)) { // 文本消息
	// todo 处理文本消息
} else if ("image".equals(msgType)) { // 图片消息
	// todo 处理图片消息
} else if ("voice".equals(msgType)) { // 语音消息
	// todo 处理语音消息
} else if ("video".equals(msgType)) { // 视频消息
	// todo 处理视频消息
} else if ("shortvideo".equals(msgType)) { // 小视频消息
	// todo 处理小视频消息
} else if ("location".equals(msgType)) { // 地理位置消息
	// todo 处理地理位置消息
} else if ("link".equals(msgType)) { // 链接消息
	// todo 处理链接消息
} else if ("event".equals(msgType)) { // 事件消息
	String event = receivedMap.get("Event").replaceAll("\\s*", "");
	if ("subscribe".equals(event)) { // 订阅事件 或 未关注扫描二维码事件
		// 获取消息模板ID
		String template_id = sysConfigService.getValue("weixin.sendMessage.model.first");
		// 获取用户数据中的openid、unionid、nickname和headimgurl放入wx_user数据库
		String openid = receivedMap.get("FromUserName").replaceAll("\\s*", "");
		String userInfoURL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + access_token + "&openid=" + openid;
		com.alibaba.fastjson.JSONObject userInfo = HttpClientUtils.httpGet(userInfoURL);
		String unionid = userInfo.getString("unionid");
		String nickname = userInfo.getString("nickname");
		String headimgurl = userInfo.getString("headimgurl");
		WXUser wxUser = wxUserService.findUserByOpenid(openid);
		if (wxUser == null) {
			wxUser = new WXUser();
			wxUser.setNickname(nickname);
			wxUser.setOpenid(openid);
			wxUser.setHeadimgurl(headimgurl);
			wxUser.setUnionid(unionid);
			wxUser.setAppid(sysConfigService.getValue("sacon.app.id"));
			wxUserService.saveOrUpdate(wxUser);
		}
		// 获取二维码中的参数进行解密
		String receivedMessage = receivedMap.get("EventKey").replaceAll("\\s*", "");
		String orderNumber = "";
		if (receivedMessage != null) {
			String[] reciveMessages = receivedMessage.split("_");
			if (reciveMessages.length > 0) {
				String temp = AESUtils.decrypt(reciveMessages[1]);
				orderNumber = temp;
			}
		}
		// 获取订单详情
		AcppOrder acppOrder = acppOrderService.findAcppOrderId(orderNumber);
		// 绑定订单,参数创建时间、unionid和价格
		if (acppOrder != null) {
			acppOrder.setObeyWxOpenId(unionid);
			acppOrder.setOrderCreationTime(new Date());
			acppOrderService.saveOrUpdate(acppOrder);
			AcppProduct product = acppProductService.selectByPrimaryKey(acppOrder.getProductId());
			if (product != null) {
				if (sysConfigService.isOpen("weixin.sendMessage.model.flag")) {
					// 初始化返回消息模板
					WeChatSendTemplateMessageModel weChatSendTemplateMessageModel = new WeChatSendTemplateMessageModel();
					weChatSendTemplateMessageModel.setTouser(openid);
					weChatSendTemplateMessageModel.setTemplate_id(template_id);
					weChatSendTemplateMessageModel.setUrl(product.getWeimengUrl());
					// 模板赋值
					Map dataMap = initCreateModel(acppOrder, product);
					weChatSendTemplateMessageModel.setData(dataMap);
					// 转换模板格式
					String json = com.alibaba.fastjson.JSONObject.toJSONString(weChatSendTemplateMessageModel);
					com.alibaba.fastjson.JSONObject resultObject = com.alibaba.fastjson.JSONObject.parseObject(json);
					// 发送模板信息
					String sendURL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + access_token;
					com.alibaba.fastjson.JSONObject sendObject = HttpClientUtils.httpPost(sendURL, resultObject);
					String errmsg = sendObject.getString("errmsg");
					if (!errmsg.equals("ok")) {
						LOG.error("errmsg" + errmsg + "	errcode" + sendObject.getString("errcode") + "	msgid" + sendObject.getString("msgid"));
					}
				}
			} else {
				LOG.error("Query product failure");
			}
		} else {
			LOG.error("Extension does not exist");
		}
		LOG.info("---------------------------------------------微信公众号扫码收到的订单号" + orderNumber);
		//

		return "success";
	} else if ("unsubscribe".equals(event)) { // 取消订阅事件
		// todo 处理取消订阅事件
	} else if ("SCAN".equals(event)) { // 已关注扫描二维码事件
		String openid = receivedMap.get("FromUserName").replaceAll("\\s*", "");
		// 检测是否已经记录到wxUser数据库
		WXUser wxUser = wxUserService.findUserByOpenid(openid);
		if (wxUser == null) {
			String userInfoURL = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + access_token + "&openid=" + openid;
			com.alibaba.fastjson.JSONObject userInfo = HttpClientUtils.httpGet(userInfoURL);
			String unionid = userInfo.getString("unionid");
			String nickname = userInfo.getString("nickname");
			String headimgurl = userInfo.getString("headimgurl");
			wxUser = new WXUser();
			wxUser.setNickname(nickname);
			wxUser.setOpenid(openid);
			wxUser.setHeadimgurl(headimgurl);
			wxUser.setUnionid(unionid);
			wxUser.setAppid(sysConfigService.getValue("sacon.app.id"));
			wxUserService.saveOrUpdate(wxUser);
		}
		// 获取消息模板ID
		String template_id = sysConfigService.getValue("weixin.sendMessage.model.first");
		//
		// 获取二维码中的参数进行解密
		String orderNumber = "";
		String receivedMessage = receivedMap.get("EventKey").replaceAll("\\s*", "");
		if (receivedMessage != null) {
			orderNumber = AESUtils.decrypt(receivedMessage);
		}

		LOG.info("---------------------------------------------微信公众号扫码收到的订单号" + orderNumber);
		//
		// 获取订单详情
		AcppOrder acppOrder = acppOrderService.findAcppOrderId(orderNumber);
		if (acppOrder != null) {
			// 绑定订单,参数创建时间、unionid和价格
			if (wxUser != null) {
				acppOrder.setObeyWxOpenId(wxUser.getUnionid());
				acppOrder.setOrderCreationTime(new Date());
				acppOrderService.saveOrUpdate(acppOrder);
			} else {
				WXUser wxUser1 = wxUserService.findUserByOpenid(openid);
				acppOrder.setObeyWxOpenId(wxUser1.getUnionid());
				acppOrder.setOrderCreationTime(new Date());
				acppOrderService.saveOrUpdate(acppOrder);
			}
			AcppProduct product = acppProductService.selectByPrimaryKey(acppOrder.getProductId());
			if (product != null) {
				if (sysConfigService.isOpen("weixin.sendMessage.model.flag")) {
					// 初始化返回消息模板
					WeChatSendTemplateMessageModel weChatSendTemplateMessageModel = new WeChatSendTemplateMessageModel();
					weChatSendTemplateMessageModel.setTouser(openid);
					weChatSendTemplateMessageModel.setTemplate_id(template_id);
					weChatSendTemplateMessageModel.setUrl(product.getWeimengUrl());
					// 模板赋值
					Map dataMap = initCreateModel(acppOrder, product);
					weChatSendTemplateMessageModel.setData(dataMap);
					// 转换模板格式
					String json = com.alibaba.fastjson.JSONObject.toJSONString(weChatSendTemplateMessageModel);
					com.alibaba.fastjson.JSONObject resultObject = com.alibaba.fastjson.JSONObject.parseObject(json);
					// 发送模板信息
					String sendURL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + access_token;
					com.alibaba.fastjson.JSONObject sendObject = HttpClientUtils.httpPost(sendURL, resultObject);
					String errmsg = sendObject.getString("errmsg");
					if (!errmsg.equals("ok")) {
						LOG.error("errmsg" + errmsg + "	errcode" + sendObject.getString("errcode") + "	msgid" + sendObject.getString("msgid"));
					}
				}
			} else {
				LOG.error("Query product failure");
			}
		} else {
			LOG.error("Extension does not exist");
		}
		return "success";
	} else if ("LOCATION".equals(event)) { // 上报地理位置事件
		// todo 处理上报地理位置事件
	} else if ("CLICK".equals(event)) { // 点击菜单拉取消息时的事件推送事件
		// todo 处理点击菜单拉取消息时的事件推送事件
	} else if ("VIEW".equals(event)) { // 点击菜单跳转链接时的事件推送
		// todo 处理点击菜单跳转链接时的事件推送
	} else if ("TEMPLATESENDJOBFINISH".equals(event)) {
		String status = receivedMap.get("Status").replaceAll("\\s*", "");
		String fromUserName = receivedMap.get("FromUserName").replaceAll("\\s*", "");
		String createTime = receivedMap.get("CreateTime").replaceAll("\\s*", "");
		String msgID = receivedMap.get("MsgID").replaceAll("\\s*", "");
		if (status.equals("success")) {
			LOG.info("用户Openid为" + fromUserName + "消息ID" + msgID + "创建时间为" + createTime + "成功!");
		} else if (status.equals("failed:user block")) {
			LOG.warn("用户Openid为" + fromUserName + "消息ID" + msgID + "创建时间为" + createTime + "用户拒收!");
		} else if (status.equals("failed: system failed")) {
			LOG.error("用户Openid为" + fromUserName + "消息ID" + msgID + "创建时间为" + createTime + "发送失败!");
		}
	}
}
return "success";

你可能感兴趣的:(技术积累,微信公众号)