1.概述


企业微信上是这样介绍的。不过经本人的研究测试,该工作流引擎的功能是比较有限的。
首先只有移动端才能发起,流程的定义是必须在企业微信控制台中定义,而且不支持条件分支,适用于比较简单的应用场景,请假之类的。而且审批界面数据展示自定义程度很低。

2.企业微信开发基础

文档链接:
https://work.weixin.qq.com/api/doc#90000/90135/90665
corpid
每个企业都拥有唯一的corpid,获取此信息可在管理后台“我的企业”-“企业信息”下查看“企业ID”(需要有管理员权限)
agentid
每个应用都有唯一的agentid。在管理后台->“应用与小程序”->“应用”,点进某个应用,即可看到agentid。
secret
secret是企业应用里面用于保障数据安全的“钥匙”,每一个应用都有一个独立的访问密钥,为了保证数据的安全,secret务必不能泄漏。
access_token
access_token是企业后台去企业微信的后台获取信息时的重要票据,由corpid和secret产生。所有接口在通信时都需要携带此信息用于验证接口的访问权限

3.审批流引擎开发

文档链接
https://work.weixin.qq.com/api/doc#90000/90135/90269

1.创建自建应用审批模板

2.前端调用页面

1.通过config接口注入权限验证配置。查看
2.通过agentConfig注入应用的权限。查看
3.调用审批流程引擎JS-API(如下文请求示例)。

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>菜鸟教程(runoob.com)</title><script src="js/jquery.min.js"></script><script src="http://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script><script>$(document).ready(function(){var link = window.location.href;$("button").click(function(){$.ajax({//请求方式type : "GET",//请求的媒体类型contentType: "application/json;charset=UTF-8",//请求地址url : "http://zdwtest.nat300.top/weichat-config/getSignature",//数据,json字符串data : {"url":link},//请求成功success : function(res) {// console.log(data);wx.config({beta: true,debug: true,appId: res.data.corpId,timestamp: res.data.timestamp,nonceStr: res.data.noncestr,signature: res.data.signature,jsApiList: ['agentConfig','openUserProfile','thirdPartyOpenPage','selectExternalContact']});wx.ready(function(){wx.agentConfig({corpid: res.data.corpId, // 必填,企业微信的corpid,必须与当前登录的企业一致agentid: res.data.agentId, // 必填,企业微信的应用idtimestamp: res.data.timestamp, // 必填,生成签名的时间戳nonceStr: res.data.noncestr, // 必填,生成签名的随机串signature: res.data.agentSignature,// 必填,签名,见附录1jsApiList: ['agentConfig','openUserProfile','thirdPartyOpenPage','selectExternalContact'], //必填success: function(res) {// 发起审批流程wx.invoke('thirdPartyOpenPage', {"oaType": "10001",// String"templateId": "e38e4df283a991b00e3394dc71fbef79_1837057289",// String"thirdNo": "t01",// 审批单号,开发者自己控制,不可重复"extData": {'fieldList': [{'title': '采购类型','type': 'text','value': '市场活动',},{'title': '采购类型','type': 'text','value': '市场活动',},{'title': '采购类型','type': 'text','value': '市场活动',},{'title': '采购类型','type': 'text','value': '市场活动',},{'title': '采购类型','type': 'text','value': '市场活动',}],}},function(res) {// 输出接口的回调信息console.log(res);});},fail: function(res) {if(res.errMsg.indexOf('function not exist') > -1){alert('版本过低请升级')}}});})}});});});</script>
</head><body>
<button>点我</button>
</body>
</html>

注意:调试前端页面必须用企业微信客户端,pc版均不支持。

3.获取签名的后台接口

