首页 > 编程语言 >Java对接企业微信审批回调

Java对接企业微信审批回调

时间:2024-09-24 16:23:22浏览次数:7  
标签:Java String request 微信 对接 System token println out

一、需求说明

用Java程序对接企业微信的审批流程,获取审批数据数据,例如:报销费用金额

二、操作步骤

2.1、分析需求

根据需求分析其实也不知道该怎么去做对接,通过不断试错,发现不需要对接第三方应用,也就是不需要进入服务商后台页面,只需要在自建应用是做好配置即可。

具体参考:https://developer.work.weixin.qq.com/document/path/90665

2.2、搭建 自建应用

前言

这里先介绍一下关键参数从哪里取,具体详见官方文档:https://developer.work.weixin.qq.com/document/path/90665#corpid

corpid,每个企业都拥有唯一的corpid,获取此信息可在管理后台“我的企业”-“企业信息”下查看“企业ID”(需要有管理员权限)

 

Token、EncodingAESKey:是在自建应用-API接受消息中随机获取的到时候进行保存即可,具体见下图

 

secret

secret是企业应用里面用于保障数据安全的“钥匙”,每一个应用都有一个独立的访问密钥,为了保证数据的安全,secret务必不能泄漏。secret查看方法:
在管理后台->“应用管理”->“应用”->“自建”,点进某个应用,即可看到。

 

2.2.1、创建 自建应用

 

注: 选择可见范围根据业务需求进行选择,如果是针对全公司的业务,则需要选全公司,不然会获取不到数据进行报错

