# Windsurf 注册自动化配置 site: name: Windsurf url: https://windsurf.com/account/register # 工作流定义 workflow: # ==================== 步骤 1: 打开注册页面 ==================== - action: navigate name: "打开注册页面" url: "https://windsurf.com/account/register" options: waitUntil: 'networkidle2' timeout: 30000 # 重试配置(参考旧框架) maxRetries: 5 retryDelay: 3000 totalTimeout: 180000 # 3分钟总超时 # URL验证(确保没有跳转到会员中心) verifyUrl: "/account/register" # 验证关键元素(确保页面完整加载) verifyElements: - '#firstName' - '#lastName' - '#email' - 'input[type="checkbox"]' waitAfter: 2000 - action: fillForm name: "填写基本信息" humanLike: true fields: firstName: find: - css: '#firstName' - name: 'firstName' value: "{{account.firstName}}" lastName: find: - css: '#lastName' - name: 'lastName' value: "{{account.lastName}}" email: find: - css: '#email' - type: 'email' value: "{{account.email}}" - action: click name: "勾选同意条款" selector: - css: 'input[type="checkbox"]' optional: true waitAfter: 500 - action: click name: "点击 Continue (基本信息)" selector: - text: 'Continue' selector: 'button, a' # 明确指定查找范围:按钮或链接 timeout: 30000 # 验证点击后密码页面出现 verifyAfter: appears: - '#password' - 'input[type="password"]' waitAfter: 2000 # ==================== 步骤 2: 设置密码 ==================== - action: wait name: "等待密码页面" type: element find: - css: '#password' timeout: 15000 - action: fillForm name: "设置密码" humanLike: true fields: password: find: - css: 'input[type="password"]' - placeholder: 'Password' value: "{{account.password}}" passwordConfirm: find: - css: 'input[placeholder*="confirmation"]' - css: 'input[placeholder*="Confirm"]' value: "{{account.password}}" - action: click name: "提交密码" selector: - text: 'Continue' selector: 'button, a' timeout: 30000 waitAfter: 2000 # ==================== 步骤 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 waitAfter: 2000 # ==================== 步骤 5: 选择计划 ==================== - action: click name: "选择计划" selector: - text: 'Select plan' selector: 'button, a' timeout: 30000 waitAfter: 2000 # ==================== 步骤 6: 填写支付信息 ==================== # 6.1 选择银行卡支付方式 - action: click name: "选择银行卡支付" selector: - css: 'input[type="radio"][value="card"]' waitAfter: 3000 # ==================== 步骤 6.2: 提交支付(带重试) ==================== - action: retryBlock name: "提交支付并验证" maxRetries: 5 retryDelay: 2000 onRetryBefore: # 重试前重新生成银行卡 - action: custom handler: "regenerateCard" steps: # 等待支付表单加载(每次重试都需要等待) - action: wait name: "等待支付表单" type: element find: - css: '#cardNumber' timeout: 30000 # 填写银行卡信息(使用重新生成的卡号) - action: fillForm name: "填写银行卡信息" humanLike: false fields: cardNumber: find: - css: '#cardNumber' value: "{{card.number}}" cardExpiry: find: - css: '#cardExpiry' value: "{{card.month}}{{card.year}}" cardCvc: find: - css: '#cardCvc' value: "{{card.cvv}}" billingName: find: - css: '#billingName' value: "{{account.firstName}} {{account.lastName}}" # 选择澳门地址(动态字段,需要自定义处理) - action: custom name: "选择澳门地址" handler: "selectBillingAddress" # 滚动到页面底部(确保订阅按钮可见) - action: scroll name: "滚动到订阅按钮" type: bottom # 提交支付 - action: click name: "点击提交支付" selector: - css: 'button[type="submit"]' # Stripe 订阅按钮 timeout: 15000 waitAfter: 2000 # 处理 hCaptcha(点击订阅后出现) - action: custom name: "hCaptcha 验证" handler: "handleHCaptcha" params: timeout: 120000 # 验证支付结果(轮询检测成功或失败) - 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: "卡片被拒绝" - elementExists: ".error-message" timeout: 15000 pollInterval: 500 onFailure: "throw" # ==================== 步骤 7: 获取订阅信息 ==================== # 7.1 跳转到订阅使用页面 - action: navigate name: "跳转订阅页面" url: "https://windsurf.com/subscription/usage" waitAfter: 3000 # 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 # 错误处理配置 errorHandling: screenshot: true retry: enabled: true maxAttempts: 3 delay: 2000