企业微信和信息门户的融合管理连接轻量级工作流引擎之三

Posted 闲人慢语

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了企业微信和信息门户的融合管理连接轻量级工作流引擎之三相关的知识,希望对你有一定的参考价值。

0 前言

在开始下笔撰写系列文章之前,我已经从事代码学习八年时间,走过一些弯路,但更多的是收获和感悟,然而一直没有诉诸文字的冲动。若非领导约稿,无论如何是不可能开始写作的,文字的表达能力固然强大,但从笔端流出的方块字,受限于知识见闻,难免露怯。苏东坡38岁时写下的句子,老夫聊发少年狂,似乎冥冥中勉励着我,或者说让我追逐回忆少不更事的心境。反观当下情形,不由得叹服那句有名的鸡汤——人生,再不疯狂,我们就老了!我想说,人生渐老,无需疯狂,打开自己就好。

 

图片源自百度百科《江城子·密州出猎》词条

回到正题,前两篇文章就企业微信审批的数据备份、接口调用和表单模拟等方面阐述,初步实现从外部环境调用企业微信审批引擎,这篇文章争取解决剩余问题。

1 优化手机号采集方式

上篇文章里面,在设计预审批表单时,对手机号字段简单套用文本字段,并未作正则表达式或短信验证码的校验。其实有些无奈,企业微信审批控件暂时做不到这种精细化操作,我们在通用页面就很难让程序识别,比如说这是普通文本字段无需校验,那是手机号字段需要校验。姑且依赖第一审批人人肉鉴别吧,同时期待企业微信对于特殊字段如手机号、邮箱账号等加以区分。但是考虑到我们做的是通用型页面,有些审批模板不一定采集发起人的手机号,那就需要在通用页面固化一个手机号控件,结合短信验证码校验。 

企业微信和信息门户的融合管理(5)连接轻量级工作流引擎之三

企业微信和信息门户的融合管理(5)连接轻量级工作流引擎之三

或者你说把页面写到小程序里面也成,经用户授权确能获取其手机号,就看你如何权衡和选择。

短信API服务我们采用苏州当地公司的产品,几年前选型时考虑套餐有效期限的因素,规避其他不符合要求的产品,选择了这款有效期限无限制的产品。

说到验证码,个人理解有很多应用场景,使用短信验证码验证手机最常见。无非就是通过统一服务下发验证码数据,接收方式可以是手机短信、邮件、企业微信消息、微信服务号消息等,应用程序根据用户录入的验证码和附带的参数,向统一服务提交校验验证码的请求,如验证通过则放行业务。

 企业微信和信息门户的融合管理(5)连接轻量级工作流引擎之三

2 预审批结果如何告知发起人

接上文,统一服务端按照平台分类,采用不同的推送方式,这里要注意,微信开放平台扫码登录从而发起审批申请的用户(新教师或临时人员),我们对他推送消息,最方便的是借助开放平台体系下对接的微信服务号。经由扫码登录后端程序拿到用户基于微信开放平台的unionID,这个编码是平台内全局唯一的,以此为请求参数,尝试获取用户基于微信服务号的openid,如成功则调用后者的模板消息接口,实现消息推送。

然而笔者认为这种方式有不确定性,强制要求用户关注这种行为于我们而言不够硬气,因此在本文实例中笔者就只是采用了微信服务号的静默授权,即便没关注依然能拿到基于微信开放平台的unionID。消息推送的手段仍首选手机短信,可以在短信里面说明,想要了解更详细的流程进展情况,请关注某某微信服务号,如何如何操作——于润物细无声中增加服务号的用户粘度。

企业微信和信息门户的融合管理(5)连接轻量级工作流引擎之三

预审批人如驳回申请,后台程序调用短信API接口将驳回的情况推送给申请人,包含审批意见、重新提交申请的链接和微信服务号的使用建议。 

企业微信和信息门户的融合管理(5)连接轻量级工作流引擎之三

申请人点击短信中的超链接,手机系统默认以浏览器打开,此时默认进入微信开放平台扫码方式,再用手机微信扫码就不方便了,因此用户最好把超链接拷贝到微信界面并打开,那样能调用微信服务号的网页授权。

3企业微信审批事件订阅

3.1 配置接收消息服务器

我们在Wechat区域的Work控制器创建分别实现GetPost请求方式的方法,Get方法用于响应企业微信发送的验证请求,而Post方法则用于接收企业微信发送的消息和事件。

