This commit is contained in:
2026-01-25 05:40:08 +08:00
parent af161cca4f
commit 32e926c4af
9 changed files with 1495 additions and 13 deletions

624
api_register.py Normal file
View File

@@ -0,0 +1,624 @@
"""
ChatGPT API 注册模块 (协议模式)
- 使用 curl_cffi 通过 API 快速完成注册
- 支持 Cookie 注入到浏览器完成支付
"""
import time
import random
import re
import uuid
from urllib.parse import unquote
try:
from curl_cffi import requests as curl_requests
CURL_CFFI_AVAILABLE = True
except ImportError:
CURL_CFFI_AVAILABLE = False
curl_requests = None
import requests
def log_status(step, message):
"""日志输出"""
timestamp = time.strftime("%H:%M:%S")
print(f"[{timestamp}] [{step}] {message}")
def log_progress(message):
"""进度输出"""
print(f" -> {message}")
def request_with_retry(func, *args, max_retries=3, **kwargs):
"""带重试的请求"""
for i in range(max_retries):
try:
return func(*args, **kwargs)
except Exception as e:
if i == max_retries - 1:
raise e
time.sleep(1)
class ChatGPTAPIRegister:
"""ChatGPT API 注册类 (协议模式)"""
def __init__(self, proxy=None):
"""初始化
Args:
proxy: 代理地址,如 "http://127.0.0.1:7890"
"""
if not CURL_CFFI_AVAILABLE:
raise ImportError("协议模式需要安装 curl_cffi: pip install curl_cffi")
self.session = curl_requests.Session(
impersonate="edge",
verify=False,
proxies={"http": proxy, "https": proxy} if proxy else {}
)
self.auth_session_logging_id = str(uuid.uuid4())
self.oai_did = ""
self.csrf_token = ""
self.authorize_url = ""
self.access_token = ""
def init_session(self) -> bool:
"""初始化会话,获取必要的 cookies 和 tokens"""
try:
resp = request_with_retry(self.session.get, "https://chatgpt.com")
if resp.status_code != 200:
log_progress(f"[X] 初始化失败: HTTP {resp.status_code}")
return False
self.oai_did = self.session.cookies.get("oai-did")
csrf_cookie = self.session.cookies.get("__Host-next-auth.csrf-token")
if csrf_cookie:
self.csrf_token = unquote(csrf_cookie).split("|")[0]
else:
log_progress("[X] 未获取到 CSRF token")
return False
# 访问登录页面
request_with_retry(
self.session.get,
f"https://chatgpt.com/auth/login?openaicom-did={self.oai_did}"
)
return True
except Exception as e:
log_progress(f"[X] 初始化异常: {e}")
return False
def get_authorize_url(self, email: str) -> bool:
"""获取授权 URL"""
try:
url = f"https://chatgpt.com/api/auth/signin/openai?prompt=login&ext-oai-did={self.oai_did}&auth_session_logging_id={self.auth_session_logging_id}&screen_hint=login_or_signup&login_hint={email}"
payload = {
"callbackUrl": "https://chatgpt.com/",
"csrfToken": self.csrf_token,
"json": "true"
}
resp = request_with_retry(
self.session.post, url, data=payload,
headers={"Origin": "https://chatgpt.com"}
)
data = resp.json()
if data.get("url") and "auth.openai.com" in data["url"]:
self.authorize_url = data["url"]
return True
log_progress(f"[X] 授权 URL 无效: {data}")
return False
except Exception as e:
log_progress(f"[X] 获取授权 URL 异常: {e}")
return False
def start_authorize(self) -> bool:
"""启动授权流程"""
try:
resp = request_with_retry(
self.session.get, self.authorize_url, allow_redirects=True
)
return "create-account" in resp.url or "log-in" in resp.url
except Exception as e:
log_progress(f"[X] 启动授权异常: {e}")
return False
def register(self, email: str, password: str) -> bool:
"""注册账户"""
try:
resp = request_with_retry(
self.session.post,
"https://auth.openai.com/api/accounts/user/register",
json={"password": password, "username": email},
headers={
"Content-Type": "application/json",
"Origin": "https://auth.openai.com"
}
)
if resp.status_code == 200:
return True
log_progress(f"[X] 注册失败: {resp.status_code} - {resp.text[:200]}")
return False
except Exception as e:
log_progress(f"[X] 注册异常: {e}")
return False
def send_verification_email(self) -> bool:
"""发送验证邮件"""
try:
resp = request_with_retry(
self.session.get,
"https://auth.openai.com/api/accounts/email-otp/send",
allow_redirects=True
)
return resp.status_code == 200
except Exception as e:
log_progress(f"[X] 发送验证邮件异常: {e}")
return False
def validate_otp(self, otp_code: str) -> bool:
"""验证 OTP 码"""
try:
resp = request_with_retry(
self.session.post,
"https://auth.openai.com/api/accounts/email-otp/validate",
json={"code": otp_code},
headers={
"Content-Type": "application/json",
"Origin": "https://auth.openai.com"
}
)
if resp.status_code == 200:
return True
log_progress(f"[X] OTP 验证失败: {resp.status_code} - {resp.text[:200]}")
return False
except Exception as e:
log_progress(f"[X] OTP 验证异常: {e}")
return False
def create_account(self, name: str, birthdate: str) -> bool:
"""创建账户 (填写姓名和生日)
Args:
name: 姓名
birthdate: 生日,格式 "YYYY-MM-DD"
"""
try:
resp = request_with_retry(
self.session.post,
"https://auth.openai.com/api/accounts/create_account",
json={"name": name, "birthdate": birthdate},
headers={
"Content-Type": "application/json",
"Origin": "https://auth.openai.com"
}
)
if resp.status_code != 200:
log_progress(f"[X] 创建账户失败: {resp.status_code} - {resp.text[:200]}")
return False
data = resp.json()
continue_url = data.get("continue_url")
if continue_url:
request_with_retry(self.session.get, continue_url, allow_redirects=True)
return True
except Exception as e:
log_progress(f"[X] 创建账户异常: {e}")
return False
def login(self, email: str, password: str) -> bool:
"""使用密码登录 (复用注册时建立的会话)"""
try:
resp = request_with_retry(
self.session.post,
"https://auth.openai.com/api/accounts/password/verify",
json={"username": email, "password": password},
headers={
"Content-Type": "application/json",
"Origin": "https://auth.openai.com"
}
)
if resp.status_code == 200:
data = resp.json()
continue_url = data.get("continue_url")
if continue_url:
request_with_retry(self.session.get, continue_url, allow_redirects=True)
return True
log_progress(f"[X] 登录失败: {resp.status_code} - {resp.text[:200]}")
return False
except Exception as e:
log_progress(f"[X] 登录异常: {e}")
return False
def get_session_token(self) -> str:
"""获取 access token"""
try:
resp = request_with_retry(self.session.get, "https://chatgpt.com/api/auth/session")
if resp.status_code == 200:
data = resp.json()
token = data.get("accessToken")
if token:
self.access_token = token
return token
log_progress(f"[X] Session 响应无 token: {str(data)[:200]}")
else:
log_progress(f"[X] Session 请求失败: {resp.status_code}")
return ""
except Exception as e:
log_progress(f"[X] 获取 token 异常: {e}")
return ""
def get_checkout_url(self) -> str:
"""通过 API 获取支付页 URL"""
try:
token = self.access_token or self.get_session_token()
if not token:
log_progress("[X] 无法获取 access token")
return ""
payload = {
"plan_name": "chatgptteamplan",
"team_plan_data": {
"workspace_name": "Sepa",
"price_interval": "month",
"seat_quantity": 5
},
"billing_details": {
"country": "DE",
"currency": "EUR"
},
"promo_campaign": {
"promo_campaign_id": "team-1-month-free",
"is_coupon_from_query_param": True
},
"checkout_ui_mode": "redirect"
}
resp = request_with_retry(
self.session.post,
"https://chatgpt.com/backend-api/payments/checkout",
json=payload,
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
"Origin": "https://chatgpt.com"
}
)
if resp.status_code == 200:
data = resp.json()
checkout_url = data.get("url")
if checkout_url:
return checkout_url
log_progress(f"[X] 响应无 URL: {resp.text[:200]}")
else:
log_progress(f"[X] 获取支付页失败: {resp.status_code} - {resp.text[:200]}")
return ""
except Exception as e:
log_progress(f"[X] 获取支付页异常: {e}")
return ""
def get_cookies(self) -> list:
"""获取所有 cookies 用于注入浏览器"""
cookies = []
for cookie in self.session.cookies.jar:
cookies.append({
"name": cookie.name,
"value": cookie.value,
"domain": cookie.domain,
"path": cookie.path or "/",
"secure": cookie.secure,
})
return cookies
def get_verification_code_api(target_email: str, mail_api_base: str, mail_api_token: str, max_retries: int = 90) -> str:
"""通过 API 获取验证码
Args:
target_email: 目标邮箱
mail_api_base: 邮件 API 地址
mail_api_token: 邮件 API Token
max_retries: 最大重试次数
Returns:
str: 验证码,失败返回空字符串
"""
log_status("API监听", "正在监听邮件...")
headers = {"Authorization": mail_api_token, "Content-Type": "application/json"}
start_time = time.time()
for i in range(max_retries):
elapsed = int(time.time() - start_time)
try:
url = f"{mail_api_base}/api/public/emailList"
payload = {"toEmail": target_email, "timeSort": "desc", "size": 20}
resp = requests.post(url, headers=headers, json=payload, timeout=10)
if resp.status_code == 200:
data = resp.json()
if data.get('code') == 200:
mails = data.get('data', [])
if mails:
for mail in mails:
html_body = mail.get('content') or mail.get('text') or str(mail)
code_match = re.search(r'\b(\d{6})\b', html_body)
if code_match:
code = code_match.group(1)
log_status("捕获", f"[OK] 提取到验证码: {code}")
return code
except Exception:
pass
if i % 5 == 0:
print(f" [监听中] 已耗时 {elapsed}秒...")
time.sleep(2)
log_status("超时", "[X] 未能获取验证码")
return ""
def api_register_flow(
email: str,
password: str,
real_name: str,
birthdate: str,
mail_api_base: str,
mail_api_token: str,
proxy: str = None,
progress_callback=None
) -> ChatGPTAPIRegister:
"""执行 API 注册流程
Args:
email: 邮箱
password: 密码
real_name: 姓名
birthdate: 生日 (YYYY-MM-DD)
mail_api_base: 邮件 API 地址
mail_api_token: 邮件 API Token
proxy: 代理地址
progress_callback: 进度回调
Returns:
ChatGPTAPIRegister: 成功返回 reg 对象,失败返回 None
"""
def log_cb(msg):
if progress_callback:
progress_callback(msg)
log_progress(msg)
reg = ChatGPTAPIRegister(proxy=proxy)
try:
log_status("API注册", "初始化会话...")
if not reg.init_session():
log_cb("[X] 初始化失败")
return None
log_cb("[OK] 会话初始化成功")
log_status("API注册", "获取授权 URL...")
if not reg.get_authorize_url(email):
log_cb("[X] 获取授权 URL 失败")
return None
log_cb("[OK] 授权 URL 获取成功")
log_status("API注册", "开始授权流程...")
if not reg.start_authorize():
log_cb("[X] 授权流程启动失败")
return None
log_cb("[OK] 授权流程已启动")
log_status("API注册", "注册账户...")
if not reg.register(email, password):
log_cb("[X] 注册失败")
return None
log_cb("[OK] 账户注册成功")
log_status("API注册", "发送验证邮件...")
if not reg.send_verification_email():
log_cb("[X] 发送验证邮件失败")
return None
log_cb("[OK] 验证邮件已发送")
# 获取验证码
otp_code = get_verification_code_api(email, mail_api_base, mail_api_token)
if not otp_code:
log_cb("[X] 未能获取验证码")
return None
log_status("API注册", f"验证 OTP: {otp_code}")
if not reg.validate_otp(otp_code):
log_cb("[X] OTP 验证失败")
return None
log_cb("[OK] OTP 验证成功")
log_status("API注册", "创建账户...")
if not reg.create_account(real_name, birthdate):
log_cb("[X] 创建账户失败")
return None
log_cb("[OK] 账户创建成功")
# 验证 session 是否有效
token = reg.get_session_token()
if token:
log_cb(f"[OK] Session 有效Token: {token[:30]}...")
else:
log_cb("[!] 注册完成但 session 可能未完全建立")
return reg
except Exception as e:
log_status("错误", f"注册异常: {e}")
return None
def api_login_flow(
email: str,
password: str,
proxy: str = None,
progress_callback=None
) -> ChatGPTAPIRegister:
"""执行 API 登录流程
Args:
email: 邮箱
password: 密码
proxy: 代理地址
progress_callback: 进度回调
Returns:
ChatGPTAPIRegister: 成功返回 reg 对象,失败返回 None
"""
def log_cb(msg):
if progress_callback:
progress_callback(msg)
log_progress(msg)
reg = ChatGPTAPIRegister(proxy=proxy)
try:
log_status("API登录", "初始化会话...")
if not reg.init_session():
log_cb("[X] 初始化失败")
return None
log_cb("[OK] 初始化成功")
log_status("API登录", "获取授权 URL...")
if not reg.get_authorize_url(email):
log_cb("[X] 获取授权 URL 失败")
return None
log_cb("[OK] 获取授权 URL 成功")
log_status("API登录", "开始授权流程...")
if not reg.start_authorize():
log_cb("[X] 授权流程失败")
return None
log_cb("[OK] 授权流程成功")
log_status("API登录", "密码验证...")
if not reg.login(email, password):
log_cb("[X] 登录失败")
return None
log_cb("[OK] 登录成功")
# 获取 token
token = reg.get_session_token()
if token:
log_status("API登录", f"Token: {token[:50]}...")
return reg
except Exception as e:
log_status("错误", f"登录异常: {e}")
return None
def is_api_mode_available() -> bool:
"""检查协议模式是否可用"""
return CURL_CFFI_AVAILABLE
def api_register_account_only(
email: str,
password: str,
real_name: str,
birthdate: str,
get_verification_code_func,
proxy: str = None,
progress_callback=None
) -> bool:
"""仅执行 API 注册流程(不含支付,用于邀请邮箱注册)
Args:
email: 邮箱
password: 密码
real_name: 姓名
birthdate: 生日 (YYYY-MM-DD)
get_verification_code_func: 获取验证码的函数,签名: func(email) -> str
proxy: 代理地址
progress_callback: 进度回调
Returns:
bool: 是否注册成功
"""
def log_cb(msg):
if progress_callback:
progress_callback(msg)
log_progress(msg)
if not CURL_CFFI_AVAILABLE:
log_status("错误", "协议模式不可用,请安装 curl_cffi")
return False
reg = ChatGPTAPIRegister(proxy=proxy)
try:
log_status("API注册", "初始化会话...")
if not reg.init_session():
log_cb("[X] 初始化失败")
return False
log_cb("[OK] 会话初始化成功")
log_status("API注册", "获取授权 URL...")
if not reg.get_authorize_url(email):
log_cb("[X] 获取授权 URL 失败")
return False
log_cb("[OK] 授权 URL 获取成功")
log_status("API注册", "开始授权流程...")
if not reg.start_authorize():
log_cb("[X] 授权流程启动失败")
return False
log_cb("[OK] 授权流程已启动")
log_status("API注册", "注册账户...")
if not reg.register(email, password):
log_cb("[X] 注册失败")
return False
log_cb("[OK] 账户注册成功")
log_status("API注册", "发送验证邮件...")
if not reg.send_verification_email():
log_cb("[X] 发送验证邮件失败")
return False
log_cb("[OK] 验证邮件已发送")
# 使用传入的函数获取验证码
log_status("API注册", "等待验证码...")
otp_code = get_verification_code_func(email)
if not otp_code:
log_cb("[X] 未能获取验证码")
return False
log_status("API注册", f"验证 OTP: {otp_code}")
if not reg.validate_otp(otp_code):
log_cb("[X] OTP 验证失败")
return False
log_cb("[OK] OTP 验证成功")
log_status("API注册", "创建账户...")
if not reg.create_account(real_name, birthdate):
log_cb("[X] 创建账户失败")
return False
log_cb("[OK] 账户创建成功")
# 验证 session 是否有效
token = reg.get_session_token()
if token:
log_cb(f"[OK] 注册完成Token: {token[:30]}...")
return True
else:
log_cb("[!] 注册完成但 session 可能未完全建立")
return True # 仍然返回成功,因为注册流程已完成
except Exception as e:
log_status("错误", f"注册异常: {e}")
return False