Automatice los flujos completos de pago: carrito, envío, pago, confirmación, manejando CAPTCHA en cada etapa.
Dónde aparecen los CAPTCHA en el proceso de pago
| etapa | Tipos comunes de CAPTCHA | gatillo |
|---|---|---|
| Añadir al carrito | reCAPTCHA v3 (invisible) | Prevención de robots |
| Iniciar sesión/guest finalizar compra | reCAPTCHA v2 | Verificación de cuenta |
| Dirección de envío | torniquete | Limitación de velocidad |
| pagina de pago | reCAPTCHA v2/v3 | Prevención de fraude |
| Confirmación de pedido | reCAPTCHA v2 | Validación final |
Arquitectura
┌────────┐ ┌───────────┐ ┌──────────┐ ┌─────────┐ ┌──────────┐
│ Cart │───▶│ Shipping │───▶│ Payment │───▶│ Review │───▶│ Confirm │
│ │ │ Address │ │ Info │ │ Order │ │ │
└────────┘ └───────────┘ └──────────┘ └─────────┘ └──────────┘
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
[CAPTCHA?] [CAPTCHA?] [CAPTCHA?] [CAPTCHA?] [CAPTCHA?]
Implementación central
Automatizador de pago
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()
Uso
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()
Manejo de casos extremos
CAPTCHA aparece después de un error de validació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
CAPTCHA basados en sesiones
Algunos sitios solo muestran CAPTCHA en la primera solicitud por sesión. Utilice cookies del navegador para mantener sesiones en todos los pasos.
Campos de formulario dinámicos
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))
)
Solución de problemas
| Problema | causa | Solución |
|---|---|---|
| Token CAPTCHA rechazado en el pago | Token caducado | Resuelva CAPTCHA inmediatamente antes de hacer clic en enviar |
| Los campos de la tarjeta no se llenan | iframe raya/Braintree | Cambiar a iframe antes de llenar |
| Redirecciones de pago para iniciar sesión | La sesión expiró | Agregar paso de inicio de sesión antes de pagar |
| El pedido falla silenciosamente | Faltan campos obligatorios | Compruebe si hay mensajes de error después de cada paso |
Preguntas frecuentes
¿Puedo probar los flujos de pago sin pagos reales?
Sí. La mayoría de las plataformas de comercio electrónico tienen modos sandbox/test con números de tarjeta de prueba. CaptchaAI resuelve los mismos CAPTCHA en entornos de prueba.
¿Cómo manejo los diferentes diseños de pago?
Utilice el patrón alternativo del selector CSS (selector1, selector2) para hacer coincidir las variaciones comunes. Personalice selectores para sitios específicos.
¿Qué pasa con los pagos de una página?
Adapte el flujo para completar todos los campos en una página y llame a _solve_if_captcha() una vez antes del envío final.
Guías relacionadas
- Envío de formulario automatizado
- Referencia rápida de API
Automatizar las pruebas de pago:manejar CAPTCHA con CaptchaAI.