استدعاء أداة الحل من معالج مسار Next.js

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

استخدم معالج POST على الخادم لإنشاء المهمة مرة واحدة، ثم استرجع معرّفها عبر GET. احتفظ بمفتاح solvethree على الخادم؛ يجب ألا يستدعي المتصفح خدمة الحل مباشرةً أو ينشئ مهمة أخرى كلما انتهت مهلة انتظار.

في هذه الصفحة

إعداد الخادم وملف تعريف الموقع

  • استخدم Node.js 22+ وحزمة SDK الرسمية لـ JavaScript. اتبع طريقة التثبيت عبر عنوان URL للحزمة في الوثائق؛ ولا تفترض توفّر حزمة في سجل npm.
  • اضبط SOLVETHREE_API_KEY وCAPTCHA_SITE وSOLVETHREE_PROXY وINTEGRATION_KEY في بيئة الخادم. لا تضف البادئة NEXT_PUBLIC_ إلى أيٍّ من السرَّين.
  • فعّل ملف تعريف لاسم المضيف المستهدف في مساحة عملك قبل استدعاء المسار. ضبط CAPTCHA_SITE لا ينشئ ملف تعريف؛ راجع إعداد ملف تعريف الموقع.
  • استبدل الإجراء login في المثال بالإجراء الذي يتطلبه تكاملك. يستخدم الطلب خادمًا وكيلاً واحدًا ويعتمد reCAPTCHA Enterprise v3 افتراضيًا؛ ولا يحتاج إلى الحقلين type أو url.

إضافة معالج الإنشاء والاسترجاع

ضع المثال في app/api/captcha/route.js. فهو يصدّر معالجات HTTP لـ App Router ويحدد صراحةً بيئة تشغيل Node.js لحزمة SDK. أبقه مسارًا على الخادم يُنفَّذ وقت الطلب، لا موردًا يُولَّد بشكل ثابت.

app/api/captcha/route.js · معالج مسار Node.js
import { Solvethree, SolvethreeError } from '@solvethree/sdk';
export const runtime = 'nodejs';
const client = new Solvethree({ apiKey: process.env.SOLVETHREE_API_KEY });
function authorized(request) {
  const key = process.env.INTEGRATION_KEY;
  return Boolean(key) && request.headers.get('x-integration-key') === key;
}
function failure(error) {
  return error instanceof SolvethreeError
    ? Response.json({ requestId: error.requestId, taskId: error.taskId }, { status: 502 })
    : Response.json({ error: 'Invalid task input or ID' }, { status: 400 });
}
export async function POST(request) {
  if (!authorized(request)) return new Response('Unauthorized', { status: 401 });
  try {
    return Response.json(await client.createTask({
      site: process.env.CAPTCHA_SITE, action: 'login', proxy: process.env.SOLVETHREE_PROXY,
      requestId: request.headers.get('x-request-id') ?? undefined,
    }, { waitMs: 0, signal: AbortSignal.timeout(20000) }));
  } catch (error) { return failure(error); }
}
export async function GET(request) {
  if (!authorized(request)) return new Response('Unauthorized', { status: 401 });
  const id = new URL(request.url).searchParams.get('id');
  if (!id) return Response.json({ error: 'Provide id' }, { status: 400 });
  try {
    return Response.json(await client.getTask(id, { waitMs: 15000, signal: AbortSignal.timeout(25000) }));
  } catch (error) { return failure(error); }
}

يستدعي POST الدالة createTask مع waitMs: 0، لذا يعيد استجابة المهمة دون انتظار حل. احفظ معرّف المهمة المُعاد. يتطلب GET ذلك المعرّف الموجود ويستدعي getTask؛ ولا ينشئ مهمة أبدًا.

يطلب GET انتظارًا يصل إلى 15 ثانية، مع مهلة منفصلة لإلغاء الطلب تبلغ 25 ثانية. أما POST فله مهلة إلغاء طلب تبلغ 20 ثانية. تحدّ هذه المهل من مدة كل طلب، لا من عمر المهمة.

