Skip to content

Commit a0f7575

Browse files
committed
Merge branch 'fork/Iamdreaming/main'
2 parents b8237d1 + 5b8d0eb commit a0f7575

1 file changed

Lines changed: 96 additions & 5 deletions

File tree

services/register/openai_register.py

Lines changed: 96 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,23 @@ def extract_oauth_callback_params_from_consent_session(session: requests.Session
397397
def exchange_platform_tokens(session: requests.Session, device_id: str, code_verifier: str, consent_url: str) -> dict | None:
398398
callback_params = extract_oauth_callback_params_from_consent_session(session, consent_url, device_id)
399399
if not callback_params:
400+
# 回退方案:直接导航 consent URL(allow_redirects=True),从最终 URL 提取 code
401+
print(f"[exchange_platform_tokens] 主方案失败,尝试回退方案, continue_url={consent_url[:120]}")
402+
try:
403+
r = session.get(consent_url, headers=navigate_headers, allow_redirects=True, verify=False, timeout=30)
404+
final_url = str(r.url)
405+
print(f"[exchange_platform_tokens] 回退 final_url={final_url[:120]}")
406+
callback_params = extract_oauth_callback_params_from_url(final_url)
407+
if not callback_params:
408+
for hist in getattr(r, "history", []) or []:
409+
loc = str(hist.headers.get("Location") or "")
410+
callback_params = extract_oauth_callback_params_from_url(loc)
411+
if callback_params:
412+
break
413+
except Exception as e:
414+
print(f"[exchange_platform_tokens] 回退方案异常: {e}")
415+
if not callback_params:
416+
print("[exchange_platform_tokens] 所有方案均无法提取 OAuth code")
400417
return None
401418
code = str(callback_params.get("code") or "").strip()
402419
if not code:
@@ -516,9 +533,18 @@ def _create_account(self, name: str, birthdate: str, index: int) -> None:
516533
detail = f", detail={json.dumps(data, ensure_ascii=False)}" if data else ""
517534
raise RuntimeError(error or f"create_account_http_{getattr(resp, 'status_code', 'unknown')}{detail}")
518535
step(index, "创建账号资料完成")
519-
536+
520537
def _login_and_exchange_tokens(self, email: str, password: str, mailbox: dict, index: int) -> dict:
521538
step(index, "开始独立登录换 token")
539+
540+
# 关键:清除注册阶段残留的认证 cookie,避免 409 invalid_state
541+
for cookie in list(self.session.cookies):
542+
if 'auth.openai.com' in cookie.domain:
543+
self.session.cookies.clear(domain=cookie.domain, path=cookie.path, name=cookie.name)
544+
# 重新设置设备 ID(必须)
545+
self.session.cookies.set("oai-did", self.device_id, domain=".auth.openai.com")
546+
self.session.cookies.set("oai-did", self.device_id, domain="auth.openai.com")
547+
522548
code_verifier, code_challenge = _generate_pkce()
523549
params = {
524550
"issuer": auth_base,
@@ -538,24 +564,88 @@ def _login_and_exchange_tokens(self, email: str, password: str, mailbox: dict, i
538564
"code_challenge_method": "S256",
539565
"auth0Client": platform_auth0_client,
540566
}
541-
resp, error = request_with_local_retry(self.session, "get", f"{auth_base}/api/accounts/authorize?{urlencode(params)}", headers=self._navigate_headers(f"{platform_base}/"), allow_redirects=True, verify=False)
567+
resp, error = request_with_local_retry(
568+
self.session, "get",
569+
f"{auth_base}/api/accounts/authorize?{urlencode(params)}",
570+
headers=self._navigate_headers(f"{platform_base}/"),
571+
allow_redirects=True, verify=False
572+
)
542573
if resp is None:
543574
raise RuntimeError(error or "platform_login_authorize_failed")
544575
step(index, "登录 authorize 完成")
576+
577+
# 提交邮箱(原样,不带 state)
578+
def _do_authorize_continue():
579+
h = self._json_headers(f"{auth_base}/log-in?usernameKind=email")
580+
h["openai-sentinel-token"] = build_sentinel_token(
581+
self.session, self.device_id, "authorize_continue"
582+
)
583+
return request_with_local_retry(
584+
self.session, "post",
585+
f"{auth_base}/api/accounts/authorize/continue",
586+
json={"username": {"kind": "email", "value": email}},
587+
headers=h,
588+
allow_redirects=False,
589+
verify=False
590+
)
591+
592+
step(index, "开始提交邮箱")
593+
resp, error = _do_authorize_continue()
594+
if resp is not None and resp.status_code == 409:
595+
step(index, "邮箱提交 invalid_state,重新 authorize 后重试")
596+
# 再次清除 cookie 并重新 authorize
597+
for cookie in list(self.session.cookies):
598+
if 'auth.openai.com' in cookie.domain:
599+
self.session.cookies.clear(domain=cookie.domain, path=cookie.path, name=cookie.name)
600+
self.session.cookies.set("oai-did", self.device_id, domain=".auth.openai.com")
601+
self.session.cookies.set("oai-did", self.device_id, domain="auth.openai.com")
602+
resp, error = request_with_local_retry(
603+
self.session, "get",
604+
f"{auth_base}/api/accounts/authorize?{urlencode(params)}",
605+
headers=self._navigate_headers(f"{platform_base}/"),
606+
allow_redirects=True, verify=False
607+
)
608+
if resp is None:
609+
raise RuntimeError(error or "platform_login_authorize_retry_failed")
610+
resp, error = _do_authorize_continue()
611+
612+
if resp is None or resp.status_code != 200:
613+
data = _response_json(resp) if resp is not None else {}
614+
detail = json.dumps(data, ensure_ascii=False) if data else ""
615+
raise RuntimeError(
616+
error or f"email_submit_http_{getattr(resp, 'status_code', 'unknown')}"
617+
+ (f": {detail}" if detail else "")
618+
)
619+
step(index, "邮箱提交完成")
620+
621+
# 密码验证
622+
step(index, "开始密码校验")
545623
headers = self._json_headers(f"{auth_base}/log-in/password")
546-
headers["openai-sentinel-token"] = build_sentinel_token(self.session, self.device_id, "password_verify")
547-
resp, error = request_with_local_retry(self.session, "post", f"{auth_base}/api/accounts/password/verify", json={"password": password}, headers=headers, allow_redirects=False, verify=False)
624+
headers["openai-sentinel-token"] = build_sentinel_token(
625+
self.session, self.device_id, "password_verify"
626+
)
627+
resp, error = request_with_local_retry(
628+
self.session, "post",
629+
f"{auth_base}/api/accounts/password/verify",
630+
json={"password": password},
631+
headers=headers,
632+
allow_redirects=False,
633+
verify=False
634+
)
548635
if resp is None or resp.status_code != 200:
549-
raise RuntimeError(error or f"password_verify_http_{getattr(resp, 'status_code', 'unknown')}")
636+
raise RuntimeError(error or f"password_verify_http_{getattr(resp, 'status_code', '')}")
550637
step(index, "密码校验完成")
638+
551639
payload = _response_json(resp)
552640
continue_url = str(payload.get("continue_url") or "").strip()
553641
page_type = str(((payload.get("page") or {}).get("type")) or "")
642+
554643
if page_type == "email_otp_verification" or "email-verification" in continue_url or "email-otp" in continue_url:
555644
step(index, "独立登录需要邮箱验证码")
556645
code = wait_for_code(mailbox)
557646
if not code:
558647
raise RuntimeError("独立登录等待验证码超时")
648+
step(index, f"收到登录验证码: {code}")
559649
resp, reason = validate_otp(self.session, self.device_id, code)
560650
if resp is None or resp.status_code != 200:
561651
print("独立登录验证码校验失败响应:", resp.text if resp is not None else "None")
@@ -565,6 +655,7 @@ def _login_and_exchange_tokens(self, email: str, password: str, mailbox: dict, i
565655
otp_payload = _response_json(resp)
566656
continue_url = str(otp_payload.get("continue_url") or continue_url).strip()
567657
step(index, "独立登录验证码校验完成")
658+
568659
if not continue_url:
569660
continue_url = f"{auth_base}/sign-in-with-chatgpt/codex/consent"
570661
tokens = exchange_platform_tokens(self.session, self.device_id, code_verifier, continue_url)

0 commit comments

Comments
 (0)