Çok adımlı bir ödeme akışını uçtan uca test eden regresyon paketleri çoğu zaman aynı yerde takılır: araya giren CAPTCHA doğrulaması. Sepet, teslimat, ödeme ve onay adımlarının herhangi birinde beliren bir reCAPTCHA ya da Turnstile, testi olduğu yerde durdurur ve CI boru hattınızı kırmızıya çevirir. Çözüm sürprizsiz: her adımda karşınıza çıkan CAPTCHA'yı CaptchaAI'ye gönderin, dönen token'ı ilgili forma enjekte edin ve akışı kesintisiz sürdürün. Bu rehber, Selenium tabanlı bir ödeme otomasyonunun beş adımını ve her adımdaki doğrulamanın nasıl çözüleceğini baştan sona gösterir.
Ödeme akışında CAPTCHA hangi adımlarda çıkar?
Bir ödeme akışında CAPTCHA tek bir yerde değil, birden çok adımda tetiklenir. Her adımın kendine özgü bir tetikleyicisi vardır; bu yüzden otomasyonunuz, akışın herhangi bir noktasında doğrulama çıkabileceğini varsaymalıdır. Aşağıdaki tablo, tipik bir e-ticaret akışında hangi adımda hangi CAPTCHA türünün ve neden göründüğünü özetler.
| Aşama | Yaygın CAPTCHA türleri | Tetikleyici |
|---|---|---|
| Sepete ekle | reCAPTCHA v3 (görünmez) | Bot önleme |
| Giriş / misafir ödeme | reCAPTCHA v2 | Hesap doğrulama |
| Teslimat adresi | Turnstile | Hız sınırı |
| Ödeme sayfası | reCAPTCHA v2/v3 | Dolandırıcılık önleme |
| Sipariş onayı | reCAPTCHA v2 | Son doğrulama |
Not: CaptchaAI bu tabloda geçen türlerin tamamını, yani reCAPTCHA v2, reCAPTCHA v3 ve Cloudflare Turnstile'ı çözer. Buna karşılık ödeme sayfanız hCaptcha kullanıyorsa bu yaklaşım o adımı kapsamaz; hCaptcha ve FunCaptcha şu an desteklenmez. Bu yüzden akışınızdaki doğrulama türlerini önceden tespit etmek, işe koyulmadan önce yapılması gereken ilk adımdır.
Otomasyon mimarisi: beş adımlık zincir
Akışı, her biri kendi formuna ve olası doğrulamasına sahip beş bağımsız aşamadan oluşan bir zincir olarak modelleyin. Otomasyon her aşamaya girdiğinde önce sayfada bir CAPTCHA olup olmadığını kontrol eder, varsa çözer, ardından alanları doldurup bir sonraki adıma ilerler. Bu tek tip döngü sayesinde, doğrulama akışın hangi adımında çıkarsa çıksın aynı _solve_if_captcha() çağrısını yeniden kullanırsınız.
┌────────┐ ┌───────────┐ ┌──────────┐ ┌─────────┐ ┌──────────┐
│ Cart │───▶│ Shipping │───▶│ Payment │───▶│ Review │───▶│ Confirm │
│ │ │ Address │ │ Info │ │ Order │ │ │
└────────┘ └───────────┘ └──────────┘ └─────────┘ └──────────┘
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
[CAPTCHA?] [CAPTCHA?] [CAPTCHA?] [CAPTCHA?] [CAPTCHA?]
Token akışı: CaptchaAI adımı nasıl çözer
Her adımda çalışan mantık aynıdır ve üç aşamadan oluşur:
- Sayfadaki
data-sitekeydeğerini ve o ankipageurlbilgisini okuyun. - Bu ikisini CaptchaAI'nin
in.phpuç noktasına gönderin ve dönen görev kimliğiyleres.phpüzerinden sonucu periyodik olarak sorgulayın. - Sonuç hazır olduğunda dönen token'ı doğru gizli alana yazıp formu gönderin.
Enjeksiyon yapılacak alan CAPTCHA türüne göre değişir: reCAPTCHA v2 ve v3 için g-recaptcha-response, Cloudflare Turnstile için cf-turnstile-response. reCAPTCHA v3'te ayrıca bir action değeri (checkout gibi) gönderilir ve bu değer sitenin beklediği eylem adıyla eşleşmelidir. Görünmez v3 doğrulamaları arka planda çalıştığından, ilk sorgulamadan önce biraz daha uzun beklemek (initial_wait=20) isabetli olur.
Temel uygulama: Selenium ile ödeme otomasyonu
CheckoutAutomator sınıfı
Aşağıdaki sınıf, CaptchaSolver yardımcısını Selenium sürücüsüyle birleştirir. _solve_if_captcha() her sayfada önce Turnstile'ı, ardından reCAPTCHA'yı arar; grecaptcha.execute bulursa doğrulamayı v3 olarak ele alır ve dönen token'ı ilgili gizli alana yazar.
import time
import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class CaptchaSolver:
BASE = "https://ocr.captchaai.com"
def __init__(self, api_key):
self.api_key = api_key
def solve(self, params, initial_wait=10):
params["key"] = self.api_key
params["json"] = 1
resp = requests.post(f"{self.BASE}/in.php", data=params).json()
if resp["status"] != 1:
raise Exception(resp["request"])
task_id = resp["request"]
time.sleep(initial_wait)
for _ in range(60):
result = requests.get(
f"{self.BASE}/res.php",
params={"key": self.api_key, "action": "get", "id": task_id, "json": 1},
).json()
if result["request"] == "CAPCHA_NOT_READY":
time.sleep(5)
continue
if result["status"] == 1:
return result["request"]
raise Exception(result["request"])
raise TimeoutError("Timed out")
class CheckoutAutomator:
def __init__(self, api_key):
self.solver = CaptchaSolver(api_key)
self.driver = webdriver.Chrome()
self.wait = WebDriverWait(self.driver, 15)
def _find(self, selector):
return self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, selector)))
def _click(self, selector):
self.wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, selector))).click()
def _fill(self, selector, value):
el = self._find(selector)
el.clear()
el.send_keys(value)
def _solve_if_captcha(self):
"""Check for and solve any CAPTCHA on the current page."""
html = self.driver.page_source
page_url = self.driver.current_url
# Turnstile
turnstile = self.driver.find_elements(By.CSS_SELECTOR, ".cf-turnstile")
if turnstile:
sitekey = turnstile[0].get_attribute("data-sitekey")
token = self.solver.solve({
"method": "turnstile",
"sitekey": sitekey,
"pageurl": page_url,
})
self.driver.execute_script(
f'document.querySelector("[name=cf-turnstile-response]").value = "{token}";'
)
return "turnstile"
# reCAPTCHA
recaptcha = self.driver.find_elements(By.CSS_SELECTOR, "[data-sitekey]")
if recaptcha and "recaptcha" in html.lower():
sitekey = recaptcha[0].get_attribute("data-sitekey")
# Check if v3 (invisible)
if "grecaptcha.execute" in html:
token = self.solver.solve({
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
"version": "v3",
"action": "checkout",
}, initial_wait=20)
else:
token = self.solver.solve({
"method": "userrecaptcha",
"googlekey": sitekey,
"pageurl": page_url,
})
self.driver.execute_script(
f'document.querySelector("[name=g-recaptcha-response]").value = "{token}";'
)
return "recaptcha"
return None
# --- Checkout Steps ---
def add_to_cart(self, product_url, quantity=1):
"""Step 1: Navigate to product and add to cart."""
self.driver.get(product_url)
time.sleep(2)
# Set quantity if field exists
qty_fields = self.driver.find_elements(By.CSS_SELECTOR, "input[name='quantity']")
if qty_fields:
qty_fields[0].clear()
qty_fields[0].send_keys(str(quantity))
self._solve_if_captcha()
self._click("[data-action='add-to-cart'], .add-to-cart, #add-to-cart")
time.sleep(2)
return True
def fill_shipping(self, address):
"""Step 2: Fill shipping address."""
self._solve_if_captcha()
field_map = {
"first_name": "#shipping-first-name, [name='firstName']",
"last_name": "#shipping-last-name, [name='lastName']",
"address": "#shipping-address, [name='address1']",
"city": "#shipping-city, [name='city']",
"state": "#shipping-state, [name='state']",
"zip": "#shipping-zip, [name='postalCode']",
"phone": "#shipping-phone, [name='phone']",
}
for field, selectors in field_map.items():
if field in address:
for selector in selectors.split(", "):
elements = self.driver.find_elements(By.CSS_SELECTOR, selector)
if elements:
elements[0].clear()
elements[0].send_keys(address[field])
break
self._solve_if_captcha()
self._click("[data-step='shipping-submit'], .continue-to-payment")
time.sleep(2)
return True
def fill_payment(self, payment):
"""Step 3: Fill payment information."""
self._solve_if_captcha()
# Handle iframe for card fields (common pattern)
iframes = self.driver.find_elements(By.CSS_SELECTOR, "iframe[name*='card']")
if iframes:
self.driver.switch_to.frame(iframes[0])
self._fill("input[name='cardnumber']", payment["card_number"])
self.driver.switch_to.default_content()
if len(iframes) > 1:
self.driver.switch_to.frame(iframes[1])
self._fill("input[name='exp-date']", payment["expiry"])
self.driver.switch_to.default_content()
if len(iframes) > 2:
self.driver.switch_to.frame(iframes[2])
self._fill("input[name='cvc']", payment["cvv"])
self.driver.switch_to.default_content()
else:
# Direct fields
self._fill("[name='cardNumber'], #card-number", payment["card_number"])
self._fill("[name='expiry'], #card-expiry", payment["expiry"])
self._fill("[name='cvv'], #card-cvv", payment["cvv"])
self._solve_if_captcha()
self._click("[data-step='payment-submit'], .continue-to-review")
time.sleep(2)
return True
def confirm_order(self):
"""Step 4: Review and confirm order."""
self._solve_if_captcha()
self._click("[data-step='confirm'], .place-order, #place-order")
time.sleep(3)
# Check for confirmation
html = self.driver.page_source.lower()
if "order confirmed" in html or "thank you" in html or "confirmation" in html:
return True
return False
def run_checkout(self, product_url, address, payment, quantity=1):
"""Run complete checkout flow."""
steps = [
("Add to cart", lambda: self.add_to_cart(product_url, quantity)),
("Proceed to checkout", lambda: self._click(".checkout-btn, a[href*='checkout']")),
("Fill shipping", lambda: self.fill_shipping(address)),
("Fill payment", lambda: self.fill_payment(payment)),
("Confirm order", lambda: self.confirm_order()),
]
for step_name, step_fn in steps:
print(f"Step: {step_name}...")
try:
result = step_fn()
print(f" ✓ {step_name} complete")
except Exception as e:
print(f" ✗ {step_name} failed: {e}")
return False
return True
def close(self):
self.driver.quit()
Otomasyonu çalıştırma
Sınıfı çalıştırmak için bir API anahtarı, ürün bağlantısı, teslimat adresi ve kart bilgileri verirsiniz. Aşağıdaki örnek, tamamen test amaçlı verilerle (Visa test kartı 4111... dahil) tek bir uçtan uca akışı çalıştırır.
automator = CheckoutAutomator("YOUR_API_KEY")
try:
success = automator.run_checkout(
product_url="https://store.example.com/product/widget-pro",
address={
"first_name": "Jane",
"last_name": "Smith",
"address": "123 Test Street",
"city": "San Francisco",
"state": "CA",
"zip": "94102",
"phone": "415-555-0100",
},
payment={
"card_number": "4111111111111111",
"expiry": "12/26",
"cvv": "123",
},
quantity=1,
)
print(f"Checkout {'succeeded' if success else 'failed'}")
finally:
automator.close()
Uç durumlar ve dayanıklılık
KVKK notu: Otomatik ödeme testlerinde gerçek müşteri verisi yerine sentetik ad, adres ve kart numaraları kullanın; kazınan veya test edilen kişisel veriler KVKK kapsamına girer.
Aşağıdaki üç durum, gerçek akışlarda otomasyonu en çok zorlayan noktalardır.
Doğrulama hatasından sonra beliren CAPTCHA
Bir alan hatalı doldurulduğunda site, ikinci denemede ek bir CAPTCHA gösterebilir. Adımı sınırlı sayıda yeniden deneyin ve her denemeden önce olası doğrulamayı çözün.
def retry_step_with_captcha(self, step_fn, max_retries=2):
for attempt in range(max_retries + 1):
try:
return step_fn()
except Exception:
if attempt < max_retries:
self._solve_if_captcha()
continue
raise
Oturum bazlı CAPTCHA'lar
Bazı siteler CAPTCHA'yı yalnızca oturumun ilk isteğinde gösterir, sonraki adımlarda tekrar sormaz. Bu yüzden adımlar arasında tarayıcı çerezlerini koruyarak aynı oturumu sürdürün; her adımda yeni oturum açmak gereksiz yere doğrulama tetikler.
Dinamik yüklenen form alanları
Adımlar çoğu zaman JavaScript ile kademeli yüklenir; bir sonraki forma geçmeden önce beklenen öğenin görünür olduğundan emin olun.
def wait_for_step(self, indicator_selector, timeout=15):
"""Wait for a step to fully load before proceeding."""
WebDriverWait(self.driver, timeout).until(
EC.presence_of_element_located((By.CSS_SELECTOR, indicator_selector))
)
Ödeme testlerini kararlı tutmanın yolları
Akışı üretimde dayanıklı kılmak için birkaç alışkanlık işleri belirgin biçimde kolaylaştırır:
- CAPTCHA'yı ilgili adımı göndermeden hemen önce çözün; erken üretilen token'lar zaman aşımına uğrar.
- Her adımdan sonra hata mesajlarını kontrol edin, akışı sessizce başarısız olmaya bırakmayın.
- Sabit
sleepbeklemeleri yerine öğe hazır olana kadar bekleyen açık koşullar kullanın. - Testleri yalnızca sandbox/test ortamlarında ve sentetik veriyle çalıştırın.
Hangi plan ve kaç thread gerekir?
CaptchaAI, çözüm başına değil eşzamanlı thread başına ücretlendirir ve her planda thread başına sınırsız çözüm sunar. Bu, ödeme testleri için önemlidir: maliyetinizi kaç CAPTCHA çözdüğünüz değil, kaç testi aynı anda çalıştırdığınız belirler. Küçük bir regresyon paketi için BASIC ($15/ay, 5 thread) yeterli olur; CI'da paralel çalışan daha geniş senaryolar için STANDARD ($30/ay, 15 thread) ya da ADVANCE ($90/ay, 50 thread) daha uygundur.
Türkiye'deki ekipler için ek bir avantaj, fiyatlandırmanın USD ve aylık sabit olmasıdır: TL'deki dalgalanmadan bağımsız, öngörülebilir bir bütçe kurabilirsiniz. Güncel plan ve thread sayıları için captchaai.com/pricing sayfasına bakın.
Sık sorulan sorular
Ödeme otomasyonu kuran ekiplerden en sık gelen sorular ve kısa yanıtları:
reCAPTCHA v3 token'ı neden ödeme adımında reddediliyor?
Genellikle iki nedenden: token'ın süresi dolmuştur ya da gönderilen action değeri sitenin beklediğiyle eşleşmez. Token'ı göndermeden hemen önce üretin ve v3 için doğru eylem adını (checkout gibi) kullanın.
CaptchaAI ödeme sayfasındaki hCaptcha'yı çözer mi?
Hayır. hCaptcha ve FunCaptcha (Arkose Labs) şu an desteklenmez. CaptchaAI ödeme akışlarında yalnızca şu türleri çözer:
- reCAPTCHA v2
- reCAPTCHA v3
- Cloudflare Turnstile
Bu yüzden akışınızdaki doğrulama türünü işe başlamadan önce belirleyin.
Ödeme akışı testlerini gerçek ödeme yapmadan çalıştırabilir miyim?
Evet. Çoğu e-ticaret platformu, test kartı numaraları içeren bir sandbox/test modu sunar. CaptchaAI, bu test ortamlarındaki CAPTCHA'ları da aynı şekilde çözer.
Aynı anda birden çok ödeme testini paralel çalıştırabilir miyim?
Evet. CaptchaAI thread bazlı çalışır ve her eşzamanlı çözüm bir thread kullanır; paralel test worker sayınızı planınızın thread sayısına göre ölçekleyin.
Sorun giderme
En sık karşılaşılan hatalar ve hızlı çözümleri:
| Sorun | Sebep | Düzeltme |
|---|---|---|
| CAPTCHA token'ı ödeme sırasında reddedildi | Token'ın süresi doldu | Gönder düğmesine basmadan hemen önce CAPTCHA'yı çözün |
| Kart alanları doldurulmuyor | Stripe/Braintree iframe'i | Doldurmadan önce iframe'e geçin |
| Ödeme adımı girişe yönlendiriyor | Oturumun süresi doldu | Ödeme öncesine bir giriş adımı ekleyin |
| Sipariş sessizce başarısız oluyor | Zorunlu alanlar eksik | Her adımdan sonra hata mesajlarını kontrol edin |
İlgili kılavuzlar
Ödeme akışı testlerinizi bugün otomatikleştirin — CAPTCHA adımını CaptchaAI ile çözün.