التحقق من صلاحية الوصول إلى كل مهمة قبل إعادتها

للوصول من المتصفح، استخدم آلية المصادقة الفعلية في تطبيقك على الخادم بدلًا من توزيع INTEGRATION_KEY. المصادقة وحدها لا تكفي: فقبول أي معرّف مهمة من مستخدم تمت مصادقته سيظل يسمح له بطلب نتيجة شخص آخر.

  1. 1.

    ربط الإنشاء بالمستدعي

    بعد أن ينشئ طلب POST مصادَق عليه مهمةً، خزّن معرّفها مرتبطًا بالمستخدم أو المستأجر الذي تمت مصادقته قبل إعادته. اربط requestId المنطقي بذلك المالك أيضًا، حتى لا تُفقد بيانات الملكية عند الاسترداد.

  2. 2.

    التحقق من الملكية قبل الاسترجاع

    عند GET، صادق على هوية المستدعي وتحقق من المعرّف المقدَّم بمقارنته بسجل الملكية قبل استدعاء getTask. ارفض المعرّفات التي لا يملكها المستدعي، ولا تُعد النتائج إلا بعد نجاح هذا التحقق.

أبقِ الموقع والإجراء والخادم الوكيل تحت تحكم الخادم، ما لم يمنح تطبيقك المستدعين صراحةً صلاحية اختيارها. تمنع قيم البيئة الثابتة في هذا المثال العميل من تغيير تلك المدخلات.

الاستعلام الدوري عن المهمة نفسها واسترداد الطلبات غير المؤكدة

  1. 1.

    مواصلة الاستعلام عن المهام التي لم تصل إلى حالة نهائية

    في حالتي pending أو solving، استرجع المعرّف نفسه مجددًا، ضمن المهلة الإجمالية لتطبيقك. انتهاء انتظار GET ليس سببًا لإنشاء مهمة أخرى.

  2. 2.

    التوقف عند ready أو failed

    وحدها الحالة ready تحتوي على حل قابل للاستخدام. في حالة failed، أوقف الاستعلام الدوري وافحص errorCode وerror؛ تُرد تكلفة محاولات الحل الفاشلة. عالج استجابات HTTP غير الناجحة قبل تفسير الاستجابة على أنها مهمة. معالج catch في المسار لا يغني عن التحقق من حالة المهمة المُعادة.

  3. 3.

    استرداد عملية الإنشاء بعد انتهاء مهلة الاتصال

    اختر x-request-id واحتفظ به قبل POST. إذا تلقيت معرّف مهمة، فاسترجعها. وإذا فُقدت استجابة الإنشاء، فكرر POST باستخدام معرّف الطلب نفسه ومدخلات المهمة دون تغيير لاسترداد المهمة الموجودة. تقبل معرّفات الطلبات من 1 إلى 64 حرفًا أو رقمًا أو شرطة سفلية أو شرطة ضمن ASCII؛ وتؤدي إعادة استخدام المعرّف مع مدخلات مختلفة إلى تعارض.

تعني المهمة ذات الحالة ready أن solvethree أنشأ حلًا، لا أن الجهة المستهدفة قبلته. لا ترسله حزمة SDK نيابةً عنك. عند الإرسال، استخدم userAgent وsecChUa المُعادَين مع الخادم الوكيل الذي نجح في الحل، وهو الخادم الوكيل المضبوط في هذا المثال ذي الخادم الوكيل الواحد. لا تنتقل إلى هوية متصفح أو عنوان IP غير مرتبطين بالحل.

عند حدوث أخطاء في الطلب أو حالات فشل نهائية، راجع مرجع أخطاء API قبل دفع تكلفة حل آخر. إعادة المحاولة بمدخلات غير صالحة دون تغيير لن تصلحها.

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

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

إنشاء مساحة عمل
استدعاء أداة الحل من معالج مسار Next.js · solvethree