# 1. 为什么选择微信测试号?
| 方案 | 优点 | 缺点 |
|---|---|---|
| 微信服务号 | 功能完整 | 需要企业资质认证(300元/年) |
| 微信订阅号 | 个人可申请 | 不支持模板消息推送 |
| Server酱/PushPlus | 接入简单 | 免费版有额度限制,可能收费 |
| 微信测试号✅ | 免费、无需认证、支持模板消息 | 仅限关注者接收,适合个人使用 |
微信测试号是腾讯为开发者提供的沙箱环境,拥有几乎所有公众号高级接口权限,最重要的是——它支持模板消息,且完全免费!
# 2. 准备工作:申请测试号与配置模板
# Step 1:申请微信测试号
访问 微信公众平台接口测试帐号 (opens new window),用微信扫码登录。
登录成功后,页面会生成你的专属 appID 和 appsecret,请妥善保存:
appID: wx1234567890abcdef
appsecret: abcdef1234567890abcdef1234567890
# Step 2:关注测试号,获取 UserId
在测试号管理页面往下翻,找到 测试号二维码,用微信扫码关注。
关注后,页面顶部的 "用户列表" 中会出现你的微信昵称,对应的 微信号 就是代码中需要的 userid

# Step 3:配置消息模板
继续往下翻,找到 模板消息接口 → 新增测试模板,添加一个模板:
- 模板标题:
通知📢(可随意) - 模板内容: 标题:{{title.DATA}} 内容:{{content.DATA}}
⚠️ 重要:模板内容中的变量名必须为
title和content,因为我们的代码中data字段正是使用这两个 key。

# 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. 注意事项与进阶优化
# ⚠️ 注意事项
- 环境变量管理:
appid和secret千万不要硬编码或提交到 Git!建议使用.env文件或环境变量。 - 模板消息限制:
- 只有关注了测试号的用户才能收到消息
- 模板内容中的变量名(
title、content)必须与后台配置一致
- Token 安全:虽然
stable_token更稳定,但 Token 本身仍然敏感,切勿暴露给前端。 - 测试号的局限:微信测试号随时可能被关闭或调整策略,如果需要长期稳定使用,建议升级为企业微信应用消息或正式认证的服务号。
# 🚀 进阶优化建议
| 优化方向 | 具体做法 |
|---|---|
| 本地 Token 缓存 | 虽然stable_token已有服务端缓存,但可在本地用 Redis 再缓存一层,减少网络请求 |
| 重试机制 | 对发送失败的消息增加指数退避重试 |
| 富文本模板 | 在微信后台配置更丰富的模板(如包含first、remark等字段) |
| 替代方案 | 如果测试号不可用,可迁移到企业微信的应用消息推送 |
# 🎉 总结
通过不到 100 行 TypeScript 代码,我们就实现了一个类型安全、支持多用户、使用最新 stable_token 接口的微信消息推送模块。无论是服务器报警、CI/CD 通知,还是给自己发个每日提醒,这套方案都能轻松胜任。
赶紧动手试试吧!扫码关注你自己的测试号,运行代码,当微信弹出那条推送消息的瞬间——属于程序员的成就感,就是这么简单 😎
参考资料: