استدعاء CAPTCHA API من Spring Boot

بقلم solvethreeمدة القراءة: 4 دقيقة

سجّل مكوّن CaptchaClient واحدًا على الخادم، وأنشئ المهمة مرة واحدة، ثم استطلع حالتها باستخدام معرّفها المحفوظ. يستخدم الكود المساعد أدناه استدعاءات Spring RestClient المتزامنة ويعيد استجابات Gson JsonObject.

في هذه الصفحة

أضف التبعيات وسجّل الكود المساعد

يستخدم الكود المساعد المرفق Java 21+ وSpring Web 7.0.10 وGson 2.15.0. في مشروع Spring Boot قائم، احتفظ بإصدار Spring المتوافق الذي تديره Boot بدلًا من تجاوز إصدار spring-web وحده لمطابقة المثال. أضف Gson كتبعية إذا لم يكن تطبيقك يتضمنه بالفعل.

Spring · خدمة RestClient من جانب الخادم
// Java 21+, Spring Web 7.0.10 and Gson 2.15.0; use your Boot dependency management.
// Save as CaptchaClient.java in your application's package.
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.net.http.HttpClient;
import java.time.Duration;
import org.springframework.http.MediaType;
import org.springframework.http.client.JdkClientHttpRequestFactory;
import org.springframework.web.client.RestClient;

public final class CaptchaClient {
    private final RestClient api;
    public CaptchaClient(String key) {
        var transport = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(10))
            .followRedirects(HttpClient.Redirect.NEVER).build();
        var factory = new JdkClientHttpRequestFactory(transport);
        factory.setReadTimeout(Duration.ofSeconds(25));
        api = RestClient.builder().baseUrl("https://api.solvethree.com/v1")
            .requestFactory(factory).defaultHeader("Authorization", "Bearer " + key).build();
    }
    public JsonObject create(String site, String proxy, String requestId) {
        var input = new JsonObject();
        input.addProperty("site", site);
        input.addProperty("action", "login");
        input.addProperty("proxy", proxy);
        input.addProperty("requestId", requestId); // Save before calling create.
        String body = api.post().uri("/tasks?waitMs=0").contentType(MediaType.APPLICATION_JSON)
            .body(input.toString()).retrieve().body(String.class);
        return JsonParser.parseString(body).getAsJsonObject();
    }
    public JsonObject get(String id) {
        if (!id.matches("[A-Za-z0-9_-]+")) throw new IllegalArgumentException("Invalid task ID");
        String body = api.get().uri("/tasks/{id}?waitMs=15000", id)
            .retrieve().body(String.class);
        return JsonParser.parseString(body).getAsJsonObject();
    }
}
// Construct once with System.getenv("SOLVETHREE_API_KEY") in a server-side @Bean.
// Call create once, save its id, then get(id) until ready/failed or your deadline.
// RestClient throws on HTTP errors; keep the saved requestId and any known task id.

احفظ الصنف باسم CaptchaClient.java ضمن حزمة تطبيقك. في دالة مصنع @Bean على الخادم، أنشئ مثيلًا منه مرة واحدة باستخدام متغير البيئة SOLVETHREE_API_KEY. تحقّق عند بدء التشغيل من أن المفتاح مُعدّ. يضيفه الكود المساعد كترويسة تفويض Bearer؛ فلا تضعه في كود المتصفح.

أعِد استخدام ذلك المكوّن عبر الحقن في المُنشئ. يمكن إعادة استخدام RestClient عبر خيوط التنفيذ، لكن كل طلب يحجب خيط التنفيذ الذي يستدعيه. لا تستدعِ هذه الدوال ضمن حلقة أحداث WebFlux. تصف وثائق عميل REST في Spring هذا العميل المتزامن.

تستخدم طبقة النقل مهلة اتصال قدرها 10 ثوانٍ، ومهلة قراءة قدرها 25 ثانية، ولا تتبع عمليات إعادة التوجيه. تُقرأ الاستجابات كسلاسل نصية وتُحلَّل باستخدام Gson، ولا تُحوَّل إلى كائنات استجابة ذات أنواع محددة.

اضبط الموقع والإجراء والوكيل

قبل استدعاء create، اضبط ملف تعريف نشطًا للموقع المستهدف في مساحة عملك. إرسال اسم مضيف وإجراء لا ينشئ ذلك الملف. راجع إعداد ملف تعريف الموقع إذا لم يكن الموقع مُعدًّا بعد.

  • مرّر اسم المضيف في site، وليس عنوان URL كاملًا لصفحة. لا يتضمن طلب reCAPTCHA حقل url أو type.
  • يثبّت الكود المساعد قيمة action على login. غيّر هذه القيمة، أو اجعلها معاملًا للدالة، إذا كان الطلب المقصود يستخدم إجراءً مختلفًا.
  • مرّر عنوان URL واحدًا لوكيل. تتطلب واجهة API واحدًا فقط من proxy أو proxyCandidates؛ وينفّذ هذا الكود المساعد خيار الوكيل الواحد.
  • لا يحدّد الكود المساعد recaptchaType، لذا تستخدم واجهة API قيمته الافتراضية enterprise-v3.