2.2.3、配置接收消息即回调地址

 

 其中回调URL的配置需要写对应的回调方法,具体可以参考:Demo(https://developer.work.weixin.qq.com/devtool/introduce?id=10128),这里建议使用XML格式,因为获取审批流程中的参数都是XML格式。具体见下图:

 

   // 这个方法是进行回调验证的。下面还有一个同样的方法差别仅是将GET换为POST方法,用于接收信息的。
  @RequestMapping(value = "/callback/data",method = RequestMethod.GET) public void connect(HttpServletRequest request, HttpServletResponse response){ //当你提交以上信息时,企业号将发送GET请求到填写的URL上,GET请求携带四个参数,企业在获取时需要做urldecode处理,否则会验证不成功 // 微信加密签名 String msg_signature = request.getParameter("msg_signature"); // 时间戳 String timestamp = request.getParameter("timestamp"); // 随机数 String nonce = request.getParameter("nonce"); // 随机字符串 String echoStr = request.getParameter("echostr"); //回调key值 String sEchoStr = null; String contacts_token = PropertiesUtil.getProperty("contacts_token"); String contacts_encodingaeskey = PropertiesUtil.getProperty("contacts_encodingaeskey"); String corpId = PropertiesUtil.getProperty("corpid"); try { PrintWriter out = response.getWriter(); WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(contacts_token,contacts_encodingaeskey,corpId); sEchoStr = wxcpt.VerifyURL(msg_signature,timestamp,nonce,echoStr); if(StringUtils.isBlank(sEchoStr)){ logger.error("URL验证失败"); } out.write(sEchoStr); out.flush(); }catch (Exception e){ logger.error("企业微信回调url验证错误",e); } }

  

2.2.4、配置IP白名单

多个IP用英文分号进行区分

 

2.2.5、在审批应用中配置回调通知

 

 

2.2.6、写程序获取审批流程数据

走完前面流程后,再部署上下面的代码后,就可以了。当有要监控回调的审批数据后,就会调用下面的方法,拿到审批数据。

具体里面会用到三个知识点。

1、会用到官方接口文档中:开发指南-回调配置-3.2 支持Http Post请求接收业务数据,详见:https://developer.work.weixin.qq.com/document/path/90930#32-%E6%94%AF%E6%8C%81http-post%E8%AF%B7%E6%B1%82%E6%8E%A5%E6%94%B6%E4%B8%9A%E5%8A%A1%E6%95%B0%E6%8D%AE

2、会用到官方接口文档中:开发指南-获取access_token,详见:https://developer.work.weixin.qq.com/document/path/91039

3、会用到官方接口文档中:审批-获取审批申请详情,详见:https://developer.work.weixin.qq.com/document/path/91983

    @RequestMapping(value = "/callback/data",method = RequestMethod.POST)
    public void acceptMessage(HttpServletRequest request, RedirectAttributes attributes, HttpSession session){
    	System.out.println("————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————");
        logger.debug("企业微信信息交互");
 
        // 微信加密签名
        String sMsgSignature = request.getParameter("msg_signature");
        // 时间戳
        String sTimestamp = request.getParameter("timestamp");
        // 随机数
        String sNonce = request.getParameter("nonce");
		System.out.println("acceptMessage方法sMsgSignature: " + sMsgSignature);
		System.out.println("acceptMessage方法sTimestamp: " + sTimestamp);
		System.out.println("acceptMessage方法sNonce: " + sNonce);

        try{
        	// 获取请求的输入流
	        ServletInputStream inputStream = request.getInputStream();
	         
	        // 创建一个 StringBuilder 对象来存储请求内容
	        StringBuilder xmlContent = new StringBuilder();
	         
	        // 使用 BufferedReader 读取输入流内容
	        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
	        String line;
	        while ((line = reader.readLine()) != null) {
	            xmlContent.append(line);
	        }
	         
	        // 关闭输入流和读取器
	        inputStream.close();
	        reader.close();
	       
	        // 输出请求内容
	        System.out.println("请求 XML 内容:" + xmlContent.toString());
	        String sReqData = xmlContent.toString();
//	        String sReqData = "<xml><ToUserName><![CDATA[wx5823bf96d3bd56c7]]></ToUserName><Encrypt><![CDATA[RypEvHKD8QQKFhvQ6QleEB4J58tiPdvo+rtK1I9qca6aM/wvqnLSV5zEPeusUiX5L5X/0lWfrf0QADHHhGd3QczcdCUpj911L3vg3W/sYYvuJTs3TUUkSUXxaccAS0qhxchrRYt66wiSpGLYL42aM6A8dTT+6k4aSknmPj48kzJs8qLjvd4Xgpue06DOdnLxAUHzM6+kDZ+HMZfJYuR+LtwGc2hgf5gsijff0ekUNXZiqATP7PF5mZxZ3Izoun1s4zG4LUMnvw2r+KqCKIw+3IQH03v+BCA9nMELNqbSf6tiWSrXJB3LAVGUcallcrw8V2t9EL4EhzJWrQUax5wLVMNS0+rUPA3k22Ncx4XXZS9o0MBH27Bo6BpNelZpS+/uh9KsNlY6bHCmJU9p8g7m3fVKn28H3KDYA5Pl/T8Z1ptDAVe0lXdQ2YoyyH2uyPIGHBZZIs2pDBS8R07+qN+E7Q==]]></Encrypt><AgentID><![CDATA[218]]></AgentID></xml>";
	        if(!sReqData.contains("wwc892952bc0c83b95")){
	        	//不是该应用
				System.out.println("错误提交应用数据");
	            System.out.println("————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————");
	        }else{
	        	
				String contacts_token = "xxx";
				String corpId = "xxxx";
				String contacts_encodingaeskey = "xxxx";
		 
				WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(contacts_token,contacts_encodingaeskey,corpId);
				String sMsg = wxcpt.DecryptMsg(sMsgSignature, sTimestamp, sNonce, sReqData);
				System.out.println("after decrypt msg: " + sMsg);
				
				// TODO: 解析出明文xml标签的内容进行处理
				// For example:
				DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
				DocumentBuilder db = dbf.newDocumentBuilder();
				StringReader sr = new StringReader(sMsg);
				InputSource is = new InputSource(sr);
				Document document = db.parse(is);

				Element root = document.getDocumentElement();
				NodeList nodelist1 = root.getElementsByTagName("SpNo");
				// 获取审批编号
				String SpNo = nodelist1.item(0).getTextContent();
				System.out.println("审批编号为:" + SpNo);
				NodeList SpStatus_Node = root.getElementsByTagName("SpStatus");
				// 申请单状态:1-审批中;2-已通过;3-已驳回;4-已撤销;6-通过后撤销;7-已删除;10-已支付
				String SpStatus = SpStatus_Node.item(0).getTextContent();
				if("2".equals(SpStatus)){
					// 当状态为2-已通过时进行存储
					//先判断该审批编号是否已存
					
					//获取accesstoken
					String accessUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
					String corpid = "xxxxx";
					String corpsecret = "xxxx";
					accessUrl=accessUrl+"?corpid="+corpid+"&corpsecret="+corpsecret;
		            System.out.println("请求access_token请求参数:"+accessUrl);
					String result = HttpUtil.get(accessUrl);
					JSONObject resultJson = JSON.parseObject(result);
		            System.out.println("请求access_token返回结果:"+resultJson);
		            String access_token = resultJson.getString("access_token");
		            
		            
		            String getapprovalUrl = "https://qyapi.weixin.qq.com/cgi-bin/oa/getapprovaldetail?access_token="+access_token;
		            JSONObject params = new JSONObject();
		            params.put("sp_no", SpNo);
		            System.out.println("请求获取审批详情接口请求参数:"+params);
		    		String post_result = HttpUtil.post(getapprovalUrl, params.toJSONString());
					JSONObject postJson = JSON.parseObject(post_result);
		            System.out.println("请求获取审批详情接口返回结果:"+postJson);
		            System.out.println("————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————");
		                     
					
				}
						
	        }
        }catch (Exception e){
            logger.error("企业微信消息交互错误",e);
        }
    }

  

三、总结

个人感觉企微的开发文档写的特别垃圾,绕来绕去的很不清晰。希望自己整理后后面再看的时候有些帮助。

标签:Java,String,request,微信,对接,System,token,println,out
From: https://www.cnblogs.com/Lonnn/p/18429282

相关文章

  • 提升前端性能的JavaScript技巧
    背景最近在开发一个全新的Web应用时,我遭遇了一个让人抓狂的问题:页面的加载速度实在是太慢了,用户点击按钮后需要等上几秒才会有反应。作为一个对用户体验有着极高要求的开发者,我怎么能忍受这种情况?于是,我决心彻底优化应用的性能。经过一番钻研和实践,我总结出了一些提升前端性能的Jav......
  • Vitepress 文档加微信网页授权登录功能
    目录前言​准备事项​实现步骤​1.建Vitepress文档项目​2.公众号配置网页授权域名​3.授权服务端开发​4.开发Vitepress登录组件​功能预览​前言​一般情况下使用Vitepress 写在线文档是用不上登录功能。如果想要实现权限控制、付费阅读等功能,不加个登录......
  • 01.Java基础语法
    1.注释1.1单行注释//单行注释1.2多行注释/*多行注释:可以注释一段文字*/1.3JavaDoc:文档注释/***文档注释*/2.标识符Java所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符。2.1标识符注意点所有标识符都应该以字母、$、_开始首字母之后可以是......
  • java中的工具类并创建工具方法文档
    编写一个方法,例如在一个有序数组里查找所需要的数字的下标publicstaticvoidsubscript(int[]a){Scannersc=newScanner(System.in);System.out.println("输入要查找的数:");intb=sc.nextInt();intx=a[a.length......
  • 适合初学者的[JAVA]:Mysql(3:Mysql事务)
    目录说明前言事务ACID:并发事务的问题:解决方案:uddolog和redolog的区别:先了解数据库的页概念:redolog:undolog:区别:mvcc:说明本文适合刚刚学习Java的初学者,也可以当成阿岩~的随手笔记.接下来就请道友们和我一起来学习吧!如果本文有写的不对的地方,......
  • 教你如何在Java中操作Redis
    Redis的Java客户端Redis的Java客户端很多,常用的几种:Jedis:基于Java的Redis客户端,提供了Redis命令的全面支持。Lettuce:高性能的Java客户端库,用于与Redis数据库进行交互。它支持同步、异步和反应式编程模型,提供了丰富的API来操作Redis。Lettuce与Jedis并列成......
  • JavaScript数据类型转换 布尔类型转换
    布尔类型转换布尔类型只有两个值:true和false。任何直观上为空的都被转换为false,其他的转换为true。显示转换为布尔类型时,使用Boolean(Value)函数。布尔类型转换规则类型类型转换后0false“0”true“”或者‘’true“”或者‘’即空字符串falsenullfalseundefinedfalseNaNfal......
  • Java怎么把多个对象的list的数据合并
    环境idea,java8方法1.使用addAll()方法想简单地想要合并List,直接使用List的addAll()方法是最直接的方式。List<YourType>list1=newArrayList<>();List<YourType>list2=newArrayList<>();//假设list1和list2已经有了数据List<YourType>merged......
  • java浅拷贝BeanUtils.copyProperties引发的RPC异常
    背景近期参与了一个攻坚项目,前期因为其他流程原因,测试时间已经耽搁了好几天了,本以为已经解决了卡点,后续流程应该顺顺利利的,没想到人在地铁上,bug从咚咚来~没有任何修改的服务接口,抛出异常:java.lang.ClassCastException:java.util.HashMapcannotbecasttocn.xxx.xxx.xxx.xx......
  • 《深入解析 Java 中的 ThreadLocal》
    ThreadLocal1.概述ThreadLocal被称为线程局部变量,用于在线程中保存数据。由于在ThreadLocal中保存的数据仅属于当前线程,所以该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。ThreadLocal用于在同一个线程间,在不同的类和方法之间共享数据的的场景,也可以......