| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- // background/steps/get-plus-link.js — Step 6: Get ChatGPT Plus Stripe checkout link
- (function attachBackgroundStep11(root, factory) {
- root.MultiPageBackgroundStep11 = factory();
- })(typeof self !== 'undefined' ? self : globalThis, function createBackgroundStep11Module() {
- const PAYURL_CHECKOUT_ENDPOINT = 'https://payurl.ark2.cn/api/checkout';
- const PAYURL_CHECKOUT_MAX_ATTEMPTS = 5;
- const PAYURL_CHECKOUT_RETRY_DELAY_MS = 1200;
- function createStep11Executor(deps = {}) {
- const {
- addLog,
- chrome,
- completeStepFromBackground,
- getTabId,
- reuseOrCreateTab,
- waitForTabStableComplete = null,
- } = deps;
- async function executeStep11() {
- await addLog('步骤 6:正在获取 ChatGPT Plus 订阅链接...');
- const tabId = await getTabId('signup-page');
- if (!tabId) {
- throw new Error('未找到 ChatGPT 标签页,请先打开 chatgpt.com');
- }
- await waitForChatGptLoginPageStable(tabId, {
- addLog,
- waitForTabStableComplete,
- });
- const accessToken = await getChatGptAccessToken(tabId, chrome, addLog);
- if (!accessToken) {
- throw new Error('未获取到 accessToken,请确认已登录 ChatGPT');
- }
- await addLog('已获取 ChatGPT Session Token,正在请求 Plus 长链...');
- const result = await requestPayurlCheckoutWithRetry(accessToken, addLog);
- if (!result.hostedUrl) {
- throw new Error('未从 payurl.ark2.cn 响应中解析到 Plus 长链');
- }
- await addLog(`已获取 Plus 链接,正在跳转到 Stripe 结账页面...`);
- await addLog(`Session ID: ${result.checkoutSessionId || '未知'}`);
- // Navigate to the Stripe checkout URL
- await reuseOrCreateTab('signup-page', result.hostedUrl, {
- reloadIfSameUrl: false,
- });
- await completeStepFromBackground(6, {
- checkoutUrl: result.hostedUrl,
- checkoutSessionId: result.checkoutSessionId,
- chatgptCheckoutUrl: result.chatgptCheckoutUrl,
- openaiPayUrl: result.openaiPayUrl,
- });
- }
- return { executeStep11 };
- }
- async function waitForChatGptLoginPageStable(tabId, deps = {}) {
- const {
- addLog,
- waitForTabStableComplete,
- } = deps;
- if (typeof waitForTabStableComplete !== 'function') {
- return null;
- }
- await addLog('步骤 6:正在等待步骤 5 登录后的 ChatGPT 页面稳定,再读取 Session...', 'info');
- const startedAt = Date.now();
- let lastTab = null;
- while (Date.now() - startedAt < 45000) {
- lastTab = await waitForTabStableComplete(tabId, {
- timeoutMs: 6000,
- retryDelayMs: 300,
- stableMs: 1500,
- initialDelayMs: 600,
- });
- if (!lastTab) {
- throw new Error('步骤 6:ChatGPT 标签页已关闭,无法获取 Session。');
- }
- const url = String(lastTab.url || '');
- if (isChatGptWebUrl(url)) {
- await addLog('步骤 6:ChatGPT 页面已稳定,开始读取 Session。', 'info');
- return lastTab;
- }
- await sleep(500);
- }
- const lastUrl = String(lastTab?.url || '');
- await addLog(
- `步骤 6:等待 ChatGPT 页面稳定超时,最后页面为 ${lastUrl || 'unknown'},将继续尝试读取 Session。`,
- 'warn'
- );
- return lastTab;
- }
- function isChatGptWebUrl(rawUrl = '') {
- try {
- const parsed = new URL(String(rawUrl || ''));
- return /(?:^|\.)chatgpt\.com$/i.test(parsed.hostname);
- } catch {
- return false;
- }
- }
- async function getChatGptAccessToken(tabId, chrome, addLog) {
- try {
- return await fetchAccessTokenFromSessionEndpoint();
- } catch (error) {
- await addLog(`后台获取 ChatGPT Session Token 失败,尝试在页面上下文重试:${error.message}`, 'warn');
- }
- const results = await chrome.scripting.executeScript({
- target: { tabId },
- func: fetchAccessTokenInPage,
- });
- const tokenResult = results?.[0]?.result;
- if (!tokenResult || tokenResult.error) {
- throw new Error(tokenResult?.error || '获取 ChatGPT Session Token 失败,请确认已登录 ChatGPT');
- }
- return String(tokenResult.accessToken || '').trim();
- }
- async function fetchAccessTokenFromSessionEndpoint() {
- const sessionResp = await fetch('https://chatgpt.com/api/auth/session', {
- credentials: 'include',
- headers: {
- 'Accept': 'application/json',
- },
- });
- const text = await sessionResp.text();
- let session = null;
- try {
- session = text ? JSON.parse(text) : null;
- } catch (error) {
- throw new Error(`Session 响应不是有效 JSON:${text.slice(0, 300)}`);
- }
- if (!sessionResp.ok) {
- throw new Error(`Session 请求失败,HTTP ${sessionResp.status}: ${JSON.stringify(session)}`);
- }
- const accessToken = String(session?.accessToken || '').trim();
- if (!accessToken) {
- throw new Error('Session 响应中没有 accessToken');
- }
- return accessToken;
- }
- /**
- * This function is executed in the page context via chrome.scripting.executeScript.
- * It has access to the page's cookies and can make same-origin requests.
- */
- async function fetchAccessTokenInPage() {
- try {
- const sessionResp = await fetch('https://chatgpt.com/api/auth/session', {
- credentials: 'include',
- });
- const session = await sessionResp.json();
- const accessToken = session?.accessToken;
- if (!accessToken) {
- return { error: '未获取到 accessToken,请确认已登录 ChatGPT' };
- }
- return { accessToken };
- } catch (e) {
- return { error: e.message };
- }
- }
- async function requestPayurlCheckoutWithRetry(accessToken, addLog) {
- let lastError = null;
- for (let attempt = 1; attempt <= PAYURL_CHECKOUT_MAX_ATTEMPTS; attempt += 1) {
- try {
- if (attempt > 1) {
- await addLog(`Plus 长链获取失败,正在重试 ${attempt}/${PAYURL_CHECKOUT_MAX_ATTEMPTS}...`, 'warn');
- await sleep(PAYURL_CHECKOUT_RETRY_DELAY_MS);
- }
- return await requestPayurlCheckout(accessToken);
- } catch (error) {
- lastError = error;
- await addLog(`Plus 长链获取失败(${attempt}/${PAYURL_CHECKOUT_MAX_ATTEMPTS}):${error.message}`, 'warn');
- }
- }
- throw new Error(`Plus 长链获取连续失败 ${PAYURL_CHECKOUT_MAX_ATTEMPTS} 次:${lastError?.message || '未知错误'}`);
- }
- async function requestPayurlCheckout(accessToken) {
- const payload = {
- token: accessToken,
- plan: 'plus',
- checkout_ui_mode: 'hosted',
- ui_language: 'en',
- country: 'US',
- currency: 'USD',
- proxy: '',
- use_promo: true,
- promo_code: 'STRIPEATLASGPT4BIZ050126',
- workspace_name: 'linux-do',
- seat_quantity: 2,
- };
- const response = await fetch(PAYURL_CHECKOUT_ENDPOINT, {
- method: 'POST',
- headers: {
- 'Accept': '*/*',
- 'Accept-Language': 'zh-CN,zh;q=0.9',
- 'Content-Type': 'application/json',
- 'DNT': '1',
- 'Origin': 'https://payurl.ark2.cn',
- 'Referer': 'https://payurl.ark2.cn/',
- },
- body: JSON.stringify(payload),
- });
- const responseText = await response.text();
- let data = null;
- try {
- data = responseText ? JSON.parse(responseText) : null;
- } catch (error) {
- throw new Error(`payurl 响应不是有效 JSON:${responseText.slice(0, 300)}`);
- }
- if (!response.ok) {
- throw new Error(`payurl 请求失败,HTTP ${response.status}: ${JSON.stringify(data)}`);
- }
- const hostedUrl = data?.url || data?.openai_payurl || data?.chatgpt_checkout_url || '';
- if (!hostedUrl) {
- throw new Error(`payurl 响应中未找到 url/openai_payurl/chatgpt_checkout_url:${JSON.stringify(data)}`);
- }
- return {
- hostedUrl,
- checkoutSessionId: data.checkout_session_id || '',
- chatgptCheckoutUrl: data.chatgpt_checkout_url || '',
- openaiPayUrl: data.openai_payurl || data.url || '',
- };
- }
- function sleep(ms) {
- return new Promise((resolve) => setTimeout(resolve, ms));
- }
- return { createStep11Executor };
- });
|