Get方式,学校后台服务器收到请求后,需要做如下操作:1)对收到的请求做Urldecode处理;2)通过参数msg_signature对请求进行校验,确认调用者的合法性;3)解密echostr参数得到消息内容;4)在1秒内响应GET请求,响应内容为上一步得到的明文消息内容。以上23步骤可以直接使用第三方开源程序包实现,比如盛派Senparc.Weixin.Work开源程序包的Signature.VerifyURL方法。

[HttpGet][ActionName("Index")]public ActionResult Get(string msg_signature, string timestamp, string nonce, string echostr){ string token = WorkApi.WeixinCorpApprovalToken; string encodingAESKey = WorkApi.WeixinCorpApprovalEncodingAESKey; string corpId = WorkApi.WeixinCorpId; var replyEchoStr = Signature.VerifyURL(token, encodingAESKey, corpId, msg_signature, timestamp, nonce, echostr); return Content(replyEchoStr);}

Post方式,学校后台服务器收到消息后,需要作如下处理:1)对msg_signature进行校验;2)解密Encrypt,得到明文的消息结构体;3)如果需要被动回复消息,构造被动响应包;4)正确响应本次请求。以上12步骤可以直接使用第三方开源程序包实现,比如盛派Senparc.Weixin.Work.Tencent开源程序包的WXBizMsgCrypt.DecryptMsg方法。3步骤包含加密被动回复消息、生成新签名、构造被动响应包三个步骤,使用WXBizMsgCrypt.EncryptMsg方法一步到位。如果后端程序无法实现34步骤,企业微信服务器每次都要重复发送三条相同的事件消息,造成不必要的服务器资源和网络开销。

