WeChatRemote是一个微信远程调用工具,使用MQTT连接本地或云端微信客户端实现远程操作
- 支持所有的Wechaty Puppet
 - 解耦Wechaty客户端与业务应用服务端,使用熟悉语言实现MQTT Client即可调用
 - 本地运行bot,远程接收消息和调用bot发消息
 
npm i wechat-remote首先启动一个wechaty客户端(目前仅支持nodejs),并使用mqtt-wechaty插件 机器人可以运行在本地或云服务器中,只需要可以访问外网,不需要配置外网IP
import { WechatyBuilder } from 'wechaty'
import {
  QRCodeTerminal,
  MqttGateway,
  MqttGatewayConfig,
} from 'wechat-remote'
const bot = WechatyBuilder.build({
  name : 'ding-dong-bot',
})
const config: MqttGatewayConfig = {
  events: [
    'login',
    'logout',
    'reset',
    'ready',
    'dirty',
    'dong',
    'error',
    // 'heartbeat',
    'friendship',
    'message', 'post',
    'room-invite', 'room-join',
    'room-leave', 'room-topic',
    'scan',
  ],
  mqtt: {
    clientId: 'ding-dong-test01', // 替换成自己的clientId,建议不少于16个字符串
    host: 'broker.emqx.io',
    password: '',
    port: 1883,
    username: '',
  },
  options:{
    secrectKey: '',
    simple: false,
  },
  token: '',
}
bot.use(
  MqttGateway(config),
  QRCodeTerminal(),
)
bot.start()
  .catch(console.error)使用MQTT可视化工具调用接口,可以快速理解学习WeChatRemote使用
- 访问 http://www.emqx.io/online-mqtt-client ,配置并连接MQTT
 - 订阅如下主题,其中的“chatbot/”之后的“+”可以换成具体的clientId
- 接收事件 thing/chatbot/+/event/post
 - 应用端下发指令 thing/chatbot/+/command/invoke
 - 接收响应 thing/chatbot/+/response/d2c/+
 
 - 查询机器人状态,向 thing/chatbot/ding-dong-test01/command/invoke 主题发布如下payload:
 
{
    "reqId":"2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method":"command",
    "version":"1.0",
    "timestamp":1705384610041,
    "name":"wechatyLogonoff",
    "params":{}
}
{
    "reqId":"2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method":"command",
    "version":"1.0",
    "timestamp":1705384610041,
    "name":"contactSay",
    "params":{
        "contacts":["atorber"],
        "messageType":"Text",
        "messagePayload":"hello"
    }
}下载安装MQTTX https://mqttx.app/zh/downloads 可以使用客户端更加稳定
以下是几种常用语言的SimpleCode,后续考虑提供SDK,期待大家贡献各种语言的sdk
- 安装依赖
 
npm install mqtt- 接收消息
 
const mqtt = require('mqtt');
// MQTT 服务器设置
const MQTT_BROKER_URL = 'mqtt://your-mqtt-broker-url';
const TOPIC = 'thing/chatbot/xxxx/event/post';
const MQTT_PORT = 1883; // 替换为你的 MQTT 服务器端口
const USERNAME = 'your-username'; // 替换为你的用户名
const PASSWORD = 'your-password'; // 替换为你的密码
// 连接选项
const options = {
  port: MQTT_PORT,
  username: USERNAME,
  password: PASSWORD,
};
// 创建 MQTT 客户端
const client = mqtt.connect(MQTT_BROKER_URL, options);
client.on('connect', () => {
  console.log('Connected to MQTT Broker:', MQTT_BROKER_URL);
  // 订阅指定主题
  client.subscribe(TOPIC, (err) => {
    if (!err) {
      console.log(`Subscribed to topic: ${TOPIC}`);
    } else {
      console.error(`Failed to subscribe: ${err}`);
    }
  });
});
client.on('message', (topic, message) => {
  if (topic === TOPIC) {
    try {
      // 尝试解析消息为 JSON
      const jsonMessage = JSON.parse(message.toString());
      console.log('Received JSON Message:', jsonMessage);
    } catch (error) {
      console.error('Received non-JSON message:', message.toString());
    }
  }
});
client.on('error', (error) => {
  console.error('MQTT Client Error:', error);
});- 调用API
 
