java监控微信公众号关注事件

监控微信公众号时间需要先完善服务器配置
微信官方文档:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
接入
这里的URL填写自己的服务器地址,需要80或者443端口,没有服务器的可以使用内网渗透工具,我使用的是cpolar,Token跟EncodingAESKey是可以随机的。
验证消息的确来自微信服务器
开发者提交信息后,微信服务器将发送GET请求到填写的服务器地址URL上。
开发者通过检验signature对请求进行校验(下面有校验方式)。若确认此次GET请求来自微信服务器,请原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败。加密/校验流程如下:
1)将token、timestamp、nonce三个参数进行字典序排序
2)将三个参数字符串拼接成一个字符串进行sha1加密
3)开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
检验signature的Java示例代码:

    @GetMapping(value = "/check-token", produces = "application/json; charset=utf-8")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "验证消息的确来自微信服务器,签名验证", notes = "验证消息的确来自微信服务器,签名验证", code = 200, produces = "application/json")
	@ApiImplicitParams({
		@ApiImplicitParam(paramType = "query", dataType = "string", name = "signature",required = true ,value = "微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。"),
		@ApiImplicitParam(paramType = "query", dataType = "string", name = "timestamp",required = true ,value = "时间戳"),
		@ApiImplicitParam(paramType = "query", dataType = "string", name = "nonce",required = true ,value = "随机数"),
		@ApiImplicitParam(paramType = "query", dataType = "string", name = "echostr",required = true ,value = "随机字符串")})
	public String checkToken(@RequestParam("signature") String signature, @RequestParam("timestamp") String timestamp,
							 @RequestParam("nonce") String nonce, @RequestParam("echostr") String echostr) {
		return  service.checkSignature(signature, timestamp, nonce,echostr);
	}
	public String checkSignature(String signature, String timestamp, String nonce, String echostr) {
		log.info("signature:{},token:{},timestamp:{},nonce:{}",signature,token,timestamp,nonce);
		// 1.将token、timestamp、nonce三个参数进行字典序排序
		String tmpStr = ShaUtil.getSHA1(token,  timestamp,  nonce);
		log.info("随机字符串echostr:{}",echostr);
		log.info("tmpStr:{}",tmpStr);
		if (tmpStr.equals(signature.toUpperCase())) {
			return echostr;
		}
		return null;
	}

ShaUtil工具类

@Slf4j
public class ShaUtil {
	/**
	 * @param token     url相关的token
	 * @param timestamp 时间戳
	 * @param nonce     随机数
	 * @return java.lang.String
	 * @Description 用SHA1算法验证Token
	 */
	public static String getSHA1(String token, String timestamp, String nonce) {

		String[] arr = new String[]{token, timestamp, nonce};
		Arrays.sort(arr);
		StringBuilder content = new StringBuilder();
		for (int i = 0; i < arr.length; i++) {
			content.append(arr[i]);
		}
		MessageDigest md = null;
		String tmpStr = null;
		try {
			md = MessageDigest.getInstance("SHA-1");
			// 将三个参数字符串拼接成一个字符串进行sha1加密
			byte[] digest = md.digest(content.toString().getBytes());
			tmpStr = byteToStr(digest);
		} catch (NoSuchAlgorithmException e) {
			log.info("错误信息:{}", e.getMessage());
		}

		return tmpStr;
	}

	/**
	 * @param byteArray
	 * @return java.lang.String
	 * @Description 将字节数组转换为十六进制字符串
	 */
	private static String byteToStr(byte[] byteArray) {
		StringBuilder strDigest = new StringBuilder();
		for (int i = 0; i < byteArray.length; i++) {
			strDigest.append(byteToHexStr(byteArray[i]));
		}
		return strDigest.toString();
	}

	/**
	 * @param mByte
	 * @return java.lang.String
	 * @Description 将字节转换为十六进制字符串
	 */
	private static String byteToHexStr(byte mByte) {
		char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
			'B', 'C', 'D', 'E', 'F'};
		char[] tempArr = new char[2];
		tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
		tempArr[1] = Digit[mByte & 0X0F];
		String s = new String(tempArr);
		return s;
	}
}

关注/取消关注事件
微信官方文档:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_event_pushes.html
用户在关注与取消关注公众号时,微信会把这个事件推送到开发者填写的URL。方便开发者给用户下发欢迎消息或者做账号的解绑。为保护用户数据隐私,开发者收到用户取消关注事件时需要删除该用户的所有信息。
微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次。
关于重试的消息排重,推荐使用FromUserName + CreateTime 排重。
假如服务器无法保证在五秒内处理并回复,可以直接回复空串,微信服务器不会对此作任何处理,并且不会发起重试。

	@PostMapping("/check-token")
	@ApiOperation(value = "关注公众号微信回调接口")
	public R<String> responseEvent(HttpServletRequest req, HttpServletResponse resp){
		return R.data(weChatService.responseEvent(req,resp));
	}
	public String responseEvent(HttpServletRequest req, HttpServletResponse resp) {
		String message = "";
		try {
			req.setCharacterEncoding("UTF-8");
			resp.setCharacterEncoding("UTF-8");

			Map<String, String> requestMap = WxMessageUtil.parseXml(req);
			log.info("解析====>{}", req);
			// 消息类型,event
			String messageType = requestMap.get("MsgType");
			// 事件类型,subscribe
			String eventType = requestMap.get("Event");
			// 发送方帐号(open_id)
			String openid = requestMap.get("FromUserName");
			// 开发者微信号
			String toUserName = requestMap.get("ToUserName");
			if ("event".equals(messageType)) {
				//判断消息类型是否是事件消息类型
				log.info("公众号====>事件消息");
				log.info("openid:{}, Event:", openid, eventType);
				if (eventType.equals("subscribe")) {
					message = "新用户关注公众号" + toUserName;
					log.info(message);
					// 具体业务
				} else if (eventType.equals("unsubscribe")) {
					message = "用户取消关注公众号" + toUserName;
					log.info(message);
					// 具体业务
				}
			}
		} catch (Exception e) {
			log.error(e.getMessage());
		}
		return message;
	}

微信有多种消息类型和事件类型,可以根据具体需求去监控不同的消息事件。
WxMessageUtil工具类

public class WxMessageUtil {
	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();
		return map;
	}
}
  • 9
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Java实现微信公众号关注登录可以通过调用微信开放平台的接口来实现。首先,需要在微信开放平台注册一个开发者账号,并创建一个应用。然后,使用Java开发框架可以通过发送HTTP请求来调用微信开放平台的接口。 在用户登录微信公众号时,首先需要引导用户点击关注按钮,跳转至微信登录授权页面。用户在页面中输入微信账号和密码,进行登录确认。然后根据微信开放平台提供的接口,获取用户的基本信息。Java中可以使用HttpClient或OkHttp等库来发送HTTP请求,获取用户登录的授权凭证access_token。 接下来,通过获取到的access_token,可以调用微信开放平台的接口来获取用户的详细信息,如用户名、头像等。具体调用的接口可以根据微信开放平台的文档进行选择和调用。 最后,将获取到的用户信息保存到数据库中,以便后续使用。在用户再次登录时,可以根据用户微信账号来查询数据库中是否已存在该用户的信息,若存在则进行登录操作,若不存在则要求用户重新关注并进行登录授权。 总体来说,Java实现微信公众号关注登录需要通过调用微信开放平台的接口来获取用户的授权凭证和详细信息,并将信息保存至数据库。在用户登录时,需要检查用户是否已关注并进行相应的登陆授权操作。这样,就可以实现Java微信公众号关注登录的功能。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值