wecomchan-github地址

创建企业微信应用

创建应用

打开并登陆 「企业微信

选择「应用管理」 → 「自建」 → 「创建应用」

上传头像并起个名字

打开创建好的应用,查看应用Agentid(WECOM_AID=企业微信应用ID)和应用Secret(WECOM_SECRET=企业微信应用Secret)

添加可信IP

获取企业ID

进入「我的企业」页面,拉到最下边,可以看到企业ID,复制并填到上方。

推送消息到微信

进入「我的企业」 → 「微信插件」,拉到下边扫描二维码,关注以后即可收到推送的消息。

服务器部署wecomchan

docker

https://github.com/easychen/wecomchan/archive/refs/heads/main.zip

下载-上传服务器-解压

修改 docker-compose.yml 默认值:

 SENDKEY=发送时用来验证的key
 WECOM_CID=企业微信公司ID
 WECOM_SECRET=企业微信应用Secret
 WECOM_AID=企业微信应用ID
 WECOM_TOUID=需要发送给的人,直接推送全公司成员@all
 ​
 REDIS_STAT=ON
 REDIS_ADDR=redis:6379
 REDIS_PASSWORD=redis的连接密码

环境变量说明

名称描述
SENDKEY发送时用来验证的key
WECOM_CID企业微信公司ID
WECOM_SECRET企业微信应用Secret
WECOM_AID企业微信应用ID
WECOM_TOUID需要发送给的人,详见企业微信官方文档
REDIS_STAT是否启用redis换缓存token,ON-启用 OFF或空-不启用
REDIS_ADDRredis服务器地址,如不启用redis缓存可不设置
REDIS_PASSWORDredis的连接密码,如不启用redis缓存可不设置

docker部署:

 docker-compose up -d

开放端口:8080

php

 <?php
 // config
 // ======================================
 define('SENDKEY', 'xxx');
 define('WECOM_CID', 'cid');
 define('WECOM_SECRET', 'secret');
 define('WECOM_AID', '1000001');
 define('WECOM_TOUID', '@all');
 ​
 // 以下配置需要有 redis 服务和 phpredis 扩展
 define('REDIS_ON', false);
 define('REDIS_HOST', '127.0.0.1');
 define('REDIS_PORT', '6379');
 define('REDIS_EXPIRED', '7000');
 define('REDIS_KEY', 'wecom_access_token');
 ​
 // ======================================
 ​
 if (strlen(@$_POST['sendkey']) < 1 || @$_POST['sendkey'] != SENDKEY) {
     die('bad params');
 }
 ​
 header("Content-Type: application/json; charset=UTF-8");
 ​
 // 根据消息类型处理不同内容
 $msgType = $_POST['msgtype'] ?? 'text';
 $response = '';
 ​
 switch ($msgType) {
     case 'text':
         $response = send_to_wecom($_POST['text'], $msgType);
         break;
     case 'image':
     case 'file':
         $mediaId = upload_media($msgType, $_FILES['media']['tmp_name']);
         $response = send_to_wecom($mediaId, $msgType);
         break;
     case 'textcard':
         $cardData = [
             'title'       => $_POST['title'],
             'description' => $_POST['description'],
             'url'         => $_POST['url'],
             'btntxt'      => $_POST['btntxt'] ?? '详情'
        ];
         $response = send_to_wecom($cardData, $msgType);
         break;
     case 'news':
         $cardData = [
             'title'       => $_POST['title'],
             'description' => $_POST['description'],
             'url'         => $_POST['url'],
             'picurl'         => $_POST['picurl']
        ];
         // $cardData = isset($_POST['articles']) ? json_decode($_POST['articles'], true) : [];
         $response = send_to_wecom($cardData, $msgType);
         break;
     default:
         die('Unsupported message type');
 }
 ​
 echo $response;
 ​
 // 获取 Access Token
 function get_access_token()
 {
     if (REDIS_ON) {
         $access_token = redis()->get(REDIS_KEY);
         if ($access_token) return $access_token;
    }
 ​
     $url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=".WECOM_CID."&corpsecret=".WECOM_SECRET;
     $result = json_decode(file_get_contents($url), true);
     
     if (isset($result['access_token'])) {
         $access_token = $result['access_token'];
         if (REDIS_ON) {
             redis()->set(REDIS_KEY, $access_token, ['ex' => REDIS_EXPIRED]);
        }
         return $access_token;
    }
     
     throw new Exception('Failed to get access token: '.json_encode($result));
 }
 ​
 // 通用消息发送
 function send_to_wecom($content, $msgType)
 {
     $access_token = get_access_token();
     $url = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={$access_token}";
 ​
     $data = [
         'touser'  => WECOM_TOUID,
         'msgtype' => $msgType,
         'agentid' => WECOM_AID,
         $msgType  => []
    ];
 ​
     switch ($msgType) {
         case 'text':
             $data['text'] = ['content' => $content];
             break;
         case 'image':
         case 'file':
             $data[$msgType] = ['media_id' => $content];
             break;
         case 'textcard':
             $data['textcard'] = [
                 'title'       => $content['title'],
                 'description' => $content['description'],
                 'url'         => $content['url'],
                 'btntxt'      => $content['btntxt']
            ];
             break;
         case 'news':
             $data['news'] = [
                 'articles' => [
                    [
                         'title'       => $content['title'],
                         'description' => $content['description'],
                         'url'         => $content['url'],
                         'picurl'      => $content['picurl']
                    ]
                ]
            ];
             break;
    }
 ​
     $ch = curl_init();
     curl_setopt_array($ch, [
         CURLOPT_URL        => $url,
         CURLOPT_POST       => true,
         CURLOPT_POSTFIELDS => json_encode($data),
         CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
         CURLOPT_RETURNTRANSFER => true,
         CURLOPT_SSL_VERIFYHOST => false,
         CURLOPT_SSL_VERIFYPEER => false,
         CURLOPT_TIMEOUT    => 10
    ]);
 ​
     $result = curl_exec($ch);
     curl_close($ch);
 ​
     return $result;
 }
 ​
 // 媒体文件上传
 function upload_media($type, $filePath)
 {
     $access_token = get_access_token();
     $url = "https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token={$access_token}&type={$type}";
 ​
     $data = ['media' => new CURLFile(realpath($filePath))];
     
     $ch = curl_init();
     curl_setopt_array($ch, [
         CURLOPT_URL        => $url,
         CURLOPT_POST       => true,
         CURLOPT_POSTFIELDS => $data,
         CURLOPT_RETURNTRANSFER => true,
         CURLOPT_SSL_VERIFYHOST => false,
         CURLOPT_SSL_VERIFYPEER => false
    ]);
 ​
     $result = json_decode(curl_exec($ch), true);
     curl_close($ch);
 ​
     if (isset($result['media_id'])) {
         return $result['media_id'];
    }
     file_put_contents('log/upload_media.log', date('[Y-m-d H:i:s]')." Upload: ".json_encode($result)."\n", FILE_APPEND);
     throw new Exception('Upload failed: '.json_encode($result));
 }
 ​
 // Redis 连接
 function redis()
 {
     static $instance = null;
     if (!$instance && REDIS_ON) {
         $instance = new Redis();
         $instance->connect(REDIS_HOST, REDIS_PORT);
    }
     return $instance;
 }
 ​

