200 lines
5.8 KiB
Markdown
200 lines
5.8 KiB
Markdown
# CapSolver API 注入修复实施记录
|
||
|
||
## 修改完成时间
|
||
2025-11-17 14:47
|
||
|
||
## 实施的修改
|
||
|
||
### 文件: `src/tools/account-register/sites/windsurf.js`
|
||
|
||
### 方法: `solveWithCapSolver()` (第767-962行)
|
||
|
||
### 修改内容
|
||
|
||
#### 1. 改进 Token 注入(第773-783行)
|
||
**修改前**: 仅简单设置 input.value
|
||
```javascript
|
||
await this.page.evaluate((solution) => {
|
||
document.querySelector('input[name="cf-turnstile-response"]').value = solution;
|
||
}, token);
|
||
```
|
||
|
||
**修改后**: 注入 token 并触发事件
|
||
```javascript
|
||
await this.page.evaluate((token) => {
|
||
const input = document.querySelector('input[name="cf-turnstile-response"]');
|
||
if (input) {
|
||
input.value = token;
|
||
// 触发各种事件以通知页面
|
||
['input', 'change', 'blur'].forEach(eventType => {
|
||
input.dispatchEvent(new Event(eventType, { bubbles: true }));
|
||
});
|
||
}
|
||
}, token);
|
||
```
|
||
|
||
**改进**: 触发 DOM 事件,让监听器检测到 token 变化
|
||
|
||
#### 2. 添加回调函数触发(第787-862行)
|
||
**新增功能**: 多种方法查找并触发 Turnstile 回调
|
||
|
||
- **方法A**: 查找 React 组件回调 `window.cf__reactTurnstileOnLoad`
|
||
- **方法B**: 从 DOM 元素 `[data-callback]` 属性获取回调名
|
||
- **方法C**: 使用 `window.turnstile.reset()` 和 `window.turnstile.execute()` API
|
||
- **方法D**: 遍历 window 对象查找包含 'turnstile' 的函数
|
||
|
||
**日志输出**: 显示每个方法的触发结果(成功 ✓ 或失败 ✗)
|
||
|
||
#### 3. 添加按钮强制激活(第876-906行)
|
||
**新增功能**: 后备方案,确保按钮可点击
|
||
|
||
```javascript
|
||
const buttonActivated = await this.page.evaluate(() => {
|
||
const buttons = Array.from(document.querySelectorAll('button'));
|
||
buttons.forEach(btn => {
|
||
if (btn.textContent.trim() === 'Continue' ||
|
||
btn.textContent.trim() === 'Submit') {
|
||
if (btn.disabled) {
|
||
btn.disabled = false;
|
||
btn.removeAttribute('disabled');
|
||
btn.classList.remove('disabled');
|
||
}
|
||
}
|
||
});
|
||
});
|
||
```
|
||
|
||
**改进**: 即使回调失败,也能确保按钮可点击
|
||
|
||
#### 4. 改进验证完成检测(第908-962行)
|
||
**修改前**:
|
||
- 检查 iframe 状态(可能无法访问)
|
||
- 超时时间 20 秒
|
||
- 失败时等待 30 秒手动操作
|
||
|
||
**修改后**:
|
||
- **检查1**: 按钮必须激活
|
||
- **检查2**: hidden input 必须有值
|
||
- **检查3**: iframe 状态(可选)
|
||
- 超时时间 10 秒(缩短)
|
||
- 轮询间隔 500ms(更频繁)
|
||
- 失败时输出详细调试信息
|
||
- 如果按钮已激活且有 token,认为成功
|
||
- 失败时等待 10 秒(缩短)
|
||
|
||
**调试信息输出**:
|
||
```javascript
|
||
{
|
||
buttonDisabled: false,
|
||
buttonText: "Continue",
|
||
hasToken: true,
|
||
tokenLength: 2000
|
||
}
|
||
```
|
||
|
||
## 关键改进点
|
||
|
||
### 1. 完整的验证流程模拟
|
||
- ✅ Token 注入
|
||
- ✅ 事件触发
|
||
- ✅ 回调调用
|
||
- ✅ 按钮激活
|
||
- ✅ 状态验证
|
||
|
||
### 2. 多重保障机制
|
||
- 4 种回调触发方法
|
||
- 强制按钮激活(后备)
|
||
- 灵活的状态检测
|
||
|
||
### 3. 详细的调试信息
|
||
- Token 长度显示
|
||
- 每个回调的触发结果
|
||
- 按钮激活状态
|
||
- 最终状态快照
|
||
|
||
### 4. 更合理的超时处理
|
||
- 缩短等待时间(10秒而非30秒)
|
||
- 提供详细的失败原因
|
||
- 智能判断是否继续
|
||
|
||
## 测试步骤
|
||
|
||
1. **运行注册流程**:
|
||
```bash
|
||
node src/cli.js register -s windsurf --keep-browser-open
|
||
```
|
||
|
||
2. **观察日志输出**:
|
||
- `[CapSolver] 注入 token 到页面 (长度: XXX)...`
|
||
- `[CapSolver] 回调触发结果:`
|
||
- 查看哪些方法成功(✓)
|
||
- 查看哪些方法失败(✗)
|
||
- `[CapSolver] 已强制激活按钮` 或 `按钮已经是激活状态`
|
||
- `[CapSolver] ✓ 验证完成确认通过`
|
||
|
||
3. **检查浏览器**:
|
||
- Turnstile checkbox 是否勾选?
|
||
- Continue 按钮是否可点击?
|
||
- 是否自动进入下一步?
|
||
|
||
4. **如果失败**:
|
||
- 查看 `[CapSolver] 当前状态:` 输出
|
||
- 判断是回调问题、按钮问题还是 iframe 问题
|
||
- 根据具体问题选择下一步方案
|
||
|
||
## 预期结果
|
||
|
||
### 成功场景
|
||
```
|
||
[Windsurf] [CapSolver] ✓ 获取到token: 0.kDqN3tMdKWreLsL90...
|
||
[Windsurf] [CapSolver] 注入 token 到页面 (长度: 2048)...
|
||
[Windsurf] [CapSolver] ✓ Token 已注入到 hidden input
|
||
[Windsurf] [CapSolver] 尝试触发 Turnstile 回调...
|
||
[Windsurf] [CapSolver] 回调触发结果:
|
||
[Windsurf] ✓ cf__reactTurnstileOnLoad
|
||
[Windsurf] ✓ window.turnstileCallback
|
||
[Windsurf] [CapSolver] 按钮已经是激活状态
|
||
[Windsurf] [CapSolver] ✓ 验证完成确认通过
|
||
[Windsurf] [CapSolver] ✓ 已点击 Continue 按钮
|
||
[Windsurf] 步骤 2 完成
|
||
```
|
||
|
||
### 部分成功场景
|
||
```
|
||
[Windsurf] [CapSolver] 回调触发结果:
|
||
[Windsurf] ✗ cf__reactTurnstileOnLoad: not a function
|
||
[Windsurf] ✓ data-callback: onTurnstileComplete
|
||
[Windsurf] [CapSolver] ✓ 已强制激活按钮
|
||
[Windsurf] [CapSolver] ✓ 验证完成确认通过
|
||
```
|
||
→ 至少一个回调成功即可
|
||
|
||
### 失败场景
|
||
```
|
||
[Windsurf] [CapSolver] ⚠️ 未找到任何回调函数
|
||
[Windsurf] [CapSolver] ✓ 已强制激活按钮
|
||
[Windsurf] [CapSolver] 验证完成检测超时
|
||
[Windsurf] [CapSolver] 当前状态: {"buttonDisabled":false,"buttonText":"Continue","hasToken":true,"tokenLength":2048}
|
||
[Windsurf] [CapSolver] ✓ 状态检查通过,继续执行
|
||
```
|
||
→ 按钮已激活且有 token,继续执行
|
||
|
||
## 后续方案
|
||
|
||
如果当前修改仍然失败,下一步考虑:
|
||
|
||
### 方案3: 提前拦截 Turnstile 初始化
|
||
在 `initBrowser()` 中使用 `evaluateOnNewDocument()` 提前注入拦截代码
|
||
|
||
### 方案2: 使用 CDP 操作 iframe
|
||
通过 Chrome DevTools Protocol 直接访问 Turnstile iframe
|
||
|
||
### 方案4: 混合方案
|
||
不用完整扩展,只注入 `inject-turnstile.js` 脚本
|
||
|
||
## 备注
|
||
|
||
- 此修改不影响扩展加载方式(第214-300行)
|
||
- 废弃的 API 方法仍保留但已标记 `@deprecated`
|
||
- 步骤2(密码设置)中的扩展等待逻辑(第507-542行)保持不变
|