# webhook机器人

## 创建流程

1. 在群聊中点击右上角的「···」图标，点击群机器人；
2. 点击添加 webhook 机器人；
3. 填写机器人名称和简介，即可添加自定义机器人到群聊中。
4. **特别特别要注意**：一定要保护好机器人的 webhook 地址，避免泄漏！不要分享到 github、博客等可被公开查阅的地方，否则坏人就可以用你的机器人来发垃圾消息了


![群机器人](https://cloudcdn.qwps.cn/open/_img/916ad6d69c.jpg)

![webhook机器人](https://cloudcdn.qwps.cn/open/_img/d62d6894ac.jpg)

![创建webhook机器人](https://cloudcdn.qwps.cn/open/_img/ea30785a55.jpg)


## 使用webhook机器人发送消息

1. 在终端某个群组添加机器人之后，可以获取到 webhook 地址，然后开发者用户按以下说明构造 post data 向这个地址发起 HTTP POST 请求，即可实现给该群组发送消息
2. webhook 格式是：https://xz.wps.cn/api/v1/webhook/send?key=xxxxxxx

webhook发送消息的限制：
1. 消息发送频率限制：每个机器人发送的消息不能超过 20 条/分钟
2. 消息内容阈值：每条消息不超过 5000 个字符

webhook消息支持3种消息类型：文本、Markdown、卡片。不同类型的消息体参数说明如下：

### 文本类型消息

#### 参数说明

| **参数**                 | **是否必填** | **说明**                        |
| :------------------- | :------ | :--------------------------- |
| msgtype              |    是    | 消息类型，固定为`text`  |
| text                 |    是    | 文本消息                    |
| ∟ content |    是    | 消息内容                    |

支持通过在消息体 content 中插入\<at>标签的方式@人，如果不填写姓名，则服务端将自动填充姓名至@人位置：

- 使用 id@人：\<at user_id=\"12345\">姓名\</at>
- 使用 email@人：\<at email=\"[somebody@wps.cn](mailto:somebody@wps.cn)\">姓名\</at>
- @所有人：\<at user_id=\"-1\">所有人\</at>

#### 代码示例

```
{
   "msgtype":"text",
   "text":{
      "content":"每日数据监控报告：\n今日数据统计结果请相关同事注意<at user_id=\"17856\">李三</at><at user_id=\"-1\">所有人</at>"
   }
}
```

#### 展示示例

![文本](https://cloudcdn.qwps.cn/open/_img/1f5dc75f65.png)



### Markdown 类型

#### 参数说明

| **参数**              | **是否必填** | **说明**          |
| :------------------- | :------ | :--------------------------- |
| msgtype           |    是    | 消息类型，固定为 `markdown`      |
| markdown          |    是    | markdown 消息 |
| ∟ text |    是    | 消息内容      |

#### 语法说明

说明：目前只支持 md 语法的子集，具体支持的元素如下（换行可以使用“双空格+\n”或“\n\n”方式），不同语法之间的组合（颜色+标题等）。
|      **名称**           | **语法**                   |      **说明**                         |
| :--------------- |:--------------------| :------------------------------------------------------------ |
|   @人        | 使用 id@人：\<at user_id="12345">姓名\</at> <br/> 使用 email@人：\<at email="somebody@wps.cn">姓名\</at> <br/> @所有人：\<at user_id="-1">所有人\</at> |            |
|    标题         | # 一级标题<br/>## 二级标题<br/>### 三级标题<br/>#### 四级标题<br/>##### 五级标题<br/>###### 六级标题                |                   |
|    引用            | > 引用内容                                  |                           |
|    加粗             | \*\*加粗\*\*       |         如移动端显示有问题可尝试在后面加空格       |
|    颜色          | \<font color='#FF0000'>颜色\</font><br/>\<font color='red'>颜色\</font>                          | 支持使用十六进制颜色值或对应颜色的英文表示       |
|    斜体            | \*斜体\* <br/> \_斜体\_               |                |
|    删除线           | \~~删除线~~                  |                                   |
|    链接               | <链接地址> <br/> \[链接名称](链接地址)                      |                             |
|    有序列表    | 1. 内容 1 <br/> 2. 内容 2                                          |                            |
|    无序列表        | - 内容 1 <br/> - 内容2                             |                          |
|    图片        | \!\[](图片地址)                                          |                      |


#### 代码示例

```
{
    "msgtype": "markdown",
    "markdown": {
        "text":"## KAE监控报警\n\n报警内容：网关入口\n\n> 备注：严重程度中等"
    }
}
```

#### 展示示例

![markdown](https://cloudcdn.qwps.cn/open/_img/8ccecb4812.png)




### 链接类型

#### 参数说明

|    **参数**    |    **是否必填**    | **说明**                                                       |
| :--------------- |:--------------------| :----------------------------------------- |
|  msgtype   |    是    | 消息类型。固定为 `link`                                 |
|  link    |    是    | 标题内容                                                   |
|  ∟ title    |    是    | 标题内容                                                   |
|  ∟ text    |    是    | markdown 格式的消息。换行可以使用“双空格+\n”或“\n\n”方式。 |
|  ∟ messageUrl |    否    | 跳转 url                                                   |
|  ∟ btnTitle  |    否    | 按钮标题，默认为“查看详情”，长度限制 12 个字符             |

#### 代码示例

```
{
    "msgtype": "link",
    "link": {
        "title": "日程提醒",
        "text": "需求评审会将于15分钟后开始↵2F-201会议室",
        "messageUrl": "https://kdocs.cn",
        "btnTitle": "查看详情"
    }
}
```

#### 展示示例

![link](https://cloudcdn.qwps.cn/open/_img/ac7b07afce.png)



### 卡片类型

#### 参数说明

|    **参数**    |    **是否必填**    | **说明**                                                       |
| :--------------- |:--------------------| :----------------------------------------- |
| msgtype |    是    | 消息类型。card-表示卡片类型                                                                 |
| card    |    是    | 卡片消息，具体内容见[搭建卡片消息](/app-integration-dev/guide/card/card-structure)，备注：目前 webhook 不支持回传型交互组件， 包括回传型按钮、列表选择器、日期选择器、输入框      |

#### 代码示例

```json
{
    "msgtype":"card",
    "card":{
        "header":{
            "title":{
                "tag":"text",
                "content":{
                    "type":"plainText",
                    "text":"标题"
                }
            },
            "subtitle":{
                "tag":"text",
                "content":{
                    "type":"plainText",
                    "text":"副标题"
                }
            }
        },
        "elements":[
            {
                "tag":"text",
                "content":{
                    "type":"markdown",
                    "text":"普通文本"
                }
            }
        ],
        "i18n":{
            "zh-TW":{
                "header":{
                    "title":{
                        "tag":"text",
                        "content":{
                            "type":"plainText",
                            "text":"標題"
                        }
                    },
                    "subtitle":{
                        "tag":"text",
                        "content":{
                            "type":"plainText",
                            "text":"副標題"
                        }
                    }
                },
                "elements":[
                    {
                        "tag":"text",
                        "content":{
                            "type":"markdown",
                            "text":"普通文本"
                        }
                    }
                ]
            },
            "en-US":{
                "header":{
                    "title":{
                        "tag":"text",
                        "content":{
                            "type":"plainText",
                            "text":"title"
                        }
                    },
                    "subtitle":{
                        "tag":"text",
                        "content":{
                            "type":"plainText",
                            "text":"sub title"
                        }
                    }
                },
                "elements":[
                    {
                        "tag":"text",
                        "content":{
                            "type":"markdown",
                            "text":"common text"
                        }
                    }
                ]
            }
        }
    }
}
```

#### 展示示例

![card](/docs/images/app-integration-dev/dev-tool-and-source/card-editor-1.png)


## 使用webhook机器人接收消息

支持开发者通过设置webhook机器人回调，接收用户在群内@机器人的消息。请注意，由于安全性要求，普通群聊消息（没有@机器人的）是不能获取到的。

![callback](https://cloudcdn.qwps.cn/open/_img/95288f5deb.jpg)


### 回调地址可用性校验

创建者在输入框中输入 url，点击保存。服务端会对该地址进行一次 GET 请求，例如：[GET] https://xz.wps.cn/api/v1/test
第三方收到请求后返回以下 response 数据即可：

```json
{
    "result":"ok"
}

```

### 发起回调

当群聊中用户@ webhook机器人时，服务端会把该条消息通过 POST 请求发送给第三方，例如：[POST] https://xz.wps.cn/api/v1/test

#### 请求参数

|   **参数**    |  **类型**  | **位置** | **说明**                               |
| :------- | :---- | :-------| :------------------------------- |
| chatid   | int64  | body | 会话 id                            |
| creator  | int64  | body | 发送者 id                          |
| content  | string | body | 内容                               |
| reply   | object | body | 回复内容                           |
| ∟ reply_content | string | body |     回复内容      |
| ∟ reply_creator | int64  | body | 回复消息发送者 id |
| robot_key | string | body | 机器人 key                         |
| url    | string | body | callback 地址创建者所填的 url 地址 |
| ctime   | int64  | body | 发送时间                           |

#### 请求参数示例

```
{
    "chatid": 12345,
    "creator": 2324234,
    "content": "@webhook机器人  111",
    "reply": {
        "reply_content": "回复内容",
        "reply_creator": 1234
    },
    "robot_key": "xxx",
    "url": "https://xxxx",
    "ctime": 3452452
}
```

#### 返回结果示例

```JSON
{
    "result":"ok"
}
```


## webhook机器人的安全设置

如果开发者未保管好 webhook 地址，可能存在地址泄漏后被恶意用来发送垃圾信息的风险，建议开发者至少选择配置一个安全设置。

### 自定义关键词

设置后，发送的消息需包含至少一个关键词，最多设置 10 个关键词。
示例：设置了关键词：报警、告警后，通过 webhook 机器人发送的消息需带有至少一个关键词，才可以发送成功。

### IP 白名单

设置后，只处理来自 IP 白名单地址范围内的请求，最多设置 10 个 IP 地址/地址段，如：192.168.1.1 或 192.168.1.1/24 或 192.168.1.\*。

### 签名校验

设置后，发送请求时需要签名验证来保障信息来源可信。

- 用户可以在 HTTP Header 中包含签名 （Authorization）。
- 签名头 （Authorization）验证码计算方法如下：Authorization:" key + ":" + sha1( secret_key + Content-Md5 + Content-Type + DATE)。

注意: HTTP Header 中必须包含以下字段

- Content-Md5 HTTP Body 中数据的 md5 值十六进制表达方式, 必需小写。
- Content-Type 目前固定为: application/json。
- DATE 取当前时间, 格式: Wed, 23 Jan 2013 06:43:08 GMT,签名默认有效时间为 15 分钟。
- Authorization 上面所说的签名头。

#### 签名代码示例

**Header**

```json
POST https://xz.wps.cn/api/v1/webhook/send
Content-Md5: d41d8cd98f00b204e9800998ecf8427e
Content-Type: application/json
DATE: Wed, 19 Oct 2021 02:16:08 GMT
Authorization:63840ea636369968f9e0de63c0ee02a1:2b9725f94fcf45216edb5392fa540e2083c25b6f
```

**go 示例代码**

```json
var calcContentMD5 string
    // 检查Date是否超过15分钟
    dateTime, err := time.Parse(layout, webhookSendRequest.Date)
    if err != nil {
        return robot.ErrWebhookSendByTimestamp

    }
    deltaTime := time.Now().Sub(dateTime)
    if deltaTime < -15*time.Minute || deltaTime > 15*time.Minute {
        return robot.ErrWebhookSendByTimestamp

    }

    // 检查Content-Md5
    contentMD5Array := md5.Sum(webhookSendRequest.Content)
    calcContentMD5 = hex.EncodeToString(contentMD5Array[:])
    if webhookSendRequest.ContentMD5 != calcContentMD5 {
        return robot.ErrWebhookSendBySign
    }

    //获取sign
    splits := strings.Split(webhookSendRequest.Auth, ":")
    if len(splits) != 2 {
        return robot.ErrWebhookSendBySign

    }
    // 计算签名
    str := secretKey + webhookSendRequest.ContentMD5 + webhookSendRequest.ContentType + webhookSendRequest.Date
    sigBytes := sha1.Sum([]byte(str))
    sig := hex.EncodeToString(sigBytes[:])
    if sig != splits[1] {
        return robot.ErrWebhookSendBySign
    }
```

### 特权用户设置

设置后，只有群主、管理员和 webhook 机器人的添加者，可以编辑或移除此机器人。

![callback](https://cloudcdn.qwps.cn/open/_img/c899100682.jpg)