4.5 KiB
4.5 KiB
MEMORY.md - 长期记忆
这个文件用于记录重要的长期知识和经验教训。
DingTalk媒体发送成功经验
日期: 2026-03-05
重要性: ⭐⭐⭐⭐⭐
问题背景
尝试通过DingTalk发送文件时遇到多次失败,反复尝试了多种方法:
- 使用message工具 - 失败("Failed to upload media")
- 直接调用robot/send API - 失败("token is not exist" / "缺少参数 access_token")
- 尝试不同的API端点和消息格式 - 大部分失败
解决方案(成功方式)
Token获取
// 关键:使用GET + URL参数(非params)
const tokenUrl = `https://oapi.dingtalk.com/gettoken?appkey=${APP_KEY}&appsecret=${APP_SECRET}`;
const response = await axios.get(tokenUrl);
const accessToken = response.data.access_token;
重要:不要使用axios.get(url, {params: {...}}),必须在URL中直接拼接参数
文件上传
const uploadUrl = `https://oapi.dingtalk.com/media/upload?access_token=${accessToken}`;
const form = new FormData();
form.append('media', fs.createReadStream(filePath));
form.append('type', 'file');
const upload = await axios.post(uploadUrl, form, {headers: form.getHeaders()});
const media_id = upload.data.media_id;
消息发送(关键成功点)
const url = "https://api.dingtalk.com/v1.0/robot/groupMessages/send";
const headers = {
"x-acs-dingtalk-access-token": accessToken, // ← 关键:在Header中
"Content-Type": "application/json"
};
const body = {
robotCode: ROBOT_CODE,
openConversationId: OPEN_CONVERSATION_ID,
msgKey: "sampleFile", // ← 文件用sampleFile,图片用sampleMarkdown
msgParam: JSON.stringify({ // ← 关键:必须是字符串!
mediaId: media_id,
fileName: fileName
})
};
const result = await axios.post(url, body, { headers });
关键msgKey对应关系
| 媒体类型 | msgKey | 测试状态 |
|---|---|---|
| 文件 | sampleFile |
✅ 验证成功 |
| 图片 | sampleMarkdown |
✅ 验证成功 |
| 视频 | sampleVideo |
待测试 |
失败原因总结
-
使用旧的robot/send API
- 返回 "token is not exist"
- 使用v1.0 API后解决
-
msgParam使用对象而非字符串
- 返回 "MissingmsgParam"
- 必须使用
JSON.stringify()
-
access_token放在错误位置
- 在URL中会失败
- 必须在Header中:
x-acs-dingtalk-access-token
验证的端点差异
| API端点 | 状态 | 说明 |
|---|---|---|
https://oapi.dingtalk.com/gettoken |
✅ 可用 | 必须用URL参数 |
https://oapi.dingtalk.com/media/upload |
✅ 可用 | 支持文件上传 |
https://api.dingtalk.com/v1.0/robot/groupMessages/send |
✅ 可用 | 成功发送消息 |
https://oapi.dingtalk.com/robot/send |
❌ 失败 | 返回token错误 |
配置信息
AppKey: ding4ursdp0l2giat4bj
AppSecret: J0gBicjKiIHoKla7WfKKhRs1Tv8L6Xd5UhW3EVQByF16G7Vn7UUcRhP6u-PBCQNo
RobotCode: ding4ursdp0l2giat4bj
OpenConversationId: cidcjYshXVtKck5LfOO9AqOJg==
成功案例
2026-03-05 18:44
- 项目:database_analysis_summary.txt
- 文件大小:3,155 bytes
- media_id: @lAjPM2GaR32g2U3OC2pNq84Clg_0
- msgKey: sampleFile
- API: /v1.0/robot/groupMessages/send
- ProcessQueryKey: lXs/uLRd0YxJVk1x0VyTLfSdY2YKCE1yrGn2vGlQ+GM=
- 状态:成功发送到钉钉群聊
经验教训
-
不要在OpenClaw环境中直接调用原始钉钉API
- OpenClaw插件会拦截请求
- 认证可能不匹配
-
msgKey是关键
- 文件 → sampleFile
- 图片 → sampleMarkdown
- 视频 → sampleVideo
-
msgParam必须是JSON字符串
- 这是容易出错的地方
- 必须用
JSON.stringify()包裹
-
使用正确的API版本
- v1.0 API是正确选择
- 旧版API不再有效
Python环境问题
日期: 2026-03-05
重要性: ⭐⭐⭐
问题: PowerShell直接调用Python时遇到路径和编码问题
解决方案:
- 设置PATH:
$env:PATH = "F:\pyenv\pyenv-win\pyenv-win\pyenv-win\versions\3.14.2;$env:PATH" - 使用UTF-8编码:
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
Git配置
日期: 2026-03-05
重要性: ⭐⭐⭐
Git服务器: git.alicorns.co.jp (Gitea)
用户: aitest
密码: Aiitest123456
主要仓库:
aitest/office-file-handler.gitaitest/dingtalk-media-sender.gitaitest/workspace.git
记录准则
- 只记录重要且会重复用到的信息
- 包括成功和失败的经验
- 提供可执行的代码示例
- 标注日期和重要性