Skip to content

OpenClaw 微信公众号接入完全指南:智能客服机器人实战

2026年4月8日

OpenClaw 微信公众号接入完全指南:智能客服机器人实战

微信公众号是最大的中文流量平台之一。把 OpenClaw 接入公众号,打造 24 小时智能客服,自动回答用户问题,提升服务效率。

接入架构

┌─────────────────────────────────────────────────────────────┐
│                  微信公众号接入架构                           │
└─────────────────────────────────────────────────────────────┘

用户发送消息


┌─────────────┐
│  微信服务器  │
└──────┬──────┘
       │ POST 请求

┌─────────────────────────────────────────────────────────────┐
│                     你的服务器                               │
│  ┌─────────────┐       ┌─────────────┐       ┌──────────┐ │
│  │  Nginx      │──────▶│  OpenClaw   │──────▶│ AI 模型  │ │
│  │  反向代理    │       │  消息处理    │       │ API      │ │
│  └─────────────┘       └─────────────┘       └──────────┘ │
└─────────────────────────────────────────────────────────────┘

       │ 回复消息

┌─────────────┐
│  微信服务器  │
└─────────────┘


用户收到回复

准备工作

所需资源

资源要求说明
微信公众号已认证服务号或订阅号未认证功能受限
服务器公网可访问域名需备案
域名已备案支持 80/443 端口
SSL 证书可选建议配置

公众号类型对比

类型消息接口自定义菜单客服消息模板消息
订阅号(未认证)
订阅号(已认证)
服务号(未认证)
服务号(已认证)

步骤一:配置公众号

获取公众号信息

1. 登录微信公众平台:https://mp.weixin.qq.com
2. 进入「设置与开发」→「基本配置」
3. 记录以下信息:
   - AppID: wx1234567890abcdef
   - AppSecret: xxxxxxxxxx
   - 服务器配置:待填写

配置服务器地址

1. 在「基本配置」页面
2. 点击「修改配置」
3. 填写:
   - URL: https://your-domain.com/wechat
   - Token: your_token_123(自定义,用于验证)
   - EncodingAESKey: 随机生成
   - 消息加解密方式: 明文模式(测试)/ 安全模式(生产)
4. 点击「提交」

步骤二:服务器验证

验证流程

微信服务器发送 GET 请求:
GET /wechat?signature=xxx&timestamp=xxx&nonce=xxx&echostr=xxx

验证逻辑:
1. 将 token、timestamp、nonce 排序
2. 拼接后进行 SHA1 加密
3. 对比 signature
4. 返回 echostr

OpenClaw 配置

json
// config.json
{
  "wechat": {
    "appId": "wx1234567890abcdef",
    "appSecret": "your_app_secret",
    "token": "your_token_123",
    "encodingAESKey": "your_aes_key"
  }
}

验证代码实现

javascript
// routes/wechat.js
const crypto = require('crypto');

// 验证服务器有效性
router.get('/wechat', (req, res) => {
  const { signature, timestamp, nonce, echostr } = req.query;
  const token = config.wechat.token;
  
  // 1. 排序
  const arr = [token, timestamp, nonce].sort();
  
  // 2. 拼接
  const str = arr.join('');
  
  // 3. SHA1 加密
  const sha1 = crypto.createHash('sha1').update(str).digest('hex');
  
  // 4. 对比
  if (sha1 === signature) {
    res.send(echostr);
  } else {
    res.status(403).send('验证失败');
  }
});

步骤三:消息处理

消息类型

类型说明示例场景
text文本消息用户提问
image图片消息图片识别
voice语音消息语音转文字
video视频消息视频分析
location地理位置消息位置服务
event事件消息关注/取消关注

消息接收处理

javascript
// 处理微信消息
router.post('/wechat', async (req, res) => {
  const xml = req.body;
  
  // 解析 XML
  const message = parseXML(xml);
  
  // 消息类型判断
  switch (message.MsgType) {
    case 'text':
      await handleTextMessage(message, res);
      break;
    case 'image':
      await handleImageMessage(message, res);
      break;
    case 'event':
      await handleEventMessage(message, res);
      break;
    default:
      res.send('success');
  }
});

