This commit is contained in:
dela
2026-03-11 14:28:17 +08:00
parent 2154a648af
commit 2c89db45c5
254 changed files with 10260 additions and 48458 deletions

View File

@@ -24,6 +24,7 @@ const logger = new Logger('run_solver');
/**
* 解析 Stripe Checkout URL
* 格式: https://pay.xxx.com/c/pay/cs_live_XXXX#pk_live_XXXX...
* https://checkout.stripe.com/c/pay/cs_live_XXXX#encoded_blob
*
* @param {string} url - Stripe Checkout URL
* @returns {{ sessionId: string, pkLive: string }}
@@ -37,25 +38,24 @@ function parseStripeUrl(url) {
const hashPart = url.split('#')[1] || '';
let pkLive = '';
if (hashPart) {
// hash 可能直接是 pk_live_XXXX 或 base64 编码的 JSON
// hash 直接是 pk_live_XXXX / pk_test_XXXX
if (hashPart.startsWith('pk_live_') || hashPart.startsWith('pk_test_')) {
pkLive = hashPart;
} else {
// 尝试 base64 JSON 解码
try {
const decoded = Buffer.from(hashPart, 'base64').toString();
const data = JSON.parse(decoded);
pkLive = data.pk || data.key || '';
} catch {
// 可能是 URL-encoded
try {
pkLive = decodeURIComponent(hashPart);
} catch {
pkLive = hashPart;
}
// hash 是 Stripe 自定义编码 blob不是 pk_live
logger.info(' hash 不是 pk_live 格式,需要从页面提取');
}
}
}
logger.info(` 提取到 pk_live: ${pkLive.substring(0, 50)}...`);
if (pkLive) {
logger.info(` 提取到 pk_live: ${pkLive.substring(0, 50)}...`);
}
// [步骤 2] 从路径提取 session_id
const urlObj = new URL(url.split('#')[0]);
@@ -66,6 +66,41 @@ function parseStripeUrl(url) {
return { sessionId, pkLive };
}
/**
* 从 Stripe Checkout 页面 HTML 中提取 pk_live
* Stripe 会把 publishable key 嵌入页面 JS/JSON 中
*/
async function fetchPkFromPage(url) {
logger.info('[步骤 1b] 从 Checkout 页面提取 pk_live...');
const resp = await fetch(url, {
headers: {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/145.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
},
});
if (!resp.ok) {
throw new Error(`获取 Checkout 页面失败 (${resp.status})`);
}
const html = await resp.text();
// 多种模式匹配 pk_live / pk_test
const patterns = [
/["'](pk_live_[A-Za-z0-9]+)["']/,
/["'](pk_test_[A-Za-z0-9]+)["']/,
/publishableKey["']\s*[:=]\s*["'](pk_(?:live|test)_[A-Za-z0-9]+)["']/,
/apiKey["']\s*[:=]\s*["'](pk_(?:live|test)_[A-Za-z0-9]+)["']/,
/key["']\s*[:=]\s*["'](pk_(?:live|test)_[A-Za-z0-9]+)["']/,
];
for (const pat of patterns) {
const m = html.match(pat);
if (m) {
logger.info(` 从页面提取到 pk_live: ${m[1].substring(0, 50)}...`);
return m[1];
}
}
throw new Error('无法从 Checkout 页面提取 pk_live请用 --pk 手动指定');
}
// ══════════════════════════════════════════════════════════════
// 步骤 2: 调用 Stripe Init API 获取 hCaptcha 参数
// ══════════════════════════════════════════════════════════════
@@ -183,6 +218,8 @@ async function main() {
const CONFIG = {
// Stripe Checkout URL测试用
stripeUrl: 'https://pay.verdent.ai/c/pay/cs_live_a1H5uyD1bkpXKyqaw0BXzwzGrdzTngoNXBO6ejdyvCmswD9D6Cqzy7URwB#pk_live_51S5juuHIX9Hc8tITIZnW34rV6PJhIzl66WgEZ8kLv',
// 手动指定 pk_live当 URL hash 不含 pk_live 时使用)
pkOverride: '',
// 直接模式参数(跳过 Stripe API 调用,直接测试 hCaptcha
direct: {
sitekey: 'ec637546-e9b8-447a-ab81-b5fb6d228ab8',
@@ -209,6 +246,8 @@ async function main() {
CONFIG.direct.host = args[++i];
} else if (args[i] === '--rqdata') {
CONFIG.direct.rqdata = args[++i];
} else if (args[i] === '--pk') {
CONFIG.pkOverride = args[++i];
} else if (args[i] === '--help' || args[i] === '-h') {
console.log(`
Stripe hCaptcha Solver Runner
@@ -225,6 +264,7 @@ Stripe hCaptcha Solver Runner
--sitekey KEY hCaptcha sitekey
--host HOST hCaptcha host
--rqdata DATA 附加 rqdata
--pk KEY 手动指定 pk_live (当 URL hash 里没有时)
--help, -h 显示帮助
`);
process.exit(0);
@@ -244,12 +284,19 @@ Stripe hCaptcha Solver Runner
// ── 完整 Stripe 流程 ──
const { sessionId, pkLive } = parseStripeUrl(stripeUrl);
if (!sessionId || !pkLive) {
logger.error('无法从 URL 提取 sessionId 或 pk_live');
if (!sessionId) {
logger.error('无法从 URL 提取 sessionId');
process.exit(1);
}
const { siteKey, rqdata, host } = await fetchStripeParams(sessionId, pkLive);
// pk_live 优先级: --pk 手动指定 > URL hash 提取 > 从页面自动抓取
let pk = CONFIG.pkOverride || pkLive;
if (!pk) {
logger.info('URL hash 中未找到 pk_live尝试从 Checkout 页面提取...');
pk = await fetchPkFromPage(stripeUrl);
}
const { siteKey, rqdata, host } = await fetchStripeParams(sessionId, pk);
if (!siteKey) {
logger.error('无法从 Stripe 获取 hCaptcha sitekey');