修改支付和注册逻辑

This commit is contained in:
dela
2026-01-25 15:14:46 +08:00
parent bc9faee4d7
commit 1d779ff036
10 changed files with 347 additions and 50 deletions

7
complete_accounts.json Normal file
View File

@@ -0,0 +1,7 @@
[
{
"account": "ngvzryure4@depart.sar.de5.net",
"password": "Jl8Or%2TMO774e1t",
"token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjE5MzQ0ZTY1LWJiYzktNDRkMS1hOWQwLWY5NTdiMDc5YmQwZSIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsiaHR0cHM6Ly9hcGkub3BlbmFpLmNvbS92MSJdLCJjbGllbnRfaWQiOiJhcHBfWDh6WTZ2VzJwUTl0UjNkRTduSzFqTDVnSCIsImV4cCI6MTc2OTkyOTczOCwiaHR0cHM6Ly9hcGkub3BlbmFpLmNvbS9hdXRoIjp7ImNoYXRncHRfY29tcHV0ZV9yZXNpZGVuY3kiOiJub19jb25zdHJhaW50IiwiY2hhdGdwdF9kYXRhX3Jlc2lkZW5jeSI6Im5vX2NvbnN0cmFpbnQiLCJpc19zaWdudXAiOnRydWUsInVzZXJfaWQiOiJ1c2VyLU5kZFJOTnprczNqS2xSaUZDRXZXTHdGayJ9LCJodHRwczovL2FwaS5vcGVuYWkuY29tL3Byb2ZpbGUiOnsiZW1haWwiOiJuZ3Z6cnl1cmU0QGRlcGFydC5zYXIuZGU1Lm5ldCIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlfSwiaWF0IjoxNzY5MDY1NzM3LCJpc3MiOiJodHRwczovL2F1dGgub3BlbmFpLmNvbSIsImp0aSI6IjE3ZjkyYjNjLTEyNGItNDk4ZC04NzljLTc4MjEwMTY5M2UyMyIsIm5iZiI6MTc2OTA2NTczNywicHdkX2F1dGhfdGltZSI6MTc2OTA2NTczNDQ3OCwic2NwIjpbIm9wZW5pZCIsImVtYWlsIiwicHJvZmlsZSIsIm9mZmxpbmVfYWNjZXNzIiwibW9kZWwucmVxdWVzdCIsIm1vZGVsLnJlYWQiLCJvcmdhbml6YXRpb24ucmVhZCIsIm9yZ2FuaXphdGlvbi53cml0ZSJdLCJzZXNzaW9uX2lkIjoiYXV0aHNlc3NfTThEV2JpczE3a3FzZldldDZjTTRZdTJvIiwic3ViIjoiYXV0aDB8T3Baa2VKeXA3cXZ2SlMxSmVacWtqbVZiIn0.uUK6F3ApO1gBkL4N794xwG4qiJTOYqaNX3k6XcSYi8Q92KyTWJQPsEZmr_Ed4fmQ-U4swStNL6n-POzECSok_tVvI57XoPhowDknVYx2ZukdxEtPH2-mGYVFPyjEOpxsJxpGDBP_toidaoE7xIMFgRtVrjehClik7rA0k5bXbYyZt-zShVBa7dpmqBE4tT4CROQ_B9xg2QlrSEIgglUWjtr04C71tWWff1Noc40wwLVDMVi0JRlWM2IlUN-MpxV6ek_T5GGHdiQKy6zL0BJMxRynK9mIVZNWWqb2oINY1hZgkMq1ISNPDtUBOk8u6uqpcowpzmlUlwKZHJXZhpaRVdWKII3WwZHsUpcsLd85pUaMDVOeYtJ_OpdyArOgSrHOncj67HsbFNWrPoKBncC2R4SiXH4awoOcFaSfNJE_lFhSoo7bC4XRR5ERbBtLCH9jYv7-q2UYJbyUB8btN3EF4Y8iCB_yGVEuYdfJUG2aYVqRwwf95AUiF66b59MeIzlm0JBQXlAPiO7U9jMKWu1I-WwKtGonh1LBf2WOT8uvu1DP_fzxHGyaINu814o_ZvQAKpwSZTxTpoTOwuPoRF1KpmJcsyDKy29XFYXMn5rWAYvPZ37hB4pFiqu5G9tvvYV_EGOHD-JlyyNRkMNkmN9Ogbz3Xc8QcSbQSiQwWsi55VE"
}
]

