Appearance
BOT应用后端开发
1.1 BOT应用与开发者交互流程图
1.2 开发者承接用户发给BOT应用的消息
用户给BOT应用发消息后,MosApp会将消息通过开发者配置的webhook透传给开发者。
1.2.1 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.2 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 开发者响应用户消息
1.3.1 MosApp open api地址
https://mos-test.mos.me/open-apis/botApp/v1/sendMessage/{token}
token为创建应用后唯一生成的字符串,请到bot应用详情中进行查看与复制,需妥善保管,不可泄露。
1.3.2 入参说明
属性 | 类型 | 必填 | 说明 |
---|---|---|---|
reqId | String | 是 | 请求id,每个请求唯一 |
conversationId | String | 是 | 会话id |
editCurrent | Boolean | 是 | 是否编辑单条消息 |
inlineMessageId | String | 是 | 内联消息id |
text | String | 是 | 消息内容 |
text | String | 是 | 按钮文案 |
type | String | 是 | 按钮类型(callback/url/miniApp)详细说明见下"内联按钮类型说明" |
data | String | 是 | 按钮键值 详细说明见下"内联按钮键值详细说明" |
内联按钮类型说明:
- callback : 回调类型,用户点击触发一条eventType=callbackQuery的消息发送至webhook,消息不显示在会话上,消息会将将按钮data值发给开发者
- url : 跳转url,点击打开浏览器显示指定链接(如果是内部链接如用户、群组、频道等链接,点击将MosApp应用内直接进入)
- miniApp: 微应用跳转按钮,用过BOT应用绑定了微应用,点击将打开绑定的微应用
内联按钮键值说明:
- 内联按钮类型是callback类型,则data为开发者配置的字符串,用户点击按钮式,MosApp会将data内容透传给开发者,方便开发者区分用户点击哪个按钮
- 内联按钮类型是url类型,则data为开发者配置的外部url链接或MosApp内部链接
- 内联按钮类型miniApp类型,则data无需配置
1.3.3 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);
}
}
}