const mqtt = require('mqtt');
const MQTT_BROKER_URL = 'mqtt://your-mqtt-broker-url';
const COMMAND_TOPIC = 'thing/chatbot/xxxx/command/invoke';
const RESPONSE_TOPIC = 'thing/chatbot/xxxx/response/d2c/+';
const MQTT_PORT = 1883; // 或者你的 MQTT 服务器端口
const USERNAME = 'your-username'; // 或者你的用户名
const PASSWORD = 'your-password'; // 或者你的密码
const message = {
  reqId: "2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
  method: "command",
  version: "1.0",
  timestamp: 1705384610041,
  name: "contactSay",
  params: {
    contacts: ["ledongmao", "choogoo"],
    messageType: "Text",
    messagePayload: "hello"
  }
};
const options = {
  port: MQTT_PORT,
  username: USERNAME,
  password: PASSWORD,
};
const client = mqtt.connect(MQTT_BROKER_URL, options);
client.on('connect', () => {
  console.log('Connected to MQTT Broker:', MQTT_BROKER_URL);
  // 订阅响应主题
  client.subscribe(RESPONSE_TOPIC, (err) => {
    if (!err) {
      console.log(`Subscribed to response topic: ${RESPONSE_TOPIC}`);
    } else {
      console.error(`Failed to subscribe: ${err}`);
    }
  });
  // 发布命令消息
  client.publish(COMMAND_TOPIC, JSON.stringify(message));
  console.log(`Message published to command topic: ${COMMAND_TOPIC}`);
});
client.on('message', (topic, message) => {
  console.log(`Received message from ${topic}: ${message.toString()}`);
});
client.on('error', (error) => {
  console.error('MQTT Client Error:', error);
});- 安装依赖
 
npm install mqtt
npm install @types/node --save-dev- 接收消息
 
import * as mqtt from 'mqtt';
// MQTT 服务器设置
const MQTT_BROKER_URL = 'mqtt://your-mqtt-broker-url';
const TOPIC = 'thing/chatbot/xxxx/event/post';
const MQTT_PORT = 1883; // 替换为你的 MQTT 服务器端口
const USERNAME = 'your-username'; // 替换为你的用户名
const PASSWORD = 'your-password'; // 替换为你的密码
// 连接选项
const options: mqtt.IClientOptions = {
  port: MQTT_PORT,
  username: USERNAME,
  password: PASSWORD,
};
// 创建 MQTT 客户端
const client = mqtt.connect(MQTT_BROKER_URL, options);
client.on('connect', () => {
  console.log('Connected to MQTT Broker:', MQTT_BROKER_URL);
  // 订阅指定主题
  client.subscribe(TOPIC, (err) => {
    if (!err) {
      console.log(`Subscribed to topic: ${TOPIC}`);
    } else {
      console.error(`Failed to subscribe: ${err}`);
    }
  });
  // 订阅指定主题
  client.subscribe(TOPIC, (err) => {
    if (!err) {
      console.log(`Subscribed to topic: ${TOPIC}`);
    } else {
      console.error(`Failed to subscribe: ${err}`);
    }
  });
});
client.on('message', (topic, message) => {
  if (topic === TOPIC) {
    try {
      // 尝试解析消息为 JSON
      const jsonMessage = JSON.parse(message.toString());
      console.log('Received JSON Message:', jsonMessage);
    } catch (error) {
      console.error('Received non-JSON message:', message.toString());
    }
  }
});
client.on('error', (error) => {
  console.error('MQTT Client Error:', error);
});- 调用API
 
import * as mqtt from 'mqtt';
import type { IClientOptions, MqttClient } from 'mqtt';
const MQTT_BROKER_URL: string = 'mqtt://your-mqtt-broker-url';
const COMMAND_TOPIC: string = 'thing/chatbot/xxxx/command/invoke';
const RESPONSE_TOPIC: string = 'thing/chatbot/xxxx/response/d2c/+';
const MQTT_PORT: number = 1883; // 或者你的 MQTT 服务器端口
const USERNAME: string = 'your-username'; // 或者你的用户名
const PASSWORD: string = 'your-password'; // 或者你的密码
interface Message {
  reqId: string;
  method: string;
  version: string;
  timestamp: number;
  name: string;
  params: {
    contacts: string[];
    messageType: string;
    messagePayload: string;
  };
}
const message: Message = {
  reqId: "2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
  method: "command",
  version: "1.0",
  timestamp: 1705384610041,
  name: "contactSay",
  params: {
    contacts: ["ledongmao", "choogoo"],
    messageType: "Text",
    messagePayload: "hello"
  }
};
const options: IClientOptions = {
  port: MQTT_PORT,
  username: USERNAME,
  password: PASSWORD,
};
const client: MqttClient = mqtt.connect(MQTT_BROKER_URL, options);
client.on('connect', () => {
  console.log('Connected to MQTT Broker:', MQTT_BROKER_URL);
  // 订阅响应主题
  client.subscribe(RESPONSE_TOPIC, (err) => {
    if (!err) {
      console.log(`Subscribed to response topic: ${RESPONSE_TOPIC}`);
    } else {
      console.error(`Failed to subscribe: ${err}`);
    }
  });
  // 发布命令消息
  client.publish(COMMAND_TOPIC, JSON.stringify(message));
  console.log(`Message published to command topic: ${COMMAND_TOPIC}`);
});
client.on('message', (topic: string, message: Buffer) => {
  console.log(`Received message from ${topic}: ${message.toString()}`);
});
client.on('error', (error: Error) => {
  console.error('MQTT Client Error:', error);
});- 安装依赖
 
