微信公众号接收消息密文解密及明文加密后自动回复

1.使用token验证后的地址接收消息

/**
	 * 将微信公众号接收信息(参数微信会携带过来)
	 * @params timestamp 时间戳
	 * @params nonce 随机串
	 * @params  msg_signature 消息签名
	 * @params  requestBody 消息体
	 * @return
	 * @throws Exception
	 */
	@PostMapping(value = "/msg")
	public String msg( @RequestBody String requestBody,
					   @RequestParam(name = "timestamp",required = false) String timestamp,
					   @RequestParam(name = "nonce", required = false) String nonce,
					   @RequestParam(name = "msg_signature", required = false) String msg_signature
	) {
		System.out.print(requestBody+"\n");
		System.out.print(timestamp+"\n");
		System.out.print(nonce+"\n");
		System.out.print(msg_signature+"\n");
		JSONObject jsonObject = new JSONObject();
		jsonObject.put("requestBody", requestBody);
		jsonObject.put("token", token);
		jsonObject.put("nonce",nonce);
		jsonObject.put("timestamp", timestamp);
		jsonObject.put("msg_signature", msg_signature);
		jsonObject.put("appId",appid);
		jsonObject.put("encodingAesKey", encodingAESKey);
		String sendUrl = "http://localhost:8080/wechat/myboot/msgDecrypt";
		String result=HttpConnection.doPost(sendUrl,jsonObject.toJSONString());
		System.out.print("明文:"+result);
		String toUserName = result.substring(result.indexOf("<xml><ToUserName><![CDATA[") + "<xml><ToUserName><![CDATA[".length(), result.indexOf("]]></ToUserName>"));
		String msgType = result.substring(result.indexOf("<MsgType><![CDATA[") +"<MsgType><![CDATA[".length(), result.indexOf("]]></MsgType>"));
		String fromUserName = result.substring(result.indexOf("<FromUserName><![CDATA[") + "<FromUserName><![CDATA[".length(), result.indexOf("]]></FromUserName>"));
		String resultStr="";
		String replay = "";
        //自己包装返回xml信息
        replay=WeChatXMLUtils.textXML(fromUserName,toUserName,new Date().getTime()+"","您好!手机号绑定成功。");
        //加密后返回加密的xml
        resultStr=send( replay, token, nonce, timestamp, appid, encodingAESKey);
		return resultStr;
	}
public static String send(String replay,String token,String nonce,String timestamp,String appid,String encodingAESKey){
		System.out.print(replay+"\n");
		String encryptUrl = "http://localhost:8080/wechat/myboot/msgEncrypt";
		JSONObject jsonObject1 = new JSONObject();
		jsonObject1.put("requestBody", replay);
		jsonObject1.put("token", token);
		jsonObject1.put("nonce",nonce);
		jsonObject1.put("timestamp", timestamp);
		jsonObject1.put("appId",appid);
		jsonObject1.put("encodingAesKey", encodingAESKey);
		String miwenResult=HttpConnection.doPost(encryptUrl,jsonObject1.toJSONString());
		System.out.print(miwenResult);
		return miwenResult;
	}
public class WeChatXMLUtils {

    public static String textXML(String toUser,String fromUser,String time,String content){
        String format ="<xml><ToUserName><![CDATA[%1$s]]></ToUserName><FromUserName><![CDATA[%2$s]]></FromUserName><CreateTime>%3$s</CreateTime><MsgType><![CDATA[text]]></MsgType><Content><![CDATA[%4$s]]></Content></xml>";

        return String.format(format, toUser, fromUser, time, content);
    }
}

 

 

2.地址:http://localhost:8080/wechat/myboot/msgDecrypt 为另一个专门微信项目的解密接口,token为验证token时写的token

 /**
     * 解密
     * @param requestBody   发送的请求本体
     * @return              消息体解密后的字符串
     * @throws Exception
     */
    @PostMapping(produces = "text/plain;charset=utf-8",value = "/msgDecrypt")
    public static String msgDecrypt(@RequestBody String requestBody) throws Exception{
        JSONObject  obj = JSONObject.parseObject(requestBody);
        String token=obj.get("token").toString();
        String replyMsg=obj.get("requestBody").toString();
        String timestamp=obj.get("timestamp").toString();
        String nonce=obj.get("nonce").toString();
        String appId=obj.get("appId").toString();
        String msgSignature=obj.get("msg_signature").toString();
        String encodingAesKey=obj.get("encodingAesKey").toString();
        WXBizMsgCrypt pc = new WXBizMsgCrypt(token, encodingAesKey, appId);
        String str=pc.decryptMsg(msgSignature, timestamp, nonce, replyMsg);
        return str;
    }

    /**
     * 加密
     * @param requestBody   加密的请求体
     * @return
     * @throws Exception
     */
    @PostMapping(produces = "text/plain;charset=utf-8",value = "/msgEncrypt")
    public static String msgEncrypt(
            @RequestBody String requestBody
    ) throws Exception{
        JSONObject  obj = JSONObject.parseObject(requestBody);
        String token=obj.get("token").toString();
        String replyMsg=obj.get("requestBody").toString();
        String timestamp=obj.get("timestamp").toString();
        String nonce=obj.get("nonce").toString();
        String appId=obj.get("appId").toString();
        String encodingAesKey=obj.get("encodingAesKey").toString();
        //创建初始化微信加解密对象
        WXBizMsgCrypt pc = new WXBizMsgCrypt(token, encodingAesKey, appId);
        //生成加密字符串
        String miwen = pc.encryptMsg(replyMsg, timestamp, nonce);
        System.out.println("加密后: " + miwen);
        return miwen;
    }

