赞
踩
因为要注册测试账号,微信需要发送对应请求后,由我们返回特定信息
官网接入文档地址:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
public class Decript { public static String SHA1(String decript) { try { MessageDigest digest = MessageDigest .getInstance("SHA-1"); digest.update(decript.getBytes()); byte messageDigest[] = digest.digest(); // Create Hex String StringBuffer hexString = new StringBuffer(); // 字节数组转换为 十六进制 数 for (int i = 0; i < messageDigest.length; i++) { String shaHex = Integer.toHexString(messageDigest[i] & 0xFF); if (shaHex.length() < 2) { hexString.append(0); } hexString.append(shaHex); } return hexString.toString(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } return ""; } }
@Service public class WxSignatureCheckService { //token,此处token内容与网站上我们填写的token一致 private final String token = "wxtoken"; public String wxSignatureCheck(String signature, String timestamp, String nonce, String echostr) { ArrayList<String> array = new ArrayList<String>(); array.add(signature); array.add(timestamp); array.add(nonce); //排序 String sortString = sort(token, timestamp, nonce); //加密 String mytoken = Decript.SHA1(sortString); //校验签名 if (mytoken != null && mytoken != "" && mytoken.equals(signature)) { System.out.println("签名校验通过。"); return echostr; //如果检验成功输出echostr,微信服务器接收到此输出,才会确认检验完成。 } else { System.out.println("签名校验失败。"); return null; } } /** * 排序方法 * @param token * @param timestamp * @param nonce * @return */ public static String sort(String token, String timestamp, String nonce) { String[] strArray = { token, timestamp, nonce }; Arrays.sort(strArray); StringBuilder sbuilder = new StringBuilder(); for (String str : strArray) { sbuilder.append(str); } return sbuilder.toString(); } }
@RestController public class WxSignatureCheckController { @Autowired private WxSignatureCheckService wxSignatureCheckService; @RequestMapping("/wx")//此处的请求路径与网站上填写的一致 public String wxSignatureCheck( @RequestParam(value = "signature") String signature, @RequestParam(value = "timestamp") String timestamp, @RequestParam(value = "nonce") String nonce, @RequestParam(value = "echostr") String echostr ){ return wxSignatureCheckService.wxSignatureCheck(signature, timestamp, nonce, echostr); } }
注意:此处我使用了内网穿透服务【ngrok】
感兴趣的可以去网上下载然后开启即可,会自动分配给我们一个域名
地址:http://ngrok.cc/login.html
参考官方手册:https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html
微信测试账号发送消息是以POST方式发送XML数据
此处以文本信息为例:
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[this is a test]]></Content>
<MsgId>1234567890123456</MsgId>
<MsgDataId>xxxx</MsgDataId>
<Idx>xxxx</Idx>
</xml>
地址:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
因为微信是通过POST请求发送XML数据,所以此处采用dom4j解析XML
①引入dom4j依赖
<!--dom4j-->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.1</version>
</dependency>
②编写service解析XML
@Service public class WxService { /** * 解析通过dom4j解析XML数据 * @param is * @return map */ public Map<String, String> parseRequest(InputStream is){ Map<String, String> map = new HashMap<>(); SAXReader reader = new SAXReader(); try{ //读取输入流,获取文档对象 Document document = reader.read(is); //根据文档对象获取根节点 Element root = document.getRootElement(); //获取根节点的所有子节点 List<Element> elements = root.elements(); for(Element e : elements){ map.put(e.getName(), e.getStringValue()); } return map; }catch (Exception e){ e.printStackTrace(); } return null; } }
③编写controller接收消息
@RestController public class WxController { @Autowired private WxService wxService; @PostMapping("/wx") public void receiveMsg(HttpServletRequest request){ try { ServletInputStream is = request.getInputStream(); Map<String, String> result = wxService.parseRequest(is); System.out.println(result); } catch (IOException e) { e.printStackTrace(); } } }
结果如下:
语音、图片、位置信息等内容,参考官方文档解析即可。
https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html
<!--xstream构建返回的XML--> <dependency> <groupId>com.thoughtworks.xstream</groupId> <artifactId>xstream</artifactId> <version>1.4.14</version> </dependency> <!--dom4j解析XML数据--> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.1</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> </dependency>
①父类:
@Data @AllArgsConstructor @NoArgsConstructor public class BaseMessage { @XStreamAlias("ToUserName") private String toUserName; @XStreamAlias("FromUserName") private String fromUserName; @XStreamAlias("CreateTime") private String createTime; @XStreamAlias("MsgType") private String msgType; @XStreamAlias("MsgId") private String msgId; //初始化默认数据 public BaseMessage(Map<String, String> requestMap){ //开始是请求方,返回数据的时候,就成为了发送方 this.toUserName = requestMap.get("FromUserName"); this.fromUserName = requestMap.get("ToUserName"); //微信中的时间默认是10位数,java的currentTimeMillis是13位,因此要除以1000 this.createTime = System.currentTimeMillis() / 1000 + ""; this.msgId = requestMap.get("MsgId"); } }
②文本消息
@Data @AllArgsConstructor @NoArgsConstructor @XStreamAlias("xml") public class TextMessage extends BaseMessage{ //文本内容 @XStreamAlias("Content") private String content; public TextMessage(Map<String, String> requestMap, String content){ super(requestMap); //设置消息类型为文本 super.setMsgType("text"); //设置文本消息 this.content = content; } }
③图片消息
@Data @AllArgsConstructor @NoArgsConstructor @XStreamAlias("xml") public class PicMessage extends BaseMessage{ //图片链接 @XStreamAlias("PicUrl") private String picUrl; //图片消息 public PicMessage(Map<String, String> requestMap, String picUrl){ super(requestMap); this.setMsgType("image"); this.picUrl = picUrl; } }
@Service public class WxService { /** * 解析通过dom4j解析XML数据 * @param is * @return map */ public Map<String, String> parseRequest(InputStream is){ Map<String, String> map = new HashMap<>(); SAXReader reader = new SAXReader(); try{ //读取输入流,获取文档对象 Document document = reader.read(is); //根据文档对象获取根节点 Element root = document.getRootElement(); //获取根节点的所有子节点 List<Element> elements = root.elements(); for(Element e : elements){ map.put(e.getName(), e.getStringValue()); } return map; }catch (Exception e){ e.printStackTrace(); } return null; } /** * 返回的消息 * @param requestMap * @return */ public String getResponse(Map<String, String> requestMap){ String msgType = requestMap.get("MsgType"); //要返回的消息 BaseMessage rtnMsg = null; switch (msgType){ //根据消息类型,处理不同消息 case "text": rtnMsg = dealTextMessage(requestMap); case "image": //TODO break; case "voice": break; case "video": break; case "shortvideo": break; case "location": break; case "link": break; default: break; } return beanToXML(rtnMsg); } /** * 将消息对象处理为XML数据包 * @param msg * @return */ public String beanToXML(BaseMessage msg){ if(msg == null){ return ""; } //公众号返回信息 XStream stream = new XStream(); //设置需要处理XStreamAlias("xml")注解的类 stream.processAnnotations(TextMessage.class); stream.processAnnotations(PicMessage.class); String xml = stream.toXML(msg); return xml; } /** * 处理文本消息 * @param requestMap * @return */ public BaseMessage dealTextMessage(Map<String, String> requestMap){ String returnMsg = "收到消息!!!"; TextMessage tm = new TextMessage(requestMap, returnMsg); return tm; } }
@PostMapping("/wx") public void receiveMsg(HttpServletRequest request, HttpServletResponse response){ try { //设置编码,防止乱码 request.setCharacterEncoding("utf8"); response.setCharacterEncoding("utf8"); //获取请求信息 ServletInputStream is = request.getInputStream(); //处理消息和事件推送 Map<String, String> requestMap = wxService.parseRequest(is); System.out.println(requestMap); //准备回复的数据包 String respXML = wxService.getResponse(requestMap); System.out.println(respXML); PrintWriter out = response.getWriter(); out.print(respXML); out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } }
在测试号上发送消息:
控制台打印消息:
其他消息处理:类似,官方其他消息XML格式
https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_standard_messages.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。