BOT应用后端开发
1.1 Bot应用与Bot应用服务端交互流程图
1.2 MosApp的Bot会话发送消息到Bot应用服务端
用户给Bot应用发消息后,MosApp会将消息通过Bot应用服务端配置的webhook透传给Bot应用服务端。
1.2.1 报文示例
java
{
"reqId": "4E3FC140-73E6-4E18-BD98-99E19A4496B9",
"botAppId": "696290824258245",
"eventType": "MESSAGE",
"conversation": {
"conversationId": "696638485037509"
},
"message": {
"messageId": "1950519940851331072",
"text": "/start",
"timestamp": 1753875167470,
"type": -1
},
"miniApp": {
"openid": "47179fef0cff7ab186e2bcc3ac46790c"
},
"sender": {
"nickname": "mosUser"
},
"timestamp": 1753875167470
}
1.2.2 webhook参数说明
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
reqId | String | 是 | 请求id,每个请求唯一 |
eventType | String | 是 | 事件类型: message/callbackQuery |
timestamp | Long | 是 | 事件发生时间戳 |
botAppId | String | 是 | bot应用id |
sender | 发送者信息对象 | ||
--nickname | String | 是 | 用户昵称 |
conversation | 会话信息对象 | ||
--conversationId | String | 是 | 会话id |
message | 用户发送的消息内容(Message 对象),仅在 eventType 为 message 时存在 | ||
--messageId | String | 否 | 用户发送的消息的消息id |
--text | String | 否 | 发送文本 |
--timestamp | Long | 否 | 消息发送时间 |
callbackQuery | 内联按钮点击事件的详细信息(CallbackQuery 对象),仅在 eventType 为 callback_query 时存在 | ||
--data | String | 否 | 回调数据(通常由开发者定义) |
--inlineMessageId | String | 否 | 内联消息id |
miniApp | 微应用信息对象 BotApp绑定了微应用,该实体有值 | ||
--openid | String | 否 | 用户在对应微应用中的openid |
1.2.3 Java使用范例
请求入参
java
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 点击内联按钮入参
* @author admin001
* @date 2025/7/8 19:55
*/
@Data
@Accessors(chain = true)
public class WebhookParam implements Serializable {
private static final long serialVersionUID = 6142195922243220516L;
/**
* 请求id,每个请求唯一
*/
private String reqId;
/**
* 事件类型: message/callbackQuery
*/
private String eventType;
/**
* 事件发生时间戳
*/
private Long timestamp;
/**
* botApp id
*/
private String botAppId;
/**
* 发送者信息,表示发起事件的用户。
*/
private UserInfo sender;
/**
* 会话信息
*/
private Conversation conversation;
/**
* 用户发送的消息内容(Message 对象),仅在 eventType 为 message 时存在
*/
private Message message;
/**
* 内联按钮点击事件的详细信息(CallbackQuery 对象),仅在 eventType 为 callback_query 时存在。
*/
private CallbackQuery callbackQuery;
/**
* 微应用信息 BotApp绑定了微应用,该实体有值
*/
private MiniApp miniApp;
// 嵌套类: 用户信息
@JsonInclude(JsonInclude.Include.NON_NULL)
@Data
public static class UserInfo implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户昵称
*/
private String nickname;
}
// 嵌套类: 会话信息
@JsonInclude(JsonInclude.Include.NON_NULL)
@Data
public static class Conversation implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 会话id
*/
private String conversationId;
}
// 嵌套类: 消息信息
@JsonInclude(JsonInclude.Include.NON_NULL)
@Data
public static class Message implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户发送的消息的消息id
*/
private String messageId;
/**
* 发送文本
*/
private String text;
/**
* 消息发送时间
*/
private Long timestamp;
}
// 嵌套类: 回调查询(内联按钮点击)
@JsonInclude(JsonInclude.Include.NON_NULL)
@Data
public static class CallbackQuery implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 回调数据(通常由开发者定义)
*/
private String data;
/**
* 内联消息id
*/
private String inlineMessageId;
}
// 嵌套类: 微应用信息
@JsonInclude(JsonInclude.Include.NON_NULL)
@Data
public static class MiniApp implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户在对应微应用中的openid
*/
private String openid;
}
}
控制器类
java
@RestController
@RequestMapping("/botApp")
@Slf4j
public class BotAppController {
@PostMapping("/webhook")
public Void miniAppLogin(@RequestBody WebhookParam webhookParam) {
log.info("webhookParam: {}", webhookParam);
// other code
}
}
1.3 Bot应用服务端发送消息到MosApp的Bot会话
1.3.1 MosApp 开放 API 地址
https://mos-test.mos.me/open-apis/botApp/v1/sendMessage/{token}
地址中的 {token} 为应用创建后唯一生成的字符串,可在 Bot 应用详情页查看并复制;请妥善保管,切勿泄露。
1.3.2 报文示例
java
{
"reqId": "2530D143-2C3E-4970-B4AE-8216CEA5653A",
"conversationId": "696638485037509",
"inlineMessageId": "",
"editCurrent": false,
"text": "Hello Bot app",
"inlineButtons": [
[
{
"data": "callbackData",
"text": "callback Button",
"type": "callback"
}
],
[
{
"data": "https://www.google.com/",
"text": "Google",
"type": "url"
}
],
[
{
"data": "",
"text": "Mini app",
"type": "miniApp"
}
]
]
}
1.3.3 入参说明
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
reqId | String | 是 | 请求id,每个请求唯一 |
conversationId | String | 是 | 会话id |
editCurrent | Boolean | 是 | 是否编辑单条消息 |
inlineMessageId | String | 是 | 内联消息id |
text | String | 是 | 消息内容 |
inlineButtons List<List<InlineButton>> | |||
inline button list object | |||
--text | String | 是 | 按钮文案 |
--type | String | 是 | 按钮类型(callback/url/miniApp)详细说明见下"内联按钮类型说明" |
--data | String | 是 | 按钮键值 详细说明见下"内联按钮键值详细说明" |
内联按钮类型说明:
- callback (回调类型) :用户点击后,会触发一条 eventType=callbackQuery 的消息,通过 webhook 发送至 Bot 应用服务端;该消息不会在会话中显示,仅将按钮的 data 值传递给Bot应用服务端。
- url (跳转链接类型):点击后将打开浏览器显示指定链接;若为内部链接(如用户、群组、频道等链接),则会在 MosApp 内打开。)
- miniApp(微应用跳转类型): 若 Bot 应用已绑定微应用,用户点击后将直接进入该绑定的微应用。
内联按钮键值说明:
- 当类型为 callback 时,data 为 Bot 应用服务端配置的字符串;用户点击按钮时,MosApp 会将该 data 内容直接透传给Bot应用服务端,便于Bot应用服务端区分用户点击的具体按钮。
- 当类型为 url 时,data 为 Bot 应用服务端配置的外部 URL 链接或 MosApp 内部链接
- 当类型为 miniApp 时,data 可配置页面路径等信息;打开微应用时,该路径会以参数形式携带在 URL 后。
1.3.4 Java使用范例
请求入参
java
package com.wecloud.modules.openapi.bot.ao;
import lombok.Data;
import java.util.List;
@Data
public class BotAppMessageAo {
/**
* 请求id
*/
private String reqId;
/**
* 会话id
*/
private String conversationId;
/**
* 消息内容
*/
private String text;
/**
* 内联按钮 二维数组
*/
private List<List<InlineButton>> inlineButtons;
/**
* 是否编辑单条消息
*/
private Boolean editCurrent;
/**
* 内联消息id
*/
private String inlineMessageId;
@Data
public static class InlineButton {
/**
* 按钮文案
*/
private String text;
/**
* 按钮类型
*/
private String type;
/**
* 按钮键值 开发者用来区分是哪个按钮
*/
private String data;
}
}
处理用户消息并响应
java
@RestController
@RequestMapping("/botApp")
@Slf4j
public class BotAppController {
// bot app token
private static final String token = "bot app token";
// open api base Request
private static final String openApiBaseUrl = "https://mos.mos.me/open-apis/botApp/v1/sendMessage/";
// envet type
private static final String EVENT_TYPE_CALLBACK_QUERY = "CALLBACK_QUERY";
private static final String EVENT_TYPE_MESSAGE = "MESSAGE";
@Autowired
private RestTemplate restTemplate;
@PostMapping("/webhook")
public Void miniAppLogin(@RequestBody WebhookParam webhookParam) {
log.info("webhookParam: {}", webhookParam);
BotAppMessageAo botAppMessageAo = new BotAppMessageAo();
WebhookParam.Conversation conversation = webhookParam.getConversation();
botAppMessageAo.setReqId(webhookParam.getReqId());
botAppMessageAo.setConversationId(conversation.getConversationId());
// 内联按钮请求
if (EVENT_TYPE_CALLBACK_QUERY.equals(webhookParam.getEventType())) {
WebhookParam.CallbackQuery callbackQuery = webhookParam.getCallbackQuery();
String data = callbackQuery.getData();
botAppMessageAo.setText(data);
// 内联按钮
List<List<InlineButton>> inlineButtons = new ArrayList<>();
// 第一行
List<InlineButton> inlineButtonRow1 = new ArrayList<>();
InlineButton row1Column1 = new InlineButton();
row1Column1.setText("row1Column1");
row1Column1.setType("callback");
row1Column1.setData("row1Column1");
inlineButtonRow1.add(row1Column1);
InlineButton row2Column2 = new InlineButton();
row2Column2.setText("row2Column2");
row2Column2.setType("callback");
row2Column2.setData("row2Column2");
inlineButtonRow1.add(row2Column2);
inlineButtons.add(inlineButtonRow1);
// 第二行
List<InlineButton> inlineButtonRow2 = new ArrayList<>();
InlineButton row2Column1 = new InlineButton();
row2Column1.setText("row2Column1");
row2Column1.setType("url");
row2Column1.setData("https://www.google.com/");
inlineButtonRow2.add(row2Column1);
inlineButtons.add(inlineButtonRow2);
// 第三行
List<InlineButton> inlineButtonRow3 = new ArrayList<>();
InlineButton row3Column1 = new InlineButton();
row3Column1.setText("row3Column1");
row3Column1.setType("miniApp");
row3Column1.setData("https://www.google.com/");
inlineButtonRow3.add(row3Column1);
inlineButtons.add(inlineButtonRow3);
botAppMessageAo.setInlineButtons(inlineButtons);
botAppMessageAo.setEditCurrent(true);
botAppMessageAo.setInlineMessageId(callbackQuery.getInlineMessageId());
}
// 消息请求
else if (EVENT_TYPE_MESSAGE.equals(webhookParam.getEventType())) {
WebhookParam.Message message = webhookParam.getMessage();
String data = message.getText();
if ("/start".equals(data)) {
botAppMessageAo.setText(data);
// 内联按钮
List<List<InlineButton>> inlineButtons = new ArrayList<>();
// 第一行
List<InlineButton> inlineButtonRow1 = new ArrayList<>();
InlineButton row1Column1 = new InlineButton();
row1Column1.setText("row1Column1");
row1Column1.setType("callback");
row1Column1.setData("row1Column1");
inlineButtonRow1.add(row1Column1);
InlineButton row2Column2 = new InlineButton();
row2Column2.setText("row2Column2");
row2Column2.setType("callback");
row2Column2.setData("row2Column2");
inlineButtonRow1.add(row2Column2);
inlineButtons.add(inlineButtonRow1);
// 第二行
List<InlineButton> inlineButtonRow2 = new ArrayList<>();
InlineButton row2Column1 = new InlineButton();
row2Column1.setText("row2Column1");
row2Column1.setType("url");
row2Column1.setData("https://www.google.com/");
inlineButtonRow2.add(row2Column1);
inlineButtons.add(inlineButtonRow2);
// 第三行
List<InlineButton> inlineButtonRow3 = new ArrayList<>();
InlineButton row3Column1 = new InlineButton();
row3Column1.setText("row3Column1");
row3Column1.setType("miniApp");
row3Column1.setData("https://www.google.com/");
inlineButtonRow3.add(row3Column1);
inlineButtons.add(inlineButtonRow3);
botAppMessageAo.setInlineButtons(inlineButtons);
botAppMessageAo.setEditCurrent(false);
botAppMessageAo.setInlineMessageId("");
} else {
botAppMessageAo.setText(data);
botAppMessageAo.setEditCurrent(false);
botAppMessageAo.setInlineMessageId("");
}
}
try {
String url = openApiBaseUrl + token;
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<BotAppMessageAo> requestEntity = new HttpEntity<>(botAppMessageAo, headers);
ResponseEntity<String> response = restTemplate.postForEntity(url, requestEntity, String.class);
} catch (Exception e) {
log.error("error ", e);
}
}
}