أنشئ المهمة مرة واحدة، ثم استطلع حالتها باستخدام معرّفها المحفوظ

  1. 1.

    احفظ معرّف طلب قبل الإنشاء

    اختر requestId يتكوّن من 1–64 حرفًا أو رقمًا من ASCII أو شرطة سفلية أو شرطة وصل. احفظه مع مدخلات المهمة قبل استدعاء create. يتيح لك استعادة المهمة نفسها إذا فُقدت استجابة الإنشاء.

  2. 2.

    استدعِ create واحفظ id المُعاد

    استدعِ دالة create الخاصة بالمكوّن، مع تمرير اسم المضيف والوكيل ومعرّف الطلب المحفوظ. ترسل طلب POST واحدًا إلى /v1/tasks مع waitMs=0. احفظ id المُعاد؛ واستخدم معرّف المهمة هذا، لا معرّف الطلب، لعمليات الاستعلام اللاحقة.

  3. 3.

    استدعِ get حتى تصل المهمة إلى حالة نهائية

    مرّر معرّف المهمة المحفوظ إلى get. يطلب كل استعلام waitMs=15000 ويحجب خيط التنفيذ أثناء انتظار الاستجابة. واصل عند pending أو solving، ضمن مهلة نهائية على مستوى التطبيق. توقّف عند ready أو failed. تحدّ مهل HTTP من مدة الطلبات الفردية، لا من مدة حلقة الاستطلاع بأكملها.

  4. 4.

    اقرأ الحل فقط عندما يكون جاهزًا

    بالنسبة إلى reCAPTCHA، أرسل solution.token إلى الهدف المقصود، وليس معرّف المهمة. استخدم userAgent وsecChUa المُعادين مع الوكيل نفسه الذي نجح الحل عبره. لا تستبدل بهما ترويسات متصفح غير مرتبطة، ولا تغيّر عنوان URL المستهدف. توفّر المهمة الجاهزة حلًا؛ لكنها لا تثبت أن الهدف قد قبل طلبك اللاحق.

عالِج أخطاء HTTP بمعزل عن المهام الفاشلة

تنتهي مهلة استدعاء create قبل أن تتلقى معرّف المهمة.

قد يكون الخادم قد أنشأ المهمة رغم أن عميلك لم يتلقَّ استجابتها.

جرّب هذا: استعد المهمة بتكرار طلب المهمة نفسه باستخدام requestId المحفوظ. تعيد المدخلات المطابقة المهمة الموجودة. لا تُنشئ معرّف طلب جديدًا إلا إذا كنت تقصد إنشاء مهمة منطقية جديدة.

يفشل استدعاء get على مستوى HTTP.

يطرح RestClient.retrieve() استثناءً عند استجابات HTTP غير الناجحة. لا يعني ذلك أن حالة المهمة هي failed.

جرّب هذا: عالِج خطأ HTTP قبل محاولة قراءة محتوى استجابة ناجحة. احتفظ بمعرّف المهمة المعروف لاستعادتها بدلًا من إنشاء مهمة أخرى. شخّص المدخلات غير الصالحة قبل إعادة المحاولة بها دون تغيير.

تحتوي استجابة المهمة على الحالة failed.

اقرأ errorCode وerror؛ ويُعدّ site-unreachable أحد رموز أخطاء المهام المحتملة.

جرّب هذا: توقّف عن استطلاع حالة تلك المهمة وعالِج السبب المُبلّغ عنه قبل بدء مهمة أخرى. تُردّ تكلفة عمليات الحل الفاشلة؛ فلا تفترض أن الفشل يعني عدم كفاية الرصيد.

تؤدي إعادة استخدام معرّف طلب إلى تعارض.

قارن مدخلات المهمة الجديدة بتلك المحفوظة لمعرّف الطلب هذا.

جرّب هذا: استخدم المدخلات الأصلية لاستعادة المهمة الموجودة. واستخدم معرّف طلب جديدًا لمدخلات مهمة مختلفة عمدًا.

لتفسير الأخطاء، راجع أخطاء CAPTCHA API.

شغّل مهمتك الأولى.

ابدأ برصيد قدره $5 في مساحة العمل.

إنشاء مساحة عمل
استدعاء CAPTCHA API من Spring Boot · solvethree