标签 企业微信 下的文章

开源微信推送服务

使用 Spring Boot 4.0 和 GraalVM Native

通过企业微信(WeCom),将系统消息稳定、合规地推送到用户的微信中接收。

整体消息流转路径如下:

HTTP 请求

企业微信 API

业务系统 / 服务

push-server

企业微信服务端

微信 App

最终效果是: 用户在微信中收到消息,但技术通道使用的是企业微信。

为什么选择企业微信?
相比微信公众号,企业微信具备天然的系统通知优势:

无缝触达:消息最终可到达 微信 App(需关注插件)。
主动推送:支持无限制的主动消息推送,适合通知。
稳定合规:官方允许的系统消息通道,不涉及内容风控。
简单易用:无需复杂的模板消息申请,开发接口清晰。

有什么需要的或者想法可以提,交流一下

项目地址

教程

1. 注册企业微信

谁都可以注册企业微信,无需认证,按说明注册并使用微信扫二维码完成管理员绑定

2. 微信插件

选择我的企业,点击微信插件,使用手机扫码关注

3. 添加应用

添加 logo 和应用名称以及可见范围,选择一个部门或者自己都行,创建应用

4. 配置应用

4.1 查看 Secret

创建完成后会进入当前页面,点击查看可以看 Secret

点击发送,可前往企业微信查看消息

点击查看,保存好,不要泄露,至关重要

4.2 配置可信 IP

在配置可信 IP 之前,我们需要先设置可信域名

可信域名需要校验域名,点击 申请校验域名 获得认证信息

下载文件放置到一个网站的根目录下,我这里放置到了自己在 cloudflare 的 Workers 和 Pages 博客上 https://mazepeng.com/

当文件可以访问到的时候就可以设置可信域名了


现在推送消息的服务必须有可信 IP,如何获得自己的 IP 呢

访问 https://ifconfig.me/ 或者直接百度 IP 就可以看到自己的公网 IP 了

点击应用管理,点击应用,拉倒最下面,配置可信 IP

5. 运行 push-server

支持 docker 部署和本地应用部署,这里我就介绍一下 docker 部署

5.1 docker 命令部署

  docker run -d \
  --name push-server \
  -p 8000:8000 \
  -e PUSH_AUTH_KEY="替换为自己的key" \
  -e PUSH_WECOM_APP_KEY="你的应用AppKey" \
  -e PUSH_WECOM_APP_SECRET="你的应用AppSecret" \
  -e PUSH_WECOM_AGENT_ID="1000001" \
  qingzhoudev/push-server:latest
  
#安全设置,默认值为下方值,需要修改添加环境变量修改
  docker run -d \
  --name push-server \
  -p 8000:8000 \
  -e PUSH_AUTH_KEY="替换为自己的key" \
  -e PUSH_WECOM_APP_KEY="你的应用AppKey" \
  -e PUSH_WECOM_APP_SECRET="你的应用AppSecret" \
  -e PUSH_WECOM_AGENT_ID="1000001" \
  -e PUSH_SECURITY_BLOCK_MINUTES="30" \
  -e PUSH_SECURITY_FAIL_WINDOW_MINUTES="5" \
  -e PUSH_SECURITY_MAX_FAILS="5" \
  -e PUSH_SECURITY_RATE_LIMIT_CAPACITY="10" \
  -e PUSH_SECURITY_RATE_LIMIT_QPS="1" \
  qingzhoudev/push-server:latest

  • PUSH_AUTH_KEY 请求头密钥,需要自己设置一个复杂的即可
  • PUSH_WECOM_APP_KEY 就是企业 ID
  • PUSH_WECOM_APP_SECRET 就是保存的 Secret
  • PUSH_WECOM_AGENT_ID 应用 ID

替换后直接 docker 启动

5.2 使用 Docker Compose

services: push-server:  qingzhoudev/push-server:latest container_name: push-server ports: - "8000:8000" volumes: - ./application-prod.yml:/app/config/application-prod.yml:ro restart: unless-stopped 

application-prod.yml 文件

