精华内容
下载资源
问答
  • 企业微信机器人
    千次阅读
    2022-04-13 11:28:00


    一、企业微信机器人用途

    本文记录将企业微信机器人应用在接口自动化测试过程中,对项目初始化异常报警以及执行结束将报告输出。
    企业微信机器人API文档:https://developer.work.weixin.qq.com/document/path/92455


    二、前置条件

    获取webhookurl

    具有后台权限的管理员添加机器人后,可读取到机器人特有的webhookurl。将机器人关联到某一群组中,请求webhookurl时,机器人将携带的消息发送至该群。
    将机器人信息写入配置文件***.ini中:

    [ALARM_ROBOT]
    # 存放webhookurl
    robot_curl=https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=****
    # 存放需要@的成员的手机号码
    mentioned_mobile_list=18*********
    

    三、方法实现

    1.发送文本消息方法

    构造请求体,txt为待发送文本;mentioned_mobile_list为需要@的成员的手机号码,通过配置文件读取。未添加对返回报文的校验,只写入日志。

    代码如下(示例):

        def send_txt(self, txt: str):
            """
            企业微信机器人发送文本,例:"广州今日天气:29度,大部分多云,降雨概率:60%"
            :param txt: 待发送文本内容
            :return:
            """
            self.req_json["msgtype"] = "text"
            self.req_json["text"] = {}
            self.req_json["text"]["content"] = txt
            self.req_json["text"]["mentioned_mobile_list"] = [phone for phone in self.robot_info['mentioned_mobile_list'].split(',')]
            try:
                resp = requests.post(url=self.robot_curl, headers=self.headers, json=self.req_json)
                mylog.info(f"企业微信机器人发送消息:req_json: {self.req_json}\n"
                           f"response: {resp.text}")
            except Exception:
                mylog.exception(f"企业微信机器人发送信息失败,text: {txt}")
    

    2.发送图片方法

    需要对图片进行base64和md5转换,附转换方法。

    代码如下(示例):

        def send_pic(self, pic_path: str) -> bool:
            """
            企业微信机器人发送图片
            :param pic_path: 图片路径
            :return:
            """
            self.req_json["msgtype"] = "image"
            self.req_json["image"] = {}
            self.req_json["image"]["base64"] = path2base64(pic_path)
            self.req_json["image"]["md5"] = path2md5(pic_path)
            try:
                resp = requests.post(url=self.robot_curl, headers=self.headers, json=self.req_json)
                mylog.info(f"企业微信机器人发送图片:req_json: {self.req_json}\n"
                           f"response: {resp.text}")
            except Exception:
                mylog.exception(f"企业微信机器人发送图片失败,req_json: {self.req_json}")
    

    base64与md5转换方法:

    import base64
    import hashlib
    def path2base64(path: str) -> str:
        """
        文件转换为base64
        :param path: 文件路径
        :return:
        """
        with open(path, "rb") as f:
            byte_data = f.read()
        base64_str = base64.b64encode(byte_data).decode("ascii")    # 二进制转base64
        return base64_str
    
    
    def path2md5(path: str) -> str:
        """
        文件转换为md5
        :param path: 文件路径
        :return:
        """
        with open(path, "rb") as f:
            byte_data = f.read()
        md5_str = md5(byte_data)
        return md5_str
    
    
    def md5(text: all) -> str:
        """
        md5加密
        :param text:
        :return:
        """
        m = hashlib.md5()
        m.update(text)
        return m.hexdigest()
    

    3.发送文件方法

    支持所有文件类型,excel/word/ppt/html/zip等等,发送文件前需要先上传文件。

    上传文件方法:

        def upload_file(self, file_path: str) -> str:
            """
            企业微信机器人上传文件,发送文件前需要现上传
            :param file_path: 文件路径
            :return:
            """
            try:
                data = {'file': open(file_path, 'rb')}
                resp = requests.post(self.upload_url, files=data)
                json_res = resp.json()
                if json_res.get('media_id'):
                    mylog.info(f"企业微信机器人上传文件成功,file:{file_path}")
                    return json_res.get('media_id')
            except Exception:
                mylog.exception(f"企业微信机器人上传文件失败,file: {file_path}")
                return ""
    

    发送文件方法:

        def send_file(self, file_path: str) -> bool:
            """
            企业微信机器人发送文件,例如:report.html
            :param file_path: 文件路径
            :return:
            """
            try:
                self.req_json["msgtype"] = "file"
                self.req_json["file"] = {}
                self.req_json["file"]["media_id"] = self.upload_file(file_path)
                resp = requests.post(url=self.robot_curl, headers=self.headers, json=self.req_json)
                mylog.info(f"企业微信机器人发送文件:req_json: {self.req_json}\n"
                           f"response: {resp.text}")
            except Exception:
                mylog.exception(f"企业微信机器人发送文件失败,req_json: {self.req_json}")
    

    四、整体代码

    import re
    import requests
    from base.init_data import InitData
    from base.my_logger import MyLogger
    from common.my_function import path2md5, path2base64
    
    mylog = MyLogger()
    
    
    class WechatRobot(InitData):
        """
        企业微信机器人发送消息类,当前支持文本、图片、文件,根据腾讯提供的API文档还支持图文、markdown、模板卡片等,待有需求时添加。
        每个机器人发送的消息不能超过20条/分钟。
        企业微信机器人API文档:https://developer.work.weixin.qq.com/document/path/92455
        """
    
        def __init__(self):
            self.headers = {'Content-Type': 'application/json'}
            self.robot_curl = self.robot_info['robot_curl']
            self.upload_url = f'https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key={re.findall("key=(.*)&*", self.robot_curl)[0]}&type=file'
            self.req_json = {}
    
        def send_txt(self, txt: str) -> bool:
            """
            企业微信机器人发送文本,例:"广州今日天气:29度,大部分多云,降雨概率:60%"
            :param txt: 待发送文本内容
            :return:
            """
            self.req_json["msgtype"] = "text"
            self.req_json["text"] = {}
            self.req_json["text"]["content"] = txt
            self.req_json["text"]["mentioned_mobile_list"] = [phone for phone in
                                                              self.robot_info['mentioned_mobile_list'].split(',')]
            try:
                resp = requests.post(url=self.robot_curl, headers=self.headers, json=self.req_json)
                mylog.info(f"企业微信机器人发送消息:req_json: {self.req_json}\n"
                           f"response: {resp.text}")
            except Exception:
                mylog.exception(f"企业微信机器人发送信息失败,text: {txt}")
    
        def send_pic(self, pic_path: str) -> bool:
            """
            企业微信机器人发送图片
            :param pic_path: 图片路径
            :return:
            """
            self.req_json["msgtype"] = "image"
            self.req_json["image"] = {}
            self.req_json["image"]["base64"] = path2base64(pic_path)
            self.req_json["image"]["md5"] = path2md5(pic_path)
            try:
                resp = requests.post(url=self.robot_curl, headers=self.headers, json=self.req_json)
                mylog.info(f"企业微信机器人发送图片:req_json: {self.req_json}\n"
                           f"response: {resp.text}")
            except Exception:
                mylog.exception(f"企业微信机器人发送图片失败,req_json: {self.req_json}")
    
        def send_file(self, file_path: str) -> bool:
            """
            企业微信机器人发送文件,例如:report.html
            :param file_path: 文件路径
            :return:
            """
            try:
                self.req_json["msgtype"] = "file"
                self.req_json["file"] = {}
                self.req_json["file"]["media_id"] = self.upload_file(file_path)
                resp = requests.post(url=self.robot_curl, headers=self.headers, json=self.req_json)
                mylog.info(f"企业微信机器人发送文件:req_json: {self.req_json}\n"
                           f"response: {resp.text}")
            except Exception:
                mylog.exception(f"企业微信机器人发送文件失败,req_json: {self.req_json}")
    
        def upload_file(self, file_path: str) -> str:
            """
            企业微信机器人上传文件,发送文件前需要现上传
            :param file_path: 文件路径
            :return:
            """
            try:
                data = {'file': open(file_path, 'rb')}
                resp = requests.post(self.upload_url, files=data)
                json_res = resp.json()
                if json_res.get('media_id'):
                    mylog.info(f"企业微信机器人上传文件成功,file:{file_path}")
                    return json_res.get('media_id')
            except Exception:
                mylog.exception(f"企业微信机器人上传文件失败,file: {file_path}")
                return ""
    
    
    if __name__ == '__main__':
        wechat_robot = WechatRobot()
        file_path = './testdatas.zip'
        wechat_robot.send_file(file_path)
    
    
    更多相关内容
  • 企业微信通过机器人提醒一些重复的内容。 可设置定时发送。 使用Delphi开发的,开发环境xe10.3.1 使用到的数据库用了SQLITE和数据库控件UNIDAC 代码是根据网络上的修修改改制作。 亲测可用
  • 企业微信机器人发送文件 php demo **介绍链接:**[企业微信机器人发送文件 php demo](https://blog.csdn.net/xjie_127/article/details/113065950)
  • 1. 主要包含3个java文件Robot.java, TextMessage.java, Utils.java 2. 网上拷贝可用的代码,只需更改机器人地址即可. 3. 包含httpclient jar包,fastjson jar包等.
  • 源码参考,欢迎下载
  • 基于Python实现企业微信机器人发送消息(文本类型消息、Markdown 类型消息、图文类型消息),实现自动化,多样化。
  • 主要介绍了Python实现企业微信机器人每天定时发消息实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 文章目录1、背景2、企业微信API3、想法4、效果5、源代码6、Github源码分享7、具体步骤7.1、创建一个群7.2、创建好后,添加一个群机器人7.3、给机器人起名字、添加头像7.4、创建好后,复制Webhook地址后,点完成7.5、...
  • 企业微信机器人每日定时推送信息脚本。 也许是最有上班感觉的摸鱼神器! 目前支持如下插件: 毒鸡汤文本(dujitang,每1小时推送) v2ex 每日最新帖子(v2ex_latest,每天08:00推送) v2ex 每日最热帖子(v2ex_hot, ...
  • 主要介绍了简单用VBS调用企业微信机器人发定时消息的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • 企业微信机器人开发思路 想到几种方式: 直接写个sh脚本,并用linux定时器执行此脚本就可以了。这种方式简单实用,不过缺点就是修改起来稍微麻烦一点 写个Qt/VS客户端程序,做好页面和每天想推送的内容,还是有点...
  • 自己写的无需安装任何软件包,可以直接运行在shell中的一个微信机器人代码,实现了二维码扫码登陆,同步心跳,保持在线,一个简陋的机器人代码,大家可以根据不同的需求来修改代码,保证可以运行,代码丑陋,介意务下!...
  • 创建企业微信群组机器人 使用管理员身份登录企业微信移动客户端 进入需要添加机器人的群组,进入群组设置,添加群组机器人 添加成功后,复制Webhook 地址 配置GitLab项目Webhook 以服务部署地址 使用Maintainer身份...
  • 推荐使用 替代本项目,无需部署,简单配置即可打通企业微信机器人与Github、Gitlab、Sentry、Jenkins 等工具 webhook。 hwamei 是一个基于 hubot 的企业微信聊天机器人,它能够通过 webhook 将收集的信息发送到...
  • 微信机器人

    2018-08-18 12:07:52
    通过Python控制机器人,在微信上实现对话和好友互动】
  • 简介 企业微信2.8.7新版本上线了“群机器人”功能, wx-chatbot是基于企业微信群机器人API的脚手架。 使用wx-chatbot 快速接入 群...企业微信机器人官方文档 博主有话说: 希望喜欢的给个star! maven依赖 等待上传
  • 企业微信机器人做交互式前端-输出 本系列所有文章请访问:概述 概述 web界面的ui和微信机器人的ui的区别在于: web界面组合多种控件完成所有信息的整体呈现与输入,信息丰富、操作高效,用户获取的信息量大、...

    用企业微信机器人做交互式前端-输出

    本系列所有文章请访问:概述

    概述

    web界面的ui和微信机器人的ui的区别在于:

    • web界面组合多种控件完成所有信息的整体呈现与输入,信息丰富、操作高效,用户获取的信息量大、容易理解,但注意力易分散

    • 微信机器人则输入输出相分离,输出是一块一块离散输出【文本按行汇集为一块,markdown、文件、图片、语音、视频都是一条消息为一块,如果有菜单,菜单也是独立的一块】;输入则是交互式的,机器人提示-用户输入,一问一答。信息的呈现较为离散,输入更是稀碎到一问一答。所以缺乏整体,而且如果输出太多,也很容易看了后面忘了前面,用户不容易理解,无法快速明确意图,但便于用户集中注意力

    为降低开发维护两套ui的工作量,微信机器人利用了web界面的定义来输出信息。

    微信机器人中共涉及到三类输出:

    • 容器表的输出

    • 数据表的输出

    • 向前端发出的提示

    在本系统的第一篇文章中,笔者就谈过:微信机器人ui的开发,必须最小化变动,最大限度的确保低成本快速定制的实现。所以针对容器表和数据表的输出都是基于web中的定义而不增加任何额外的属性,只增加一些规范性约定,对于遵守这些规范的web界面,可直接用于微信机器人的输出而不需要增加任何额外的工作量。

    容器表输出

    jxTMS中的web界面是基于web文件定义然后动态生成的:web界面定义。基于此,对容器表的约束就是:

    1、用于数据输入输出的控件都是成对的:一个文本控件用来提示说明,然后紧跟着一个绑定了数据名的控件用于输入输出数据

    2、只接受部分控件

    • 未绑定数据名的控件支持:text类型的控件用于提取其text属性作为数据显示的提示词;a、button类型的控件提取为操作,用于动态添加子菜单选项

    • 绑定数据名的控件支持:text【文本】、input【单行输入】、dtpicker【时间】、combobox【下拉框】类型的控件直接输出,textarea【多行输入】、htmlContainer【html文本】类型的控件需要用base64解码后输出,此外还支持markdown【md格式文本】、file【文件】、img【图片】、voice【语音】、video【视频】等类型

    注1:对于markdown类型来说,由于企业微信机API文档提示目前仅支持markdown语法子集,所以在编写此类知识时得考虑到企业微信的支持能力。同时,markdown控件在web界面中是显示用的输出型控件,markdown文本的编辑则需要codeEditor控件,由于用codeEditor控件直接编辑markdown文本需要非常熟悉markdown语法,所以建议用外部的markdown编辑器编辑后直接复制到codeEditor控件中。此外,jxTMS中常用的编辑器lightweightEditor控件,其编辑出来的是用于web界面显示的html格式的文本,无法用于markdown输出。markdown类型输出示例如下:

    web显示

    注2:对于voice、video类型来说,web界面中并没有相对应的控件,所以虽然微信机器人可以发送这些类型的信息给用户,但jxTMS后台却没有相应的管理界面。因此是暂时保留

    注3:对于file类型来说,web界面中主要用于excel导入【下载就是一个链接】,所以和voice、video一样,都已经实现了,但还需要在具体应用中逐步成熟

    如,本系列开始我们所演示的容器表测试的web定义为:

    //容器表带操作按钮
    web wxTestCT type div;
    web wxTestCTt1 parent wxTestCT type table title='完成',width=600;
    with wxTestCTt1 row 0 col c0 web n type text text='说明:',width=100;
    with wxTestCTt1 row 0 col c1 web n bind testIn1 type text width=500;
    
    with wxTestCTt1 row 1 col c0 web n type a width=80,text='接受',motion=cmd,demand=wxTestCTAccept,
    	 params={'active':'accept'};
    with wxTestCTt1 row 1 col c1 web n type a width=80,text='拒绝',motion=cmd,demand=wxTestCTReject,
    	 params={'active':'reject'};
    

    其对应的初始化事件响应函数为:

    @myModule.wxDisp('tms','容器表测试'.decode('utf-8'),'测试'.decode('utf-8'))
    @myModule.event('prepareDisp', 'wxTestCT')
    def wxTest(self, db, ctx):
    	jx.log('wxTestCT disp')
    	self.setOutput('testIn1','from wxTestCT')
    

    在web界面的显示是:

    web显示

    而在微信机器人推送给我们时的显示是:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kzMsESsG-1636512124349)(http://115.29.52.95:10002/images/wxRobot-1-4.png)]

    即,微信机器人对web定义的处理是

    //跳过,如果有多个则会自动插入一个回车
    web wxTestCT type div;
    //跳过,如果有多个则会自动插入一个回车
    web wxTestCTt1 parent wxTestCT type table title='完成',width=600;
    
    //一个没有bind的text控件和其后的一个带bind的控件被转换为微信输出中的一行
    //其中前者的text作为提示词直接输出
    with wxTestCTt1 row 0 col c0 web n type text text='说明:',width=100;
    //后者将接收事件响应函数中输出到所绑定的数据名testIn1的值拼接到提示词之后
    with wxTestCTt1 row 0 col c1 web n bind testIn1 type text width=500;
    
    //两个不带绑定的控件,被提取为操作,作为子菜单动态添加到容器表测试的菜单中
    //此时,如果用户输入1,则执行wxTestCTAccept命令;输入2,则执行wxTestCTReject,同时将参数合并到两命令的输入流中
    with wxTestCTt1 row 1 col c0 web n type a width=80,text='接受',motion=cmd,demand=wxTestCTAccept,
    	 params={'active':'accept'};
    with wxTestCTt1 row 1 col c1 web n type a width=80,text='拒绝',motion=cmd,demand=wxTestCTReject,
    	 params={'active':'reject'};
    

    容器表的输出在大多数情况下是比较简单的:

    • 按一个提示控件和一个数据控件成对提取,然后在输出时,将提示与数据控件的实时值拼接为一行

    • 操作按钮提取为动态生成的菜单中的一项

    但是,有一种容器表就会非常麻烦了,那就是流程,如报销审批,各环节都可录入意见、执行同意或拒绝操作,但绝不能让部门经理的同意操作取代掉总经理的同意操作。即一个流程是共享读、分段操作的,即所有信息都能看到,但输入和可点击的操作按钮是按任务流转到执行人才能操作自己所负责的那一部分的。所以流程的容器表的输入输出控制是非常麻烦的,需要微信机器人跟踪流程的流转来确定该如何动态控制输入、输出与操作菜单。本文暂不展开。

    数据表输出

    web端的数据表一般是下面这样的:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sSVHRwQE-1636512124351)(http://115.29.52.95:10002/images/wxRobot-1-5.png)]

    包括三个部分:

    • 最上面的工具条【多见于容器表,数据表用的比较少】

    • 查询条件设置面板,包括相应的查询条件设置和一个【搜索】按钮,以实现条件查询

    • 分页的数据列表,但其分页需要web端的分页控件配合来实现;此外,每行数据还可以执行多种操作

    由于带查询的分页数据表是针对web端定制的,所以其就不如容器表这么简单的就可以转换给微信机器人使用。所以微信机器人所使用的数据表,一般是web端数据表的简化复制品,即从web的数据表定义中复制过来,然后去掉:

    • 查询面板【因为前面已经说过了:微信机器人输入输出相分离】,条件查询当然也可以实现,但需要配合下节的交互式输入,目前暂不考虑

    • 分页控件,微信机器人根本就没有前端界面,所以web界面中的前端分页后端配合的机制是无法实现的,因此微信机器人中的数据表改由后台来控制分页,默认每页8行数据

    • 限制每行只能有一个操作,这个原因很简单,数据表就是一个多行的输出,如果每行再有两个或以上的操作,那菜单显示与选中的操作就太复杂了

    同时,由于数据表是一个多行输出,而考虑到手机宽度很小,所以数据表中的每一列数据都会转成和容器表中相同的一行【提示:值】来显示,所以数据表中的每一行就转换为一块,如下图中的第二个输出:

    数据表输出

    显然,用于微信机器人的数据表的信息密度是和不能和web端一样的,必须得精干再精干一些。

    上图的数据表在web文件中的定义是:

    //数据表
    web wxTestDT type div;
    web wxTestDTt1 parent wxTestDT type table title="noUsed";
    with wxTestDTt1 col taskID head taskID hide=true;
    with wxTestDTt1 col taskName head 工作内容 width=160;
    with wxTestDTt1 col taskState head 状态 width=60;
    with wxTestDTt1 col op head 操作 web n type a
        width=60,motion=cmd,demand=wxTest,text='查看',require=[{"paramName":"taskID"}];
    

    大家注意观察这个数据表的定义,再和上面的实际输出进行对比,就能观察到数据表实际定义了四列,其中:

    • 工作内容和状态这两列正常显示了出来

    • taskID这一列被定义为hide,所以没有显示,其主要用于保存每行任务所对应的任务ID,以提供给【查看】操作,使得用户在选择了相应的行后可以正确的显示出相应的任务

    • 操作这一列,也没有显示,但笔者在列表后又按了一个1,其实就相当于请求执行第一行的【查看】按钮所对应的wxTest命令,并使用了第一行隐藏起来的taskID进行调用,以查看该任务的详情

    命令输出

    在web界面中,命令几乎不会独立出现,基本都是依附于容器表和数据表的,这是因为命令没有自己的界面,所以需要容器表和数据表来提供输入输出和用户交流,所以不需要任何输入输出就意味着这是一个有着清晰目的的固定指令。这种脱离上下文的固定指令一般都是系统动作,如个人的登出、系统的关闭、热机刷新等等。

    注:即便是【热机刷新】,笔者都制作了一个提示界面和一个按钮【还带有操作前确认】,让用户在执行这种对系统有重大意义的操作前冷静再冷静,确认是真要这么干

    但在微信机器人的ui中,由于其输入与输出相分离,所以独立的命令就有了意义,如前面说过的【新成员注册】功能就是一个命令,因为其不需要输出。

    严格来说,【新成员注册】也不是不需要输出,因为总是需要一个执行结果的提示吧。但考虑到这样的输出既非常简单,使用起来又是非常频繁的,如果每个独立的命令就为了一个执行结果提示还得制作一个界面,显然是太过低效了。所以针对执行结果的提示,jxTMS中特别定义了一个名为execResultDescr的输出变量,只要是向其输出,jxTMS就会自动通过微信机器人发送给当前用户。

    注1:如果web界面未定义绑定了execResultDescr的输出控件,则数据会发送到前端作为本地变量保存,即web界面中如果定义了绑定了execResultDescr的输出控件,则该控件显示用户输出内容;如果未定义,则浏览器中jxTMS前端的运行环境中会增加一个名为execResultDescr的本地变量

    注2:如果是静态web界面,则execResultDescr会放入请求结果中

    对于捆绑给带有界面的容器表的命令,可以正常使用self.setOutput函数输出,由于容器表可能有很多数据项,而其捆绑的命令可能只会涉及到其中一部分,所以命令的输出是增量的,即jxTMS会收集命令中用self.setOutput函数输出的那些数据项,并只将其与对应的提示成对输出。

    主动提示

    我们到目前所讲述的都是和某个用户在和其会话中向对方发送消息,如果在公告、主动通知【如有新任务到达等】等非会话场景下,向其发送消息则如下调用:

    #发送消息
    self.sendWXMsg(db,ctx,appName,peopleAbbr,msg,vs)
    

    其中:

    • appName:就是机器人名

    • peopleAbbr:成员在组织中的别名【没有重名就是其姓名】,不给则是发给所有人

    • msg:以花括号对为占位符的消息模板。如:你有新工作:{},发布人是:{}

    • vs:变参的值数组,就是用vs中的值,逐一替换掉msg中的花括号对

    如:

    self.sendWXMsg(db,ctx,'tms','测试用户123'.decode('utf-8'),'你有新工作:{},发布人是:{}'.decode('utf-8'),'起来干活了'.decode('utf-8'),'你老板'.decode('utf-8'))
    

    则,用户【测试用户123】就会在企业微信中收到tms机器人发布的:

    你有新工作:起来干活了,发布人是:你老板
    

    还可以发送图片和文件:

    #发送图片
    self.sendWXMsg(db,ctx,appName,peopleAbbr,path)
    #发送文件
    self.sendWXMsg(db,ctx,appName,peopleAbbr,path)
    

    jxTMS目前已打包为docker容器,可以下拉jxTMS的docker镜像并按jxTMS使用示例尝试使用。

    展开全文
  • 企业微信机器人做交互式前端-添加微信功能 本系列所有文章请访问:概述 开通机器人 微信机器人先要在企业微信的后台开通: 创建应用 获取该应用的发送秘钥 生成该应用接收令牌 生成该应用接收秘钥 注1:...

    用企业微信机器人做交互式前端-添加微信功能

    本系列所有文章请访问:概述

    开通机器人

    微信机器人先要在企业微信的后台开通:

    • 创建应用

    • 获取该应用的发送秘钥

    • 生成该应用接收令牌

    • 生成该应用接收秘钥

    注1:该机器人的接收服务器url为:jxTMS服务器IP:端口号/企业微信号/应用ID。如:http://tms.myJxTMS.com:10018/ww4exxxxxxxxxxxxxxx/1000002/

    注2:目前jxTMS暂不支持https协议

    然后在jxTMS服务器上以manager角色访问快捷栏【企业微信->查看】打开本企业的企业微信配置界面,然后点击【添加机器人】在jxTMS服务器上以上述信息来配置该机器人:

    开通机器人

    注:如果是公共应用,则两个角色处都不填,所有企业微信中的成员都可以访问该机器人。如果填了,那访问规则如下:

    • 如果填了拒绝访问的角色列表,则角色集【该成员所映射的角色以及这些角色所映射的虚拟角色】中存在这些角色的成员会被拒绝

    • 这时,如果没填允许角色,则其他成员都可以访问

    • 如果也填了允许角色,则角色集中存在这些角色的成员会被允许访问

    • 其他成员全部拒绝

    配置完成后,jxTMS会自动为该机器人创建一个虚拟的uri:/corpid/appID,用以接收企业微信服务器发送过来的用户在企业微信中发给该机器人的消息。由于企业微信在正式提供服务前需验证接收url的工作是否正常,所以整个开通过程是:

    1、在企业微信后台创建应用并生成前述这些信息【但暂不验证】

    2、用这些信息在jxTMS开通微信机器人

    3、在企业微信后台验证该url

    之后就可以在企业微信中看到在【名称】中填入的微信机器人名,如tms、hr、进销存等,用户就可以访问该机器人查询信息或办理业务了。

    注:一个企业不管有多少个机器人、不管这些机器人叫什么、干什么,对jxTMS来说,这些机器人只是用来和用户打交道的ui,只是用来增强操作内聚性、强化业务管控的一种组织方式。同一个企业的微信机器人之间并未有任何隔离,不需要考虑互联互通的问题。操作的安全性由jxTMS自身的权限系统、安全设计等予以保证

    添加微信功能

    向微信机器人添加一个功能项非常简单,如上文的容器表测试的定义:

    @myModule.wxDisp('tms','容器表测试'.decode('utf-8'),'测试'.decode('utf-8'))
    @myModule.event('prepareDisp', 'wxTestCT')
    def wxTest(self, db, ctx):
    	jx.log('wxTestCT disp')
    	self.setOutput('testIn1','from wxTestCT')
    

    可以看出,就是在通常的入口函数【参考其中的动作按钮的响应函数一节】定义后,额外添加一个jxTMS提供的java编写的wx修饰:

    wx(String appName,String title,String path,String verifyStr,Boolean dataTable)
    

    其中:

    • appName:微信机器人名,就是上面在jxTMS中添加机器人时所填写的机器人名称【不是在企业微信后台所填写的应用名,当然,这两者最好一致】

    注:可定义多个机器人,各机器人的菜单根据wx修饰分别创建

    • title:显示在菜单中的功能名,如上篇文章中的【容器表测试】

    • path:从根菜单出发,一个子菜单一个子菜单的找到该功能的路径,每层子菜单选项的title用英文句号分隔,如【组织管理.人事管理】,则本功能菜单项就会出现:主菜单->组织管理->人事管理下。path中的这些子菜单如未创建,则jxTMS在向微信机器人添加时会自动创建

    注:未指定path,则不会出现在任何静态定义的菜单中,而只能作为其它功能菜单动态添加的子菜单项出现

    • verifyStr:根据当前的业务上下文来确定本功能菜单项是否动态的出现在父菜单中。如,【新成员注册】就定义了verifyStr为:caller.id==0,意为检测调用者的id是否为0,为0则显示该菜单项

    • dataTable:指示是否为数据表的菜单项

    然后分别针对容器表、数据表、命令提供了三个对应的简写修饰函数符:

    容器表:wxDisp(String appName,String title,String path)
    数据表:wxDataTable(String appName,String title,String path)
    命令:wxOP(String appName,String title,String verifyStr)
    

    如果简写不能满足需要,还是需要用wx进行修饰,如【新成员注册】就比较特殊,应修饰为:

    @myModule.wx('tms','新成员注册'.decode('utf-8'),'root','caller.id==0',False)
    @myModule.event('cmd', 'wxAddPeople')
    def wxAddPeople(self,db,ctx):
    	......
    

    这是由于【新成员注册】必须挂在根目录下,否则新用户看不到。

    注:所有的子菜单,如果没有定义verifyStr,jxTMS会默认添加一个【caller.id>0】,以阻止未注册用户使用

    用wx修饰符修饰后,该事件响应函数自动添加到该机器人的树状菜单中【未指定path的就没有固定的锚定点,而是由容器表或数据表动态添加】,jxTMS会在运行时自动为其准备好运行环境和上下文,并重定向输入输出到微信机器人的收发处理流中,使得该函数无缝工作在微信机器人中。

    注:jxTMS确保事件响应函数对基于自身的动态web ui、对静态web ui和基于微信机器人的ui工作逻辑完全一致。使得基于自身动态web界面所开发的业务逻辑可无缝支持静态web界面和微信机器人。这样当需要这些ui时,可利用jxTMS低成本快速定制的能力,开发相应的动态web界面并验证后,确保一个工作稳定且业务已经验证的后台

    jxTMS目前已打包为docker容器,可以下拉jxTMS的docker镜像并按jxTMS使用示例尝试使用。

    展开全文
  • 企业微信机器人做交互式前端-交互式输入 本系列所有文章请访问:概述 概述 jxTMS所实现的微信机器人其工作的逻辑闭环是: 1、微信机器人向用户显示菜单 2、用户输入菜单选项 3、jxTMS提示用户输入 4、用户输入 5、...

    用企业微信机器人做交互式前端-交互式输入

    本系列所有文章请访问:概述

    概述

    jxTMS所实现的微信机器人其工作的逻辑闭环是:

    1、微信机器人向用户显示菜单

    2、用户输入菜单选项

    3、jxTMS提示用户输入

    4、用户输入

    5、所有等待中的变量全部完成输入后,jxTMS显示所有的用户输入【包括默认值】,并提示用户确认

    6、用户确认后,将所有用户输入【包括默认值】合并到事件响应函数的输入流中

    7、jxTMS将事件响应函数投入运行

    8、jxTMS将程序执行结果输出显示给用户

    9、向用户显示菜单,然后等待用户输入菜单选项

    所以用户输入时有两个状态:

    • 菜单选择状态

    • 变量输入状态

    jxTMS需要跟踪并适时切换用户的当前状态,以准确的从用户输入流中分离出菜单选择操作和变量值输入。其中,变量的输入是交互式的,即微信机器人先提示用户现在需要输入什么内容,然后等待用户输入,用户输入后再提示输入下一个变量,等所有变量输入完毕,然后再向用户显示其所有的输入值【包括未输入变量的默认值】,然后等待用户确认。

    用户需要在ui的引导下,充分理解业务办理的目的、要求其输入的是什么、有什么要求,准确表达、准确操作。而交互式对话的好处就在于信息比较集中、精准,用户的注意力会比较集中,不太容易被多余的信息干扰而理解错误,但需要在每一步都有足够的说明与引导。

    web界面由于信息丰富而且是整体呈现给用户,所以其数据控件前的提示词就不需要很长很多,这在web界面下是不会影响用户对业务的理解。但提取出来用到微信机器人中显示给用户看,就会因为信息量太小而让用户困惑,不知道要干什么、该如何做。

    所以,jxTMS的微信机器人设计成了输入输出相分离,不会将从web界面的定义中提取到的提示词用于交互输入。原因就在于web界面中对单个数据的提示词过于简短,用在交互式输入时会由于信息不足而影响用户的理解。因此微信机器人专门设计了交互式对话的定义语句,以提供足够的说明信息来帮助用户完整、准确的理解当前场景下输入的目的、意图与要求。

    校验与默认值

    输入需要校验。我们都知道业务管理系统有句名言:垃圾进、垃圾出。而校验就是用来检验输入的数据是否满足某种要求的、确保数据的源头质量,在jxTMS中叫做:数据约束。由于jxTMS已经具备了数据约束的能力,所以直接引用就好了。

    默认值在web界面中用处不大,因为web界面有丰富的控件,可以帮助用户快捷输入,使用默认值所提高的效率意义不大,反而需要通过让用户自己选择来进一步明确其意图同时还可以避免用户由于信息量过大,在还没完全理解的情况下就直接操作带来意外。即,web界面中由于信息丰富、操作效率高,反而要限制默认值的使用,以避免用户误操作【即实际意图未必是默认值所表达的,但由于信息量太大,用户分心了,没注意看也没仔细去理解】。

    但在交互式输入中,默认值在效率提升方面就价值巨大了,同时由于是用户一个字一个字输入的,其肯定是足够冷静、足够想明白到底要干什么的了,所以在交互式对话中,能用默认值就一定要用,除非默认值会导致重大的表达错误。

    交互式输入的定义

    通过上面的讨论,我们已经知道了,交互式输入的一个输入单元,就是一个五元组:

    • 变量名,可以让事件响应代码用self.getInput函数读取到用户的输入值

    • 提示说明,在用户输入前推送给用户,以帮助用户理解要输入的信息是用来干什么的、有什么样的要求

    • 校验表达式,在用户输入后,用来验证用户输入是否符合要求

    • 校验规则说明,校验失败后会向用户推送的输入要求说明

    • 默认值,用多数人的同样输入来减少用户输入、提高效率

    注:实际中还有一个区分是否需要base64编码的指示,因为如果需要输入的数据同时可以显示在微信机器人与web中,对于web界面中的某些取值是base64编码的数据控件,如textarea、htmlContainer等,就也必须进行base64编码。因为这些控件在web端时都可能输入特殊字符,不用base64编码就无法正确的传递

    所以其定义就是用这五个元素对事件响应函数进行修饰就可以了:

    PyObject wxPrompt(String bind,String prompt,Object defaultValue,String verifyStr,String verifyRuleDescr,Boolean base64)
    

    各变量的意义非常直白,就不复赘述了。wxPrompt必须跟在wx修饰或其衍生出的wxOP、wxDisp、wxDataTable之后【python修饰符是最开始的修饰符最后使用】,示例如下:

    @myModule.wxPrompt('var2','变量2'.decode('utf-8'),'tv2','len>2 and len<5','长度应大于2且小于5'.decode('utf-8'),False)
    @myModule.wxPrompt('var1','变量1'.decode('utf-8'),'tv1')
    @myModule.wx('tms','第一个测试'.decode('utf-8'),'测试'.decode('utf-8'),None,False)
    @myModule.event('cmd', 'wxTest')
    def wxTest(self, db, ctx):
    	......
    

    上述示例给【测试->第一个测试】这个命令型微信功能添加了两个交互式输入变量:var1和var2。其中var1由于不需要检验,所以采用了简写,var2则限制其长度只能是3或者4个字符。两变量都还提供了默认值。大家可以看一下这个定义的实际交互过程:

    交互式输入

    在父菜单中输入3选择【第一个测试】执行时,由于两变量都提供了默认值,所以jxTMS直接显示用户输入确认表,请用户确认其输入。用户此时对var1的值不同意,输入1想修改var1的值,这时jxTMS发送输入提示,用户再次输入后,jxTMS再次显示用户输入确认表。此时,如果用户想修改var2的值,但输入不符合要求时:

    交互式输入校验

    如果最后用户确认其输入,输入y即可。

    注:目前尚不支持【取消所有输入,终止执行】。这是由于微信机器人的菜单选择和输入是混流的,需要依靠严密的状态跟踪来确定用户当前的输入是分流给菜单选择还是变量输入,打断闭环的【选中菜单项->用户输入->执行->输出结果->显示菜单】处理逻辑再行恢复出原本的流会导致处理逻辑异常复杂,很可能导致状态恢复错误。而jxTMS对微信机器人的支持是全新的功能,整个工作逻辑还未经大量应用考验,所以笔者权衡再三,暂时取消了该功能

    用户输入完毕,jxTMS会将用户输入重定向到事件响应函数,用self.getInput函数即可读取到相应的用户输入了。

    临时性输入

    在业务办理时,有时会出现突发性的输入请求。比如,在新成员注册时,有可能出现重名。jxTMS解决重名的办法是不直接使用名字,而是使用简称:如果没有重名就直接用名字做简称,如果有重名则需要起一个区别性的简称。那么在新成员注册时,简称就不是必须要求用户输入的【而且不重名时,各人简称的默认值还不一样】,但当用户提交注册时,发现有重名则需要提示用户输入一个简称,而当输入的简称依然有重名时,还需要反复做出提示直到没有重名。

    注:哈,笔者曾就职过的一家企业,三十多人有三个人重名,最后:大xx、小xx、女xx,还得写到通讯录中:) 这个印象深刻到在jxTMS中,一个组织有三个名字:给人用的简称、给人用的唯一性全名【一般是工商注册名】、给机器用的英文唯一名【数据库、消息接收都以此名为准】

    针对这样的需求jxTMS增加了一个临时性输入的功能:

    #设置临时性输入提示,需要临时增加几个就调用几次
    setTmpExpect(String bind,String prompt,Object defaultValue,String verifyStr,String verifyRuleDescr)
    #提交临时性输入提示
    commitTmpExpect(IDBop db,context ctx)
    #结束临时性输入提示
    clearTmpExpect()
    

    各函数以及参数的意义一目了然,我们举个例子就好:

    @myModule.wx('tms','临时提示测试'.decode('utf-8'),'测试'.decode('utf-8'),None,False)
    @myModule.event('cmd', 'wxTest2')
    def wxTest2(self, db, ctx):
    	v2 = self.getInputString('v2')
    	if v2 is None:
    		#没有v2变量的输入值,临时设置一个v2变量的输入
    		self.setTmpExpect('v2','临时需要输入一个字符串'.decode('utf-8'),None,'len>2','长度大于2'.decode('utf-8'))
    		self.commitTmpExpect(db,ctx)
    
    		return False
    
    	jx.log('v2:{}',v2)
    
    	#由于设置了临时提示,必须加以清除,以避免对其后的临时性提示造成干扰
    	self.clearTmpExpect()
    
    	return False
    

    则【临时提示测试】在执行时,发现缺少v2变量,就临时为其创建一个临时性的输入提示,然后请求输入v2变量,在得到v2变量后,必须及时调用clearTmpExpect函数来取消临时性输入的状态。

    jxTMS目前已打包为docker容器,可以下拉jxTMS的docker镜像并按jxTMS使用示例尝试使用。

    展开全文
  • php基于thinkphp的多账号多微信机器人系统源码.zip
  • 为您提供VLW 微信机器人框架下载,VLW是一款基于PCVX功能强大而又完全的微信机器人框架,支持二次开发,调用简单,上手迅速,不再需要自己动手实现繁琐的微信功能,最重要的是稳定挂机不掉线!功能介绍 已提供以下...
  • 企业微信机器人

    千次阅读 2019-10-08 07:04:24
    今天升级了企业微信,发现新增了一个机器人功能,于是好奇的玩了一下。 目前发现该机器人主要用途是用来发布定时消息,或者发布监控程序报告。 代码如下: 1.控制层 package com.qt.controller; import ...
  • 我这里最看重的是他的自动创建外部群拉入客户和销售,并能用接口查询群聊记录,连企业微信会话存档的费用都省了,把机器人拉群里,@机器人问问题可以预先设置简单的问答库。另一个我看重的功能是自动通过好友请求,...
  • GitLab设置通知企业微信机器人

    千次阅读 2022-03-11 23:14:44
    将Gitlab的push、tag push、merge request和pipeline等等推送到企业微信机器人
  • 在企业运营中,为了实现工作效率和执行效率的提升,往往会选择在社群中使用群聊机器人进行协助管理。机器人可以定时或者按照一定的...1、注册企业微信 注册地址: https://work.weixin.qq.com/wework_admin/register_
  • 如何制作一个企业微信机器人

    千次阅读 2022-04-21 17:10:19
    1、创建一个企业微信机器人你会发现它其实就是一个接口。 以及有它的配置说明,发送不同格式或类型的消息。 2、编辑脚本 导入依赖的jar包 <dependency> <groupId>org.apache.httpcomponents&...
  • # 2020-02-21 12:26:12 s = current_weather data = { "msgtype": "text", "text": { "content": s, } } r = requests.post( url='http://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=企业微信机器人key',...
  • 企业微信机器人做交互式前端-附录二 本系列所有文章请访问:概述 微信机器人的开发过程 jxTMS的微信机器人就单纯的开发来说是很简单的: 1、开通微信机器人,详见添加微信功能中的【开通机器人】一节 2、对需要...
  • 企业微信机器人做交互式前端-本地测试 本系列所有文章请访问:概述 本地测试 通过前面的讲解,可以看出来:用jxTMS开发一个微信机器人非常简单。但再简单,未经测试不得上线,所以在开发好微信机器人应用后需要...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,197
精华内容 6,478
关键字:

企业微信机器人

友情链接: elcFORxanda.rar