@Api(value="企业微信相关信息获取",description = "企业微信相关信息获取")
@RequestMapping("/weichat-config")
@Controller
public class WeiChatConfigController {@AutowiredApprovalPrecessService approvalPrecessService;@ApiOperation(value = "获取前端登录时需要的签名信息",notes = "获取前端登录时需要的签名信息",httpMethod = "GET")@RequestMapping(value = "/getSignature",method = RequestMethod.GET)@ResponseBodypublic RestResult<WeixinConfigDTO> getTWeixinConfig(String url){WeixinConfigDTO tWeixinConfig = approvalPrecessService.getTweixinConfig(url);return new RestResult(tWeixinConfig);}
}
public class ApprovalProcessServiceImpl implements ApprovalPrecessService {
//    private static log log = log.getlog(ApprovalProcessServiceImpl.class);
//    private static PropertiesFileUtil propertiesFileUtil = new  PropertiesFileUtil();
//  @Autowired
//  TWeixinConfigMapper tWeixinConfigMapper;@Autowiredprivate WeichatService weichatService;@Overridepublic String getSignature(String jsTickt,String noncestr,String timestamp,String url) throws Exception {String str = "jsapi_ticket="+jsTickt+"&"+"noncestr="+noncestr+"&"+"timestamp="+timestamp+"&"+"url="+url;return DigestUtils.sha1Hex(str);}@Overridepublic WeixinConfigDTO getTweixinConfig(String url){WeixinConfigDTO weixinConfigDTO = new WeixinConfigDTO();try {String agentId = WeiChatConfigConstants.QIYEWEICHAT_AGENTID;String corpId = WeiChatConfigConstants.QIYEWEICHAT_CORPID;String secret = WeiChatConfigConstants.QIYEWEICHAT_CORPSECRET;String accessToken = weichatService.getWeiChatAccessTokern();//企业的jsTicktString jsTickt  = CallWxUtil.getJsTicket(accessToken);//应用的jsTicktString agentJsTickt = CallWxUtil.getAgentJsTicket(accessToken);String timestamp=String.valueOf(System.currentTimeMillis());String noncestr =getRandomString(16);String userUrl=url;String signature  = getSignature(jsTickt, noncestr, timestamp, userUrl);String agentSignature = getSignature(agentJsTickt, noncestr, timestamp, userUrl);weixinConfigDTO.setCorpId(corpId);weixinConfigDTO.setAgentId(agentId);weixinConfigDTO.setCorpSecret(secret);weixinConfigDTO.setSignature(signature);weixinConfigDTO.setAgentSignature(agentSignature);weixinConfigDTO.setNoncestr(noncestr);weixinConfigDTO.setJsapiTicket(jsTickt);weixinConfigDTO.setTimestamp(Long.valueOf(timestamp));weixinConfigDTO.setAccessToken(accessToken);}catch (Exception e){log.info(e.getMessage());log.info("获取签名异常!!");}return  weixinConfigDTO;}private static String getRandomString(int length){String keyString = "ergrfewfwdgggcvv;uihefujsncjdvngrjegeuirgverggvbergbvuigverug";int len = keyString.length();StringBuffer str = new StringBuffer();for(int i=0;i<length;i++){str.append(keyString.charAt((int) Math.round(Math.random() * (len - 1))));}return str.toString();}
}

获取jsticket 参考文档
https://work.weixin.qq.com/api/doc#10029/获取应用的jsapi_ticket

其中jsticket是签名的重要参数,和access_token一样具有时效性,建议缓存处理。

4.接受审批回调信息的接口

文档参考:https://work.weixin.qq.com/api/doc#90000/90135/90930
首先在控制台配置url为介绍审批回调信息的接口,然后随机生成token,encodingAESkey,建议生成后固定。

企业微信首先会对回调接口进行校验,成功之后便会推送回调信息。
这里GET 为检验接口,
1.对收到的请求,解析上述的各个参数值(参数值需要做Urldecode处理)
2.根据已有的token,结合第1步获取的参数timestamp, nonce, echostr重新计算签名,然后与参数msg_signature检查是否一致,确认调用者的合法性。计算方法参考:消息体签名检验
3.解密echostr参数得到消息内容(即msg字段)
4.在1秒内响应GET请求,响应内容为上一步得到的明文消息内容(不能加引号,不能带bom头,不能带换行符)
POST为推送接口
1.对msg_signature进行校验
2.解密Encrypt,得到明文的消息结构体(消息结构体后面章节会详说)
3.如果需要被动回复消息,构造被动响应包
4.正确响应本次请求
· 企业微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次
· 当接收成功后,http头部返回200表示接收ok,其他错误码企业微信后台会一律当做失败并发起重试

@Controller
@RequestMapping("/weichat-callBack")
public class WeiChatCallbackController {@Autowiredprivate WeiChatCallbackService weiChatCallbackService;//第一次get请求验证@GetMapping(value = "/callBack")@ResponseBodypublic String verifyURL(String msg_signature, String timestamp, String nonce, String echostr) {return weiChatCallbackService.verifyURL(msg_signature,timestamp,nonce,echostr);}//接受post请求消息推送@PostMapping("/callBack")@ResponseBodypublic void callBack(HttpServletRequest request, String msg_signature, String timestamp, String nonce)  {weiChatCallbackService.doCallBack(request, msg_signature, timestamp, nonce);}}
public class WeiChatCallbackServiceImpl implements WeiChatCallbackService {private WXBizMsgCrypt getWXBizMsgCrypt() throws AesException {String sToken = WeiChatConfigConstants.QIYEWEICHAT_MSGTOKEN;String sCorpID = WeiChatConfigConstants.QIYEWEICHAT_CORPID;String sEncodingAESKey = WeiChatConfigConstants.QIYEWEICHAT_ENCODINGAESKEY;return new WXBizMsgCrypt(sToken, sEncodingAESKey, sCorpID);}@Overridepublic String verifyURL(String msg_signature, String timestamp, String nonce, String echostr) {try {WXBizMsgCrypt wxcpt = getWXBizMsgCrypt();String sEchoStr; //需要返回的明文sEchoStr = wxcpt.VerifyURL(msg_signature, timestamp,nonce, echostr);return sEchoStr;} catch (Exception e) {//验证URL失败,错误原因请查看异常e.printStackTrace();log.error(e.getMessage());}return "无";}@Overridepublic void doCallBack(HttpServletRequest request, String msg_signature, String timestamp, String nonce) {// post请求的密文数据try {WXBizMsgCrypt wxcpt = getWXBizMsgCrypt();InputStream inputStream = request.getInputStream();String sPostData = IOUtils.toString(inputStream,"UTF-8");String sMsg = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, sPostData);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();//获取消息类型String msgType = getContentByTagName(root,"MsgType");System.out.println("MsgType:" + msgType);//处理文本信息if (WeiChatMsgTypeEnum.TEXT.getValueInFact().equals(msgType)){dealWeiChatTextMsg(root);//处理事件信息}else if (WeiChatMsgTypeEnum.EVENT.getValueInFact().equals(msgType)){dealWeiChatEventMsg(root);}} catch (Exception e) {// TODO// 解密失败,失败原因请查看异常e.printStackTrace();log.error(e.getMessage());}}private void dealWeiChatTextMsg(Element root) {String content = getContentByTagName(root,"Content");System.out.println("Content:" + content);content = getContentByTagName(root,"FromUserName");System.out.println("FromUserName:" + content);}private void dealWeiChatEventMsg(Element root) {String content = getContentByTagName(root,"OpenSpName");System.out.println("审批模板名称:" + content);content = getContentByTagName(root,"ApplyUserName");System.out.println("提交人姓名:" + content);content = getContentByTagName(root,"NodeStatus");System.out.println("节点审批状态:" + content);}private String getContentByTagName(Element root, String tagName){NodeList nodelist = root.getElementsByTagName(tagName);String Content = nodelist.item(0).getTextContent();return Content;}}

解密,签名的工具类可参考官方的demo
https://work.weixin.qq.com/api/doc#90000/90138/90307
下载java 版即可

4.效果测试

这里使用移动端app测试,必须让项目处于公网可信域名下。笔者是通过内网穿透到自己买的域名上,具体可以自己学习研究。
同时在工作台配置

在企业微信上打开前端页面


点击提交

后台回调到审批信息回传信息

企业微信开发实战:自建审批流引擎相关推荐

  1. 企业微信开发实战(五、自建应用-审批流程引擎之配置可信任域名、创建审批模版、发起审批)

    文章目录 四.自建应用-审批流程引擎 1.概述 2.创建自建应用审批模板 2.1创建自建审批应用 2.2配置可信任域名 2.3创建审批模版 3.自建应用发起审批 3.1概述 3.2代码实战 3.2.1 ...

  2. 企业微信开发实战(四、OA审批之企业假期管理配置、获取成员假期余额、修改成员假期余额)

    文章目录 7.获取企业假期管理配置 7.1概述 7.2代码实战 8.获取成员假期余额 8.1概述 8.2代码实战 8.3试错 9.修改成员假期余额 9.1概述 9.2代码实战 9.3试错 源码 赞赏 ...

  3. 企业微信开发(自建应用h5)

    1.企微后台(管理应用.设置应用可见人员范围等):企业微信 2. 企微开发者中心(API文档):简易教程 - 接口文档 - 企业微信开发者中心 3. oAuth2链接创建(静默授权和手动授权):开始开 ...

