# 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行）保持不变