// 处理文本消息
async function handleTextMessage(message, res) {
  const { FromUserName, ToUserName, Content } = message;
  
  // 调用 OpenClaw 处理
  const reply = await openclaw.chat({
    userId: FromUserName,
    message: Content
  });
  
  // 返回 XML 格式回复
  const xml = buildTextReply({
    ToUserName: FromUserName,
    FromUserName: ToUserName,
    CreateTime: Date.now(),
    Content: reply
  });
  
  res.set('Content-Type', 'text/xml');
  res.send(xml);
}

XML 解析与构建

javascript
// 解析微信 XML
function parseXML(xml) {
  const result = {};
  xml2js.parseString(xml, { explicitArray: false }, (err, parsed) => {
    if (!err) {
      result = parsed.xml;
    }
  });
  return result;
}

// 构建文本回复 XML
function buildTextReply(data) {
  return `<xml>
    <ToUserName><![CDATA[${data.ToUserName}]]></ToUserName>
    <FromUserName><![CDATA[${data.FromUserName}]]></FromUserName>
    <CreateTime>${data.CreateTime}</CreateTime>
    <MsgType><![CDATA[text]]></MsgType>
    <Content><![CDATA[${data.Content}]]></Content>
  </xml>`;
}

步骤四:智能回复实现

OpenClaw 技能配置

javascript
// skills/wechat-reply/SKILL.md
---
name: wechat-reply
description: 微信公众号智能回复技能
permissions: [network-access]
---

# 微信公众号智能回复

根据用户消息类型,智能生成回复内容。

## 使用方法

用户发送消息 → 自动回复

## 功能特点

- 意图识别
- 多轮对话
- 上下文记忆
- 知识库查询

多轮对话管理

javascript
// 会话管理
class SessionManager {
  constructor() {
    this.sessions = new Map();
  }
  
  getSession(userId) {
    if (!this.sessions.has(userId)) {
      this.sessions.set(userId, {
        messages: [],
        context: {},
        lastActive: Date.now()
      });
    }
    return this.sessions.get(userId);
  }
  
  addMessage(userId, message) {
    const session = this.getSession(userId);
    session.messages.push(message);
    session.lastActive = Date.now();
    
    // 保留最近 20 条消息
    if (session.messages.length > 20) {
      session.messages.shift();
    }
  }
  
  clearSession(userId) {
    this.sessions.delete(userId);
  }
}

// 使用示例
const sessionManager = new SessionManager();

async function handleTextMessage(message, res) {
  const userId = message.FromUserName;
  const content = message.Content;
  
  // 获取会话历史
  const session = sessionManager.getSession(userId);
  
  // 添加用户消息
  sessionManager.addMessage(userId, {
    role: 'user',
    content: content
  });
  
  // 调用 AI 生成回复
  const reply = await generateReply(session.messages);
  
  // 添加助手消息
  sessionManager.addMessage(userId, {
    role: 'assistant',
    content: reply
  });
  
  // 返回回复
  res.send(buildTextReply({
    ToUserName: userId,
    FromUserName: message.ToUserName,
    Content: reply
  }));
}

步骤五:自定义菜单

创建菜单

javascript
// 创建自定义菜单
async function createMenu() {
  const menu = {
    button: [
      {
        type: 'click',
        name: '产品介绍',
        key: 'PRODUCT_INTRO'
      },
      {
        type: 'click',
        name: '使用帮助',
        key: 'HELP'
      },
      {
        name: '更多',
        sub_button: [
          {
            type: 'view',
            name: '官网',
            url: 'https://your-website.com'
          },
          {
            type: 'click',
            name: '联系客服',
            key: 'CONTACT'
          }
        ]
      }
    ]
  };
  
  const accessToken = await getAccessToken();
  
  const response = await axios.post(
    `https://api.weixin.qq.com/cgi-bin/menu/create?access_token=${accessToken}`,
    menu
  );
  
  return response.data;
}

菜单事件处理

javascript
// 处理菜单点击事件
async function handleEventMessage(message, res) {
  const { FromUserName, ToUserName, Event, EventKey } = message;
  
  let reply = '';
  
  switch (Event) {
    case 'subscribe':
      reply = '欢迎关注!发送任意消息开始对话。';
      break;
    case 'unsubscribe':
      // 清理会话
      sessionManager.clearSession(FromUserName);
      break;
    case 'CLICK':
      reply = await handleMenuClick(EventKey);
      break;
  }
  
  if (reply) {
    res.send(buildTextReply({
      ToUserName: FromUserName,
      FromUserName: ToUserName,
      Content: reply
    }));
  } else {
    res.send('success');
  }
}