[HttpPost][ActionName("Index")]public ActionResult Post(string msg_signature, string timestamp, string nonce){ string token = WorkApi.WeixinCorpApprovalToken; string encodingAESKey = WorkApi.WeixinCorpApprovalEncodingAESKey; string corpId = WorkApi.WeixinCorpId; WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token, encodingAESKey, corpId); string postString, sMsg = ""; using (Stream stream = Request.InputStream) { byte[] postBytes = new byte[stream.Length]; stream.Read(postBytes, 0, (int)stream.Length); postString = Encoding.UTF8.GetString(postBytes); int flag = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, postString, ref sMsg); if (flag == 0) { string sTimeStamp = DateTime.Now.ToUnixTime().ToString(); string sReplyMsg = sTimeStamp; nonce = RandomHelper.GetInteger(); string sEncryptMsg = ""; wxcpt.EncryptMsg(sReplyMsg, timestamp, nonce, ref sEncryptMsg); try { var aei = WorkApi.Basic.Event.GetApprovalEventInfo(sMsg);//将获取到的XML字符串转换成审批状态变化事件实体类 Log.Write(aei);//写到服务器硬盘,用于调试。 new ApprovalEventController().Save(aei);//将审批事件数据写到数据库 } catch (Exception ex) { Log.Write(ex); } return Content(sEncryptMsg);//响应企业微信服务器 } else { Log.Write("解密消息失败!"); } } return View();}

当然,企业微信官方网站提供了以上三个函数的源代码,但是总感觉不如在NuGet下载第三方包库来得方便。

3.2 将事件数据转成审批状态变化事件实体类数据

第一步比较简单,就是个体力活,按照事件格式参数说明,编写这几个类:ApprovalEventInfo(审批事件信息)、ApprovalInfo(审批信息)、ApprovalApplyer(申请人信息)、ApprovalSpRecord(审批流程信息)、ApprovalSpRecordDetail(审批节点详情)、ApprovalNotifyer(抄送信息)、ApprovalComment(备注信息)等实体类。

第二步使用XmlHelper将XML字符串转换成ApprovalEventInfo审批事件信息实体类,代码比较简单,就是百度出来几十条都是一模一样的那种。但是,报错!

using (StringReader sr = new StringReader(strXML)){ XmlSerializer serializer = new XmlSerializer(typeof(T)); return serializer.Deserialize(sr) as T;}

究其原因,因为企业微信返回的事件数据格式是下面这个样子的!假如说SpRecord节点外面再套个SpRecords该有多好,那样笔者就能在相应类属性处冠上[XmlArray("SpRecords"), XmlArrayItem("SpRecord")],然后就不会报错,转换结果轻轻松松的就能出来。当然了,实话实说,笔者在XML操作这一块技艺生疏,如果读者有好办法请留言告知。

<ApprovalInfo> <SpRecord> </SpRecord> <SpRecord> </SpRecord> <Notifyer> </Notifyer> <Notifyer> </Notifyer> <Comments> </Comments> <Comments> </Comments></ApprovalInfo>

暂时找不到好办法,只好再干体力活!使用System.Xml.Linq类库的ElementDescendants等方法,遍历XML元素的节点,根据ApprovalEventInfo的类定义读取数据。以下代码以读取抄送信息为例。

aei.ApprovalInfo.Notifyer = new List<ApprovalNotifyer> { };foreach (var nodeNotifyer in nodeApprovalInfo.Descendants("Notifyer"))//读取抄送信息列表{ aei.ApprovalInfo.Notifyer.Add(new ApprovalNotifyer//遍历并依次加入到审批信息的抄送信息属性 { UserId = nodeNotifyer.Element("UserId").Value, });}

3.3 保存审批状态变化事件数据

按照下图创建审批状态变化事件表,简称审批事件表,把CreateTime、SpNoStatuChangeEvent作为复合主键进行保存。

 企业微信和信息门户的融合管理(5)连接轻量级工作流引擎之三

这里要注意,如果依托这个表管理多个企业微信账号的审批事件数据,则需把接收方也作为复合主键,我们目前只使用掌上理工,校友会账号虽然已注册,但尚未提上推广应用的日程,因此不存在多个企业ID,也就没把接收方列为复合主键。

3.4 处置审批状态变化事件数据

应用场景较多,上表是结合学校企业微信审批应用实际运行的审批模板而制定的处置策略。我们以第一个策略为例,在企业微信端的“教师入职基础信息申报”审批流程被驳回或通过时,向原发起人(新教师)推送手机短信告知。既然已经把审批事件数据写入到数据库,那就可以创建Windows服务程序,定时检测数据库,按需进行操作。

Models.CampusIntelligentEntities db = new Models.CampusIntelligentEntities();var listInductionDeclare = db.ci_wx_work_sp_approval_event//获取事件列表 .Where(e => e.TemplateId == "3TmkwX7Y3ffkeHQW7TcSWWBcoNwEC2zLARWNFotK" && e.StatuChangeEvent == 2 || e.StatuChangeEvent == 3);foreach (var approval_event in listInductionDeclare){ try { var approval_process = db.ci_wx_work_sp_approval_process//获取预审批数据 .FirstOrDefault(e => e.sp_no == approval_event.SpNo.ToString()); var form_data = JObject.Parse(approval_process.local_form_data);//获取预审批表单的数据 string mobile_phone = Convert.ToString(form_data["mobile_phone"]); var message_content = string.Format("老师您好,您发起的{0}已被{1}。",//构造短信内容 approval_event.SpName, approval_event.StatuChangeEvent == 2 ? "通过" : "驳回"); var result = JuheApi.SchoolNotice.Message.Send(new SendMessageRequest { mobile = mobile_phone },//调用短信API new List<CommonPair> { new CommonPair { key = "content", value = message_content } }); } catch { }}

4 后记

企业微信审批引擎的一整套流程我们终于走完,为了方便企业通讯录之外的人员发起审批,我们提出预审批的概念并实现。预审批通过后,后端程序自动调用企业微信审批引擎,使得业务流程能在企业内部正常流转,而当流程运行完毕,后端程序又能继续按照我们的意愿完成指定的任务。最后笔者提出几点优化的想法。

4.1 优化预审批部门/成员控件

这个就是精细化管理的范围了,企业微信提供的部门/成员组件,如有精力我们可以做进一步的封装。当我们在企业微信后台创建好审批模板,我们在自建系统对该模板中的部门/成员控件设置相应的筛选条件,这样在预审批时用户只能看到我们希望他看到的那些数据。

4.2 细化文本/数字/金额控件分类并增加校验规则

4.3 审批事件处置策略

假如把策略固化在Windows服务程序,那么每次有新增的策略又要修改并重新发布,并不灵活,如有可能,通过自建系统表单配置策略。


本文由【理工威客】原创或编辑整理。相关转载内容只为公益分享传播之用,非商业用途。文章或图片版权属于原作者。如遇到:来源标注错误或侵犯了您的合法权益,请第一时间联系我们,邮箱:yearnforjam@163.com,我们将及时审核、更正或删除,谢谢。

以上是关于企业微信和信息门户的融合管理连接轻量级工作流引擎之三的主要内容,如果未能解决你的问题,请参考以下文章

微信上怎么设置接收企业微信

开源工作流软件开发平台介绍?

钉钉,企业微信,华为welink,头条飞书,各有啥优势?

《C#开发微信门户及应用》

员工10000人的大企业,如何实现工作门户数字化升级?

配置企业应用业务流程别头大,有工作流引擎就不怕