Tài Liệu Tham Khảo

Chrome DevTools Protocol + CaptchaAI để chẩn đoán CAPTCHA trong môi trường kiểm thử

Phạm vi an toàn: Hướng dẫn này chỉ áp dụng cho môi trường QA, staging hoặc pre-production thuộc sở hữu hoặc được uỷ quyền của bạn. Nội dung bao gồm các mẫu chẩn đoán, kiểm thử và quan sát cho tích hợp CAPTCHA của chính bạn — không áp dụng cho bên thứ ba hoặc luồng không được phép.

Widget CAPTCHA không hiển thị trên staging, hoặc backend từ chối một token trông có vẻ hợp lệ — thay vì đoán mò qua tab Network, hãy bật thẳng Chrome DevTools Protocol (CDP) và quan sát request, sitekey cùng vòng đời trang ở mức giao thức để tìm đúng nguyên nhân. Bài này đi thẳng vào ba việc: bắt request mạng, phát hiện sitekey trên trang QA, và gửi tác vụ tới CaptchaAI để xác thực toàn bộ luồng — trong staging bạn sở hữu.

Checklist trước khi bắt đầu chẩn đoán

  1. Phạm vi kiểm thử giới hạn trong ứng dụng của bạn hoặc tài nguyên đã được uỷ quyền.
  2. API key CaptchaAI nằm trong CI secret hoặc vault, không trong mã nguồn.
  3. Mỗi lần chạy ghi lại thời gian gọi và mã trạng thái phản hồi.
  4. Có chính sách thử lại idempotent, kèm giới hạn cho lỗi tạm thời.
  5. Bài kiểm thử tái lập được trên CI mà không cần can thiệp thủ công.

Bước 1: Bắt request mạng bằng CDP

CDP giao tiếp với Chrome qua WebSocket, nên bạn thấy request ngay khi gửi đi thay vì lọc thủ công trong tab Network. Network.enable bật domain theo dõi mạng; Network.requestWillBeSent bắn sự kiện cho mỗi request, kể cả request nền mà widget CAPTCHA tự gọi khi khởi tạo.

import asyncio, json
from playwright.async_api import async_playwright

async def trace_qa():
    async with async_playwright() as p:
        browser = await p.chromium.launch()
        ctx = await browser.new_context()
        page = await ctx.new_page()
        client = await ctx.new_cdp_session(page)
        await client.send('Network.enable')
        client.on('Network.requestWillBeSent', lambda e: print(e['request']['url']))
        await page.goto('https://staging.example.com/captcha-demo')

Chạy đoạn trên với trang QA và so sánh danh sách request với kỳ vọng: script recaptcha hay challenges.cloudflare.com có được tải không, request có bị CSP chặn không.

Bước 2: Phát hiện sitekey trên trang kiểm thử nội bộ

Mở trang QA (ví dụ https://staging.example.com/captcha-demo) và đọc data-sitekey từ phần tử .g-recaptcha hoặc .cf-turnstile — làm trực tiếp qua Runtime.evaluate của CDP thay vì bấm chuột trong Elements panel. So sánh sitekey đọc được với cấu hình backend; lệch nhau ở bước này là nguyên nhân phổ biến nhất khiến widget hiển thị sai môi trường.

Bước 3: Gửi tác vụ tới CaptchaAI và polling kết quả

Sau khi xác nhận sitekey đúng, gửi tác vụ tới in.php cùng URL staging. Polling res.php cho đến khi có kết quả — nghĩa là chủ động hỏi lại endpoint định kỳ thay vì chờ callback. Ghi thời gian giải làm chỉ số chẩn đoán: nếu dài bất thường so với production, vấn đề thường ở mạng nội bộ, không phải ở CaptchaAI.

Một đội QA outsourcing ở TP.HCM từng gặp đúng tình huống này: CI chạy song song nhiều luồng kiểm thử checkout, vài luồng báo ERROR_NO_SLOT_AVAILABLE giữa giờ cao điểm. Bật CDP trên luồng lỗi, đối chiếu log với ID task gửi tới CaptchaAI, thường lộ nguyên nhân trong vài phút thay vì rerun cả suite.

Bước 4: Xác thực token ở backend

Đính token vào biểu mẫu QA, gửi và quan sát qua CDP xem backend trả mã thành công hay không. Nếu bị từ chối, đối chiếu action, sitekeysecret với server — sai lệch một trong ba giá trị này là nguyên nhân phổ biến nhất, dù token CaptchaAI hợp lệ.

Ví dụ code: gọi CaptchaAI từ script kiểm thử

Đoạn Python dưới đây minh hoạ luồng tối thiểu để kiểm thử widget CAPTCHA trên staging qua CaptchaAI.

import os
import requests

API_KEY = os.environ['CAPTCHAAI_KEY']
QA_PAGE_URL = os.environ['QA_PAGE_URL']  # ví dụ https://staging.example.com/qa-login
QA_SITE_KEY = os.environ['QA_SITE_KEY']


def submit_qa_recaptcha() -> str:
    payload = {
        'clientKey': API_KEY,
        'task': {
            'type': 'NoCaptchaTaskProxyless',
            'websiteURL': QA_PAGE_URL,
            'websiteKey': QA_SITE_KEY,
        },
    }
    response = requests.post(
        'https://api.captchaai.com/createTask',
        json=payload,
        timeout=30,
    )
    response.raise_for_status()
    return response.json()['taskId']


def fetch_qa_result(task_id: str) -> dict:
    payload = {'clientKey': API_KEY, 'taskId': task_id}
    response = requests.post(
        'https://api.captchaai.com/getTaskResult',
        json=payload,
        timeout=30,
    )
    response.raise_for_status()
    return response.json()

Các lỗi thường gặp khi chẩn đoán

Vấn đề Nguyên nhân thường gặp Cách xử lý
Test không tìm thấy widget Selector đổi hoặc widget load muộn Kiểm tra selector, dùng wait_for_selector
CaptchaAI trả ERROR_NO_SLOT_AVAILABLE Hàng đợi đầy khi nhiều luồng CI chạy song song Thử lại với backoff trong pipeline
Backend QA từ chối token Sai action, sitekey hoặc secret Đối chiếu cấu hình backend với staging

Ghi log và khả năng quan sát cho pipeline QA

  • Ghi thời gian lấy token, mã trạng thái HTTP, ID task và độ sâu hàng đợi cho mỗi lần chạy.
  • Tách các môi trường (development, staging, pre-production) thành kênh log riêng biệt.
  • Liên kết các bước bằng một correlation id; phát lại được cả kịch bản từ một id thường giảm một nửa thời gian chẩn đoán sự cố.

Câu hỏi thường gặp

CDP khác gì so với tab Network của DevTools?

Tab Network là giao diện thủ công cho cùng dữ liệu; CDP lập trình hoá việc bắt request và ghi log tự động trong CI.

Có thể đặt API key CaptchaAI trực tiếp trong mã không?

Không. Nạp khoá qua secret manager của CI, biến môi trường hoặc vault. Khoá đã commit vào kho mã phải xoay vòng ngay.

Nên retry bao nhiêu lần khi gặp lỗi tạm thời?

Thử lại idempotent kèm exponential backoff (1s, 2s, 4s) và giới hạn trên. Lỗi mạng, mã 5xx và ERROR_NO_SLOT_AVAILABLE phù hợp để thử lại; lỗi xác thực kéo dài thì nên sửa cấu hình trước.

Hướng dẫn liên quan an toàn

Xác thực tích hợp CAPTCHA của bạn trong môi trường nội bộ với CaptchaAI.

Os comentários estão desativados para este artigo.