上手
整体流程如下,按顺序完成即可跑通最小闭环:
- 创建机器人:App 内创建,保存
bot_token与webhook_secret(创建时返回,用于校验推送签名)。 - 配置 Webhook:在机器人设置里填写公网 HTTPS 地址(如
https://your.domain/webhook),用户发消息时服务端会 POST 到此地址。 - 接收事件:你的服务解析 JSON,根据
event_type分支处理(见 Webhook)。 - 调用 API 回复:用
bot_token调/bot/sendmessage等接口发消息。
1. 鉴权 Token
下列机器人 API(发消息、改消息、上传等)均需在 Header 携带 Authorization: Bearer YOUR_BOT_TOKEN。Token 泄露等同于机器人账号被盗,请勿写入前端或公开仓库。
2. 发一条文字(最小示例)
curl -X POST "https://api.bi.ink/bot/sendmessage" \
-H "Authorization: Bearer YOUR_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"target_user_id": "user_456",
"message_type": "text",
"content": "你好,我是机器人"
}'
会话目标二选一:群聊填 group_id;私聊填 target_user_id(用户 ID,不是 username)。
3. 发图片(先上传再发送)
图片 / 视频 / 音频 / 文件需先上传拿 file_id,再调用发消息接口。
# ① 上传
curl -X POST "https://api.bi.ink/bot/uploadfile" \
-H "Authorization: Bearer YOUR_BOT_TOKEN" \
-F "file=@/path/to/image.jpg"
# ② 发送(用上一步返回的 file_id)
curl -X POST "https://api.bi.ink/bot/sendmessage" \
-H "Authorization: Bearer YOUR_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"group_id": "group_123",
"message_type": "image",
"file_id": "file_123456",
"content": "可选说明文字"
}'
鉴权与响应
机器人 API 请求头
路径以 /bot/sendmessage、/bot/getme 等为代表的接口,使用 bot_token 鉴权:
Authorization: Bearer YOUR_BOT_TOKEN Content-Type: application/json
App 内管理机器人(创建、改 Webhook、重置 Token)走用户登录态 access_token,与 bot_token 不同,详见 App 内机器人管理页。
统一响应格式
成功时 code 为 200(部分旧接口也可能为 0),业务数据在 data 里;失败时 code 非 200,msg 为错误说明。
{
"code": 200,
"msg": "发送成功",
"data": { ... }
}
| HTTP 状态 | 常见原因 |
|---|---|
| 401 | Token 无效、过期或未携带 |
| 403 | 机器人不在群内、无禁言/删消息权限、只能编辑自己的消息等 |
| 400 | 参数缺失、group_id 与 target_user_id 均未填等 |
消息类型
message_type 取值与 JSON 骨架如下(group_id / target_user_id 按会话类型选一个)。
文本 text
纯文字。
{
"group_id": "group_123",
"message_type": "text",
"content": "这是一条文本消息"
}
| 字段 | 类型 | 说明 | 必填 |
|---|---|---|---|
message_type |
string | 固定 text |
是 |
content |
string | 正文 | 是 |
图片 image
JPG / PNG / GIF 等,需先有 file_id。
{
"group_id": "group_123",
"message_type": "image",
"content": "可选说明",
"file_id": "file_123456"
}
| 字段 | 类型 | 说明 | 必填 |
|---|---|---|---|
message_type |
string | 固定 image |
是 |
file_id |
string | 上传接口返回 | 是 |
content |
string | 说明,可空 | 否 |
视频 video
如 MP4、MOV。
{
"group_id": "group_123",
"message_type": "video",
"content": "可选说明",
"file_id": "file_123456"
}
| 字段 | 类型 | 说明 | 必填 |
|---|---|---|---|
message_type |
string | 固定 video |
是 |
file_id |
string | 上传接口返回 | 是 |
content |
string | 说明,可空 | 否 |
音频 audio
如 MP3、WAV、M4A。
{
"group_id": "group_123",
"message_type": "audio",
"content": "可选说明",
"file_id": "file_123456"
}
| 字段 | 类型 | 说明 | 必填 |
|---|---|---|---|
message_type |
string | 固定 audio |
是 |
file_id |
string | 上传接口返回 | 是 |
content |
string | 说明,可空 | 否 |
文件 file
任意附件类型。
{
"group_id": "group_123",
"message_type": "file",
"content": "可选说明",
"file_id": "file_123456"
}
| 字段 | 类型 | 说明 | 必填 |
|---|---|---|---|
message_type |
string | 固定 file |
是 |
file_id |
string | 上传接口返回 | 是 |
content |
string | 说明,可空 | 否 |
贴纸 sticker
传 file_id 即可,服务端会解析资源。
{
"group_id": "group_123",
"message_type": "sticker",
"file_id": "sticker_123456"
}
骰子 dice
当前仅支持标准骰子 🎲(点数 1–6)。暂不支持飞镖、篮球等其他互动 emoji。点数由服务端随机生成,请求里不能指定,也不能在发完后再查接口补拿——必须在当次响应或 Webhook 里读取。
① 机器人发骰子
content 可省略(默认 🎲),一般只需 message_type: "dice" 加会话目标即可。
curl -X POST "https://api.bi.ink/bot/sendmessage" \
-H "Authorization: Bearer YOUR_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"target_user_id": "user_456",
"message_type": "dice"
}'
② 如何获取点数(机器人自己发的)
调用 /bot/sendmessage 成功后,从响应体读取:
data.content.value → 整数 1–6,即本次掷出的点数。
{
"code": 200,
"msg": "发送成功",
"data": {
"message_id": "msg_abc123",
"conversation_id": "private_xxx_yyy",
"message_type": "dice",
"content": {
"type": "dice",
"emoji": "🎲",
"text": "🎲",
"value": 4
},
"created_at": 1732636800
}
}
data.content 是对象(不是字符串)。业务里用 result["data"]["content"]["value"] 即可。可同时保存 message_id 供后续引用。
| 字段 | 类型 | 说明 | 必填 |
|---|---|---|---|
message_type |
string | 固定 dice |
是 |
content |
string | 可省略;若填则仅 🎲 有效,其他 emoji 会被服务端归一为 🎲 |
否 |
③ 用户发骰子(Webhook 推送)
用户向机器人私聊或群内发送骰子时,Webhook 里 message_type 为 dice,但 content 是JSON 字符串,需先解析再取 value:
# Webhook 收到用户骰子 import json dice = json.loads(event["content"]) points = dice["value"] # 1-6
{
"event_type": "private_message",
"message_type": "dice",
"content": "{\"type\":\"dice\",\"emoji\":\"🎲\",\"text\":\"🎲\",\"value\":5}"
}
两种场景对比
| 场景 | 点数在哪 | content 格式 |
|---|---|---|
| 机器人调用 sendmessage 发骰子 | HTTP 响应 data.content.value |
对象 |
| 用户发骰子 → Webhook 通知机器人 | Webhook 正文 content 解析后的 value |
JSON 字符串,需 parse |
联系人 contact
分享名片,file_id 此处为用户相关标识(与业务约定一致)。
{
"group_id": "group_123",
"message_type": "contact",
"file_id": "user_123456"
}
按钮与回复
内联键盘
发消息时在 extra.inline_keyboard 里放二维数组,每项为 text + callback_data。
{
"group_id": "group_123",
"message_type": "text",
"content": "请选择:",
"extra": {
"inline_keyboard": [
[
{"text": "确认", "callback_data": "confirm"},
{"text": "取消", "callback_data": "cancel"}
],
[
{"text": "查看详情", "callback_data": "detail"}
]
]
}
}
回调怎么处理
- 用户点了按钮,你的 Webhook 会收到
event_type为callback_query的 JSON。 - 里面会有
callback_id(形如cb_userId_xxx)、callback_data、原消息message_id、点击人sender_id。 - 在约 30 秒内请求
POST /bot/answercallback,把callback_id回给服务端;需要的话再调editmessage改文案或清掉键盘。
Webhook 回调示例
{
"event_type": "callback_query",
"message_id": "msg_abc123",
"sender_id": "user_xxx",
"sender_username": "john",
"sender_display_name": "John Doe",
"group_id": "group_123",
"group_title": "测试群组",
"message_type": "callback",
"content": "confirm",
"timestamp": 1732636800,
"callback_id": "cb_user123_abc12345",
"callback_data": "confirm"
}
应答回调
curl -X POST "https://api.bi.ink/bot/answercallback" \
-H "Authorization: Bearer YOUR_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"callback_id": "cb_user123_abc12345",
"text": "操作成功",
"show_alert": false
}'
text:提示文案;show_alert 为 true 时用弹窗,否则多为轻提示;url 可选,给按钮跳转用。
回复某条消息
{
"group_id": "group_123",
"message_type": "text",
"content": "回复内容",
"reply_to_id": "msg_123456"
}
引用消息
{
"group_id": "group_123",
"message_type": "text",
"content": "引用回复",
"quote_message_id": "msg_123455"
}
Webhook
在 App 机器人设置中配置 webhook_url 后,相关事件会以 POST + JSON 推送到你的服务器。你的服务应在几秒内返回 HTTP 2xx;耗时逻辑请异步处理,否则可能触发重试(最多 1 次)。
推送请求头
| Header | 说明 |
|---|---|
Content-Type: application/json |
固定 JSON 正文 |
X-Bot-Token |
机器人 Token,可用于核对来源 |
X-Bot-User-Id |
机器人用户 ID |
X-Webhook-Signature |
对原始 JSON 正文的 HMAC-SHA256 十六进制签名(配置了 webhook_secret 时才有) |
签名校验(推荐)
创建机器人时会得到 webhook_secret。收到推送后,用同样算法验签,防止伪造请求:
import hmac, hashlib def verify_webhook(raw_body: bytes, secret: str, signature: str) -> bool: expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, signature or "")
事件类型 event_type
| event_type | 何时触发 | 说明 |
|---|---|---|
private_message |
用户私聊机器人 | group_id 为空 |
group_message |
群内有人发消息 | 机器人须在群内且拥有读消息权限(can_read_messages=1) |
callback_query |
用户点击内联按钮 | 含 callback_id,须在 30 秒内 answercallback |
member_joined |
新成员入群 | message_type 为 member_event;content 为邀请人 user_id(无则为空) |
member_left |
成员退群 / 被踢 | content 为原因:left / kicked / banned |
group_dissolved |
群被解散 | content 固定 dissolved |
载荷字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
event_type | string | 事件类型,见上表 |
message_id | string | 消息 ID(成员事件可能为空) |
sender_id | string | 发送者 / 相关用户 ID |
sender_username | string | 发送者 @用户名 |
sender_display_name | string | 发送者昵称 |
sender_avatar_url | string | 发送者头像 |
sender_role | string | 群内角色:owner / admin / member(仅群消息) |
group_id | string | 群组 ID,私聊为空 |
group_title | string | 群名称 |
message_type | string | 消息类型:text、image、dice、callback 等 |
content | string | 文本内容;骰子为 JSON 字符串(见下) |
timestamp | int | Unix 秒级时间戳 |
callback_id | string | 按钮回调 ID(仅 callback_query) |
callback_data | string | 按钮自定义数据(仅 callback_query) |
私聊文字消息示例
{
"event_type": "private_message",
"message_id": "msg_abc123",
"sender_id": "user_xxx",
"sender_username": "john",
"sender_display_name": "John Doe",
"group_id": "",
"message_type": "text",
"content": "你好",
"timestamp": 1732636800
}
群消息示例
{
"event_type": "group_message",
"message_id": "msg_grp_001",
"sender_id": "user_xxx",
"sender_username": "alice",
"sender_display_name": "Alice",
"sender_role": "member",
"group_id": "group_123",
"group_title": "测试群组",
"message_type": "text",
"content": "/help",
"timestamp": 1732636800
}
用户掷骰子(Webhook)
用户发送骰子时,message_type 为 dice,content 为 JSON 字符串。解析后取 value(1–6)。与机器人自己发骰子不同:Webhook 里 content 是字符串,sendmessage 响应里 content 是对象。详见 骰子。
{
"event_type": "private_message",
"message_id": "msg_dice_001",
"sender_id": "user_xxx",
"message_type": "dice",
"content": "{\"type\":\"dice\",\"emoji\":\"🎲\",\"text\":\"🎲\",\"value\":5}",
"timestamp": 1732636800
}
新成员入群示例
{
"event_type": "member_joined",
"sender_id": "user_newbie",
"sender_username": "newbie",
"sender_display_name": "新同学",
"group_id": "group_123",
"group_title": "欢迎群",
"message_type": "member_event",
"content": "user_inviter_id",
"timestamp": 1732636800
}
接口列表
以下接口均使用 bot_token 鉴权,请求方法均为 POST,路径前缀 /bot/。
| 路径 | 作用 |
|---|---|
/bot/getme | 获取当前机器人信息 |
/bot/sendmessage | 发送消息(文本 / 媒体 / 骰子 / 按钮等) |
/bot/editmessage | 编辑机器人自己发的消息 |
/bot/deletemessage | 删除消息(单条或批量) |
/bot/uploadfile | 上传文件,获取 file_id |
/bot/answercallback | 响应内联按钮点击 |
/bot/botapisetcommands | 设置命令菜单(最多 100 条) |
/bot/botapigetcommands | 读取命令菜单 |
/bot/getgroup | 获取机器人所在群资料 |
/bot/mutemember | 禁言成员 / 全员禁言 |
/bot/unmutemember | 解除禁言 / 解除全员禁言 |
sendmessage 公共参数
| 字段 | 类型 | 说明 | 必填 |
|---|---|---|---|
group_id | string | 群 ID(群聊) | 与 target_user_id 二选一 |
target_user_id | string | 用户 ID(私聊) | 与 group_id 二选一 |
message_type | string | 见消息类型 | 是 |
content | string | 文本 / 说明 / 骰子 emoji | 视类型而定 |
file_id | string | 媒体文件 ID(上传接口返回) | 媒体类必填 |
reply_to_id | string | 回复某条消息 | 否 |
quote_message_id | string | 引用某条消息 | 否 |
mention_user_ids | string[] | @提及的用户名列表(username,非 user_id) | 否 |
mention_all | bool | @所有人 | 否 |
extra.inline_keyboard | array | 内联按钮,见按钮与回复 | 否 |
上传文件 uploadfile
POST /bot/uploadfile,multipart/form-data,字段名 file。单文件最大 100MB,支持常见图片 / 视频 / 音频 / 文档 / 压缩包。
curl -X POST "https://api.bi.ink/bot/uploadfile" \ -H "Authorization: Bearer YOUR_BOT_TOKEN" \ -F "file=@/path/to/file.jpg"
{
"code": 200,
"msg": "文件上传成功",
"data": {
"file_id": "file_123456"
}
}
发消息 sendmessage
POST /bot/sendmessage。媒体类传 file_id;骰子见 骰子——点数在响应 data.content.value,无单独查询接口。
{
"code": 200,
"msg": "发送成功",
"data": {
"message_id": "msg_xxx",
"conversation_id": "private_bot_user",
"message_type": "dice",
"content": {
"type": "dice",
"emoji": "🎲",
"text": "🎲",
"value": 3
},
"created_at": 1732636800
}
}
编辑消息
POST /bot/editmessage
{
"message_id": "msg_xxx",
"content": "已更新",
"extra": {
"inline_keyboard": []
}
}
删消息
POST /bot/deletemessage。单条:
{ "message_id": "msg_xxx" }
多条:
{ "message_ids": ["msg_123", "msg_456", "msg_789"] }
群里通常要有管理权限或机器人被授予相应能力;私聊里参与者规则以客户端为准。
当前机器人信息 getme
POST /bot/getme,无请求体。返回机器人 user_id、username、昵称、头像等。
{
"code": 200,
"msg": "获取成功",
"data": {
"user_id": "bot_xxx",
"username": "my_bot",
"display_name": "我的机器人",
"bio": "简介",
"avatar_url": "https://...",
"status": 1,
"created_at": "2025-01-01 00:00:00"
}
}
群资料 getgroup
POST /bot/getgroup,机器人须在目标群内。为隐私考虑不返回群主 ID。
// 请求
{ "group_id": "group_123" }
// 响应 data
{
"group_id": "group_123",
"title": "测试群",
"description": "群简介",
"avatar": "https://...",
"member_count": 128,
"is_public": 1,
"is_cy": 0,
"created_at": "2025-01-01 00:00:00"
}
应答按钮 answercallback
POST /bot/answercallback,收到 callback_query 后尽快调用。
{
"callback_id": "cb_user123_abc12345",
"text": "操作成功",
"show_alert": false,
"url": ""
}
| 字段 | 类型 | 说明 | 必填 |
|---|---|---|---|
callback_id |
string | Webhook 里原样带回 | 是 |
text |
string | 提示文案 | 否 |
show_alert |
bool | 是否弹窗 | 否 |
url |
string | 打开链接 | 否 |
命令菜单
设置:POST /bot/botapisetcommands
{
"commands": [
{"command": "start", "description": "开始使用"},
{"command": "help", "description": "帮助"},
{"command": "price", "description": "查价"}
]
}
读取:POST /bot/botapigetcommands
群成员禁言 mutemember / unmutemember
机器人须为群主、管理员,或被授予 can_mute_members 权限。不能禁言群主或其他管理员。
// 禁言单人 3600 秒(1 小时);mute_duration=0 表示永久
{
"group_id": "group_123",
"member_user_id": "user_456",
"mute_duration": 3600
}
// 全员禁言:member_user_id 传 "all" 或 "*"
{
"group_id": "group_123",
"member_user_id": "all",
"mute_duration": 0
}
// 解除单人禁言
{
"group_id": "group_123",
"member_user_id": "user_456"
}
// 解除全员禁言
{
"group_id": "group_123",
"member_user_id": "all"
}
不提供「拉取完整群成员列表」接口;定向操作请使用业务侧已知的 user_id。
常见问题
- 收不到 Webhook?
- 确认 URL 为公网 HTTPS;App 内已保存 Webhook;机器人已加入目标群且拥有读消息权限(群消息)。本地调试可用 ngrok 等隧道。
- 群消息是否必须 @ 机器人?
- 群内所有消息都会推送给有读权限的机器人(与 Telegram 不同),请在业务层自行过滤命令或关键词。
- 私聊用户 ID 从哪来?
- Webhook 推送里的
sender_id即为target_user_id,回复私聊时原样填入即可。 - 机器人发骰子后怎么知道点数?
- 看当次
/bot/sendmessage响应里的data.content.value(整数 1–6)。没有「按 message_id 再查点数」的接口,发完必须当场读响应。 - 骰子能指定点数吗?
- 不能。仅支持 🎲(1–6),由服务端
crypto/rand随机,Bot 与用户均不可指定或篡改。 - 按钮点了没反应?
- 须在 30 秒内调用
/bot/answercallback并传入 Webhook 里的callback_id;可用editmessage更新原消息或清空键盘。 - code 用 200 还是 0?
- 新接口统一
200表示成功;示例代码中建议写code in (0, 200)兼容旧版。
示例代码
Python:发文字
import requests
def send_text_message(bot_token, group_id, content):
url = "https://api.bi.ink/bot/sendmessage"
headers = {
"Authorization": f"Bearer {bot_token}",
"Content-Type": "application/json"
}
data = {
"group_id": group_id,
"message_type": "text",
"content": content
}
response = requests.post(url, json=data, headers=headers)
return response.json()
Python:上传后发图
import requests
def upload_file(bot_token, file_path):
url = "https://api.bi.ink/bot/uploadfile"
headers = {"Authorization": f"Bearer {bot_token}"}
with open(file_path, 'rb') as f:
files = {'file': f}
response = requests.post(url, files=files, headers=headers)
result = response.json()
if result.get('code') == 200:
return result['data']['file_id']
raise RuntimeError(result.get('msg', 'upload failed'))
def send_image_message(bot_token, group_id, file_id, caption=""):
url = "https://api.bi.ink/bot/sendmessage"
headers = {
"Authorization": f"Bearer {bot_token}",
"Content-Type": "application/json"
}
data = {
"group_id": group_id,
"message_type": "image",
"file_id": file_id,
"content": caption
}
response = requests.post(url, json=data, headers=headers)
return response.json()
file_id = upload_file(bot_token, "/path/to/image.jpg")
send_image_message(bot_token, "group_123", file_id, "说明")
Python:带按钮
def send_message_with_buttons(bot_token, group_id, content):
url = "https://api.bi.ink/bot/sendmessage"
headers = {
"Authorization": f"Bearer {bot_token}",
"Content-Type": "application/json"
}
data = {
"group_id": group_id,
"message_type": "text",
"content": content,
"extra": {
"inline_keyboard": [
[
{"text": "确认", "callback_data": "confirm"},
{"text": "取消", "callback_data": "cancel"}
]
]
}
}
return requests.post(url, json=data, headers=headers).json()
Python:Flask 收 Webhook(含验签 + 私聊回复)
import json, hmac, hashlib, requests
from flask import Flask, request
app = Flask(__name__)
BOT_TOKEN = "your_bot_token"
WEBHOOK_SECRET = "your_webhook_secret"
API_BASE = "https://api.bi.ink"
def verify_signature(raw: bytes, sig: str) -> bool:
expected = hmac.new(WEBHOOK_SECRET.encode(), raw, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, sig or "")
def api_post(path, payload):
return requests.post(
f"{API_BASE}{path}",
json=payload,
headers={"Authorization": f"Bearer {BOT_TOKEN}", "Content-Type": "application/json"},
timeout=10,
)
@app.route("/webhook", methods=["POST"])
def webhook():
raw = request.get_data()
if not verify_signature(raw, request.headers.get("X-Webhook-Signature", "")):
return "invalid signature", 403
event = json.loads(raw)
et = event.get("event_type")
if et == "private_message" and event.get("content") == "/start":
api_post("/bot/sendmessage", {
"target_user_id": event["sender_id"],
"message_type": "text",
"content": "欢迎使用,发送 /help 查看命令",
})
elif et == "private_message" and event.get("message_type") == "dice":
dice = json.loads(event["content"])
api_post("/bot/sendmessage", {
"target_user_id": event["sender_id"],
"message_type": "text",
"content": f"你掷出了 {dice['value']} 点",
})
elif et == "callback_query":
api_post("/bot/answercallback", {
"callback_id": event["callback_id"],
"text": "已收到",
"show_alert": False,
})
return "OK", 200
Python:机器人发骰子并读取点数
import requests
def send_dice_and_get_value(bot_token, target_user_id):
r = requests.post(
"https://api.bi.ink/bot/sendmessage",
json={
"target_user_id": target_user_id,
"message_type": "dice",
},
headers={"Authorization": f"Bearer {bot_token}"},
timeout=10,
).json()
if r.get("code") not in (0, 200):
raise RuntimeError(r.get("msg", "send failed"))
# 点数在这里 —— 必须是对象,不是字符串
value = r["data"]["content"]["value"]
message_id = r["data"]["message_id"]
return value, message_id
# 示例:掷骰后回复文字
points, _ = send_dice_and_get_value(BOT_TOKEN, "user_456")
requests.post(
"https://api.bi.ink/bot/sendmessage",
json={
"target_user_id": "user_456",
"message_type": "text",
"content": f"机器人掷出了 {points} 点",
},
headers={"Authorization": f"Bearer {BOT_TOKEN}"},
)
Python:Flask 收 Webhook(按钮回调,精简版)
import requests
from flask import Flask, request
app = Flask(__name__)
BOT_TOKEN = "your_bot_token"
API_BASE_URL = "https://api.bi.ink"
@app.route('/webhook', methods=['POST'])
def webhook():
event = request.json
if event.get('event_type') == 'callback_query':
callback_id = event['callback_id']
callback_data = event['callback_data']
message_id = event['message_id']
if callback_data == 'confirm':
answer_callback(callback_id, '已确认', False)
edit_message(message_id, '已确认', {'inline_keyboard': []})
elif callback_data == 'cancel':
answer_callback(callback_id, '已取消', False)
return 'OK', 200
def answer_callback(callback_id, text, show_alert):
requests.post(
f"{API_BASE_URL}/bot/answercallback",
json={"callback_id": callback_id, "text": text, "show_alert": show_alert},
headers={"Authorization": f"Bearer {BOT_TOKEN}", "Content-Type": "application/json"},
)
def edit_message(message_id, content, extra):
requests.post(
f"{API_BASE_URL}/bot/editmessage",
json={"message_id": message_id, "content": content, "extra": extra},
headers={"Authorization": f"Bearer {BOT_TOKEN}", "Content-Type": "application/json"},
)
Go:发文字
package main
import (
"bytes"
"encoding/json"
"net/http"
)
func sendMessage(botToken, groupID, content string) error {
url := "https://api.bi.ink/bot/sendmessage"
data := map[string]interface{}{
"group_id": groupID,
"message_type": "text",
"content": content,
}
jsonData, _ := json.Marshal(data)
req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonData))
req.Header.Set("Authorization", "Bearer "+botToken)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}
Node:Express Webhook
const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());
const BOT_TOKEN = 'your_bot_token';
const API_BASE_URL = 'https://api.bi.ink';
app.post('/webhook', async (req, res) => {
const event = req.body;
if (event.event_type === 'private_message' && event.content === '/start') {
await axios.post(`${API_BASE_URL}/bot/sendmessage`, {
target_user_id: event.sender_id,
message_type: 'text',
content: '欢迎使用'
}, { headers: { Authorization: `Bearer ${BOT_TOKEN}` } });
} else if (event.event_type === 'callback_query') {
await axios.post(`${API_BASE_URL}/bot/answercallback`, {
callback_id: event.callback_id,
text: '收到',
show_alert: false
}, { headers: { Authorization: `Bearer ${BOT_TOKEN}` } });
}
res.status(200).send('OK');
});
app.listen(3000);