# Windsurf 注册自动化配置 site: name: Windsurf url: https://windsurf.com/account/register # 工作流定义 workflow: # ==================== 步骤 1: 打开注册页面并填写信息(带重试) ==================== - action: retryBlock name: "打开注册页面并填写基本信息" maxRetries: 3 retryDelay: 3000 steps: # 1.1 导航到注册页面 - action: navigate name: "打开注册页面" url: "https://windsurf.com/account/register" options: waitUntil: 'networkidle2' timeout: 30000 # URL验证(确保没有跳转到会员中心) verifyUrl: "/account/register" # 验证关键元素(确保页面完整加载) verifyElements: - '#firstName' - '#lastName' - '#email' - 'input[type="checkbox"]' # 1.2 填写基本信息 - action: fillForm name: "填写基本信息" fields: firstName: "{{account.firstName}}" lastName: "{{account.lastName}}" email: "{{account.email}}" # 1.3 勾选同意条款 - action: click name: "勾选同意条款" selector: - css: 'input[type="checkbox"]' optional: true # 1.4 点击 Continue - action: click name: "点击 Continue (基本信息)" selector: - text: 'Continue' selector: 'button, a' # 明确指定查找范围:按钮或链接 timeout: 30000 # 验证点击后密码页面出现 verifyAfter: appears: - '#password' - 'input[type="password"]' # ==================== 步骤 2: 设置密码 ==================== - action: fillForm name: "设置密码" fields: password: "{{account.password}}" passwordConfirmation: "{{account.password}}" - action: click name: "提交密码" selector: - text: 'Continue' selector: 'button, a' timeout: 30000 # ==================== 步骤 2.5: Cloudflare Turnstile 验证 ==================== - action: custom name: "Cloudflare Turnstile 验证" handler: "handleTurnstile" params: timeout: 30000 maxRetries: 3 # 重试策略: # - 'refresh': 刷新页面(适用于保持状态的网站) # - 'restart': 刷新后重新填写(适用于刷新=重置的网站,如 Windsurf) # - 'wait': 只等待不刷新 retryStrategy: 'restart' # Windsurf 刷新会回到第一步 optional: true # ==================== 步骤 3: 邮箱验证 ==================== # 需要自定义处理:获取邮件验证码 + 填写6个输入框 - action: custom name: "邮箱验证" handler: "handleEmailVerification" params: timeout: 120000 # ==================== 步骤 4: 跳过问卷调查 ==================== - action: click name: "跳过问卷" selector: - text: 'Skip this step' selector: 'button, a' - text: 'skip' selector: 'button, a' exact: false # ==================== 步骤 5: 选择计划 ==================== - action: click name: "选择计划" selector: - text: 'Select plan' selector: 'button, a' timeout: 30000 # 等待跳转到 Stripe 支付页面(通用 URL 等待) - action: wait name: "等待跳转到 Stripe" type: url urlContains: "stripe.com" timeout: 20000 # ==================== 步骤 6: 填写支付信息(带重试) ==================== - action: retryBlock name: "提交支付并验证" maxRetries: 9999 # 无限重试,直到成功 retryDelay: 15000 # 增加到15秒,避免触发Stripe风控 onRetryBefore: # 生成银行卡(第一次或重试都生成新卡) - action: custom handler: "generateCard" steps: # 6.1 选择银行卡支付方式(每次重试都重新选择) - action: click name: "选择银行卡支付" selector: - css: 'input[type="radio"][value="card"]' verifyAfter: checked: true # 验证 radio button 是否选中 # 填写支付信息(银行卡+国家+地址) - action: fillForm name: "填写支付信息" fields: cardNumber: "{{card.number}}" cardExpiry: "{{card.month}}{{card.year}}" cardCvc: "{{card.cvv}}" billingName: "{{account.firstName}} {{account.lastName}}" billingCountry: find: - css: '#billingCountry' value: "MO" type: "select" addressLine1: find: - css: 'input[placeholder*="地址"]' - css: 'input[placeholder*="Address"]' value: "kowloon" # 滚动到页面底部(确保订阅按钮可见) - action: scroll name: "滚动到订阅按钮" type: bottom # 提交支付(内部会等待按钮变为可点击状态) - action: click name: "点击提交支付" selector: - css: 'button[data-testid="hosted-payment-submit-button"]' - css: 'button[type="submit"]' timeout: 30000 # 给足够时间等待按钮从 disabled 变为可点击 waitForEnabled: true # 循环等待按钮激活(不是等待出现,而是等待可点击) # 验证点击是否生效(检查按钮状态变化) - action: custom name: "验证订阅按钮点击生效" handler: "verifySubmitClick" # 处理 hCaptcha(等待60秒让用户手动完成) - action: custom name: "hCaptcha 验证" handler: "handleHCaptcha" # 验证支付结果(轮询检测成功或失败) - action: verify name: "验证支付结果" conditions: success: - urlNotContains: "stripe.com" - urlNotContains: "checkout.stripe.com" failure: - textContains: "card was declined" - textContains: "Your card was declined" - textContains: "declined" - textContains: "卡片被拒绝" - textContains: "我们无法验证您的支付方式" - textContains: "我们未能验证您的支付方式" - textContains: "请选择另一支付方式并重试" - elementExists: ".error-message" timeout: 15000 pollInterval: 500 onFailure: "throw" # ==================== 步骤 7: 获取订阅信息 ==================== # 7.1 跳转到订阅使用页面 - action: navigate name: "跳转订阅页面" url: "https://windsurf.com/subscription/usage" # 7.2 提取配额信息 - action: extract name: "提取配额信息" selector: "p.caption1.font-medium.text-sk-black\\/80 span.caption3 span" multiple: true contextKey: "quotaRaw" required: false # 7.3 提取账单周期信息 - action: extract name: "提取账单周期" selector: "p.caption1" extractType: "text" filter: contains: "Next billing cycle" regex: "(\\d+)\\s+days?.*on\\s+([A-Za-z]+\\s+\\d+,\\s+\\d{4})" saveTo: days: "$1" date: "$2" contextKey: "billingInfo" required: false # 7.4 处理提取的数据(自定义) - action: custom name: "处理订阅数据" handler: "processSubscriptionData" optional: true # ==================== 步骤 8: 保存到数据库 ==================== - action: custom name: "保存到数据库" handler: "saveToDatabase" optional: true # ==================== 步骤 9: 退出登录 ==================== - action: click name: "点击退出登录" selector: - text: "Log out" options: exact: true caseInsensitive: false # 错误处理配置 errorHandling: screenshot: true retry: enabled: true maxAttempts: 3 delay: 2000