栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

微信公众号java开发:验证消息的确来自微信服务器

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

微信公众号java开发:验证消息的确来自微信服务器

微信公众号开发,微信服务需要认证服务,官方文档如下:

引入jar包如下:


	com.github.binarywang
	weixin-java-mp
	3.6.0


	com.github.liyiorg
	weixin-popular
	2.8.24


	org.dom4j
	dom4j
	2.1.3

代码如下:

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONObject;
import com.cetcnav.lbs.pis.util.DateUtil;
import com.cetcnav.operations.Attention.service.AttentionService;
import com.cetcnav.operations.cache.CacheManger;
import com.cetcnav.operations.entity.UserApp;
import com.cetcnav.operations.user.service.UserAppService;
import com.cetcnav.operations.util.WXUtil;
import com.cetcnav.operations.util.WeixinUtil;
import com.cetcnav.operations.util.constant.OperationsConstant;
import com.cetcnav.operations.util.constant.WXConstant;
import com.cetcnav.operations.util.properties.RouteUrlPropertiesUtils;

import weixin.popular.bean.xmlmessage.XMLImageMessage;
import weixin.popular.bean.xmlmessage.XMLMessage;
import weixin.popular.support.ExpireKey;
import weixin.popular.support.expirekey.DefaultExpireKey;


@RestController
@RequestMapping("/rest/wxauth")
public class WXAuthWebServiceController {
	private static Logger log = LoggerFactory.getLogger(WXAuthWebServiceController.class);


	@Autowired
	private UserAppService userAppService;
	
	
	// 重复通知过滤
	private static ExpireKey expireKey = new DefaultExpireKey();

	@RequestMapping(value = "", method = RequestMethod.GET)
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {

		// 1、验证消息的确来自微信服务器
		String signature = request.getParameter("signature");
		String timestamp = request.getParameter("timestamp");
		String nonce = request.getParameter("nonce");
		String echostr = request.getParameter("echostr");
		String token = OperationsConstant.WECHAT_TOKEN;
		String jiami = "";
		try {
			// 这里是对三个参数进行加密
			jiami = SHA1.getSHA1(token, timestamp, nonce, "");
		} catch (AesException e) {
			e.printStackTrace();
		}
		log.info("验证消息的确来自微信服务器 :加密" + jiami);
		log.info("验证消息的确来自微信服务器 :本身" + signature);
		if (jiami.equals(signature)) {
			// 返回echostr给微信服务器
			OutputStream os = response.getOutputStream();
			os.write(URLEncoder.encode(echostr, "UTF-8").getBytes());
			os.flush();
			os.close();
		}
	}
	
	@RequestMapping(value = "", method = RequestMethod.POST)
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		PrintWriter out = response.getWriter();
		// 2、接收微信服务器推送的时间信息
		// xml请求解析
		Map requestMap = WXUtil.parseXml(request);

		if (requestMap.get("MsgType") != null) {
			// 发送方帐号(open_id)
			String fromUserName = requestMap.get("FromUserName");
			// 公众帐号
			String toUserName = requestMap.get("ToUserName");
			// 消息类型
			String msgType = requestMap.get("MsgType");
			// 消息创建时间 (整型)
			String createTime = requestMap.get("CreateTime");

			String key = fromUserName + "-" + toUserName + "-" + createTime;
			// 重复通知不作处理
			if (expireKey.exists(key)) {
				log.info("重复通知了");
				return;
			}
			// 事件处理开始
			if (msgType.equals(WXConstant.REQ_MESSAGE_TYPE_EVENT)) {
				// 事件类型
				String eventType = requestMap.get("Event");
				// 微信关注事件
				if (eventType.equals(WXConstant.EVENT_TYPE_SUBSCRIBE)) {
					String unionid = CacheManger.getUnionId(fromUserName);
					if (StringUtils.isBlank(unionid)) {
						log.error("公众号关注,unionid获取为空。");
						return;
					}
					// 关注时触发 * 累加关注积分
					attentionService.attentionInterface(unionid);

					UserApp userApp = userAppService.getUserAppByUnionIdAndType(unionid,
							OperationsConstant.APP_TYPE_OPERATIONS);
					if (userApp == null) {
						// userapp里存储公众号账号信息
						UserApp ua = new UserApp();
						ua.setApptype(OperationsConstant.APP_TYPE_OPERATIONS);
						ua.setOpenid(fromUserName);
						ua.setUnionId(unionid);
						ua.setUpdatetime(DateUtil.getCurrentTime());
						ua.setDeleted(false);
						userAppService.add(ua);
					}
					// XMLMessage xmlTextMessage = new
					// XMLTextMessage(fromUserName,toUserName,"积分兑换流程如下:n");
					// String textMessage = xmlTextMessage.toXML();
					// out.print(textMessage);

					// 调用客服接口 客服接口-发消息
					String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN"
							.replace("ACCESS_TOKEN", CacheManger.ACCESS_TOKEN);
					String json = "{"touser":"OPENID","msgtype":"text","text":{"content":"DATA"}}"
							.replace("OPENID", fromUserName)
							.replace("DATA", "欢迎关注图:n");
					JSONObject jsonStr = WeixinUtil.httpRequest(url, "POST", json);
					log.info(jsonStr.toString());

					XMLMessage xmlImageMessage = new XMLImageMessage(fromUserName, toUserName,
							RouteUrlPropertiesUtils.getString("attention.image.id"));
					String imageMessage = xmlImageMessage.toXML();
					out.print(imageMessage);
				} else if (eventType.equals(WXConstant.EVENT_TYPE_UNSUBSCRIBE)) {
					// 取消关注,用户接受不到我们发送的消息了,可以在这里记录用户取消关注的日志信息
				}
			}
		}
		out.close();
	}
}

微信推送信息类型:

public class WXConstant {
	
	public static final String REQ_MESSAGE_TYPE_EVENT = "event";
	
	public static final String REQ_MESSAGE_TYPE_TEXT = "text";
 
	
	public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";
 
	
	public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";
 
	
	public static final String EVENT_TYPE_CLICK = "CLICK";
	
	
	public static final String MESSAGE_SCAN="SCAN";//未关注公众号扫描二维码
	public static final String MESSAGE_TEXT="text";//文本
	public static final String MESSAGE_IMAGE="image";//图片
	public static final String MESSAGE_VOICE="voice";//语音
	public static final String MESSAGE_VIDEO="video";//视频
	public static final String MESSAGE_LINK="link";//连接
	public static final String MESSAGE_LOCATION="location";//地理位置事件
	public static final String MESSAGE_EVENT="event";//事件
	public static final String MESSAGE_SUBSCRIBE="subscribe";//关注
	public static final String MESSAGE_UNSUBSCRIBE="unsubscribe";//取消关注
	public static final String MESSAGE_CLICK="CLICK";//点击
	public static final String MESSAGE_VIEW="VIEW";//t跳转链接url
}

SHA1加密方法:

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


public class SHA1 {

	
	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);
		}
	}
}

AesException

@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;
	}

}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/844870.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号