一、需求说明
用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-已通过时进行存储//先判断该审批编号是否已存//获取accesstokenString 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);}}
三、总结
个人感觉企微的开发文档写的特别垃圾,绕来绕去的很不清晰。希望自己整理后后面再看的时候有些帮助。