调用模板

PHP 调用模板

1. 文本消息

 file_get_contents('https://example.com/send-post.php?sendkey=xxx&text=test'.'value:'.urlencode($value).);
 $apiUrl = 'https://example.com/send-post.php'; 
 $sendkey="xxx";
 $text='',
 ​
 $data = [
   'sendkey' => $sendkey,
   'msgtype' => 'text',
   'text' => $text
 ];
 ​
 $ch = curl_init($url);
 curl_setopt_array($ch, [
   CURLOPT_POST       => true,
   CURLOPT_POSTFIELDS => $data,
   CURLOPT_RETURNTRANSFER => true
 ]);
 $response = curl_exec($ch);
 curl_close($ch);
 ​
 echo "Response: " . $response;

2. 文字卡片消息

 $apiUrl = 'https://example.com/send-post.php'; 
 $sendkey="xxx";
 ​
 $data = [
   'sendkey'    => $sendkey,
   'msgtype'   => 'textcard',
   'title'      => "标题",
   'description' => "描述\n",
   'url'        => 'https://example.com/',
   'btntxt'     => '点击查看'
 ​
 ];
 ​
 $ch = curl_init($url);
 curl_setopt_array($ch, [
   CURLOPT_POST       => true,
   CURLOPT_POSTFIELDS => $data,
   CURLOPT_RETURNTRANSFER => true
 ]);
 // 发送请求
 $response = curl_exec($ch);
 curl_close($ch);
 ​
 echo "Response: " . $response;

3. 图文卡片消息

 $apiUrl = 'https://example.com/send-post.php'; 
 $sendkey="xxx";
 ​
 ​
 $data = [
   'sendkey'    => $sendkey,
   'msgtype'   => 'news',
   'title'      => "标题",
   'description' => "描述\n点击查看",
   'picurl' => 'img/cover.jpg',
   'url'        => 'https://example.com/'
 ];
 ​
 $ch = curl_init($url);
 curl_setopt_array($ch, [
   CURLOPT_POST       => true,
   CURLOPT_POSTFIELDS => $data,
   CURLOPT_RETURNTRANSFER => true
 ]);
 // 发送请求
 $response = curl_exec($ch);
 curl_close($ch);
 ​
 echo "Response: " . $response;

