aaaaa
This commit is contained in:
parent
b0b81e9279
commit
468d4d6d73
@ -1048,7 +1048,7 @@ class WindsurfRegister {
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交支付(递归重试)
|
||||
* 提交支付(递归重试,轮询检测)
|
||||
*/
|
||||
async submitPayment(retryCount = 0, maxRetries = 5) {
|
||||
if (retryCount >= maxRetries) {
|
||||
@ -1068,16 +1068,37 @@ class WindsurfRegister {
|
||||
|
||||
await submitButton.click();
|
||||
logger.success(this.siteName, ' → ✓ 已点击订阅按钮');
|
||||
await this.human.randomDelay(3000, 5000);
|
||||
|
||||
// 处理验证码
|
||||
await this.handleHCaptcha();
|
||||
// 等待一下让 Stripe 开始处理
|
||||
await this.human.randomDelay(2000, 3000);
|
||||
|
||||
// 检查卡是否被拒绝
|
||||
// 检查是否有验证码(快速检查)
|
||||
const hasHCaptcha = await this.page.evaluate(() => {
|
||||
return !!(
|
||||
document.querySelector('iframe[src*="hcaptcha.com"]') ||
|
||||
document.querySelector('.h-captcha')
|
||||
);
|
||||
});
|
||||
|
||||
if (hasHCaptcha) {
|
||||
logger.info(this.siteName, ' → 检测到验证码,处理中...');
|
||||
await this.handleHCaptcha();
|
||||
await this.human.randomDelay(1000, 2000);
|
||||
}
|
||||
|
||||
// 开始轮询检测:同时等待成功或失败
|
||||
logger.info(this.siteName, ' → 轮询检测支付结果...');
|
||||
const startTime = Date.now();
|
||||
const maxWait = 30000; // 最多等待30秒
|
||||
let checkCount = 0;
|
||||
|
||||
while (Date.now() - startTime < maxWait) {
|
||||
checkCount++;
|
||||
|
||||
// 1. 优先检查是否有错误(卡被拒绝)
|
||||
const cardRejected = await this.checkCardRejected();
|
||||
if (cardRejected) {
|
||||
logger.warn(this.siteName, ` → ⚠️ 银行卡被拒绝!(第 ${retryCount + 1}/${maxRetries} 次)`);
|
||||
logger.warn(this.siteName, ` → ⚠️ 银行卡被拒绝!(第 ${retryCount + 1}/${maxRetries} 次,检测了 ${checkCount} 次)`);
|
||||
|
||||
// 生成新卡
|
||||
logger.info(this.siteName, ' → 生成新的银行卡信息...');
|
||||
@ -1102,11 +1123,52 @@ class WindsurfRegister {
|
||||
return await this.submitPayment(retryCount + 1, maxRetries);
|
||||
}
|
||||
|
||||
// 等待支付成功
|
||||
await this.waitForPaymentSuccess();
|
||||
// 2. 检查是否支付成功(跳转离开 Stripe)
|
||||
const currentUrl = this.page.url();
|
||||
if (!currentUrl.includes('stripe.com') && !currentUrl.includes('checkout.stripe.com')) {
|
||||
const totalTime = ((Date.now() - startTime) / 1000).toFixed(1);
|
||||
this.registrationTime = new Date();
|
||||
logger.success(this.siteName, ` → ✓ 支付成功!(耗时: ${totalTime}秒,检测了 ${checkCount} 次)`);
|
||||
logger.info(this.siteName, ` → 当前页面: ${currentUrl}`);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 3. 每5秒输出一次进度
|
||||
const elapsed = Date.now() - startTime;
|
||||
if (elapsed > 0 && elapsed % 5000 === 0) {
|
||||
logger.info(this.siteName, ` → 支付处理中... (${(elapsed/1000).toFixed(0)}秒,已检测 ${checkCount} 次)`);
|
||||
}
|
||||
|
||||
// 4. 等待500ms后继续检测
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
}
|
||||
|
||||
// 超时:视为可能失败,生成新卡重试
|
||||
logger.warn(this.siteName, ` → ⚠️ 支付超时(${maxWait/1000}秒),共检测 ${checkCount} 次`);
|
||||
logger.info(this.siteName, ` → 将生成新卡重试 (第 ${retryCount + 1}/${maxRetries} 次)`);
|
||||
|
||||
// 生成新卡
|
||||
const cardGen = new CardGenerator();
|
||||
const newCard = cardGen.generate('unionpay');
|
||||
logger.info(this.siteName, ` → 新卡号: ${newCard.number}`);
|
||||
|
||||
this.cardInfo = {
|
||||
number: newCard.number,
|
||||
month: newCard.month,
|
||||
year: newCard.year,
|
||||
cvv: newCard.cvv,
|
||||
country: 'MO'
|
||||
};
|
||||
|
||||
// 重新填写卡信息
|
||||
await this.fillCardForm(newCard, true);
|
||||
logger.success(this.siteName, ' → ✓ 已更新银行卡信息');
|
||||
await this.human.randomDelay(2000, 3000);
|
||||
|
||||
// 递归重试
|
||||
return await this.submitPayment(retryCount + 1, maxRetries);
|
||||
}
|
||||
|
||||
/**
|
||||
* 步骤6: 填写支付信息
|
||||
*/
|
||||
@ -1155,55 +1217,75 @@ class WindsurfRegister {
|
||||
logger.info(this.siteName, `[步骤 7/${this.getTotalSteps()}] 获取订阅信息`);
|
||||
|
||||
try {
|
||||
// 0. 检查并关闭可能存在的弹窗("要打开 Windsurf 吗?")
|
||||
logger.info(this.siteName, ' → 检查是否有弹窗需要关闭...');
|
||||
// 0. 先关闭多余的窗口/标签页
|
||||
logger.info(this.siteName, ' → 检查并关闭多余窗口...');
|
||||
try {
|
||||
await new Promise(resolve => setTimeout(resolve, 2000)); // 等待弹窗出现
|
||||
const pages = await this.browser.pages();
|
||||
logger.info(this.siteName, ` → 当前共有 ${pages.length} 个页面`);
|
||||
|
||||
// 方法1: 尝试按ESC键关闭浏览器原生对话框
|
||||
logger.info(this.siteName, ' → 尝试按ESC键关闭原生对话框...');
|
||||
await this.page.keyboard.press('Escape');
|
||||
await this.human.randomDelay(500, 1000);
|
||||
if (pages.length > 1) {
|
||||
// 保留一个 windsurf.com 的页面,关闭其他
|
||||
let validPage = null;
|
||||
const pagesToClose = [];
|
||||
|
||||
// 方法2: 尝试查找并点击网页内的按钮(如果是HTML弹窗)
|
||||
const closeDialog = await this.page.evaluate(() => {
|
||||
// 查找包含"取消"或"打开Windsurf"的按钮
|
||||
const buttons = Array.from(document.querySelectorAll('button'));
|
||||
const cancelBtn = buttons.find(btn =>
|
||||
btn.textContent.includes('取消') ||
|
||||
btn.textContent.includes('打开Windsurf') ||
|
||||
btn.textContent.includes('Cancel')
|
||||
);
|
||||
|
||||
if (cancelBtn) {
|
||||
// 优先点击"取消"按钮
|
||||
const actualCancelBtn = buttons.find(btn =>
|
||||
btn.textContent.includes('取消') ||
|
||||
btn.textContent.includes('Cancel')
|
||||
);
|
||||
if (actualCancelBtn) {
|
||||
actualCancelBtn.click();
|
||||
return '取消';
|
||||
for (const page of pages) {
|
||||
try {
|
||||
const url = page.url();
|
||||
if (url.includes('windsurf.com') && !validPage) {
|
||||
validPage = page;
|
||||
logger.info(this.siteName, ` → ✓ 保留: ${url}`);
|
||||
} else {
|
||||
cancelBtn.click();
|
||||
return '打开Windsurf';
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
if (closeDialog) {
|
||||
logger.success(this.siteName, ` → ✓ 已关闭HTML弹窗(点击了"${closeDialog}")`);
|
||||
await this.human.randomDelay(1000, 2000);
|
||||
} else {
|
||||
logger.success(this.siteName, ' → ✓ 已尝试关闭原生对话框(ESC键)');
|
||||
pagesToClose.push(page);
|
||||
logger.info(this.siteName, ` → ✗ 关闭: ${url}`);
|
||||
}
|
||||
} catch (e) {
|
||||
logger.info(this.siteName, ` → 关闭弹窗时出错: ${e.message}`);
|
||||
pagesToClose.push(page);
|
||||
}
|
||||
}
|
||||
|
||||
// 1. 跳转到订阅使用页面
|
||||
// 如果没找到 windsurf 页面,保留第一个
|
||||
if (!validPage && pages.length > 0) {
|
||||
validPage = pages[0];
|
||||
pagesToClose.shift();
|
||||
}
|
||||
|
||||
// 关闭多余页面
|
||||
for (const page of pagesToClose) {
|
||||
try {
|
||||
await page.close();
|
||||
} catch (e) {
|
||||
// 忽略
|
||||
}
|
||||
}
|
||||
|
||||
this.page = validPage;
|
||||
logger.success(this.siteName, ` → ✓ 已关闭 ${pagesToClose.length} 个多余页面`);
|
||||
}
|
||||
} catch (e) {
|
||||
logger.warn(this.siteName, ` → 关闭窗口失败: ${e.message}`);
|
||||
}
|
||||
|
||||
await this.human.randomDelay(1000, 2000);
|
||||
|
||||
// 1. 持续按ESC关闭弹窗(循环5次,确保关闭)
|
||||
logger.info(this.siteName, ' → 关闭可能存在的对话框...');
|
||||
for (let i = 0; i < 5; i++) {
|
||||
try {
|
||||
await this.page.keyboard.press('Escape');
|
||||
await new Promise(resolve => setTimeout(resolve, 300));
|
||||
} catch (e) {
|
||||
// 忽略
|
||||
}
|
||||
}
|
||||
logger.success(this.siteName, ' → ✓ 已按5次ESC键');
|
||||
|
||||
await this.human.randomDelay(500, 1000);
|
||||
|
||||
// 2. 跳转到订阅使用页面
|
||||
logger.info(this.siteName, ' → 跳转到订阅使用页面...');
|
||||
const currentUrl = this.page.url();
|
||||
logger.info(this.siteName, ` → 当前页面: ${currentUrl}`);
|
||||
|
||||
await this.page.goto('https://windsurf.com/subscription/usage', {
|
||||
waitUntil: 'networkidle2',
|
||||
timeout: 30000
|
||||
|
||||
Loading…
Reference in New Issue
Block a user