微信测试号实现免费消息推送 📱

7/16/2026

# 1. 为什么选择微信测试号?

方案 优点 缺点
微信服务号 功能完整 需要企业资质认证(300元/年)
微信订阅号 个人可申请 不支持模板消息推送
Server酱/PushPlus 接入简单 免费版有额度限制,可能收费
微信测试号 免费、无需认证、支持模板消息 仅限关注者接收,适合个人使用

微信测试号是腾讯为开发者提供的沙箱环境,拥有几乎所有公众号高级接口权限,最重要的是——​它支持模板消息​,且完全免费!


# 2. 准备工作:申请测试号与配置模板

# Step 1:申请微信测试号

访问 微信公众平台接口测试帐号 (opens new window),用微信扫码登录。

登录成功后,页面会生成你的专属 appID 和 ​appsecret​,请妥善保存:

appID:      wx1234567890abcdef
appsecret:  abcdef1234567890abcdef1234567890

# Step 2:关注测试号,获取 UserId

在测试号管理页面往下翻,找到 ​测试号二维码​,用微信扫码关注。

关注后,页面顶部的 "用户列表" 中会出现你的微信昵称,对应的 微信号 就是代码中需要的 userid

image

# Step 3:配置消息模板

继续往下翻,找到 ​模板消息接口 → 新增测试模板​,添加一个模板:

  • 模板标题​:通知📢(可随意)
  • 模板内容​: 标题:{{title.DATA}} 内容:{{content.DATA}}

⚠️ ​重要​:模板内容中的变量名必须为 titlecontent,因为我们的代码中 data 字段正是使用这两个 key。

image


# 3. 核心代码解析

我们的代码由三个核心函数组成,层层递进:

getStableToken()  →  获取 Access Token
    ↓
sendWxMessage()   →  发送单条模板消息
    ↓
sendWxpush()      →  批量发送(多用户)

# 3.1 获取稳定的 Access Token — getStableToken

export async function getStableToken(
  appid: string,
  secret: string
): Promise<string> {
  const tokenUrl = 'https://api.weixin.qq.com/cgi-bin/stable_token';
  const payload: StableTokenRequest = {
    grant_type: 'client_credential',
    appid,
    secret,
    force_refresh: false,
  };

  const response = await fetch(tokenUrl, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload),
  });

  const data = await response.json() as StableTokenResponse;
  if (!data.access_token) {
    throw new Error(
      `WXPush 获取 access_token 失败: ${JSON.stringify(data)}`
    );
  }
  return data.access_token;
}

💡 亮点:为什么用 stable_token 而不是传统的 token 接口?

传统的 /cgi-bin/token 接口有一个经典坑:​频繁刷新会导致旧 Token 立即失效​,在多实例部署时极易出现 Token 互相覆盖的问题。

stable_token 是微信官方推出的​更稳定的 Token 获取方式​,它有以下优势:

  • ✅ 由微信服务器端管理 Token 的生命周期,避免多实例冲突
  • force_refresh: false 时,返回的 Token 在有效期内保持不变
  • ✅ 更适合无状态 / Serverless 环境

# 3.2 发送单条模板消息 — sendWxMessage

export async function sendWxMessage(
  options: SendWxMessageOptions
): Promise<WxApiResponse> {
  const {
    accessToken,
    userid,
    template_id,
    base_url = '',
    title,
    content,
  } = options;

  const sendUrl = `https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=${accessToken}`;
  const payload: TemplateSendPayload = {
    touser: userid,
    template_id,
    url: base_url,
    data: {
      title: { value: title || '', color: '#173177' },
      content: { value: content || '' },
    },
  };

  const response = await fetch(sendUrl, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload),
  });

  return response.json() as Promise<WxApiResponse>;
}

这里调用了微信的 ​发送模板消息 API​,核心参数说明:

参数 说明
touser 接收者的 OpenID
template_id 在测试号后台配置的模板 ID
url 点击消息后跳转的链接(可选)
data.title 对应模板中的{{title.DATA}},设置了深蓝色#173177
data.content 对应模板中的{{content.DATA}}

# 3.3 批量推送封装 — sendWxpush

