wechat-enterprise-sdk


Namewechat-enterprise-sdk JSON
Version 1.0.1 PyPI version JSON
download
home_pagehttps://github.com/somenzz/wechat_enterprise
SummaryNone
upload_time2025-10-25 02:57:24
maintainerNone
docs_urlNone
authorsomenzz
requires_pythonNone
licenseMIT
keywords python wechat enterprise wechat_enterprise send message
VCS
bugtrack_url
requirements requests requests_toolbelt
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 用 Python 发送企业微信消息

[](https://pypi.org/project/wechat-enterprise-sdk/)
[](https://opensource.org/licenses/MIT)

一个用于发送企业微信应用消息的 Python SDK,内置智能 Access Token 缓存。

## 核心特性

  * **消息发送**:支持发送文本、Markdown、图片、文件等消息。
  * **智能混合缓存**:自动管理 `access_token`,结合**内存缓存**(适用于常驻服务)和**文件缓存**(适用于高频短脚本,如 Cron),自动续期,避免 API 频率限制。
  * **API 封装**:简洁的 API,已封装获取部门、成员信息、手机号换 UserID 等常用接口。
  * **健壮的错误处理**:自动处理 API 响应,非 0 `errcode` 将抛出 `WechatEnterpriseError` 异常。

## 安装

```sh
pip install wechat-enterprise-sdk
```

本库依赖 `requests`。

## 快速上手

下面是一个完整的使用示例:

```python
from pathlib import Path
from wechat_enterprise import WechatEnterprise, WechatEnterpriseError

if __name__ == '__main__':
    # 替换为你自己的企业微信凭证
    CORP_ID = "YOUR_CORP_ID"
    APP_ID = "YOUR_APP_ID"        # (AgentId)
    CORP_SECRET = "YOUR_CORP_SECRET"

    # 接收消息的用户账号
    USER_LIST = ["ZhangSan", "LiSi"]

    try:
        # 1. 初始化
        # 默认会在当前目录创建 'we_token_cache.json' 用于文件缓存
        wechat = WechatEnterprise(corpid=CORP_ID, ...appid=APP_ID, corpsecret=CORP_SECRET)

        # 2. 发送文本
        print("正在发送文本消息...")
        response_text = wechat.send_text("这是一条来自 SDK 的测试文本消息。", USER_LIST)
        print(f"发送成功: {response_text}")

        # 3. 发送 Markdown
        print("\n正在发送 Markdown 消息...")
        markdown_content = (
            "**Markdown 测试**\n"
            "> 引用内容\n"
            "包含 `code` 和 [链接](https://work.weixin.qq.com/api/doc/90000/90135/90236)"
        )
        response_md = wechat.send_markdown(markdown_content, USER_LIST)
        print(f"发送成功: {response_md}")

        # 4. 发送文件 (示例)
        # print("\n正在发送文件...")
        # test_file_path = "./test_upload.txt"
        # with open(test_file_path, "w") as f:
        #     f.write("这是一个测试上传的文件。")
        #
        # response_file = wechat.send_file(test_file_path, USER_LIST)
        # print(f"发送成功: {response_file}")

        # 5. 获取用户信息
        print(f"\n正在获取用户 {USER_LIST[0]} 的信息...")
        user_info = wechat.get_user_info(USER_LIST[0])
        print(f"获取成功: {user_info.get('name')}")
        
        # 6. 根据手机号获取 userid
        # user_id = wechat.get_userid("13800138000")
        # print(f"\n手机号对应的 userid: {user_id}")


    except WechatEnterpriseError as e:
        # 捕获 API 业务异常
        print(f"企业微信 API 出错: {e}")
    except Exception as e:
        # 捕获其他异常,如网络连接、文件读写等
        print(f"发生其他错误: {e}")
```

## 核心功能:Access Token 混合缓存

为了避免 `access_token` 在常驻内存的程序中和频繁调用的短脚本中被过度请求,本库默认启用了一个\*\*内存缓存(一级)+ 文件缓存(二级)\*\*的混合策略。

  * **内存缓存**:Token 加载到实例内存中,在程序/实例的生命周期内极速获取。
  * **文件缓存**:当内存缓存失效时(如脚本重启),会尝试从文件加载 Token,避免了不必要的 API 请求。

### 1\. 默认行为 (推荐)

默认情况下,文件缓存被启用,并会在当前工作目录创建 `we_token_cache.json` 文件。

```python
# 将在 ./we_token_cache.json 读写缓存
wechat = WechatEnterprise(CORP_ID, APP_ID, CORP_SECRET)
```

### 2\. 自定义缓存路径

你可以通过 `cache_path` 参数指定一个自定义的 `Path` 对象路径。

```python
from pathlib import Path

# 指定缓存文件到 /tmp/cache/ 目录下
custom_path = Path("/tmp/cache/my_wechat_token.json")
wechat = WechatEnterprise(CORP_ID, APP_ID, CORP_SECRET, cache_path=custom_path)
```

### 3\. 禁用文件缓存 (仅使用内存缓存)

如果你在只读文件系统(如某些 Serverless 环境)或不希望创建文件,可以将 `cache_path` 设为 `None` 来禁用文件缓存。

```python
# 禁用文件缓存,仅使用实例内存缓存
wechat_mem_only = WechatEnterprise(CORP_ID, APP_ID, CORP_SECRET, cache_path=None)
```

## API 概览

### 消息发送

  * `wechat.send_text(content: str, users: List[str]) -> dict`
  * `wechat.send_markdown(content: str, users: List[str]) -> dict`
  * `wechat.send_image(image_path: str, users: List[str]) -> dict`
  * `wechat.send_file(file_path: str, users: List[str]) -> dict`

### 用户与部门

  * `wechat.get_user_info(userid: str) -> dict`
      * 获取成员详细信息。
  * `wechat.get_userid(telephone: str) -> Optional[str]`
      * 根据手机号获取成员 `userid`。
  * `wechat.get_department_id(dept_id: int = 0) -> dict`
      * 获取部门列表。
  * `wechat.get_department_userlist(department_id: int = 1) -> dict`
      * 获取部门成员简易列表。

## Todo

  * [ ] 添加企业微信的其他实用功能(如群机器人、审批等)。

## 联系我

添加微信 「somenzz-enjoy」 备注 「github」

个人公众号 「Python七号」,微信搜一搜关注。

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/somenzz/wechat_enterprise",
    "name": "wechat-enterprise-sdk",
    "maintainer": null,
    "docs_url": null,
    "requires_python": null,
    "maintainer_email": null,
    "keywords": "python wechat enterprise, wechat_enterprise, send message",
    "author": "somenzz",
    "author_email": "somenzz@163.com",
    "download_url": "https://files.pythonhosted.org/packages/ee/7a/cb9ccd570dad843fdd285d95f0b2d2b602f38fcc2d844abd1561b80799c8/wechat_enterprise_sdk-1.0.1.tar.gz",
    "platform": null,
    "description": "# \u7528 Python \u53d1\u9001\u4f01\u4e1a\u5fae\u4fe1\u6d88\u606f\n\n[](https://pypi.org/project/wechat-enterprise-sdk/)\n[](https://opensource.org/licenses/MIT)\n\n\u4e00\u4e2a\u7528\u4e8e\u53d1\u9001\u4f01\u4e1a\u5fae\u4fe1\u5e94\u7528\u6d88\u606f\u7684 Python SDK\uff0c\u5185\u7f6e\u667a\u80fd Access Token \u7f13\u5b58\u3002\n\n## \u6838\u5fc3\u7279\u6027\n\n  * **\u6d88\u606f\u53d1\u9001**\uff1a\u652f\u6301\u53d1\u9001\u6587\u672c\u3001Markdown\u3001\u56fe\u7247\u3001\u6587\u4ef6\u7b49\u6d88\u606f\u3002\n  * **\u667a\u80fd\u6df7\u5408\u7f13\u5b58**\uff1a\u81ea\u52a8\u7ba1\u7406 `access_token`\uff0c\u7ed3\u5408**\u5185\u5b58\u7f13\u5b58**\uff08\u9002\u7528\u4e8e\u5e38\u9a7b\u670d\u52a1\uff09\u548c**\u6587\u4ef6\u7f13\u5b58**\uff08\u9002\u7528\u4e8e\u9ad8\u9891\u77ed\u811a\u672c\uff0c\u5982 Cron\uff09\uff0c\u81ea\u52a8\u7eed\u671f\uff0c\u907f\u514d API \u9891\u7387\u9650\u5236\u3002\n  * **API \u5c01\u88c5**\uff1a\u7b80\u6d01\u7684 API\uff0c\u5df2\u5c01\u88c5\u83b7\u53d6\u90e8\u95e8\u3001\u6210\u5458\u4fe1\u606f\u3001\u624b\u673a\u53f7\u6362 UserID \u7b49\u5e38\u7528\u63a5\u53e3\u3002\n  * **\u5065\u58ee\u7684\u9519\u8bef\u5904\u7406**\uff1a\u81ea\u52a8\u5904\u7406 API \u54cd\u5e94\uff0c\u975e 0 `errcode` \u5c06\u629b\u51fa `WechatEnterpriseError` \u5f02\u5e38\u3002\n\n## \u5b89\u88c5\n\n```sh\npip install wechat-enterprise-sdk\n```\n\n\u672c\u5e93\u4f9d\u8d56 `requests`\u3002\n\n## \u5feb\u901f\u4e0a\u624b\n\n\u4e0b\u9762\u662f\u4e00\u4e2a\u5b8c\u6574\u7684\u4f7f\u7528\u793a\u4f8b\uff1a\n\n```python\nfrom pathlib import Path\nfrom wechat_enterprise import WechatEnterprise, WechatEnterpriseError\n\nif __name__ == '__main__':\n    # \u66ff\u6362\u4e3a\u4f60\u81ea\u5df1\u7684\u4f01\u4e1a\u5fae\u4fe1\u51ed\u8bc1\n    CORP_ID = \"YOUR_CORP_ID\"\n    APP_ID = \"YOUR_APP_ID\"        # (AgentId)\n    CORP_SECRET = \"YOUR_CORP_SECRET\"\n\n    # \u63a5\u6536\u6d88\u606f\u7684\u7528\u6237\u8d26\u53f7\n    USER_LIST = [\"ZhangSan\", \"LiSi\"]\n\n    try:\n        # 1. \u521d\u59cb\u5316\n        # \u9ed8\u8ba4\u4f1a\u5728\u5f53\u524d\u76ee\u5f55\u521b\u5efa 'we_token_cache.json' \u7528\u4e8e\u6587\u4ef6\u7f13\u5b58\n        wechat = WechatEnterprise(corpid=CORP_ID, ...appid=APP_ID, corpsecret=CORP_SECRET)\n\n        # 2. \u53d1\u9001\u6587\u672c\n        print(\"\u6b63\u5728\u53d1\u9001\u6587\u672c\u6d88\u606f...\")\n        response_text = wechat.send_text(\"\u8fd9\u662f\u4e00\u6761\u6765\u81ea SDK \u7684\u6d4b\u8bd5\u6587\u672c\u6d88\u606f\u3002\", USER_LIST)\n        print(f\"\u53d1\u9001\u6210\u529f: {response_text}\")\n\n        # 3. \u53d1\u9001 Markdown\n        print(\"\\n\u6b63\u5728\u53d1\u9001 Markdown \u6d88\u606f...\")\n        markdown_content = (\n            \"**Markdown \u6d4b\u8bd5**\\n\"\n            \"> \u5f15\u7528\u5185\u5bb9\\n\"\n            \"\u5305\u542b `code` \u548c [\u94fe\u63a5](https://work.weixin.qq.com/api/doc/90000/90135/90236)\"\n        )\n        response_md = wechat.send_markdown(markdown_content, USER_LIST)\n        print(f\"\u53d1\u9001\u6210\u529f: {response_md}\")\n\n        # 4. \u53d1\u9001\u6587\u4ef6 (\u793a\u4f8b)\n        # print(\"\\n\u6b63\u5728\u53d1\u9001\u6587\u4ef6...\")\n        # test_file_path = \"./test_upload.txt\"\n        # with open(test_file_path, \"w\") as f:\n        #     f.write(\"\u8fd9\u662f\u4e00\u4e2a\u6d4b\u8bd5\u4e0a\u4f20\u7684\u6587\u4ef6\u3002\")\n        #\n        # response_file = wechat.send_file(test_file_path, USER_LIST)\n        # print(f\"\u53d1\u9001\u6210\u529f: {response_file}\")\n\n        # 5. \u83b7\u53d6\u7528\u6237\u4fe1\u606f\n        print(f\"\\n\u6b63\u5728\u83b7\u53d6\u7528\u6237 {USER_LIST[0]} \u7684\u4fe1\u606f...\")\n        user_info = wechat.get_user_info(USER_LIST[0])\n        print(f\"\u83b7\u53d6\u6210\u529f: {user_info.get('name')}\")\n        \n        # 6. \u6839\u636e\u624b\u673a\u53f7\u83b7\u53d6 userid\n        # user_id = wechat.get_userid(\"13800138000\")\n        # print(f\"\\n\u624b\u673a\u53f7\u5bf9\u5e94\u7684 userid: {user_id}\")\n\n\n    except WechatEnterpriseError as e:\n        # \u6355\u83b7 API \u4e1a\u52a1\u5f02\u5e38\n        print(f\"\u4f01\u4e1a\u5fae\u4fe1 API \u51fa\u9519: {e}\")\n    except Exception as e:\n        # \u6355\u83b7\u5176\u4ed6\u5f02\u5e38\uff0c\u5982\u7f51\u7edc\u8fde\u63a5\u3001\u6587\u4ef6\u8bfb\u5199\u7b49\n        print(f\"\u53d1\u751f\u5176\u4ed6\u9519\u8bef: {e}\")\n```\n\n## \u6838\u5fc3\u529f\u80fd\uff1aAccess Token \u6df7\u5408\u7f13\u5b58\n\n\u4e3a\u4e86\u907f\u514d `access_token` \u5728\u5e38\u9a7b\u5185\u5b58\u7684\u7a0b\u5e8f\u4e2d\u548c\u9891\u7e41\u8c03\u7528\u7684\u77ed\u811a\u672c\u4e2d\u88ab\u8fc7\u5ea6\u8bf7\u6c42\uff0c\u672c\u5e93\u9ed8\u8ba4\u542f\u7528\u4e86\u4e00\u4e2a\\*\\*\u5185\u5b58\u7f13\u5b58\uff08\u4e00\u7ea7\uff09+ \u6587\u4ef6\u7f13\u5b58\uff08\u4e8c\u7ea7\uff09\\*\\*\u7684\u6df7\u5408\u7b56\u7565\u3002\n\n  * **\u5185\u5b58\u7f13\u5b58**\uff1aToken \u52a0\u8f7d\u5230\u5b9e\u4f8b\u5185\u5b58\u4e2d\uff0c\u5728\u7a0b\u5e8f/\u5b9e\u4f8b\u7684\u751f\u547d\u5468\u671f\u5185\u6781\u901f\u83b7\u53d6\u3002\n  * **\u6587\u4ef6\u7f13\u5b58**\uff1a\u5f53\u5185\u5b58\u7f13\u5b58\u5931\u6548\u65f6\uff08\u5982\u811a\u672c\u91cd\u542f\uff09\uff0c\u4f1a\u5c1d\u8bd5\u4ece\u6587\u4ef6\u52a0\u8f7d Token\uff0c\u907f\u514d\u4e86\u4e0d\u5fc5\u8981\u7684 API \u8bf7\u6c42\u3002\n\n### 1\\. \u9ed8\u8ba4\u884c\u4e3a (\u63a8\u8350)\n\n\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u6587\u4ef6\u7f13\u5b58\u88ab\u542f\u7528\uff0c\u5e76\u4f1a\u5728\u5f53\u524d\u5de5\u4f5c\u76ee\u5f55\u521b\u5efa `we_token_cache.json` \u6587\u4ef6\u3002\n\n```python\n# \u5c06\u5728 ./we_token_cache.json \u8bfb\u5199\u7f13\u5b58\nwechat = WechatEnterprise(CORP_ID, APP_ID, CORP_SECRET)\n```\n\n### 2\\. \u81ea\u5b9a\u4e49\u7f13\u5b58\u8def\u5f84\n\n\u4f60\u53ef\u4ee5\u901a\u8fc7 `cache_path` \u53c2\u6570\u6307\u5b9a\u4e00\u4e2a\u81ea\u5b9a\u4e49\u7684 `Path` \u5bf9\u8c61\u8def\u5f84\u3002\n\n```python\nfrom pathlib import Path\n\n# \u6307\u5b9a\u7f13\u5b58\u6587\u4ef6\u5230 /tmp/cache/ \u76ee\u5f55\u4e0b\ncustom_path = Path(\"/tmp/cache/my_wechat_token.json\")\nwechat = WechatEnterprise(CORP_ID, APP_ID, CORP_SECRET, cache_path=custom_path)\n```\n\n### 3\\. \u7981\u7528\u6587\u4ef6\u7f13\u5b58 (\u4ec5\u4f7f\u7528\u5185\u5b58\u7f13\u5b58)\n\n\u5982\u679c\u4f60\u5728\u53ea\u8bfb\u6587\u4ef6\u7cfb\u7edf\uff08\u5982\u67d0\u4e9b Serverless \u73af\u5883\uff09\u6216\u4e0d\u5e0c\u671b\u521b\u5efa\u6587\u4ef6\uff0c\u53ef\u4ee5\u5c06 `cache_path` \u8bbe\u4e3a `None` \u6765\u7981\u7528\u6587\u4ef6\u7f13\u5b58\u3002\n\n```python\n# \u7981\u7528\u6587\u4ef6\u7f13\u5b58\uff0c\u4ec5\u4f7f\u7528\u5b9e\u4f8b\u5185\u5b58\u7f13\u5b58\nwechat_mem_only = WechatEnterprise(CORP_ID, APP_ID, CORP_SECRET, cache_path=None)\n```\n\n## API \u6982\u89c8\n\n### \u6d88\u606f\u53d1\u9001\n\n  * `wechat.send_text(content: str, users: List[str]) -> dict`\n  * `wechat.send_markdown(content: str, users: List[str]) -> dict`\n  * `wechat.send_image(image_path: str, users: List[str]) -> dict`\n  * `wechat.send_file(file_path: str, users: List[str]) -> dict`\n\n### \u7528\u6237\u4e0e\u90e8\u95e8\n\n  * `wechat.get_user_info(userid: str) -> dict`\n      * \u83b7\u53d6\u6210\u5458\u8be6\u7ec6\u4fe1\u606f\u3002\n  * `wechat.get_userid(telephone: str) -> Optional[str]`\n      * \u6839\u636e\u624b\u673a\u53f7\u83b7\u53d6\u6210\u5458 `userid`\u3002\n  * `wechat.get_department_id(dept_id: int = 0) -> dict`\n      * \u83b7\u53d6\u90e8\u95e8\u5217\u8868\u3002\n  * `wechat.get_department_userlist(department_id: int = 1) -> dict`\n      * \u83b7\u53d6\u90e8\u95e8\u6210\u5458\u7b80\u6613\u5217\u8868\u3002\n\n## Todo\n\n  * [ ] \u6dfb\u52a0\u4f01\u4e1a\u5fae\u4fe1\u7684\u5176\u4ed6\u5b9e\u7528\u529f\u80fd\uff08\u5982\u7fa4\u673a\u5668\u4eba\u3001\u5ba1\u6279\u7b49\uff09\u3002\n\n## \u8054\u7cfb\u6211\n\n\u6dfb\u52a0\u5fae\u4fe1 \u300csomenzz-enjoy\u300d \u5907\u6ce8 \u300cgithub\u300d\n\n\u4e2a\u4eba\u516c\u4f17\u53f7 \u300cPython\u4e03\u53f7\u300d\uff0c\u5fae\u4fe1\u641c\u4e00\u641c\u5173\u6ce8\u3002\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": null,
    "version": "1.0.1",
    "project_urls": {
        "Homepage": "https://github.com/somenzz/wechat_enterprise"
    },
    "split_keywords": [
        "python wechat enterprise",
        " wechat_enterprise",
        " send message"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "5f318ec14d7254a0e3b197bf596532e9a76ae62b54d10cde96027b12ddc7dff7",
                "md5": "f25d08e8ff17da7682dee239ec452855",
                "sha256": "334a6c3882f8264c44e543b410297f3700dac75ff6ba8c29d82dae0d8595664f"
            },
            "downloads": -1,
            "filename": "wechat_enterprise_sdk-1.0.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "f25d08e8ff17da7682dee239ec452855",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": null,
            "size": 8645,
            "upload_time": "2025-10-25T02:57:23",
            "upload_time_iso_8601": "2025-10-25T02:57:23.022350Z",
            "url": "https://files.pythonhosted.org/packages/5f/31/8ec14d7254a0e3b197bf596532e9a76ae62b54d10cde96027b12ddc7dff7/wechat_enterprise_sdk-1.0.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "ee7acb9ccd570dad843fdd285d95f0b2d2b602f38fcc2d844abd1561b80799c8",
                "md5": "ff9302a9b32f204ba3763b84b180e489",
                "sha256": "0dee78a5aac56d5cfeee4fded12e5b9a0d7b8c58e855bbbff75e5c8db0b3a09b"
            },
            "downloads": -1,
            "filename": "wechat_enterprise_sdk-1.0.1.tar.gz",
            "has_sig": false,
            "md5_digest": "ff9302a9b32f204ba3763b84b180e489",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": null,
            "size": 10746,
            "upload_time": "2025-10-25T02:57:24",
            "upload_time_iso_8601": "2025-10-25T02:57:24.356158Z",
            "url": "https://files.pythonhosted.org/packages/ee/7a/cb9ccd570dad843fdd285d95f0b2d2b602f38fcc2d844abd1561b80799c8/wechat_enterprise_sdk-1.0.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-25 02:57:24",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "somenzz",
    "github_project": "wechat_enterprise",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "requests",
            "specs": []
        },
        {
            "name": "requests_toolbelt",
            "specs": []
        }
    ],
    "lcname": "wechat-enterprise-sdk"
}
        
Elapsed time: 2.95009s