  4. 企业微信开发:自建应用配置可信域名(一)

    前言   企业微信自建应用配置网页授权可信任域名(需要管理员权限) 配置   打开应用管理 - 选择已经创建的应用,找到如图内容   配置网页授权及 JS-SDK,直接输入域名,然后点击申请校验域名, ...

  5. 企业微信开发实战(一、相关说明及注册企业微信)

    文章目录 一.写着前面 1.说明 2.环境 二.注册企业微信 源码 赞赏 一.写着前面 1.说明 1.官方文档地址:https://open.work.weixin.qq.com/api/doc/90 ...

  6. 企业微信开发——企业内部自建应用开发(第一篇)---环境搭建

    一.背景介绍 现在越来越多的企业开始注重私域流量的运营和建设,防止客户随着人员流动而流失,所以就出现了基于企业微信开发的需求,但是目前关于企业微信开发的生态环境依旧不太丰富,腾讯的api文档写的也是晦 ...

  7. 服务器端缓存企业微信,企业微信开发

    企业微信开发又以下三类,可以根据需要查看相应的文档 企业内部应用开发:开发内部使用应用,开发个性化办公应用 第三方应用开发:开发出来的应用可供其他企业使用 第三方应用开发.png 智慧硬件开发 企业内 ...

  8. 企业微信开发第三方应用开发视频教程,ToB Dev李月喜全网首发

    csdn程序员学院<企业微信三方应用开发>视频课程,全网企业微信三方应用开发教程首发, https://edu.csdn.net/course/detail/30582  即将完结欢迎试看 ...

  9. Spring 3.x企业应用开发实战

    Java技术大系 Spring 3.x企业应用开发实战 陈雄华    林开雄      著 Publishing House ofElectronics Industry 北京·  BEIJING 内 ...

  10. 23 20210525+0529直播 企业微信接口测试实战1+2

    文章目录 企业微信接口测试实战1 RESTFUL 规范 实战内容 接口测试基础 restful 架构 接口测试流程 接口自动化脚本编写 项目流程 需求分析 需求理解 接口业务关系 接口测试用例编写思路 ...

最新文章

  1. C++类的定义和声明
  2. 牛客网(剑指offer) 第十五题 反转链表
  3. SharePoint2010 连接配置数据库字符串保存位置(转)
  4. 初学者学python,列表推导到zip()函数,必须会的五种技巧
  5. springbatch导出mysql数据到外部文件
  6. A-Webkit第四章:添加学生
  7. 代码平台Github半年发布125项更新,私库无限免费开启(附步骤)
  8. mysql 命令行关闭fuw_网络管理 - eSight V300R009C00 维护指南 12 - 华为
  9. 解决方案 | 解决Adobe Acrobat 2020安装报错的一些问题,如无法打开键
  10. Windows 10 (64位)下 VMware 15虚拟机下载及安装教程(内附安装包)
  11. Ubuntu mate自启脚本/命令+关闭图形桌面
  12. 多点移动电子地图定位
  13. ubuntu下重装WIN7
  14. 江苏省计算机高考试题,08-12江苏省单招计算机原理高考试题汇总
  15. Python中rect属性
  16. 【汽车配件管理系统-管理员-配件管理模块】配件管理分类
  17. METIS安装与使用
  18. 目标检测训练数据扩充增强工具使用说明
  19. 工作生活可能用得到的资源
  20. 网络层(2.网际协议IP)

热门文章

  1. 单片机简易计算机设计实物,单片机设计的带余数的简易计算器
  2. 遥感式雷达监测水位流速设备
  3. dell服务器开机蓝屏无限重启,戴尔电脑不停蓝屏重启怎么办
  4. 教你如何将 Excel 中的数据按模板批量生成 Word、Excel、PPT、PDF 以及 Txt 类型的文本文件
  5. 关于DiskGenius 克隆分区和系统迁移问题,以及如何解决缺少系统引导、双硬盘双系统引导问题,多个启动项
  6. xmapp老是端口占用
  7. 寻路大数据:海量数据与大规模分析
  8. PS制作简洁漂亮的立体抽丝文字
  9. 汉印扫描器设置软件_汉印HPRTK180打印机驱动
  10. 牛头刨床设计matlab生成图片,牛头刨床matlab程序---机械原理课程设计