// 处理菜单点击
async function handleMenuClick(key) {
  const menuReplies = {
    'PRODUCT_INTRO': '我们提供 AI 智能客服解决方案...',
    'HELP': '使用方法:直接发送消息即可获得智能回复',
    'CONTACT': '客服微信:xxx,工作时间:9:00-18:00'
  };
  
  return menuReplies[key] || '功能开发中';
}

步骤六:客服消息

发送客服消息

javascript
// 发送客服消息(主动推送)
async function sendCustomMessage(userId, content) {
  const accessToken = await getAccessToken();
  
  const response = await axios.post(
    `https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=${accessToken}`,
    {
      touser: userId,
      msgtype: 'text',
      text: {
        content: content
      }
    }
  );
  
  return response.data;
}

// 发送图片消息
async function sendImageMessage(userId, mediaId) {
  const accessToken = await getAccessToken();
  
  const response = await axios.post(
    `https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=${accessToken}`,
    {
      touser: userId,
      msgtype: 'image',
      image: {
        media_id: mediaId
      }
    }
  );
  
  return response.data;
}

获取 Access Token

javascript
// Access Token 管理
class AccessTokenManager {
  constructor(appId, appSecret) {
    this.appId = appId;
    this.appSecret = appSecret;
    this.token = null;
    this.expiresAt = 0;
  }
  
  async getToken() {
    // 如果 token 有效,直接返回
    if (this.token && Date.now() < this.expiresAt) {
      return this.token;
    }
    
    // 获取新 token
    const response = await axios.get(
      `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${this.appId}&secret=${this.appSecret}`
    );
    
    this.token = response.data.access_token;
    this.expiresAt = Date.now() + (response.data.expires_in - 300) * 1000;
    
    return this.token;
  }
}

完整示例

主程序入口

javascript
// app.js
const express = require('express');
const wechatRoute = require('./routes/wechat');

const app = express();

// 解析 XML
app.use(express.text({ type: 'text/xml' }));

// 微信路由
app.use('/', wechatRoute);

// 启动服务
app.listen(3000, () => {
  console.log('OpenClaw 微信公众号服务已启动');
});

Nginx 配置

nginx
# /etc/nginx/sites-available/wechat.conf
server {
    listen 80;
    server_name your-domain.com;
    
    location /wechat {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

常见问题

Q1: 验证失败怎么办?

检查清单:
□ Token 是否一致
□ URL 是否可访问
□ 服务器是否返回 echostr
□ 防火墙是否开放端口

Q2: 消息收不到?

排查步骤:
1. 检查公众号后台消息配置
2. 查看服务器日志
3. 确认消息加解密方式
4. 测试 URL 是否正常

Q3: 回复超时?

微信服务器要求 5 秒内响应:

解决方案:
1. 快速返回 success
2. 使用客服消息异步回复
3. 优化 AI 响应速度

部署上线

部署清单

□ 服务器部署 OpenClaw
□ 配置域名和 SSL
□ 公众号后台配置服务器地址
□ 测试验证流程
□ 测试消息收发
□ 上线运营

总结

功能实现难度说明
服务器验证★★☆签名校验
消息收发★★☆XML 解析
智能回复★★★AI 集成
自定义菜单★★☆API 调用
客服消息★★☆主动推送

接入核心要点:

  • 公众号需认证才能使用完整功能
  • 服务器必须公网可访问
  • 5 秒内必须响应,否则超时
  • 客服消息用于异步回复

微信公众号接入 OpenClaw,让你的公众号变成 24 小时智能客服,自动回答用户问题,提升服务效率。关键是处理好消息格式和响应时间。

不要孤军奋战啦!

加入微信群一起学习交流 AI

与大神一起使用 OpenClaw、Hermes、Claude Code、Seedance 2.0、GPT-Image-2 等

微信公众号

扫码关注微信公众号
私信 "加群",将自动获取微信群二维码

探索 AI 世界,掌握智能未来