View File

@@ -52,7 +52,7 @@ EU_BILLING_CONFIG = {
# 团队计划详情
'team_plan_data': {
'workspace_name': 'Sepa', # 工作空间名称
'workspace_name': None, # None = 自动生成随机名称,或设置字符串使用固定值
'price_interval': 'month', # 'month' 或 'year'
'seat_quantity': 5, # 座位数量(团队计划最少 5 个)
},
@@ -82,3 +82,21 @@ EU_BILLING_CONFIG = {
# 调试模式
DEBUG = True
# 人类行为延迟配置(秒)
DELAY_CONFIG = {
# 注册流程延迟
'after_registration': {'min': 3.0, 'max': 8.0}, # 注册成功后
'before_get_token': {'min': 2.0, 'max': 5.0}, # 获取token前
'after_get_token': {'min': 1.5, 'max': 4.0}, # 获取token后
'before_billing': {'min': 2.0, 'max': 6.0}, # 生成账单前
'after_billing': {'min': 2.0, 'max': 5.0}, # 生成账单后
'before_payment': {'min': 3.0, 'max': 7.0}, # 开始支付前
# 支付流程延迟
'between_payment_steps': {'min': 1.0, 'max': 3.0}, # 支付步骤之间
'polling_interval': {'min': 3.0, 'max': 5.0}, # 轮询间隔
# 批量操作延迟
'between_accounts': {'min': 30.0, 'max': 60.0}, # 账号之间原10秒太短
}

View File

@@ -11,7 +11,9 @@ from modules.tempmail import TempMailClient
from modules.billing import EUBillingGenerator
from modules.iban_generator import GermanIbanGenerator
from modules.notion_client import NotionClient
from config import TEMPMAIL_CONFIG, DEBUG
from modules.delay_utils import HumanDelay
from modules.data_generator import generate_payment_info
from config import TEMPMAIL_CONFIG, DEBUG, DELAY_CONFIG
class CompleteRegistrationFlow:
@@ -97,20 +99,32 @@ class CompleteRegistrationFlow:
if not result.get('success'):
return result
# 延迟:注册完成后,模拟用户查看邮箱/确认的时间
HumanDelay.custom(**DELAY_CONFIG['after_registration'])
# 获取 Access Token
try:
# 延迟准备获取token
HumanDelay.custom(**DELAY_CONFIG['before_get_token'])
access_token = self.registrar._step5_get_access_token()
result['access_token'] = access_token
if DEBUG:
print(f"✅ Access Token 获取成功")
# 延迟获取token后
HumanDelay.custom(**DELAY_CONFIG['after_get_token'])
except Exception as e:
result['billing_error'] = f"获取 Access Token 失败: {str(e)}"
return result
# 生成账单链接
try:
# 延迟:准备生成账单
HumanDelay.custom(**DELAY_CONFIG['before_billing'])
billing_generator = EUBillingGenerator()
billing_result = billing_generator.generate_checkout_url(access_token)
@@ -118,6 +132,9 @@ class CompleteRegistrationFlow:
result['checkout_url'] = billing_result.checkout_url
if DEBUG:
print(f"✅ 账单链接生成成功")
# 延迟:生成账单后
HumanDelay.custom(**DELAY_CONFIG['after_billing'])
else:
result['billing_error'] = billing_result.error
@@ -183,35 +200,40 @@ class CompleteRegistrationFlow:
result['output_format'] = output_format
return result
# 准备支付信息(使用默认值或用户提供的值)
default_payment_info = {
"name": "John Doe",
"address_line1": "123 Main Street",
"city": "New York",
"postal_code": "10001",
"state": "NY",
"country": "US"
}
# 准备支付信息(使用随机生成或用户提供的值)
if payment_info:
default_payment_info.update(payment_info)
# 用户提供了自定义信息
final_payment_info = payment_info
else:
# 生成随机真实的支付信息
final_payment_info = generate_payment_info()
if DEBUG:
print(f"💳 [Payment] 使用支付信息:")
print(f" 姓名: {final_payment_info['name']}")
print(f" 地址: {final_payment_info['address_line1']}")
print(f" 城市: {final_payment_info['city']}, {final_payment_info['state']} {final_payment_info['postal_code']}")
# 延迟:准备支付
HumanDelay.custom(**DELAY_CONFIG['before_payment'])
# 执行支付
try:
payment_result = self.registrar.add_payment_method(
checkout_session_url=checkout_url,
iban=iban,
name=default_payment_info['name'],
name=final_payment_info['name'],
email=result['email'],
address_line1=default_payment_info['address_line1'],
city=default_payment_info['city'],
postal_code=default_payment_info['postal_code'],
state=default_payment_info['state'],
country=default_payment_info['country']
address_line1=final_payment_info['address_line1'],
city=final_payment_info['city'],
postal_code=final_payment_info['postal_code'],
state=final_payment_info['state'],
country=final_payment_info.get('country', 'US')
)
if payment_result.get('success'):
result['payment_added'] = True
result['payment_info'] = final_payment_info # 保存使用的支付信息
if DEBUG:
print(f"✅ 支付方式添加成功")
else:

View File

@@ -17,6 +17,7 @@ except ImportError:
USE_CURL_CFFI = False
from config import EU_BILLING_CONFIG, FINGERPRINT_CONFIG, DEBUG, HTTP_CONFIG
from modules.data_generator import WorkspaceNameGenerator
if USE_CURL_CFFI and DEBUG:
print("[Billing] Using curl_cffi for requests")
@@ -228,13 +229,18 @@ class EUBillingGenerator:
Returns:
Complete request payload
"""
# 获取配置中的 workspace_name如果为 None 则自动生成
workspace_name = EU_BILLING_CONFIG.get('team_plan_data', {}).get('workspace_name')
if workspace_name is None:
workspace_name = WorkspaceNameGenerator.generate()
payload = {
"plan_name": EU_BILLING_CONFIG.get('plan_name', 'chatgptteamplan'),
"team_plan_data": EU_BILLING_CONFIG.get('team_plan_data', {
'workspace_name': 'Sepa',
'price_interval': 'month',
'seat_quantity': 5,
}),
"team_plan_data": {
'workspace_name': workspace_name, # 使用动态或配置的值
'price_interval': EU_BILLING_CONFIG.get('team_plan_data', {}).get('price_interval', 'month'),
'seat_quantity': EU_BILLING_CONFIG.get('team_plan_data', {}).get('seat_quantity', 5),
},
"billing_details": EU_BILLING_CONFIG.get('billing_details', {
'country': 'DE',
'currency': 'EUR',

151
modules/data_generator.py Normal file
View File

@@ -0,0 +1,151 @@
"""
真实数据生成器
用于生成更真实的姓名、地址等信息,避免固定值
"""
import secrets
from typing import Dict
class NameGenerator:
"""真实姓名生成器"""
# 美国常见姓氏Top 50
LAST_NAMES = [
"Smith", "Johnson", "Williams", "Brown", "Jones",
"Garcia", "Miller", "Davis", "Rodriguez", "Martinez",
"Hernandez", "Lopez", "Gonzalez", "Wilson", "Anderson",
"Thomas", "Taylor", "Moore", "Jackson", "Martin",
"Lee", "Perez", "Thompson", "White", "Harris",
"Sanchez", "Clark", "Ramirez", "Lewis", "Robinson",
"Walker", "Young", "Allen", "King", "Wright",
"Scott", "Torres", "Nguyen", "Hill", "Flores",
"Green", "Adams", "Nelson", "Baker", "Hall",
"Rivera", "Campbell", "Mitchell", "Carter", "Roberts"
]
# 美国常见名字Top 50
FIRST_NAMES_MALE = [
"James", "Robert", "John", "Michael", "David",
"William", "Richard", "Joseph", "Thomas", "Christopher",
"Charles", "Daniel", "Matthew", "Anthony", "Mark",
"Donald", "Steven", "Andrew", "Paul", "Joshua",
"Kenneth", "Kevin", "Brian", "George", "Timothy",
"Ronald", "Edward", "Jason", "Jeffrey", "Ryan",
"Jacob", "Gary", "Nicholas", "Eric", "Jonathan",
"Stephen", "Larry", "Justin", "Scott", "Brandon",
"Benjamin", "Samuel", "Raymond", "Gregory", "Alexander",
"Patrick", "Frank", "Dennis", "Jerry", "Tyler"
]
FIRST_NAMES_FEMALE = [
"Mary", "Patricia", "Jennifer", "Linda", "Barbara",
"Elizabeth", "Susan", "Jessica", "Sarah", "Karen",
"Lisa", "Nancy", "Betty", "Margaret", "Sandra",
"Ashley", "Kimberly", "Emily", "Donna", "Michelle",
"Carol", "Amanda", "Dorothy", "Melissa", "Deborah",
"Stephanie", "Rebecca", "Sharon", "Laura", "Cynthia",
"Kathleen", "Amy", "Angela", "Shirley", "Anna",
"Brenda", "Pamela", "Emma", "Nicole", "Helen",
"Samantha", "Katherine", "Christine", "Debra", "Rachel",
"Carolyn", "Janet", "Catherine", "Maria", "Heather"
]
@staticmethod
def generate_full_name() -> str:
"""生成真实的英文全名"""
first_name = secrets.choice(
NameGenerator.FIRST_NAMES_MALE if secrets.randbelow(2) == 0
else NameGenerator.FIRST_NAMES_FEMALE
)
last_name = secrets.choice(NameGenerator.LAST_NAMES)
return f"{first_name} {last_name}"
class AddressGenerator:
"""美国地址生成器"""
STREET_NAMES = [
"Main", "Oak", "Maple", "Cedar", "Elm", "Washington",
"Lake", "Hill", "Park", "Pine", "First", "Second",
"Third", "Broadway", "Church", "Spring", "River", "Sunset"
]
STREET_TYPES = [
"Street", "Avenue", "Road", "Boulevard", "Drive",
"Lane", "Way", "Court", "Place", "Circle"
]
# 美国主要城市和州
CITIES = [
{"city": "New York", "state": "NY", "zip_prefix": "100"},
{"city": "Los Angeles", "state": "CA", "zip_prefix": "900"},
{"city": "Chicago", "state": "IL", "zip_prefix": "606"},
{"city": "Houston", "state": "TX", "zip_prefix": "770"},
{"city": "Phoenix", "state": "AZ", "zip_prefix": "850"},
{"city": "Philadelphia", "state": "PA", "zip_prefix": "191"},
{"city": "San Antonio", "state": "TX", "zip_prefix": "782"},
{"city": "San Diego", "state": "CA", "zip_prefix": "921"},
{"city": "Dallas", "state": "TX", "zip_prefix": "752"},
{"city": "San Jose", "state": "CA", "zip_prefix": "951"},
{"city": "Austin", "state": "TX", "zip_prefix": "787"},
{"city": "Jacksonville", "state": "FL", "zip_prefix": "322"},
{"city": "Fort Worth", "state": "TX", "zip_prefix": "761"},
{"city": "Columbus", "state": "OH", "zip_prefix": "432"},
{"city": "Charlotte", "state": "NC", "zip_prefix": "282"},
{"city": "Seattle", "state": "WA", "zip_prefix": "981"},
{"city": "Denver", "state": "CO", "zip_prefix": "802"},
{"city": "Boston", "state": "MA", "zip_prefix": "021"},
{"city": "Portland", "state": "OR", "zip_prefix": "972"},
{"city": "Miami", "state": "FL", "zip_prefix": "331"}
]
@staticmethod
def generate_address() -> Dict[str, str]:
"""生成完整的美国地址"""
street_number = secrets.randbelow(9900) + 100
street_name = secrets.choice(AddressGenerator.STREET_NAMES)
street_type = secrets.choice(AddressGenerator.STREET_TYPES)
address_line1 = f"{street_number} {street_name} {street_type}"
location = secrets.choice(AddressGenerator.CITIES)
zip_code = location["zip_prefix"] + f"{secrets.randbelow(100):02d}"
return {
"address_line1": address_line1,
"city": location["city"],
"state": location["state"],
"postal_code": zip_code,
"country": "US"
}
class WorkspaceNameGenerator:
"""工作空间名称生成器"""
PREFIXES = [
"Tech", "Digital", "Cloud", "Data", "Smart",
"Innovate", "Future", "Global", "Rapid", "Prime",
"Meta", "Quantum", "Synergy", "Vertex", "Apex",
"Nexus", "Elite", "Pioneer", "Summit", "Venture"
]
SUFFIXES = [
"Labs", "Works", "Solutions", "Systems", "Dynamics",
"Tech", "AI", "Hub", "Studio", "Group",
"Partners", "Innovations", "Ventures", "Digital", "Cloud"
]
@staticmethod
def generate() -> str:
"""生成工作空间名称"""
prefix = secrets.choice(WorkspaceNameGenerator.PREFIXES)
suffix = secrets.choice(WorkspaceNameGenerator.SUFFIXES)
return f"{prefix}{suffix}"
# 便捷函数
def generate_payment_info() -> Dict[str, str]:
"""生成完整的支付信息(姓名 + 地址)"""
name = NameGenerator.generate_full_name()
address = AddressGenerator.generate_address()
return {
"name": name,
**address
}

42
modules/delay_utils.py Normal file
View File

@@ -0,0 +1,42 @@
"""
随机延迟工具
模拟真实用户行为的延迟模式
"""
import time
import secrets
from config import DEBUG
class HumanDelay:
"""模拟人类行为的延迟"""
@staticmethod
def short_action(min: float = 0.5, max: float = 2.0):
"""短操作延迟(例如:点击按钮)"""
delay = min + (max - min) * (secrets.randbelow(1000) / 1000.0)
if DEBUG:
print(f"⏱️ [Delay] Short action: {delay:.2f}s")
time.sleep(delay)
@staticmethod
def medium_action(min: float = 2.0, max: float = 5.0):
"""中等操作延迟(例如:阅读内容)"""
delay = min + (max - min) * (secrets.randbelow(1000) / 1000.0)
if DEBUG:
print(f"⏱️ [Delay] Medium action: {delay:.2f}s")
time.sleep(delay)
@staticmethod
def long_action(min: float = 5.0, max: float = 10.0):
"""长操作延迟(例如:页面加载)"""
delay = min + (max - min) * (secrets.randbelow(1000) / 1000.0)
if DEBUG:
print(f"⏱️ [Delay] Long action: {delay:.2f}s")
time.sleep(delay)
@staticmethod
def custom(min: float, max: float):
"""自定义范围延迟"""
delay = min + (max - min) * (secrets.randbelow(1000) / 1000.0)
if DEBUG:
print(f"⏱️ [Delay] Custom: {delay:.2f}s")
time.sleep(delay)

View File

@@ -15,6 +15,18 @@ class BrowserFingerprint:
def __init__(self, session_id: str = None):
self.session_id = session_id or str(uuid.uuid4())
# 新增: 使用确定性方法从 session_id 派生 Stripe 指纹
import hashlib
seed = hashlib.sha256(self.session_id.encode()).hexdigest()
# seed 是64个hex字符我们需要确保切片正确
# 从 seed 生成一致的 guid/muid/sid
# UUID需要32个hex字符去掉连字符额外部分直接拼接
self.stripe_guid = seed[:8] + '-' + seed[8:12] + '-' + seed[12:16] + '-' + seed[16:20] + '-' + seed[20:32] + seed[32:40]
self.stripe_muid = seed[:8] + '-' + seed[8:12] + '-' + seed[12:16] + '-' + seed[16:20] + '-' + seed[20:32] + seed[40:46]
self.stripe_sid = seed[:8] + '-' + seed[8:12] + '-' + seed[12:16] + '-' + seed[16:20] + '-' + seed[20:32] + seed[46:52]
self.user_agent = FINGERPRINT_CONFIG['user_agent']
self.screen_width = FINGERPRINT_CONFIG['screen_width']
self.screen_height = FINGERPRINT_CONFIG['screen_height']
@@ -93,7 +105,15 @@ class BrowserFingerprint:
return {
'oai-did': self.session_id,
}
def get_stripe_fingerprint(self) -> Dict[str, str]:
"""获取 Stripe 支付指纹(与 session_id 一致派生)"""
return {
'guid': self.stripe_guid,
'muid': self.stripe_muid,
'sid': self.stripe_sid,
}
def get_headers(self, with_sentinel: str = None, host: str = 'auth.openai.com') -> Dict[str, str]:
"""生成 HTTP headers支持多域名"""

View File

@@ -1,4 +1,4 @@
import random
import secrets
import string
class IbanUtils:
@@ -35,13 +35,26 @@ class IbanUtils:
class GermanBankData:
"""
从 JS 源码模块 5009 中提取的德国 BLZ (Bankleitzahl) 列表。
这是生成有效格式的关键。
这是生成有效格式的关键。扩充版50个真实银行代码
"""
BLZ_LIST = [
"10020200", "20120200", "25020200", "30020500",
"50020200", "50021000", "50021100", "50021120",
"51020000", "55020000", "60120200", "70220200",
"74020100", "74020150"
# 原有的14个
"10020200", "20120200", "25020200", "30020500",
"50020200", "50021000", "50021100", "50021120",
"51020000", "55020000", "60120200", "70220200",
"74020100", "74020150",
# 新增36个真实的德国银行代码
"10050000", "10070024", "10080000", "10090000",
"20050000", "20070000", "20080000", "20090000",
"25050000", "25070024", "25080020", "25090700",
"30050000", "30060010", "30070024", "30080000",
"37060193", "38070024", "40050000", "40060000",
"40070024", "41070024", "43060967", "44050000",
"50050000", "50060400", "50070024", "50080000",
"60050000", "60060000", "60070070", "60080000",
"70050000", "70070024", "70080000", "70090100",
"76050101", "79050000", "80053782", "86055592"
]
class GermanIbanGenerator:
@@ -54,8 +67,8 @@ class GermanIbanGenerator:
self.total_length = 22 # 德国 IBAN 标准总长度
def _generate_account_number(self, length):
"""生成指定长度的随机账号 (数字)"""
return "".join(random.choices(string.digits, k=length))
"""生成指定长度的随机账号(使用 secrets 模块)"""
return "".join(secrets.choice(string.digits) for _ in range(length))
def generate(self, quantity=1):
"""
@@ -63,8 +76,8 @@ class GermanIbanGenerator:
"""
results = []
for _ in range(quantity):
# 1. 随机选择一个真实的银行代码 (BLZ) - 8位
blz = random.choice(GermanBankData.BLZ_LIST)
# 1. 使用 secrets.choice 随机选择银行代码 (BLZ) - 8位
blz = secrets.choice(GermanBankData.BLZ_LIST)
# 2. 计算剩余需要的账号长度
# 德国结构: DE(2) + Check(2) + BLZ(8) + Account(10) = 22

View File

@@ -4,6 +4,7 @@
import json
from typing import Dict, Optional
import secrets
import random
import uuid
import requests
from urllib.parse import urlparse
@@ -696,9 +697,8 @@ class OpenAIRegistrar:
url = "https://auth.openai.com/api/accounts/create_account"
# 生成随机姓名和生日
import random
import string
random_name = ''.join(random.choices(string.ascii_lowercase, k=8))
from modules.data_generator import NameGenerator
random_name = NameGenerator.generate_full_name()
# 生成随机生日(1980-2000年之间)
year = random.randint(1980, 2000)

View File

@@ -10,6 +10,8 @@ from typing import Dict, Optional
import logging
from .http_client import HTTPClient
from .fingerprint import BrowserFingerprint
from .delay_utils import HumanDelay
from config import DEBUG, DELAY_CONFIG
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@@ -35,14 +37,31 @@ class StripePaymentHandler:
self.stripe_api_base = "https://api.stripe.com"
self.stripe_version = "2020-08-27;custom_checkout_beta=v1"
# 会话指纹(每次运行生成新的
self.guid = str(uuid.uuid4()) + str(uuid.uuid4())[:8]
self.muid = str(uuid.uuid4()) + str(uuid.uuid4())[:6]
self.sid = str(uuid.uuid4()) + str(uuid.uuid4())[:6]
# HTTP客户端必须复用以保持指纹一致
if http_client:
self.http_client = http_client
# 从 http_client 的 fingerprint 获取一致的指纹
stripe_fp = self.http_client.fingerprint.get_stripe_fingerprint()
self.guid = stripe_fp['guid']
self.muid = stripe_fp['muid']
self.sid = stripe_fp['sid']
else:
# 如果没有提供 http_client创建新的警告这会导致指纹不一致
from .fingerprint import BrowserFingerprint
from .http_client import HTTPClient
fingerprint = BrowserFingerprint()
self.http_client = HTTPClient(fingerprint)
stripe_fp = fingerprint.get_stripe_fingerprint()
self.guid = stripe_fp['guid']
self.muid = stripe_fp['muid']
self.sid = stripe_fp['sid']
if DEBUG:
print("⚠️ [Payment] 创建了新的 HTTP 客户端,指纹可能不一致")
# 归因元数据
self.client_session_id = str(uuid.uuid4())
self.checkout_config_id = "9e2d84a8-5eec-41bf-aae8-24d59824ec84"
# 随机生成 checkout_config_id(不再使用固定值)
self.checkout_config_id = str(uuid.uuid4())
# HTTP客户端使用curl_cffi
if http_client:
@@ -264,13 +283,12 @@ class StripePaymentHandler:
logger.error(f"❌ Exception confirming payment: {e}")
return False
def poll_payment_status(self, max_attempts: int = 20, interval: int = 3) -> Dict:
def poll_payment_status(self, max_attempts: int = 20) -> Dict:
"""
轮询支付状态直到完成
轮询支付状态直到完成(使用随机延迟)
Args:
max_attempts: 最大轮询次数
interval: 轮询间隔(秒)
Returns:
最终状态字典
@@ -315,15 +333,15 @@ class StripePaymentHandler:
logger.error(f"❌ Payment {state}")
return result
# 继续轮询
time.sleep(interval)
# 继续轮询 - 使用随机延迟
HumanDelay.custom(**DELAY_CONFIG['polling_interval'])
else:
logger.warning(f"Poll returned status {response.status_code}")
time.sleep(interval)
HumanDelay.custom(**DELAY_CONFIG['polling_interval'])
except Exception as e:
logger.error(f"❌ Exception polling status: {e}")
time.sleep(interval)
HumanDelay.custom(**DELAY_CONFIG['polling_interval'])
logger.warning("⚠️ Max polling attempts reached")
return {"state": "timeout"}