push: auth: key: "CHANGE_ME" security: block-minutes: 30 fail-window-minutes: 5 max-fails: 5 rate-limit-capacity: 10 rate-limit-qps: 1 wecom: app-key: "CHANGE_ME" app-secret: "CHANGE_ME" agent-id: 1000001 webhook-url: server: port: 8000 

5.3 企业 ID

5.4 应用 ID

6 推送消息

和正常接收微信消息一样,没有什么区别

curl -X POST http://localhost:8000/api/v1/push \
  -H "X-API-Key: 替换为自己的key" \
  -H "Content-Type: application/json" \
  -d '{
"target": "ZhangSan|LiSi",
"type": "TEXT",
"content": "系统通知:您的任务已构建完成。"
}'
curl -X POST http://localhost:8000/api/v1/push \ -H "X-API-Key: 替换为自己的key" \ -H "Content-Type: application/json" \ -d '{
"target": "MaZePeng",
"type": "TEXT_CARD",
"title": "测试Push Server",
"content": "我是 Push Server,这是我作为服务端的第一条消息",
"url": "https://www.mazepeng.com"
}'
curl -X POST http://localhost:8000/api/v1/push \ -H "X-API-Key: 替换为自己的key" \ -H "Content-Type: application/json" \ -d '{
"target": "MaZePeng",
"type": "NEWS",
"articles": [
{
"title": "测试 Article",
"description": "我是描述",
"url": "https://www.mazepeng.com",
"picUrl": "https://mazepeng.com/img/bg/a_larger_image_of_the_homepage.jpg"
}
]
}'

类型有:

  • TEXT
  • MARKDOWN(微信不支持)
  • TEXT_CARD
  • NEWS

📌 转载信息
原作者:
mazp
转载时间:
2026/1/14 10:25:03

RT
最近用 Claude Code 编程过程中,发现企业微信经常无故退出,问了周围的人好像没有这种情况,
难道是因为我开的文档太多了?
以为是自己手抖按到了 command + Q ?

后来强制自己不怎么按键盘,发现还是会退出,甚至还给企业微信提了一个意见。

再往后,发现 claude code 在重启服务的时候是先执行的 lsof -ti:8080

我启动企业微信后执行了一下看看,果然,企业微信的进程也在其中。

哈哈哈哈,可以入选 "你被哪个后来知道很 sb 的 BUG 困扰过一周以上吗?" 话题了,虽然还没有到一周。

你被哪个后来知道很 sb 的 BUG 困扰过一周以上吗?

最近公司需要晚上企微打卡作为加班证据。于是乎就想着实现一个自动化企业微信打卡功能解放下班时间。

需求清单

  • 自动跳过节假日和调休打卡

  • 拒绝死板,在指定时间段内的随机时间打卡

  • 手机能自动亮屏、上滑、解开图案锁


实践:

实践步骤:安卓机 → AI (生成脚本) → Hamibot(远程)

  1. 一台闲置安卓(我以 Android 16 / 系统 ColorOS16 为例)。

  2. 手机下载安装 Hamibot。Web 端注册配对,获取远程控制权限。

  1. 脚本编写,

脚本逻辑

  1. 调用 API 查今天是不是法定节假日 / 调休。

  2. 打卡时间随机延迟 0-5 分钟。

  3. 执行模拟上滑与手势路径(图案解锁)。

  4. 靠坐标解锁,靠文字识别自动点击(工作台 → 打卡 → 上班 / 下班打卡)。

脚本如下,佬友们可自定义修改第二、三步骤。目前的脚本逻辑是设置的 5 分钟随机时间,息屏下需绘制图案解锁。

/*
 * 名称:企业微信自动打卡(智能节假日版)
 * 功能:跳过节假日/周末 + 识别调休 + 随机延迟 + 强力解锁 + 自动打卡
 */

auto.waitFor();
var width = device.width;
var height = device.height;

// ================= 配置区 =================

// 1. 随机延迟时间 (分钟)
var maxDelayMinutes = 5; 

// 2. 您的定制解锁坐标 (a -> b -> c -> d)
var unlockPoints = [
    [302, 1429], 
    [628, 1421], 
    [636, 1746], 
    [274, 1766] 
];

var punchText = "上班打卡"; 
// =========================================

