py-wecom-toolkit 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- py_wecom_toolkit-1.0.0/LICENSE +21 -0
- py_wecom_toolkit-1.0.0/PKG-INFO +522 -0
- py_wecom_toolkit-1.0.0/README.md +459 -0
- py_wecom_toolkit-1.0.0/pyproject.toml +59 -0
- py_wecom_toolkit-1.0.0/setup.cfg +4 -0
- py_wecom_toolkit-1.0.0/src/py_wecom_toolkit/__init__.py +43 -0
- py_wecom_toolkit-1.0.0/src/py_wecom_toolkit/server/__init__.py +559 -0
- py_wecom_toolkit-1.0.0/src/py_wecom_toolkit/server/materials.py +256 -0
- py_wecom_toolkit-1.0.0/src/py_wecom_toolkit/server/messages.py +793 -0
- py_wecom_toolkit-1.0.0/src/py_wecom_toolkit/server/responses.py +59 -0
- py_wecom_toolkit-1.0.0/src/py_wecom_toolkit/server/utils.py +158 -0
- py_wecom_toolkit-1.0.0/src/py_wecom_toolkit/webhook/__init__.py +406 -0
- py_wecom_toolkit-1.0.0/src/py_wecom_toolkit/webhook/messages.py +971 -0
- py_wecom_toolkit-1.0.0/src/py_wecom_toolkit/webhook/responses.py +191 -0
- py_wecom_toolkit-1.0.0/src/py_wecom_toolkit/webhook/utils.py +310 -0
- py_wecom_toolkit-1.0.0/src/py_wecom_toolkit.egg-info/PKG-INFO +522 -0
- py_wecom_toolkit-1.0.0/src/py_wecom_toolkit.egg-info/SOURCES.txt +18 -0
- py_wecom_toolkit-1.0.0/src/py_wecom_toolkit.egg-info/dependency_links.txt +1 -0
- py_wecom_toolkit-1.0.0/src/py_wecom_toolkit.egg-info/requires.txt +15 -0
- py_wecom_toolkit-1.0.0/src/py_wecom_toolkit.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 郭磊
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: py-wecom-toolkit
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: 企业微信 SDK,提供企业微信 API 的 Python 封装,支持同步和异步调用。
|
|
5
|
+
Author-email: Guolei <174000902@qq.com>
|
|
6
|
+
Maintainer-email: Guolei <174000902@qq.com>
|
|
7
|
+
License: MIT License
|
|
8
|
+
|
|
9
|
+
Copyright (c) 2026 郭磊
|
|
10
|
+
|
|
11
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
13
|
+
in the Software without restriction, including without limitation the rights
|
|
14
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
15
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
16
|
+
furnished to do so, subject to the following conditions:
|
|
17
|
+
|
|
18
|
+
The above copyright notice and this permission notice shall be included in all
|
|
19
|
+
copies or substantial portions of the Software.
|
|
20
|
+
|
|
21
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
22
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
23
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
24
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
25
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
26
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
27
|
+
SOFTWARE.
|
|
28
|
+
|
|
29
|
+
Project-URL: Homepage, https://gitee.com/guolei19850528/py_wecom_toolkit
|
|
30
|
+
Project-URL: Repository, https://gitee.com/guolei19850528/py_wecom_toolkit.git
|
|
31
|
+
Project-URL: Documentation, https://gitee.com/guolei19850528/py_wecom_toolkit
|
|
32
|
+
Keywords: wecom,python,client,api,企业微信,异步调用,server,消息推送,文件上传,webhook,机器人
|
|
33
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
34
|
+
Classifier: Development Status :: 4 - Beta
|
|
35
|
+
Classifier: Intended Audience :: Developers
|
|
36
|
+
Classifier: Programming Language :: Python :: 3
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
41
|
+
Classifier: Operating System :: OS Independent
|
|
42
|
+
Classifier: Topic :: Communications
|
|
43
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
44
|
+
Classifier: Typing :: Typed
|
|
45
|
+
Requires-Python: >=3.10
|
|
46
|
+
Description-Content-Type: text/markdown
|
|
47
|
+
License-File: LICENSE
|
|
48
|
+
Requires-Dist: httpx>=0.27.0
|
|
49
|
+
Requires-Dist: pydantic>=2.0
|
|
50
|
+
Requires-Dist: jsonpath-ng>=1.5.3
|
|
51
|
+
Requires-Dist: jsonschema>=4.21.0
|
|
52
|
+
Requires-Dist: diskcache>=5.6.3
|
|
53
|
+
Requires-Dist: redis>=4.6.0
|
|
54
|
+
Requires-Dist: py-httpx-toolkit>=1.0.1
|
|
55
|
+
Provides-Extra: dev
|
|
56
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
57
|
+
Requires-Dist: pytest-cov>=4.0; extra == "dev"
|
|
58
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
59
|
+
Requires-Dist: setuptools>=61.0; extra == "dev"
|
|
60
|
+
Requires-Dist: twine>=4.0; extra == "dev"
|
|
61
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
62
|
+
Dynamic: license-file
|
|
63
|
+
|
|
64
|
+
# py-wecom-toolkit
|
|
65
|
+
|
|
66
|
+
企业微信 API 的 Python SDK,提供完整的企业微信接口封装,支持同步和异步调用方式。
|
|
67
|
+
|
|
68
|
+
## 项目主页
|
|
69
|
+
|
|
70
|
+
- **项目地址**: [https://gitee.com/guolei19850528/py_wecom_toolkit](https://gitee.com/guolei19850528/py_wecom_toolkit)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
## 功能特性
|
|
74
|
+
|
|
75
|
+
### Webhook 模块 (`py_wecom_toolkit.webhook`)
|
|
76
|
+
- 企业微信 Webhook 消息发送
|
|
77
|
+
- 支持文本、Markdown、MarkdownV2、图片、图文、文件、语音、模板卡片等消息类型
|
|
78
|
+
- 支持同步和异步两种调用方式
|
|
79
|
+
- 媒体文件上传功能
|
|
80
|
+
|
|
81
|
+
### Server 模块 (`py_wecom_toolkit.server`)
|
|
82
|
+
- 企业微信 Server API 集成
|
|
83
|
+
- 获取 access_token(支持 diskcache 和 Redis 缓存)
|
|
84
|
+
- 获取 API 域名 IP 列表
|
|
85
|
+
- 获取回调 IP 列表
|
|
86
|
+
- 消息发送和素材管理
|
|
87
|
+
- 支持同步和异步两种调用方式
|
|
88
|
+
|
|
89
|
+
## 依赖包
|
|
90
|
+
|
|
91
|
+
```txt
|
|
92
|
+
httpx>=0.27.0
|
|
93
|
+
pydantic>=2.0
|
|
94
|
+
jsonpath-ng>=1.5.3
|
|
95
|
+
jsonschema>=4.21.0
|
|
96
|
+
diskcache>=5.6.3
|
|
97
|
+
redis>=4.6.0
|
|
98
|
+
py-httpx-toolkit>=1.0.1
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## 安装方式
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
pip install py-wecom-toolkit
|
|
105
|
+
```
|
|
106
|
+
### UV 安装
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
|
|
110
|
+
uv add py-wecom-toolkit
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
## 项目结构
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
src/py_wecom_toolkit/
|
|
118
|
+
├── __init__.py # 主模块入口
|
|
119
|
+
├── server/ # Server API 模块
|
|
120
|
+
│ ├── __init__.py # Base 类(access_token管理、IP查询)
|
|
121
|
+
│ ├── materials.py # 素材管理
|
|
122
|
+
│ ├── messages.py # 消息模型
|
|
123
|
+
│ ├── responses.py # 响应模型
|
|
124
|
+
│ └── utils.py # 工具函数
|
|
125
|
+
└── webhook/ # Webhook 模块
|
|
126
|
+
├── __init__.py # Webhook 客户端类
|
|
127
|
+
├── messages.py # 消息模型
|
|
128
|
+
├── responses.py # 响应模型
|
|
129
|
+
└── utils.py # 工具函数
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## 使用示例
|
|
133
|
+
|
|
134
|
+
### Webhook 使用示例
|
|
135
|
+
|
|
136
|
+
**同步发送文本消息**:
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
from py_wecom_toolkit.webhook import Webhook
|
|
140
|
+
from py_wecom_toolkit.webhook.messages import Text, TextContent
|
|
141
|
+
|
|
142
|
+
# 初始化 Webhook
|
|
143
|
+
webhook = Webhook(key="your_webhook_key")
|
|
144
|
+
|
|
145
|
+
# 发送文本消息
|
|
146
|
+
response = webhook.send(Text(text=TextContent(content="Hello World")))
|
|
147
|
+
print(response.json())
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
**异步发送消息**:
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
import asyncio
|
|
154
|
+
from py_wecom_toolkit.webhook import Webhook
|
|
155
|
+
from py_wecom_toolkit.webhook.messages import Markdown, MarkdownContent
|
|
156
|
+
|
|
157
|
+
async def main():
|
|
158
|
+
webhook = Webhook(key="your_webhook_key")
|
|
159
|
+
response = await webhook.async_send(
|
|
160
|
+
Markdown(markdown=MarkdownContent(content="**Hello** from async"))
|
|
161
|
+
)
|
|
162
|
+
print(response.json())
|
|
163
|
+
|
|
164
|
+
asyncio.run(main())
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**上传媒体文件**:
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
from py_wecom_toolkit.webhook import Webhook
|
|
171
|
+
|
|
172
|
+
webhook = Webhook(key="your_webhook_key")
|
|
173
|
+
|
|
174
|
+
with open("test.txt", "rb") as f:
|
|
175
|
+
response = webhook.upload_media(files={"file": ("test.txt", f)})
|
|
176
|
+
print(response.json()) # {"errcode": 0, "media_id": "xxx", ...}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Server 使用示例
|
|
180
|
+
|
|
181
|
+
**获取 access_token**:
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
from py_wecom_toolkit.server import Base
|
|
185
|
+
from diskcache import Cache
|
|
186
|
+
|
|
187
|
+
# 创建缓存实例
|
|
188
|
+
cache = Cache("./cache")
|
|
189
|
+
|
|
190
|
+
# 初始化 Server 客户端
|
|
191
|
+
server = Base(
|
|
192
|
+
corpid="your_corpid",
|
|
193
|
+
corpsecret="your_corpsecret",
|
|
194
|
+
cache_config={"instance": cache}
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
# 刷新 access_token
|
|
198
|
+
server.refresh_access_token()
|
|
199
|
+
print(server.access_token)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**异步获取 access_token**:
|
|
203
|
+
|
|
204
|
+
```python
|
|
205
|
+
import asyncio
|
|
206
|
+
import redis
|
|
207
|
+
from py_wecom_toolkit.server import Base
|
|
208
|
+
|
|
209
|
+
async def main():
|
|
210
|
+
r = redis.Redis(host='localhost', port=6379, db=0)
|
|
211
|
+
server = Base(
|
|
212
|
+
corpid="your_corpid",
|
|
213
|
+
corpsecret="your_corpsecret",
|
|
214
|
+
cache_config={"instance": r}
|
|
215
|
+
)
|
|
216
|
+
await server.async_refresh_access_token()
|
|
217
|
+
print(server.access_token)
|
|
218
|
+
|
|
219
|
+
asyncio.run(main())
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
**获取回调 IP**:
|
|
223
|
+
|
|
224
|
+
```python
|
|
225
|
+
from py_wecom_toolkit.server import Base
|
|
226
|
+
|
|
227
|
+
server = Base(corpid="your_corpid", corpsecret="your_corpsecret")
|
|
228
|
+
server.refresh_access_token()
|
|
229
|
+
response = server.getcallbackip()
|
|
230
|
+
print(response.json())
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## API 说明
|
|
234
|
+
|
|
235
|
+
### Webhook 模块 API
|
|
236
|
+
|
|
237
|
+
#### Webhook 类
|
|
238
|
+
|
|
239
|
+
**初始化参数**:
|
|
240
|
+
|
|
241
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
242
|
+
|------|------|------|--------|------|
|
|
243
|
+
| key | str | 是 | - | Webhook密钥 |
|
|
244
|
+
| base_url | str | 否 | `https://qyapi.weixin.qq.com/` | 企业微信API基础URL |
|
|
245
|
+
| mentioned_list | list/tuple | 否 | `[]` | 默认@用户ID列表 |
|
|
246
|
+
| mentioned_mobile_list | list/tuple | 否 | `[]` | 默认@用户手机号列表 |
|
|
247
|
+
| client_kwargs | dict | 否 | `{}` | HTTP客户端配置参数 |
|
|
248
|
+
|
|
249
|
+
**方法**:
|
|
250
|
+
|
|
251
|
+
| 方法名 | 说明 | 参数 | 返回值 |
|
|
252
|
+
|--------|------|------|--------|
|
|
253
|
+
| `send(message)` | 同步发送消息 | `message`: 消息对象或字典 | `httpx.Response` |
|
|
254
|
+
| `async_send(message)` | 异步发送消息 | `message`: 消息对象或字典 | `await httpx.Response` |
|
|
255
|
+
| `upload_media(file_type, **kwargs)` | 同步上传媒体文件 | `file_type`: "file"或"voice",`files`: 文件参数 | `httpx.Response` |
|
|
256
|
+
| `async_upload_media(file_type, **kwargs)` | 异步上传媒体文件 | `file_type`: "file"或"voice",`files`: 文件参数 | `await httpx.Response` |
|
|
257
|
+
|
|
258
|
+
#### Webhook 消息类型
|
|
259
|
+
|
|
260
|
+
| 消息类型 | 类名 | 说明 |
|
|
261
|
+
|----------|------|------|
|
|
262
|
+
| 文本 | `Text` | 支持@用户,最长2048字节 |
|
|
263
|
+
| Markdown | `Markdown` | 支持标准Markdown语法 |
|
|
264
|
+
| MarkdownV2 | `MarkdownV2` | 支持字体颜色等扩展样式 |
|
|
265
|
+
| 图片 | `Image` | 需要base64编码和md5值 |
|
|
266
|
+
| 图文 | `News` | 支持1-8篇文章 |
|
|
267
|
+
| 文件 | `File` | 需要先上传获取media_id |
|
|
268
|
+
| 语音 | `Voice` | 需要先上传获取media_id |
|
|
269
|
+
| 模板卡片 | `TemplateCard` | 支持多种卡片类型 |
|
|
270
|
+
|
|
271
|
+
**文本消息示例**:
|
|
272
|
+
|
|
273
|
+
```python
|
|
274
|
+
from py_wecom_toolkit.webhook.messages import Text, TextContent
|
|
275
|
+
|
|
276
|
+
message = Text(
|
|
277
|
+
text=TextContent(
|
|
278
|
+
content="Hello World",
|
|
279
|
+
mentioned_list=["user1", "@all"],
|
|
280
|
+
mentioned_mobile_list=["13800138000"]
|
|
281
|
+
)
|
|
282
|
+
)
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
**图文消息示例**:
|
|
286
|
+
|
|
287
|
+
```python
|
|
288
|
+
from py_wecom_toolkit.webhook.messages import News, NewsContent, NewsArticle
|
|
289
|
+
|
|
290
|
+
message = News(
|
|
291
|
+
news=NewsContent(
|
|
292
|
+
articles=[
|
|
293
|
+
NewsArticle(
|
|
294
|
+
title="文章标题",
|
|
295
|
+
description="文章描述",
|
|
296
|
+
url="https://example.com",
|
|
297
|
+
picurl="https://example.com/image.jpg"
|
|
298
|
+
)
|
|
299
|
+
]
|
|
300
|
+
)
|
|
301
|
+
)
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Server 模块 API
|
|
305
|
+
|
|
306
|
+
#### Base 类
|
|
307
|
+
|
|
308
|
+
**初始化参数**:
|
|
309
|
+
|
|
310
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
311
|
+
|------|------|------|--------|------|
|
|
312
|
+
| corpid | str | 是 | - | 企业ID |
|
|
313
|
+
| corpsecret | str | 是 | - | 应用密钥 |
|
|
314
|
+
| agentid | str/int | 否 | - | 企业应用ID |
|
|
315
|
+
| base_url | str | 否 | `https://qyapi.weixin.qq.com/` | 企业微信API基础URL |
|
|
316
|
+
| cache_config | dict | 否 | `{}` | 缓存配置 |
|
|
317
|
+
| client_kwargs | dict | 否 | `{}` | HTTP客户端配置参数 |
|
|
318
|
+
|
|
319
|
+
**cache_config 参数**:
|
|
320
|
+
|
|
321
|
+
| 参数 | 类型 | 必填 | 默认值 | 说明 |
|
|
322
|
+
|------|------|------|--------|------|
|
|
323
|
+
| instance | Cache/Redis | 否 | `None` | 缓存实例(diskcache.Cache或redis.Redis) |
|
|
324
|
+
| key | str | 否 | `pywecom_server_{corpid}_{agentid}` | 缓存键名 |
|
|
325
|
+
| expire | int | 否 | `7100` | 缓存过期时间(秒) |
|
|
326
|
+
|
|
327
|
+
**方法**:
|
|
328
|
+
|
|
329
|
+
| 方法名 | 说明 | 参数 | 返回值 |
|
|
330
|
+
|--------|------|------|--------|
|
|
331
|
+
| `gettoken()` | 同步获取access_token | - | `httpx.Response` |
|
|
332
|
+
| `async_gettoken()` | 异步获取access_token | - | `await httpx.Response` |
|
|
333
|
+
| `get_api_domain_ip()` | 同步获取API域名IP | - | `httpx.Response` |
|
|
334
|
+
| `async_get_api_domain_ip()` | 异步获取API域名IP | - | `await httpx.Response` |
|
|
335
|
+
| `getcallbackip()` | 同步获取回调IP | - | `httpx.Response` |
|
|
336
|
+
| `async_getcallbackip()` | 异步获取回调IP | - | `await httpx.Response` |
|
|
337
|
+
| `refresh_access_token()` | 同步刷新access_token | `cache_config` | `self` |
|
|
338
|
+
| `async_refresh_access_token()` | 异步刷新access_token | `cache_config` | `await self` |
|
|
339
|
+
|
|
340
|
+
#### Sender 类
|
|
341
|
+
|
|
342
|
+
继承自 `Base` 类,新增消息发送方法:
|
|
343
|
+
|
|
344
|
+
| 方法名 | 说明 | 参数 | 返回值 |
|
|
345
|
+
|--------|------|------|--------|
|
|
346
|
+
| `send(message)` | 同步发送消息 | `message`: 消息对象或字典 | `httpx.Response` |
|
|
347
|
+
| `async_send(message)` | 异步发送消息 | `message`: 消息对象或字典 | `await httpx.Response` |
|
|
348
|
+
|
|
349
|
+
#### Server 消息类型
|
|
350
|
+
|
|
351
|
+
| 消息类型 | 类名 | 说明 |
|
|
352
|
+
|----------|------|------|
|
|
353
|
+
| 文本 | `Text` | 支持@用户 |
|
|
354
|
+
| 图片 | `Image` | 需要media_id |
|
|
355
|
+
| 语音 | `Voice` | 需要media_id |
|
|
356
|
+
| 视频 | `Video` | 需要media_id |
|
|
357
|
+
| 文件 | `File` | 需要media_id |
|
|
358
|
+
| 文本卡片 | `TextCard` | 带标题和链接的卡片 |
|
|
359
|
+
| 图文 | `News` | 支持1-8篇文章 |
|
|
360
|
+
| 图文(mpnews) | `MpNews` | 素材库文章 |
|
|
361
|
+
| Markdown | `Markdown` | Markdown格式消息 |
|
|
362
|
+
| 小程序通知 | `MiniprogramNotice` | 小程序模板消息 |
|
|
363
|
+
| 模板卡片 | `TemplateCard` | 支持多种卡片类型 |
|
|
364
|
+
|
|
365
|
+
**发送文本消息示例**:
|
|
366
|
+
|
|
367
|
+
```python
|
|
368
|
+
from py_wecom_toolkit.server.messages import Sender, Text, TextContent
|
|
369
|
+
|
|
370
|
+
sender = Sender(corpid="your_corpid", corpsecret="your_corpsecret", agentid=1000001)
|
|
371
|
+
sender.refresh_access_token()
|
|
372
|
+
response = sender.send(Text(text=TextContent(content="Hello")))
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
**发送图文消息示例**:
|
|
376
|
+
|
|
377
|
+
```python
|
|
378
|
+
from py_wecom_toolkit.server.messages import Sender, News, NewsArticlesContent, NewsArticleContent
|
|
379
|
+
|
|
380
|
+
sender = Sender(corpid="your_corpid", corpsecret="your_corpsecret", agentid=1000001)
|
|
381
|
+
sender.refresh_access_token()
|
|
382
|
+
|
|
383
|
+
message = News(
|
|
384
|
+
news=NewsArticlesContent(
|
|
385
|
+
articles=[
|
|
386
|
+
NewsArticleContent(
|
|
387
|
+
title="文章标题",
|
|
388
|
+
description="描述",
|
|
389
|
+
url="https://example.com",
|
|
390
|
+
picurl="https://example.com/image.jpg"
|
|
391
|
+
)
|
|
392
|
+
]
|
|
393
|
+
)
|
|
394
|
+
)
|
|
395
|
+
response = sender.send(message)
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### 响应模型
|
|
399
|
+
|
|
400
|
+
响应结果可通过 `response.json()` 获取,企业微信API响应结构:
|
|
401
|
+
|
|
402
|
+
```python
|
|
403
|
+
{
|
|
404
|
+
"errcode": 0, # 错误码,0表示成功
|
|
405
|
+
"errmsg": "ok", # 错误信息
|
|
406
|
+
"access_token": "...", # access_token(仅gettoken接口)
|
|
407
|
+
"media_id": "...", # 媒体文件ID(仅上传接口)
|
|
408
|
+
"ip_list": [...] # IP列表(仅IP查询接口)
|
|
409
|
+
}
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
**错误码说明**:
|
|
413
|
+
|
|
414
|
+
| 错误码 | 说明 |
|
|
415
|
+
|--------|------|
|
|
416
|
+
| 0 | 成功 |
|
|
417
|
+
| 40001 | 获取access_token时AppSecret错误 |
|
|
418
|
+
| 40002 | 不合法的凭证类型 |
|
|
419
|
+
| 40003 | 不合法的UserID |
|
|
420
|
+
| 40014 | 不合法的access_token |
|
|
421
|
+
| 40033 | 不合法的字符 |
|
|
422
|
+
| 40056 | 不合法的agentid |
|
|
423
|
+
| 40060 | 不合法的media_id |
|
|
424
|
+
| 50000 | 企业不存在 |
|
|
425
|
+
| 60001 | 应用不存在 |
|
|
426
|
+
| 60002 | 应用已停用 |
|
|
427
|
+
|
|
428
|
+
## 工具函数说明
|
|
429
|
+
|
|
430
|
+
### Webhook 工具函数 (`py_wecom_toolkit.webhook.utils`)
|
|
431
|
+
|
|
432
|
+
| 函数名 | 说明 | 参数 | 返回值 |
|
|
433
|
+
|--------|------|------|--------|
|
|
434
|
+
| `json_find_first(expression, data)` | 使用JSONPath查找第一个匹配项 | `expression`: JSONPath表达式,`data`: JSON数据 | 匹配值或None |
|
|
435
|
+
| `json_is_valid(schema, data)` | JSON Schema校验 | `schema`: Schema字典,`data`: 待校验数据 | bool |
|
|
436
|
+
| `image_to_base64_and_md5(image_path)` | 图片转Base64和MD5 | `image_path`: 图片文件路径 | Tuple[str, str] |
|
|
437
|
+
| `build_success_instance(response)` | 转换为Success响应模型 | `response`: Response对象或dict | Success |
|
|
438
|
+
| `build_send_instance(response)` | 转换为Send响应模型 | `response`: Response对象或dict | Send |
|
|
439
|
+
| `build_upload_media_instance(response)` | 转换为UploadMedia响应模型 | `response`: Response对象或dict | UploadMedia |
|
|
440
|
+
| `success_validator(response, schema)` | 校验errcode是否为0 | `response`: Response对象或dict | bool |
|
|
441
|
+
|
|
442
|
+
**图片转换示例**:
|
|
443
|
+
|
|
444
|
+
```python
|
|
445
|
+
from py_wecom_toolkit.webhook.utils import image_to_base64_and_md5
|
|
446
|
+
from py_wecom_toolkit.webhook.messages import Image, ImageContent
|
|
447
|
+
|
|
448
|
+
base64_str, md5_str = image_to_base64_and_md5("path/to/image.jpg")
|
|
449
|
+
message = Image(image=ImageContent(base64=base64_str, md5=md5_str))
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
**响应校验示例**:
|
|
453
|
+
|
|
454
|
+
```python
|
|
455
|
+
from py_wecom_toolkit.webhook import Webhook
|
|
456
|
+
from py_wecom_toolkit.webhook.utils import build_send_instance, success_validator
|
|
457
|
+
|
|
458
|
+
webhook = Webhook(key="your_key")
|
|
459
|
+
response = webhook.send(message)
|
|
460
|
+
|
|
461
|
+
# 校验响应
|
|
462
|
+
if success_validator(response):
|
|
463
|
+
result = build_send_instance(response)
|
|
464
|
+
print(f"发送成功: {result.errmsg}")
|
|
465
|
+
else:
|
|
466
|
+
print("发送失败")
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
### Server 工具函数 (`py_wecom_toolkit.server.utils`)
|
|
470
|
+
|
|
471
|
+
| 函数名 | 说明 | 参数 | 返回值 |
|
|
472
|
+
|--------|------|------|--------|
|
|
473
|
+
| `json_find_first(expression, data)` | 使用JSONPath查找第一个匹配项 | `expression`: JSONPath表达式,`data`: JSON数据 | 匹配值或None |
|
|
474
|
+
| `json_is_valid(schema, data)` | JSON Schema校验 | `schema`: Schema字典,`data`: 待校验数据 | bool |
|
|
475
|
+
| `build_success_instance(response)` | 转换为Success响应模型 | `response`: Response对象或dict | Success |
|
|
476
|
+
| `success_is_valid(response, schema)` | 校验errcode是否为0 | `response`: Response对象或dict | bool |
|
|
477
|
+
|
|
478
|
+
**响应校验示例**:
|
|
479
|
+
|
|
480
|
+
```python
|
|
481
|
+
from py_wecom_toolkit.server.messages import Sender, Text, TextContent
|
|
482
|
+
from py_wecom_toolkit.server.utils import build_success_instance, success_is_valid
|
|
483
|
+
|
|
484
|
+
sender = Sender(corpid="your_corpid", corpsecret="your_corpsecret", agentid=1000001)
|
|
485
|
+
sender.refresh_access_token()
|
|
486
|
+
response = sender.send(Text(text=TextContent(content="Hello")))
|
|
487
|
+
|
|
488
|
+
# 校验响应
|
|
489
|
+
if success_is_valid(response):
|
|
490
|
+
result = build_success_instance(response)
|
|
491
|
+
print(f"发送成功: {result.errmsg}")
|
|
492
|
+
else:
|
|
493
|
+
print("发送失败")
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
**JSONPath查找示例**:
|
|
497
|
+
|
|
498
|
+
```python
|
|
499
|
+
from py_wecom_toolkit.server.utils import json_find_first
|
|
500
|
+
|
|
501
|
+
data = {
|
|
502
|
+
"result": {
|
|
503
|
+
"items": [
|
|
504
|
+
{"id": 1, "name": "item1"},
|
|
505
|
+
{"id": 2, "name": "item2"}
|
|
506
|
+
]
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
# 使用JSONPath查找第一个item的name
|
|
511
|
+
name = json_find_first("$.result.items[0].name", data)
|
|
512
|
+
print(name) # item1
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
## 参考文档
|
|
516
|
+
|
|
517
|
+
- [企业微信 Webhook API](https://developer.work.weixin.qq.com/document/path/91770)
|
|
518
|
+
- [企业微信 Server API](https://developer.work.weixin.qq.com/document/path/90664)
|
|
519
|
+
|
|
520
|
+
## 许可证
|
|
521
|
+
|
|
522
|
+
MIT License
|