3.解密方法为微信官方的方法

官方地址:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1434696670

 

 

### 微信公众号安全模式下Java实现消息加密解密方法 #### 创建消息类 为了更好地管理和传递消息参数,在`com.caisin.weixin.domain`包内定义了一个名为`Message`的数据传输对象DTO,该对象包含了签名验证所需的基本字段如signature, timestamp, nonce等,并且还加入了特定于加密场景下的属性msg_signature与encrypt_type来支持后续的操作[^1]。 ```java package com.caisin.weixin.domain; import lombok.Data; @Data public class Message { private String signature; private String timestamp; private String nonce; private String openid; private String msg_signature; private String encrypt_type; } ``` #### 处理接收到的消息并进行解密操作 当服务器接收到来自微信服务器推送过来的消息时,会先经过一系列的安全校验流程确认求合法性之后再着手处理实际业务逻辑。对于开启了安全模式的情况而言,则需要额外完成对消息体本身的解码工作以便获取真实的内容数据[^2]。 ```java // 假设已经完成了必要的初始化设置并且得到了待解析的XML字符串形式的消息文本 String encryptedXmlContent = ... ; // 来源于HTTP POST Body中的原始xml格式报文体 WXBizMsgCrypt pc = new WXBizMsgCrypt(token, encodingAesKey, appId); try{ // 调用DecryptMsg接口传入相应的参数执行具体的解密动作得到明文版本的信息结构化表示 String decryptResult = pc.DecryptMsg(msgSignature, timeStamp, nonce, encryptedXmlContent); }catch(AESException e){ log.error("Failed to decrypt message",e); } // 将解密后的结果转换成易于理解的日志输出供调试查看用途 log.info("\n消息解密后内容为:\n[{}] ",decryptResult); ``` #### 发送响应前实施加密保护措施 针对某些敏感性的交互场合或是出于整体架构设计上的考量,可能还会涉及到主动向客户端发送信息之前也需要对其进行相应程度上的编码转换过程以保障通信链路两端间交换资料时不被窃听篡改等问题发生。此时可以利用官方提供的工具类来进行此部分工作的封装简化[^3]。 ```java // 准备好要发出的文字表述型态的通知讯息实体实例 TextResponse textResp = TextResponse.builder().content("这是测试回复").build(); String plainTextReply = XmlUtils.toXml(textResp); // 使用相同的三元组作为输入条件调用EncryptMsg函数获得最终对外呈现形态的结果串 String cipheredResponse; try{ cipheredResponse = pc.EncryptMsg(plainTextReply,timeStamp,nonce); } catch (AESException ex) { throw new RuntimeException(ex.getMessage(),ex); } // 设置HttpResponseEntity主体载荷部分携带上述加工完毕的数据返回给对方 HttpServletResponse response.getWriter().write(cipheredResponse); ``` #### 验证接入有效性 最后值得注意的是,在初次配置完成后应当按照指引文档里提到的方式去尝试触发一次简单的握手测试——即通过GET方式访问指定URL地址的同时附加几个固定的查询参数让远端服务能够据此判断本地部署的服务程序是否正常在线可用;一旦匹配成功则应回显由微信公众平台随机生成的一段字符echostr证明一切就绪等待进一步指令下达[^4]。 ```java if ("GET".equalsIgnoreCase(request.getMethod())) { try { boolean result = wxCheck.checkSignature(signature,timestamp,nonce,token); if(result && StringUtils.isNotBlank(echoStr)){ PrintWriter out = resp.getWriter(); out.print(echoStr); out.flush(); out.close(); } }catch(Exception e){ logger.error("Error during check signature.",e); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值