export async function sendWxpush(
  options: SendWxpushOptions
): Promise<WxSendResult> {
  const { appid, secret, userid, template_id, title, content, base_url } =
    options;

  // 1. 获取 Token
  const accessToken = await getStableToken(appid, secret);

  // 2. 解析用户列表(支持 "|" 分隔多个 OpenID)
  const userList = userid
    .split('|')
    .map((uid) => uid.trim())
    .filter(Boolean);

  // 3. 并发发送给所有用户
  const results = await Promise.all(
    userList.map((id) =>
      sendWxMessage({
        accessToken,
        userid: id,
        template_id,
        base_url,
        title,
        content,
      })
    )
  );

  // 4. 结果统计
  const successCount = results.filter((r) => r.errmsg === 'ok').length;
  const failedResults = results.filter((r) => r.errmsg !== 'ok');
  if (failedResults.length > 0) {
    const error = new Error('WXPush 部分发送失败');
    (error as Error & { details: WxApiResponse[] }).details = failedResults;
    throw error;
  }

  return {
    name: 'wxpush',
    success: true,
    total: results.length,
    successCount,
    details: results,
  };
}

💡 设计亮点​:

  • 多用户支持​:通过 | 分隔符,一次调用可推送给多个用户(比如给自己和家人同时推送)
  • 并发发送​:使用 Promise.all 并发请求,提升推送效率
  • 错误收集​:精确识别哪些用户发送成功、哪些失败,并将失败详情附加到 Error 对象上
  • TypeScript 类型安全​:完善的 Interface 定义,开发体验极佳

# 4. 实战调用示例

# 最简调用:给自己发一条消息

import { sendWxpush } from './wxpush';

async function main() {
  const result = await sendWxpush({
    appid: 'wx1234567890abcdef',
    secret: 'abcdef1234567890abcdef1234567890',
    userid: 'oXxXxXxXx_Your_OpenID_Here',
    template_id: 'OPENTEMPLATE1234567890',
    title: '🚀 部署通知',
    content: '您的博客项目已成功部署到生产环境!\n部署时间:2026-07-16 16:00:00',
  });

  console.log(`✅ 推送完成!成功发送 ${result.successCount} 条消息`);
}

main().catch(console.error);

# 进阶:给多个用户推送,附带跳转链接

await sendWxpush({
  appid: process.env.WX_APPID!,
  secret: process.env.WX_SECRET!,
  // 用 | 分隔多个 OpenID
  userid: 'oXxXx_OpenID_1|oXxXx_OpenID_2',
  template_id: process.env.WX_TEMPLATE_ID!,
  title: '⚠️ 服务器告警',
  content: 'CPU 使用率超过 90%,请及时处理!\n当前负载:92.3%',
  base_url: 'https://your-monitor-dashboard.com',  // 点击消息跳转监控面板
});

# 在定时任务中使用(搭配 node-cron)

import cron from 'node-cron';
import { sendWxpush } from './wxpush';

// 每天早上 9:00 推送日报
cron.schedule('0 9 * * *', async () => {
  await sendWxpush({
    appid: 'your_appid',
    secret: 'your_secret',
    userid: 'your_openid',
    template_id: 'your_template_id',
    title: '📅 每日提醒',
    content: '新的一天开始了,今天也要加油哦!💪',
  });
});

# 5. 注意事项与进阶优化

# ⚠️ 注意事项

  1. 环境变量管理​:appidsecret 千万不要硬编码或提交到 Git!建议使用 .env 文件或环境变量。
  2. 模板消息限制​:
    • 只有关注了测试号的用户才能收到消息
    • 模板内容中的变量名(titlecontent)必须与后台配置一致
  3. Token 安全​:虽然 stable_token 更稳定,但 Token 本身仍然敏感,切勿暴露给前端。
  4. 测试号的局限​:微信测试号随时可能被关闭或调整策略,如果需要长期稳定使用,建议升级为企业微信应用消息或正式认证的服务号。

# 🚀 进阶优化建议

优化方向 具体做法
本地 Token 缓存 虽然stable_token已有服务端缓存,但可在本地用 Redis 再缓存一层,减少网络请求
重试机制 对发送失败的消息增加指数退避重试
富文本模板 在微信后台配置更丰富的模板(如包含firstremark等字段)
替代方案 如果测试号不可用,可迁移到企业微信的应用消息推送

# 🎉 总结

通过不到 100 行 TypeScript 代码,我们就实现了一个类型安全、支持多用户、使用最新 stable_token 接口的微信消息推送模块。无论是服务器报警、CI/CD 通知,还是给自己发个每日提醒,这套方案都能轻松胜任。

赶紧动手试试吧!扫码关注你自己的测试号,运行代码,当微信弹出那条推送消息的瞬间——属于程序员的成就感,就是这么简单 😎


参考资料​: