7f19b12e74
Co-Authored-By: Claude <noreply@anthropic.com>
5.6 KiB
5.6 KiB
Phase 0 侦察结论(实现期实测补充)
1. 登录与鉴权 ✅
GET /newuc/login/getSecureKey(公开接口,无需登录)返回 RSA 公钥:→ 密码用 RSA 加密(PKCS1 v1.5,exponent=0x10001=65537,modulus 为返回的 hex)。{"code":10000,"data":{"public_exponent":"10001","modulus":"9a370c33...(hex)"}}POST /usercenter/login/pcLogin:请求体{account, password}(password=RSA 加密后的 hex/base64)—— 字段名为推断,实现时若失败尝试{username, password}/{account, pwd}等变体。登录成功返回会话 cookie +userid/company。- 数据接口鉴权 = 会话 cookie:实测在登录后的页内用
fetch('/wechatweb/...', {credentials:'include'})(不带userid/company等自定义头)即可 200 返回数据。自定义请求头(userid/company/source:yunkepc/channel:4)是信息性的,非必需。- 影响:
YunkeClient只需持有会话 cookie 即可调所有数据接口;自定义头可继续带(无害)。
- 影响:
- 会话可从 localStorage 重建:
userid、company、h5Token、userList都在 localStorage(冒烟脚本 existing-session 模式可据此 + cookie 运行)。
2. 微信消息类型码 ✅(实测枚举)
| type | 含义 | 处理 |
|---|---|---|
1 |
文字 | 存 text |
-2 |
日期分隔符 | 丢弃(非真实消息) |
2 |
图片/表情(webp) | file/fileTh 为直接 URL + md5 → 下载去重 |
3 |
图片(旧格式) | file 为不透明 ID(如 07215407292664565911ce5105)→ 需另解析/下载接口 ⏳ |
4 |
视频(mp4) | file 直接 URL + md5 → 下载 |
10 |
系统/链接/名片/邀请 | file 为 support.weixin.qq.com/... URL → 非媒体,跳过下载 |
6 9 13 15 21 22 |
其他(语音/文件/转账/红包/引用等疑似的码) | ⏳ 实现期按需枚举确认(raw_json 已留底) |
normalize_wechat_type已映射1→text、-2→divider;需补2→image、3→image_legacy、4→video、10→system等。
3. 媒体下载机制 ✅
聊天媒体(图片/视频/文件):
- 主机:
wx.oss.yunkecn.com - 路径:
/wechatMsgFile/{companyCode}/{userId}/ossCallback/{aa}/{bb}/{cc}/{md5}.{ext}- 例:
https://wx.oss.yunkecn.com/wechatMsgFile/8m0atd/{userId}/ossCallback/ea/8f/74/ea8f74e7797e63505731e8c51222c554.webp
- 例:
- 消息里给
file(原图)/fileTh(缩略图)/fileHd(高清) +md5(去重键) - 直接 GET 即可下载(公开 OSS,无需鉴权);按
md5去重存储 - 例外:type=
3图片的file是不透明 ID(非 URL)→ 需另找下载接口 ⏳
通话录音 / 语音通话录音:
- 主机:
yunke-pcfile.oss-cn-beijing.aliyuncs.com - 电话录音:
/callFile/{company}/{userId}/YYYY/MMDD/{callNumber}_{ts}.mp3(PhoneCall.recordFile) - 微信语音通话录音:
/wechat-call/{company}/{imei}/ossCallback/{ts}_{ts}.mp3(voiceCall.ossFileName)
头像:wx.qlogo.cn、mmhead.c2c.wechat.com、pc.oss.yunkecn.com(外链,抓到即下载)
4. 语音通话 ✅
POST /wechatweb/callRecord/queryWeChatVoiceList,total=333- 字段:
id、userId/userName/userPhone/userWeChatNickName/userWeChatHeadImg(员工)、talker/talkerNickName/talkerAlias/talkerHeadImg(客户)、callType、isSend(0呼入/1呼出)、callStatus(1接通有录音/2无应答)、ossFileName(录音URL)、ossFileExist、duration(秒,字符串)/durationFile(秒,int)、startTime/endTime、weChatId、remark(如"通话时长02:31"/"对方无应答")、isRoom(群通话?)、callFileId - 归一到
PhoneCall表,channel='voice_call',record_file←ossFileName
5. WhatsApp 联系人 ✅
POST /qqweb/WhatsAppUser/businessFriendList,total=11292- 字段:
uid(员工phone@s.whatsapp.net)、userId/userName/salePhone/salesNickName(员工)、friendUid(客户→friend_id)、nickName、phone、createTime/lastUpdate、groupNum/contactsNum/talkerCount/messageCount/sensitiveWordNum - 归一到
Customer表,channel='whatsapp'
6. WhatsApp 媒体 ⏳
- 消息里给
mediaName(文件名,如{uid}_{keyId}.jpg),非 URL → 需专门下载接口 - ⏳ 实现期:读
whatsapp-service-*.js或触发一次真实图片加载,找到mediaName → 文件的下载接口(很可能也是wx.oss.yunkecn.com或同系 OSS)
7. 群成员昵称 ⏳
chatroom/getChatroomList的memberIds给的是分号分隔的 wxid 列表(不含昵称/头像)- ⏳ 群内成员的昵称/头像可能需另调接口(实现期确认);本期可先存 wxid,昵称后补
对实现的影响(解锁项)
- 登录:
app/session/login.py::encrypt_password改为真实 RSA(用cryptography从 modulus/exponent 构造公钥加密)→ 解锁自动登录 + 真实端到端冒烟 - 媒体下载(M2.6):微信 type 2/4 直接 URL 下载、按 md5 去重;type 3 标记待解析;type 10 跳过
- 语音通话(M2.4):
queryWeChatVoiceList字段已确认,录音直链下载 - WhatsApp 联系人(M3.3):
businessFriendList字段已确认 - 鉴权简化:
YunkeClientcookie-only 即可(自定义头可选)