终局
This commit is contained in:
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user