pip install paho-mqtt- 接收消息
 
import json
import paho.mqtt.client as mqtt
# MQTT 服务器设置
MQTT_BROKER_URL = 'mqtt://your-mqtt-broker-url'
TOPIC = 'thing/chatbot/xxxx/event/post'
MQTT_PORT = 1883  # 替换为你的 MQTT 服务器端口
USERNAME = 'your-username'  # 替换为你的用户名
PASSWORD = 'your-password'  # 替换为你的密码
# 连接成功回调函数
def on_connect(client, userdata, flags, rc):
    print(f'Connected to MQTT Broker: {MQTT_BROKER_URL}')
    client.subscribe(TOPIC)
    print(f'Subscribed to topic: {TOPIC}')
# 接收消息回调函数
def on_message(client, userdata, msg):
    if msg.topic == TOPIC:
        try:
            # 尝试解析消息为 JSON
            json_message = json.loads(msg.payload.decode())
            print('Received JSON Message:', json_message)
        except ValueError:
            print('Received non-JSON message:', msg.payload.decode())
# MQTT 客户端设置
client = mqtt.Client()
client.username_pw_set(USERNAME, PASSWORD)
client.on_connect = on_connect
client.on_message = on_message
# 连接 MQTT Broker
client.connect(MQTT_BROKER_URL, MQTT_PORT, 60)
# 网络循环,以处理回调函数并保持脚本运行
client.loop_forever()- 调用API
 
import json
import paho.mqtt.client as mqtt
MQTT_BROKER_URL = 'mqtt://your-mqtt-broker-url'
COMMAND_TOPIC = 'thing/chatbot/xxxx/command/invoke'
RESPONSE_TOPIC = 'thing/chatbot/xxxx/response/d2c/+'
MQTT_PORT = 1883  # 或者你的 MQTT 服务器端口
USERNAME = 'your-username'  # 或者你的用户名
PASSWORD = 'your-password'  # 或者你的密码
message = {
    "reqId": "2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method": "command",
    "version": "1.0",
    "timestamp": 1705384610041,
    "name": "contactSay",
    "params": {
        "contacts": ["ledongmao", "choogoo"],
        "messageType": "Text",
        "messagePayload": "hello"
    }
}
def on_connect(client, userdata, flags, rc):
    print(f"Connected to MQTT Broker: {MQTT_BROKER_URL}")
    # 订阅响应主题
    client.subscribe(RESPONSE_TOPIC)
    print(f"Subscribed to response topic: {RESPONSE_TOPIC}")
    # 发布命令消息
    client.publish(COMMAND_TOPIC, json.dumps(message))
    print(f"Message published to command topic: {COMMAND_TOPIC}")
def on_message(client, userdata, msg):
    print(f"Received message from {msg.topic}: {msg.payload.decode()}")
def on_error(client, userdata, rc):
    print(f"MQTT Client Error: {rc}")
client = mqtt.Client()
client.username_pw_set(USERNAME, PASSWORD)
client.on_connect = on_connect
client.on_message = on_message
client.on_error = on_error
client.connect(MQTT_BROKER_URL.replace('mqtt://', ''), MQTT_PORT, 60)
client.loop_forever()- 安装依赖
 
go get github.com/eclipse/paho.mqtt.golang- 接收消息
 
package main
import (
    "encoding/json"
    "fmt"
    "os"
    "time"
    mqtt "github.com/eclipse/paho.mqtt.golang"
)
const (
    MQTT_BROKER_URL = "tcp://your-mqtt-broker-url:1883" // 注意更换为你的 MQTT 服务器地址和端口
    TOPIC           = "thing/chatbot/xxxx/event/post"   // 更换为你的主题
    USERNAME        = "your-username"                   // 更换为你的用户名
    PASSWORD        = "your-password"                   // 更换为你的密码
)
func onConnectHandler(client mqtt.Client) {
    if token := client.Subscribe(TOPIC, 0, onMessageReceivedHandler); token.Wait() && token.Error() != nil {
        fmt.Println("Subscribe error:", token.Error())
        os.Exit(1)
    }
    fmt.Println("Connected to MQTT Broker:", MQTT_BROKER_URL)
    fmt.Println("Subscribed to topic:", TOPIC)
}
func onMessageReceivedHandler(client mqtt.Client, msg mqtt.Message) {
    fmt.Printf("Received message on topic %s: %s\n", msg.Topic(), string(msg.Payload()))
    var jsonMessage map[string]interface{}
    if err := json.Unmarshal(msg.Payload(), &jsonMessage); err != nil {
        fmt.Println("Error parsing JSON message:", err)
    } else {
        fmt.Println("Received JSON Message:", jsonMessage)
    }
}
func main() {
    opts := mqtt.NewClientOptions().AddBroker(MQTT_BROKER_URL).SetUsername(USERNAME).SetPassword(PASSWORD)
    opts.SetDefaultPublishHandler(onMessageReceivedHandler)
    opts.OnConnect = onConnectHandler
    client := mqtt.NewClient(opts)
    if token := client.Connect(); token.Wait() && token.Error() != nil {
        fmt.Println("Connection error:", token.Error())
        os.Exit(1)
    }
    // Keep the main function running until interrupted
    select {}
}- API调用
 