function main() {
    console.show(); 
    log("脚本已启动,正在检查节假日...");

    // --- 第一步:检查是否为节假日 ---
    // 如果是假期或周末(且非调休),直接退出脚本
    if (isHolidayOrWeekend()) {
        log("今天是节假日或周末,无需打卡");
        log("脚本自动退出");
        sleep(3000);
        exit();
        return;
    }

    // --- 第二步:随机延迟 (模拟真人) ---
    var delayTime = random(0, maxDelayMinutes * 60 * 1000); 
    log("今天是工作日,准备打卡");
    log("随机延迟: " + (delayTime / 1000).toFixed(1) + " 秒");
    
    sleep(delayTime);
    log(">>> 延迟结束,开始行动");

    // --- 第三步:执行解锁流程 ---
    smartUnlock();

    // --- 第四步:打开企业微信 ---
    log("打开企业微信...");
    launchApp("企业微信");
    sleep(6000); 
    waitForPackage("com.tencent.wework");

    // --- 第五步:寻找工作台 ---
    var workbench = null;
    for (var i = 0; i < 5; i++) {
        workbench = text("工作台").findOne(2000);
        if (workbench) break;
    }
    if (workbench) {
        clickElement(workbench);
        sleep(3000);
    }

    // --- 第六步:进入打卡应用 ---
    log("寻找打卡图标...");
    var checkInApp = text("打卡").findOne(5000);
    if (checkInApp) {
        clickElement(checkInApp);
        log("进入打卡页面,等待加载...");
        sleep(8000); 
    }

    // --- 第七步:执行打卡点击 ---
    log("寻找按钮: " + punchText);
    var punchBtn = text(punchText).findOne(3000);
    if (!punchBtn) punchBtn = descContains("打卡").findOne(2000);

    if (punchBtn) {
        clickElement(punchBtn);
        toast("✅ 打卡指令已执行");
        log("打卡成功!");
    } else {
        log("未识别到文字,执行坐标盲点兜底...");
        click(width / 2, height * 0.65); 
    }
    
    log("脚本运行结束");
    sleep(3000);
}

// === 新增:节假日检查函数 ===
function isHolidayOrWeekend() {
    // 获取今天的日期格式 YYYY-MM-DD
    var date = new Date();
    var year = date.getFullYear();
    var month = date.getMonth() + 1;
    var day = date.getDate();
    month = month < 10 ? '0' + month : month;
    day = day < 10 ? '0' + day : day;
    var dateStr = year + '-' + month + '-' + day;
    
    var apiUrl = "http://timor.tech/api/holiday/info/" + dateStr;
    log("正在查询日期: " + dateStr);
    
    try {
        // --- 关键修改点:添加 User-Agent 伪装 ---
        var res = http.get(apiUrl, {
            headers: {
                "User-Agent": "Mozilla/5.0 (Linux; Android 10; Mobile) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.181 Mobile Safari/537.36",
                "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
            }
        });
        // -------------------------------------
        if (res.statusCode == 200) {
            var json = res.body.json();
            // API 返回值 type 类型:
            // 0: 工作日, 1: 周末, 2: 节日, 3: 调休(要上班)
            var type = json.type.type;
            var name = json.type.name;
            
            if (type == 0) {
                log("API判定: 普通工作日");
                return false; // 不跳过
            } else if (type == 1) {
                log("API判定: 周末 (" + name + ")");
                return true;  // 跳过
            } else if (type == 2) {
                log("API判定: 节假日 (" + name + ")");
                return true;  // 跳过
            } else if (type == 3) {
                log("API判定: 调休工作日 (" + name + ")");
                return false; // 不跳过 (这是关键!周日调休上班)
            }
        } else {
            log("API 请求失败,状态码: " + res.statusCode);
        }
    } catch (e) {
        log("网络请求异常: " + e);
        log("⚠️ 为了防止漏打卡,网络错误时默认视为工作日");
    }
    
    // 如果网络失败,默认返回 false (即视为工作日,确保安全)
    // return false;
}