4.图片消息

 $apiUrl = 'https://example.com/send-post.php'; 
 $sendkey="xxx";
 // 本地图片路径
 $imagePath = '/path/to/your';
 $imageName='image.jpg';
 $fullPath=$imagePath.'/'.$imageName;
 ​
 $postData = [
   'sendkey' => $sendkey,
   'msgtype' => 'image'
 ];
 $fileData = [
   'media' => new CURLFile($fullPath, 'image/jpeg', $imageName)
 ];
 ​
 ​
 $ch = curl_init();
 curl_setopt_array($ch, [
   CURLOPT_URL => $apiUrl,
   CURLOPT_POST => true,
   CURLOPT_POSTFIELDS => array_merge($postData, $fileData),
   CURLOPT_RETURNTRANSFER => true,
   CURLOPT_SSL_VERIFYHOST => false,
   CURLOPT_SSL_VERIFYPEER => false
 ]);
 ​
 // 发送请求
 $response = curl_exec($ch);
 curl_close($ch);
 ​
 echo "Response: " . $response;

5.文件消息

txt、pdf、doc、docx、ppt、pptx、xls、xlsx、xml、jpg、jpeg、png、bmp、gif

 $apiUrl = 'https://example.com/send-post.php'; 
 $sendkey="xxx";
 // 本地文件路径
 $filePath = '/path/to/your';
 $fileName ='file.pdf' ;
 $fullPath=$filePath.'/'.$fileName;
 ​
 $postData = [
   'sendkey' => $sendkey,
   'msgtype' => 'file'
 ];
 ​
 $fileData = [
   'media' => new CURLFile($fullPath, 'application/pdf',$fileName)
 ];
 ​
 // 发送请求
 $ch = curl_init();
 curl_setopt_array($ch, [
   CURLOPT_URL => $apiUrl,
   CURLOPT_POST => true,
   CURLOPT_POSTFIELDS => array_merge($postData, $fileData),
   CURLOPT_RETURNTRANSFER => true
 ]);
 ​
 $response = curl_exec($ch);
 curl_close($ch);
 ​
 echo "响应结果: " . $response;

Python 调用模板

1. 文本消息

 import requests
 ​
 apiUrl = "https://example.com/send-post.php"
 sendkey="xxx"
 ​
 data = {
   'sendkey': sendkey,  
   "msgtype": "text",
   "text": "需要发送的文字内容"
 }
 ​
 response = requests.post(apiUrl, data=data)
 print(response.text)

2. 文字卡片消息

 import requests
 ​
 apiUrl = "https://example.com/send-post.php"  
 sendkey="xxx"
 ​
 data = {
   'sendkey': sendkey,        
   'msgtype': 'textcard',      
   'title': '测试标题',
   'description': '测试消息\n包含多行文本描述',
   'url': 'https://example.com',
   'btntxt': '点击查看'
 }
 ​
 # 发送 POST 请求
 response = requests.post(apiUrl, data=data)
 print(response.text)

3. 图文卡片消息

 import requests
 ​
 apiUrl = "https://example.com/send-post.php"
 sendkey="xxx"
 ​
 data = {
   'sendkey': sendkey,          
   'msgtype': 'news',      
   'title': '测试标题',
   'description': '测试消息\n包含多行文本描述',
   'url': 'https://example.com',
   'picurl': 'https://example.com/path/to/image.jpg'
 }
 ​
 # 发送 POST 请求
 response = requests.post(apiUrl, data=data)
 print(response.text)

4.图片消息

 import requests
 ​
 apiUrl = "https://example.com/send-post.php"
 sendkey="xxx"
 # 本地图片路径
 image_path = "C:\Scrip\Other\img\image.jpg"
 ​
 data = {
   'sendkey': sendkey,
   'msgtype': 'image'
 }
 ​
 files = {
   'media': open(image_path, 'rb')
 }
 ​
 # 发送请求
 response = requests.post(apiUrl, data=data, files=files)
 print("Response:", response.text)

5.文件消息

txt、pdf、doc、docx、ppt、pptx、xls、xlsx、xml、jpg、jpeg、png、bmp、gif

 import requests
 ​
 apiUrl = "https://example.com/send-post.php"
 sendkey="xxx"
 # 本地文件路径
 file_path = "/path/to/your/file.docx"        
 ​
 data = {
   'sendkey': sendkey,
   'msgtype': 'file'
 }
 ​
 files = {
   'media': open(file_path, 'rb')
 }
 ​
 # 发送请求
 response = requests.post(apiUrl, data=data, files=files)
 print("响应内容:", response.text)

1


GitHub:https://github.com/easychen/wecomchan

https://developer.work.weixin.qq.com/document/path/90236


THE END