- 安装依赖
 
<dependencies>
    <dependency>
        <groupId>org.eclipse.paho</groupId>
        <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
        <version>1.2.5</version>
    </dependency>
</dependencies>- 接收消息
 
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.json.JSONObject;
public class MqttSubscribeSample {
    public static void main(String[] args) {
final String brokerUrl = "tcp://your-mqtt-broker-url:1883"; // 替换为你的MQTT Broker的URL
final String topic = "thing/chatbot/xxxx/event/post"; // 替换为你的主题
final String clientId = "JavaClient";
final String username = "your-username"; // 替换为你的用户名
final String password = "your-password"; // 替换为你的密码
    try {
        MqttClient sampleClient = new MqttClient(brokerUrl, clientId);
        MqttConnectOptions connOpts = new MqttConnectOptions();
        connOpts.setCleanSession(true);
        connOpts.setUserName(username);
        connOpts.setPassword(password.toCharArray());
        
        System.out.println("Connecting to broker: " + brokerUrl);
        sampleClient.connect(connOpts);
        System.out.println("Connected");
        
        sampleClient.setCallback(new MqttCallback() {
            @Override
            public void connectionLost(Throwable cause) {
                System.out.println("Connection lost!");
            }
            
            @Override
            public void messageArrived(String topic, MqttMessage message) throws Exception {
                System.out.println("Message arrived: " + message.toString());
                try {
                    JSONObject jsonMessage = new JSONObject(message.toString());
                    System.out.println("Received JSON Message: " + jsonMessage.toString(2)); // Indent with 2 spaces
                } catch (Exception e) {
                    System.out.println("Received non-JSON message: " + message.toString());
                }
            }
            
            @Override
            public void deliveryComplete(IMqttDeliveryToken token) {
                // Not used in this example
            }
        });
        
        System.out.println("Subscribing to topic: " + topic);
        sampleClient.subscribe(topic);
    } catch(Exception e) {
        System.out.println("Exception: " + e.getMessage());
    }
}- API调用
 
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.json.JSONObject;
public class MqttClientDemo {
    private static final String MQTT_BROKER_URL = "tcp://your-mqtt-broker-url:1883";
    private static final String COMMAND_TOPIC = "thing/chatbot/xxxx/command/invoke";
    private static final String RESPONSE_TOPIC = "thing/chatbot/xxxx/response/d2c/+";
    private static final String USERNAME = "your-username";
    private static final String PASSWORD = "your-password";
    public static void main(String[] args) {
        try {
            MqttClient client = new MqttClient(MQTT_BROKER_URL, MqttClient.generateClientId());
            MqttConnectOptions options = new MqttConnectOptions();
            options.setUserName(USERNAME);
            options.setPassword(PASSWORD.toCharArray());
            
            client.setCallback(new MqttCallback() {
                @Override
                public void connectionLost(Throwable cause) {
                    System.out.println("MQTT Client Error: " + cause.getMessage());
                }
                @Override
                public void messageArrived(String topic, MqttMessage message) {
                    System.out.println("Received message from " + topic + ": " + new String(message.getPayload()));
                }
                @Override
                public void deliveryComplete(IMqttDeliveryToken token) {
                }
            });
            client.connect(options);
            System.out.println("Connected to MQTT Broker: " + MQTT_BROKER_URL);
            
            client.subscribe(RESPONSE_TOPIC);
            System.out.println("Subscribed to response topic: " + RESPONSE_TOPIC);
            
            JSONObject message = new JSONObject();
            message.put("reqId", "2a42cff1-bfb5-4d5d-b185-353c8c71a00b");
            message.put("method", "command");
            message.put("version", "1.0");
            message.put("timestamp", 1705384610041L);
            message.put("name", "contactSay");
            JSONObject params = new JSONObject();
            params.put("contacts", new String[]{"ledongmao", "choogoo"});
            params.put("messageType", "Text");
            params.put("messagePayload", "hello");
            message.put("params", params);
            client.publish(COMMAND_TOPIC, new MqttMessage(message.toString().getBytes()));
            System.out.println("Message published to command topic: " + COMMAND_TOPIC);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }
}其他语言示例欢迎在评论里粘贴代码或提需求,也可以交给GPTs 多语言代码转换大师
:::warning 目前仅实现了常用API的支持,其他API需求可以在评论中留言,当然API的范围不能超出Wechaty支持范围 ::: 远程调用调用端向 thing/chatbot/${clinetId}/command/invoke发送调用指令(其中${clinetId}表示具体的clientId) Wechaty客户端接收到指令后向thing/chatbot/${clinetId}/response/d2c/${reqId}主题推送响应消息 应用端订阅响应消息:
- 订阅指定请求消息:thing/chatbot/xxxx/response/d2c/1234
 - 订阅所有请求消息:thing/chatbot/xxxx/response/d2c/+
 
- 请求
 
{
    "reqId":"2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method":"command",
    "version":"1.0",
    "timestamp":1705384610041,
    "name":"wechatyLogonoff",
    "params":{}
}- 响应
 
{
  "reqId": "2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
  "method": "response",
  "version": "1.0",
  "timestamp": 1705408082094,
  "name": "wechatyLogonoff",
  "code": 200,
  "message": "success",
  "params": {
    "logonoff": true
  }
}- 请求
 
{
    "reqId":"2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method":"command",
    "version":"1.0",
    "timestamp":1705384610041,
    "name":"wechatyUserSelf",
    "params":{}
}- 响应
 
{
  "reqId": "2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
  "method": "response",
  "version": "1.0",
  "timestamp": 1705408574486,
  "name": "wechatyUserSelf",
  "code": 200,
  "message": "success",
  "params": {
    "_events": {},
    "_eventsCount": 0,
    "id": "@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299",
    "payload": {
      "alias": "",
      "avatar": "/cgi-bin/mmwebwx-bin/webwxgeticon?seq=1851844649&username=@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299&skey=@crypt_3f47a99d_1d59eeac1c79b47948fa86522b106b12",
      "friend": false,
      "gender": 2,
      "id": "@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299",
      "name": "瓦力",
      "phone": [],
      "star": false,
      "type": 1
    }
  }
}- 请求
 
{
    "reqId":"2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method":"command",
    "version":"1.0",
    "timestamp":1705384610041,
    "name":"contactFindAll",
    "params":{
      "size":100
    }
}- 响应
 
{
    "reqId":"2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method":"response",
    "version":"1.0",
    "timestamp":1705384610041,
    "code":200,
    "message":"success",
    "name":"contactFindAll",
    "params":{
        "page":1,
        "size":100,
        "total":3500,
        "items":[
            {
                "_events":{
                },
                "_eventsCount":0,
                "id":"@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299",
                "payload":{
                    "alias":"",
                    "avatar":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=11550719&username=@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299&skey=@crypt_3f47a99d_1d59eeac1c79b47948fa86522b106b12",
                    "friend":false,
                    "gender":2,
                    "id":"@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299",
                    "name":"瓦力",
                    "phone":[
                    ],
                    "star":false,
                    "type":1
                }
            },
            {
                "_events":{
                },
                "_eventsCount":0,
                "id":"@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299",
                "payload":{
                    "alias":"",
                    "avatar":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=11550719&username=@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299&skey=@crypt_3f47a99d_1d59eeac1c79b47948fa86522b106b12",
                    "friend":false,
                    "gender":2,
                    "id":"@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299",
                    "name":"瓦力",
                    "phone":[
                    ],
                    "star":false,
                    "type":1
                }
            }
        ]
    }
}- 请求
 
alias、id、name至少填写一个
{
    "reqId":"2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method":"command",
    "version":"1.0",
    "timestamp":1705384610041,
    "name":"contactFind",
    "params":{
        "alias":"",
        "id":"@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299",
        "name":"瓦力"
    }
}- 响应
 
{
    "reqId":"2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method":"response",
    "version":"1.0",
    "timestamp":1705384610041,
    "code":200,
    "message":"success",
    "name":"contactFind",
    "params":{
        "_events":{},
        "_eventsCount":0,
        "id":"@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299",
        "payload":{
            "alias":"",
            "avatar":"/cgi-bin/mmwebwx-bin/webwxgeticon?seq=11550719&username=@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299&skey=@crypt_3f47a99d_1d59eeac1c79b47948fa86522b106b12",
            "friend":false,
            "gender":2,
            "id":"@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299",
            "name":"瓦力",
            "phone":[],
            "star":false,
            "type":1
        }
    }
}目前仅支持发送文本消息,图片、文件、视频、语音等消息即将支持
- 请求
 
{
    "reqId":"2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method":"command",
    "version":"1.0",
    "timestamp":1705384610041,
    "name":"contactSay",
    "params":{
        "contacts":[
            "ledongmao",
            "choogoo"
        ],
        "messageType":"Text",
        "messagePayload":"hello"
    }
}- 响应
 
返回发送结果列表
{
    "reqId":"2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method":"response",
    "version":"1.0",
    "timestamp":1705384610041,
    "code":200,
    "message":"success",
    "name":"contactSay",
    "params":{
      "success":[],
      "fail":[]
    }
}- 请求
 
{
    "reqId":"2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method":"command",
    "version":"1.0",
    "timestamp":1705384610041,
    "name":"roomFindAll",
    "params":{
      "size":100
    }
}- 响应
 
{
    "reqId":"2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method":"response",
    "version":"1.0",
    "timestamp":1705384610041,
    "code":200,
    "message":"success",
    "name":"roomFindAll",
    "params":{
        "page":1,
        "size":100,
        "count":3500,
        "items":[
            {
                "_events":{},
                "_eventsCount":0,
                "id":"19036636423@chatroom",
                "payload":{
                    "adminIdList":[],
                    "avatar":"",
                    "external":false,
                    "id":"19036636423@chatroom",
                    "ownerId":"",
                    "topic":"宁波金茂汇项目团队"
                }
            },
            {
                "_events":{},
                "_eventsCount":0,
                "id":"19036636423@chatroom",
                "payload":{
                    "adminIdList":[],
                    "avatar":"",
                    "external":false,
                    "id":"19036636423@chatroom",
                    "ownerId":"",
                    "topic":"宁波金茂汇项目团队"
                }
            }
        ]
    }
}- 请求
 
{
    "reqId":"2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method":"command",
    "version":"1.0",
    "timestamp":1705384610041,
    "name":"roomFind",
    "params":{
        "id":"@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299",
        "topic":"瓦力是群主"
    }
}- 响应
 
{
  "reqId": "2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
  "method": "response",
  "version": "1.0",
  "timestamp": 1705418869966,
  "name": "roomFind",
  "code": 200,
  "message": "success",
  "params": {
    "_events": {},
    "_eventsCount": 0,
    "id": "5550027590@chatroom",
    "payload": {
      "adminIdList": [
        "wxid_m7kf9tq12"
      ],
      "avatar": "",
      "external": false,
      "id": "5550027590@chatroom",
      "memberIdList": [
        "wxid_m7kf9tq12",
        "tyutl",
        "wxid_0f57221"
      ],
      "ownerId": "wxid_m7kf9tq12",
      "topic": "瓦力是群主"
    }
  }
}- 请求
 
id、topic至少填写一项
{
    "reqId":"2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method":"command",
    "version":"1.0",
    "timestamp":1705384610041,
    "name":"roomMemberAllGet",
    "params":{
        "size":100,
        "id":"@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299",
        "topic":"瓦力是群主"
    }
}- 响应
 
{
  "reqId": "2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
  "method": "response",
  "version": "1.0",
  "timestamp": 1705462410448,
  "name": "roomMemberAllGet",
  "code": 200,
  "message": "success",
  "params": {
    "page": 1,
    "size": 100,
    "total": 3,
    "items": [
      {
        "_events": {},
        "_eventsCount": 0,
        "id": "wxid_pnza7m7kf9tq12",
        "payload": {
          "alias": "",
          "friend": true,
          "id": "wxid_pnza7m7kf9tq12",
          "name": "瓦力",
          "phone": [],
          "type": 1
        }
      },
      {
        "_events": {},
        "_eventsCount": 0,
        "id": "tyutluyc",
        "payload": {
          "alias": "超哥",
          "friend": true,
          "id": "tyutluyc",
          "name": "luyuchao",
          "phone": [],
          "type": 1
        }
      },
      {
        "_events": {},
        "_eventsCount": 0,
        "id": "wxid_0o1t51l3f57221",
        "payload": {
          "alias": "",
          "avatar": "https://wx.qlogo.cn/mmhead/ver_1/xUlBgtTamVSCTw5KnGTxusBCT6eSQSgwDoRnp18ICZRp5JcWWFju1aLCzj5UurApCMDcLmfGOyxvDSwPL9yyoIB9zug49f5QjbI2HTk4ib1w/132",
          "friend": false,
          "gender": 0,
          "id": "wxid_0o1t51l3f57221",
          "name": "大师",
          "phone": [],
          "type": 1
        }
      }
    ]
  }
}目前仅支持发送文本消息,图片、文件、视频、语音等消息即将支持
- 请求
 
{
    "reqId":"2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method":"command",
    "version":"1.0",
    "timestamp":1705384610041,
    "name":"roomSay",
    "params":{
        "rooms":[
            "[email protected]"
        ],
        "messageType":"Text",
        "messagePayload":"hello"
    }
}- 响应
 
{
  "reqId": "2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
  "method": "response",
  "version": "1.0",
  "timestamp": 1705461448305,
  "name": "roomSay",
  "code": 200,
  "message": "success",
  "params": {
    "id": "[email protected]"
  }
}有瑕疵,调试中...
- 请求
 
{
    "reqId":"2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method":"command",
    "version":"1.0",
    "timestamp":1705384610041,
    "name":"roomSayAt",
    "params":{
        "contacts":[
            "ledongmao",
            "choogoo"
        ],
        "room":"[email protected]",
        "messageType":"Text",
        "messagePayload":"hello"
    }
}- 响应
 
{
  "reqId": "2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
  "method": "response",
  "version": "1.0",
  "timestamp": 1705462056289,
  "name": "roomSayAt",
  "code": 200,
  "message": "success"
}- 请求
 
{
    "reqId":"2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
    "method":"command",
    "version":"1.0",
    "timestamp":1705384610041,
    "name":"messageSay",
    "params":{
      "id":"xxxxx",
      "messageType":"Text",
      "messagePayload":"hello"
    }
}- 响应
 
{
  "reqId": "2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
  "method": "response",
  "version": "1.0",
  "timestamp": 1705463098535,
  "name": "messageSay",
  "code": 200,
  "message": "success",
  "params": {
    "id": "clrh8op130002yszc9col2coq"
  }
}{
  "reqId": "2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
  "method": "response",
  "version": "1.0",
  "timestamp": 1705463049890,
  "name": "messageSay",
  "code": 200,
  "message": "消息不存在",
  "params": {}
}事件被推送到 thing/chatbot/${clinetId}/event/post主题(其中${clinetId}表示具体的clientId) 订阅thing/chatbot/xxxx/event/post接收事件数据
{
  "reqId": "2a42cff1-bfb5-4d5d-b185-353c8c71a00b",
  "method": "event",
  "version": "1.0",
  "timestamp": 1705384610041,
  "name": "scan",
  "params": {
    "qrcode": "https://login.weixin.qq.com/l/gaD8UC3bcA==",
    "status": 2
  }
}{
  "reqId": "6e80b9ce-3585-46d2-982c-9be0087f21e2",
  "method": "event",
  "version": "1.0",
  "timestamp": 1705384714220,
  "name": "login",
  "params": {
    "_events": {},
    "_eventsCount": 0,
    "id": "@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299",
    "payload": {
      "alias": "",
      "avatar": "/cgi-bin/mmwebwx-bin/webwxgeticon?seq=11550719&username=@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299&skey=@crypt_3f47a99d_1d59eeac1c79b47948fa86522b106b12",
      "friend": false,
      "gender": 2,
      "id": "@a4c7b5b71eb79b5f790f5d4c2270b0f3b787952a3a8ca08b228efe4832021299",
      "name": "瓦力",
      "phone": [],
      "star": false,
      "type": 1
    }
  }
}{
  "reqId": "e0e8fb62-42a0-4b7c-9217-c3aadb9059dd",
  "method": "event",
  "version": "1.0",
  "timestamp": 1705384609786,
  "name": "logout",
  "params": [
    {
      "_events": {},
      "_eventsCount": 0,
      "id": "@85ee0016d30773031e259b3de554c8542340104d9b7a2c2646f73076b990130a",
      "payload": {
        "alias": "",
        "avatar": "/cgi-bin/mmwebwx-bin/webwxgeticon?seq=1946854219&username=@85ee0016d30773031e259b3de554c8542340104d9b7a2c2646f73076b990130a&skey=@crypt_3f47a99d_291be9b57007f9ec09ccd9cfda807c9c",
        "friend": false,
        "gender": 2,
        "id": "@85ee0016d30773031e259b3de554c8542340104d9b7a2c2646f73076b990130a",
        "name": "瓦力",
        "phone": [],
        "star": false,
        "type": 1
      }
    },
    "logout()"
  ]
}{
  "reqId": "46d3bcb9-f21b-4236-91a3-88efb99ff9f9",
  "method": "event",
  "version": "1.0",
  "timestamp": 1705384530329,
  "name": "ready",
  "params": []
}{
  "reqId": "52bd5dae-6cf5-44bb-a76c-982744ba585e",
  "method": "event",
  "version": "1.0",
  "timestamp": 1705384604626,
  "name": "error",
  "params": [
    {
      "code": 2,
      "details": "Error: 连续3次同步失败,5s后尝试重启\n    at C:\\Users\\Administrator\\Documents\\GitHub\\plugin-contrib\\node_modules\\wechat4u\\src\\wechat.js:100:19\n    at processTicksAndRejections (node:internal/process/task_queues:96:5)",
      "message": "连续3次同步失败,5s后尝试重启",
      "name": "Error",
      "stack": "Error: 连续3次同步失败,5s后尝试重启\n    at C:\\Users\\Administrator\\Documents\\GitHub\\plugin-contrib\\node_modules\\wechat4u\\src\\wechat.js:100:19\n    at processTicksAndRejections (node:internal/process/task_queues:96:5)"
    }
  ]
}{
  "reqId": "2ee3362b-3142-44d5-b859-a15cb4177445",
  "method": "event",
  "version": "1.0",
  "timestamp": 1705384017113,
  "name": "message",
  "params": {
    "_events": {},
    "_eventsCount": 0,
    "id": "8768818756347691243",
    "payload": {
      "id": "8768818756347691243",
      "talkerId": "@d3cc07d80f9add1b4acd87e49817d061",
      "text": "h",
      "timestamp": 1705384016,
      "type": 7,
      "roomId": "@@e3e01b946e9f19978ad0718269b78b4f5dc853fd8eda5aa2dd5601ac57cdb3a5",
      "mentionIdList": []
    }
  }
}{
  "reqId": "b8ae2de2-19a3-4533-a5d5-9c2b7630a113",
  "method": "thing.event.post",
  "version": "1.0",
  "timestamp": 1705385708810,
  "events": {
    "onMessage": {
      "_id": "clrfyma84006vropd2i4ecmax",
      "data": {
        "_events": {},
        "_eventsCount": 0,
        "id": "clrfyma84006vropd2i4ecmax",
        "payload": {
          "id": "clrfyma84006vropd2i4ecmax",
          "listenerId": "",
          "roomId": "19036636423@chatroom",
          "talkerId": "wxid_zqbyd7b5kwy322",
          "text": "各位领导、同事\n      关于集团第四季度模拟钓鱼邮件演练,金茂商业有7名同事点击钓鱼链接,按总部要求加强各单位钓鱼邮件的识别、防御和处理能力。\n我们项目出现中招情况,故此,进行项目全员钓鱼邮件专题考试,希望大家在钓鱼邮件方面进一步加强安全意识意识和处置技能。\n以下为考试链接,请全员在1月19日前完成考试,我们将在群内公示考试人数。\nhttps://docs.chinajinmao.cn/form/ew/HOasNVyb/\n邀你填写「预防钓鱼邮件专题考试」",
          "timestamp": 1705385708356,
          "toId": "",
          "type": 7
        }
      },
      "room": {
        "_events": {},
        "_eventsCount": 0,
        "id": "19036636423@chatroom",
        "payload": {
          "adminIdList": [],
          "avatar": "",
          "external": false,
          "id": "19036636423@chatroom",
          "ownerId": "",
          "topic": "宁波金茂汇项目团队"
        }
      },
      "talker": {
        "_events": {},
        "_eventsCount": 0,
        "id": "wxid_zqbyd7b5kwy322",
        "payload": {
          "friend": true,
          "id": "wxid_zqbyd7b5kwy322",
          "name": "清昼",
          "phone": [],
          "type": 1
        }
      },
      "time": "56011-07-10 20:19:16",
      "timestamp": 1705385708356000
    }
  }
}https://wechaty.js.org/docs/api/wechaty
| Name | Type | Description | 
|---|---|---|
| error | string | When the bot get error, there will be a Wechaty error event fired. | 
| login | string | After the bot login full successful, the event login will be emitted, with a Contact of current logined user. | 
| logout | string | Logout will be emitted when bot detected log out, with a Contact of the current login user. | 
| heartbeat | string | Get bot's heartbeat. | 
| friendship | string | When someone sends you a friend request, there will be a Wechaty friendship event fired. | 
| message | string | Emit when there's a new message. | 
| ready | string | Emit when all data has load completed, in wechaty-puppet-padchat, it means it has sync Contact and Room completed | 
| room-join | string | Emit when anyone join any room. | 
| room-topic | string | Get topic event, emitted when someone change room topic. | 
| room-leave | string | Emit when anyone leave the room. | 
| room-invite | string | Emit when there is a room invitation, see more in RoomInvitation | 
| If someone leaves the room by themselves, wechat will not notice other people in the room, so the bot will never get the "leave" event. | ||
| scan | string | A scan event will be emitted when the bot needs to show you a QR Code for scanning.  It is recommend to install qrcode-terminal(run npm install qrcode-terminal) in order to show qrcode in the terminal.  | 