// === 智能解锁函数 ===
function smartUnlock() {
    if (!device.isScreenOn()) {
        log("屏幕熄灭,开始解锁...");
        device.wakeUp();
        sleep(2000); 
        
        log("执行上滑...");
        gesture(300, [width / 2, height * 0.8], [width / 2, height * 0.1]);
        sleep(1500); 
        
        log("绘制图案...");
        gesture.apply(null, [2000].concat(unlockPoints));
        sleep(3000); 
    }
}

function clickElement(uiobj) {
    if (uiobj) {
        if (uiobj.clickable()) {
            uiobj.click();
        } else {
            var p = uiobj.parent();
            if (p && p.clickable()) {
                p.click();
            } else {
                click(uiobj.bounds().centerX(), uiobj.bounds().centerY());
            }
        }
    }
}

main();
  1. Hamibot 配置脚本 + 定时任务。

实践效果
(解锁那段被录制软件屏蔽成了黑屏)

实现企业微信全自动 “无感知” 打卡5

常见问题

  • 强烈建议使用闲置机,隐私第一,且不打扰到日常机的使用。

  • hamibot 偶尔被误杀后台需要重新开启无障碍。

  • hamibot 开启的权限有哪些?

这是我运行整套流程给 app 开的权限,比较关注软件权限问题的佬友可以参考。




📌 转载信息
原作者:
ssm_123
转载时间:
2026/1/4 12:23:46

功能

1. 多种消息推送方式:

  • 邮件消息,
  • 微信测试号,
  • 企业微信应用号,
  • 企业微信群机器人
  • 飞书群机器人,
  • 钉钉群机器人,
  • Bark App,
  • WebSocket 客户端(官方客户端,接入文档),

2. 多种用户登录注册方式:

  • 邮箱登录注册以及通过邮箱进行密码重置。
  • GitHub 开放授权。
  • 微信公众号授权(需要额外部署 WeChat Server)。

3. 支持 Markdown 。

2. 支持用户管理。

3. Cloudflare Turnstile 用户校验。

4. 支持在线发布公告,设置关于界面以及页脚。

部署 & 配置

仅单个可执行文件,没有其他依赖开箱即用,同时也提供了 Docker 镜像。

部署:docker run -d --restart always --name message-pusher -p 3000:3000 -v /home/ubuntu/data/message-pusher:/data justsong/message-pusher

更新:docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtower -cR

(由于之前是 Node.js 项目,且没有提供 Docker 镜像,大家一般是直接 Git clone ,所以 README 上显示的 docker pulls 的次数目前并没有很多。)

具体的部署和配置方法还请参考项目 README 。

演示

在线演示: https://msgpusher.com

截图展示:

其他

项目地址: https://github.com/songquanpeng/message-pusher

需要自己设置以下内容

corpid = ''  #企业微信的 corpid
corpsecret = ''  #企业微信 corpsecret
appid = ''  #企业微信 appid
import datetime
import json
import requests as req
import sys
 
stoday = datetime.datetime.now().strftime('%m%d')
full_stoday = datetime.datetime.now().strftime('%Y-%m-%d')
 
corpid = ''
corpsecret = ''
appid = ''
 
 
def send_wx(x):
    url = f'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpid}&corpsecret={corpsecret}'
    r = req.get(url, timeout=5)
    tokens = json.loads(r.text)['access_token']
    url = f"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={tokens}"
    data = {
        "touser": "@all",
        "msgtype": "text",
        "agentid": appid,
        "text": {
            "content": x
        },
        "safe": 0,
    }
    data = json.dumps(data)
    return req.post(url, data=data, timeout=9).text
 
 
headers = {
    'user-agent':
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'
}
r = req.get('https://news-at.zhihu.com/api/4/news/latest',
            headers=headers)  # 获取知乎API
rjson = json.loads(r.text)
if not rjson:
    sys.exit()
 
ls = [f'----- {full_stoday} -----']
for i in rjson['stories']:
    biaoti = i['title']
    url = i['url']
    riqi = i['ga_prefix'][:4]
 
    if riqi == stoday:
        if '·' in biaoti:
            biaoti = f'★{biaoti}'
        ls.append(f'\n<a href=\"{url}\">{biaoti}</a>')
 
send_wx('\n'.join(ls))