Skip to content
جميع المقالات

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

تشارلز أرشيبونغ

, المؤسس المشارك

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

عنوان رئيسي "أعد المحاولة دون دفع مرتين" بجانب رسم توضيحي لأقواس إعادة المحاولة المتقطعة التي تتقارب على علامة صح واحدة، على تدرج لوني نيلي داكن.

أهم النقاط

  • يؤدي تكرار metadata.requestId إلى إرجاع عملية التحقق الحالية بدلاً من إنشاء عملية تحقق جديدة.
  • قم بإنشاء معرف الطلب من سجلك الخاص وقم بتخزينه قبل المحاولة الأولى، وليس داخل حلقة إعادة المحاولة.
  • إعادة المحاولة 429، 502، 503، 504 وفشل الاتصال مع التراجع؛ التعامل مع الاستجابات الأخرى من نوع 4xx على أنها أخطاء يجب إصلاحها.
  • يشير الرمز 202 فقط إلى أن العملية في قائمة الانتظار. أما فشل التحقق فهو نتيجة يجب التعامل معها، وليس خطأً يستدعي إعادة المحاولة.

لإعادة محاولة طلب التحقق بأمان، أرسل نفسmetadata.requestIdفي كل مرة تعيد المحاولة. Toden يعالجrequestIdكمفتاح التكرار الخاص بك: إذا وصل طلب معrequestIdلقد استخدمت مؤسستك بالفعل، API يقوم بإعادة التحقق الحالي بدلاً من إنشاء تحقق ثانٍ، ولن يتم تحصيل رسوم منك مرتين.

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

ما الذي يحدث خطأً في غياب خاصية التكرار؟

الحالة الكلاسيكية هي حدوث مهلة بعد نجاح العملية. يرسل خادمكPOST /api/kyc/verify، ال API يقبل النظام الطلب ويضعه في قائمة انتظار التحقق، لكن الرد يضيع أثناء عودته: انقطاع اتصال الهاتف المحمول، أو انتهاء مهلة موازن الأحمال، أو إعادة تشغيل الحاوية. من جانبكم، فشل الطلب. من جانبنا، نجح.

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

بنفسrequestId، تعيد المحاولة التحقق الأصلي، ولا يكلف فقدان الاستجابة شيئًا.

كيف يعمل requestId على نقطة التحقق؟

إنه موجود داخل الطلبmetadataالكائن. من مرجع التحقق من الإنشاء (يفتح في علامة تبويب جديدة) :

{
  "country": "NG",
  "idType": "bvn",
  "idNumber": "12345678901",
  "externalUserId": "user_42",
  "metadata": { "requestId": "order_1001", "loanId": "loan_20191" }
}

يتم إرجاع أول طلب202 Accepted:

{
  "verificationId": "ver_01j9...",
  "status": "processing",
  "externalUserId": "user_42",
  "metadata": { "loanId": "loan_20191" }
}

تم تقديم طلب لاحق بنفس الصيغةrequestIdيعيد هذا التحقق، بغض النظر عن الحالة التي وصل إليها، على سبيل المثال{ "verificationId": "ver_01j9...", "status": "approved" }.externalUserIdوتعود بياناتك الوصفية تمامًا كما تم تخزينها، لذا فإن إعادة المحاولة والأصل يتطابقان.

يتم تحديد نطاق المفاتيح لمؤسستك. إذا كانrequestIdيصطدم بشخص ينتمي إلى منظمة أخرى، API عمليات الإرجاع403مع{ "error": "Forbidden" }بدلاً من الكشف عن أي شيء بخصوص عملية التحقق تلك.

أين يجب عليك إنشاء معرف الطلب (requestId)؟

من سجلّك الخاص، وقبل إرسال أي شيء. نمطٌ ثابت:

  1. عندما يبدأ العميل عملية التحقق من الهوية، قم بإنشاء صف في قاعدة البيانات الخاصة بك لتلك المحاولة (طلب، خطوة إعداد، قرض).

  2. استنتجrequestIdمن ذلك الصف، على سبيل المثالkyc-application-8841، وتخزينها في الصف.

  3. أرسل الطلب مع تلك القيمة المخزنة.

  4. في أي محاولة إعادة، اقرأ القيمة من الصف. لا تقم أبدًا بحساب قيمة جديدة.

ثلاث قواعد تلي ذلك:

  • لا تستخدم عشوائيًا UUID يتم توليدها لكل HTTPهذا مُعرّف فريد للمكالمة، وهو عكس ما تحتاجه .

  • قم بتسميته. مجرد1001من المحتمل أن تتعارض مع سجلاتك الأخرى بمرور الوقت، ويحدث تعارض بين المؤسسات403بادئة مثلkyc-application-يجعل القيمة واضحة لا لبس فيها.

  • لا تصدر نسخة جديدة إلا للتحقق الحقيقي. إذا رُفض طلب أحد العملاء وقررتَ السماح له بالبدء من جديد، فهذا يُعد تحققًا منطقيًا جديدًا بنسخة جديدة.requestIdإن إعادة استخدام القديم سيؤدي ببساطة إلى إرجاع عملية التحقق المرفوضة.

إذا أعاد المراجع التحقق حتى يتمكن المتقدم من إعادة بعض الخطوات، فلن تحتاج إلى طلب جديد.requestIdعلى الإطلاق. يحتفظ التحقق الذي يتم إرساله مرة أخرى أو التحقق منه مجددًا بمعرفه، ويظهر إعادة الإرسال كطلب جديد.attemptكما هو موضح في مرجع نتيجة التحقق (يفتح في علامة تبويب جديدة) .

عندما SDK يقوم بتقديم الطلبات نيابةً عنك

معظم عمليات التكامل لا تستدعي/verifyمباشرةً. تقوم حزم تطوير البرامج (SDKs) الخاصة بالويب، وReact Native، وFlutter بإجراء المكالمة عندما يضغط مقدم الطلب على زر الإرسال. وهي تقبلmetadataمع خاصتكrequestId(metadata={{ requestId: "order_1001" }}في React Native،metadata: {'requestId': 'order_1001'}في Flutter)، لذا ينطبق نفس المبدأ: مرر قيمة مشتقة من سجلك الخاص، وليس قيمة يتم إنشاؤها من جديد في كل مرة يتم فيها تحميل الشاشة.

ما هي الاستجابات التي يجب عليك إعادة تجربتها؟

وثائق الأخطاء (يفتح في علامة تبويب جديدة) واضحة، وهي مرتبطة بجدول قصير.

إجابة

إعادة المحاولة؟

ما يجب القيام به

202 Accepted

لا

تم. تتبعverificationId.

429 Too Many Requests

نعم

انتظرRateLimit-Resetثوانٍ، ثم أعد المحاولة بنفس الطريقةrequestId.

502،503،504

نعم

التراجع الأسي مع التذبذب، نفس الشيءrequestId.

تمت إعادة ضبط الاتصال، DNS فشل، مهلة زمنية

نعم

كما سبق. قد يكون الطلب قد نجح، وهذا هو السبب تحديدًا لـrequestIdالأمور.

500

ليس بشكل أعمى

احتفظ بتفاصيل الطلب واتصل بالدعم إذا استمرت المشكلة.pricing_not_configuredلن يتم إصلاح المشكلة عند إعادة المحاولة.

400 Invalid request body

لا

أصلح الحمولة. اقرأmessage.

401 Invalid API key

لا

افحص المفتاح وبيئته.

403 business_not_approved

لا

يتطلب الإنتاج ملف تعريف تجاري معتمد.

403 Forbidden

لا

لكrequestIdيتعارض مع خطة منظمة أخرى. خطة الجيل الخاصة بك ليست فريدة بما فيه الكفاية.

الحد الأقصى الموثق هو 100 طلب لكل 15 دقيقة لكل عميل، معRateLimit-Limit،RateLimit-RemainingوRateLimit-Resetعناوين الاستجابات. القراءةRateLimit-Remainingيُتيح هذا الخيار إبطاء عملية المعالجة الجماعية قبل رفضها، بدلاً من إبطائها بعد ذلك. وتشير صفحة حدود المعدل (يفتح في علامة تبويب جديدة) إلى أن هذه الحدود قد تختلف بين بيئة الاختبار وبيئة الإنتاج، ويمكن تعديلها بما يتناسب مع حسابك.

كيف تبدو حلقة إعادة المحاولة الآمنة؟

إصدار مصغر من Node.js، باستخدام المتغير العامfetchيتم تسلسل البيانات مرة واحدة، خارج الحلقة، لذا فإن كل محاولة ترسل بايتات متطابقة بنفس الطريقة.requestId.

const VERIFY_URL = 'https://api.toden.co/api/kyc/verify';
const RETRYABLE = new Set([429, 502, 503, 504]);
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const backoff = (attempt) => Math.min(30_000, 500 * 2 ** attempt) * (0.5 + Math.random());

export async function submitVerification(body, apiKey, maxAttempts = 5) {
  if (!body.metadata?.requestId) throw new Error('metadata.requestId is required');
  const payload = JSON.stringify(body);

  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    let res;
    try {
      res = await fetch(VERIFY_URL, {
        method: 'POST',
        headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' },
        body: payload,
      });
    } catch (networkError) {
      if (attempt === maxAttempts) throw networkError;
      await sleep(backoff(attempt));
      continue;
    }

    if (res.ok) return res.json(); // 202 for a new verification, or the existing one on a replay

    if (!RETRYABLE.has(res.status) || attempt === maxAttempts) {
      const detail = await res.json().catch(() => ({}));
      throw Object.assign(new Error(detail.error ?? `HTTP ${res.status}`), { status: res.status, detail });
    }

    const resetSeconds = Number(res.headers.get('RateLimit-Reset'));
    await sleep(res.status === 429 && resetSeconds > 0 ? resetSeconds * 1000 : backoff(attempt));
  }
}

لاحظ ما هو غائب: لا توجد إعادة محاولة400،401أو403ولا يوجد مُعرّف جديد في أي مكان. يُقدّم المُتصلrequestIdلقد تم تخزينها بالفعل.

هل يُعتبر فشل عملية التحقق أمراً يستدعي إعادة المحاولة؟

لا، والخلط بينهما مصدر شائع للتكرار.202هذا يعني فقط أن الطلب قد تم وضعه في قائمة الانتظار. لا يزال من الممكن أن تنتهي عملية التحقق.declinedإما لعدم تطابق الوجه، أو لعدم العثور على الهوية في قاعدة البيانات الحكومية. هذه نتائج يتم الحصول عليها عبر روابط الويب أو الاستطلاعات، ولكل منها...reasonومستقرreasonCodeإنهم ليسوا كذلك HTTP أخطاء.

إذا كانت آلية إعادة المحاولة تراقب النتائج وتعيد الإرسال عند الرفض، فستتلقى إما نفس رسالة التحقق المرفوضة (نفسrequestIdأو إنشاء عملية تحقق ثانية مدفوعة الأجر لنفس المدخلات الخاطئة (جديدة)requestIdلا يُجدي أيٌّ منهما نفعًا. انفصل عن...reasonCodeبدلاً من ذلك: اطلب صورة جديدة علىdocument_blurryللحصول على رقم مصحح فيidentity_not_foundوإخضاع الشخص لعملية تحقق جديدة أو معاد إجراؤها عن قصد.

هل يحتاج جانب webhook إلى خاصية التكرار أيضًا؟

نعم. قد تصل نفس رسالة الويب هوك أكثر من مرة، لأن عملية الإرسال تُعاد حتى يقر بها الطرفية. تشير وثائق الويب هوك (يفتح في علامة تبويب جديدة) إلى ضرورة إزالة التكرارات فيX-Myaza-Deliveryالعنوان، أو علىverificationIdسجّل ما قمت بمعالجته، واجعل المعالج غير فعال في المرة الثانية. إن الإرسال والاستقبال المتكررين معًا هما ما يجعلان العملية تتم مرة واحدة فقط من وجهة نظر العميل.

قائمة التحقق

  • واحدrequestIdلكل عملية تحقق منطقية، مستمدة من سجلك الخاص ومُصنفة حسب المساحة.

  • يتم تخزينها قبل المحاولة الأولى؛ تتم قراءتها مرة أخرى، ولا يتم إعادة إنشائها عند إعادة المحاولة.

  • مرّ عبر SDK 'smetadataعندما SDK يقوم بتقديم الطلبات نيابةً عنك.

  • محاولات أخرى429،502،503،504وأعطال الشبكة فقط، مع إمكانية التراجع وRateLimit-Resetقيمة.

  • نتائج مثلdeclinedتمت إدارته بواسطةreasonCodeلا يتم ذلك عن طريق إعادة الإرسال.

  • تمت إزالة التكرارات من معالج WebhookX-Myaza-DeliveryأوverificationId.

يوجد عقد الطلب الكامل في مرجع التحقق من الإنشاء (يفتح في علامة تبويب جديدة) ، ويربط مركز المطورين باقي الأجزاء. API .

المصادر

تشارلز أرشيبونغ

عن الكاتب

Charles Archibong

المؤسس المشارك

شارك تشارلز أرتشيبونغ في تأسيس شركة Toden. وهو يكتب عن التحقق من الهوية، والتكنولوجيا المالية، والعمل العملي لبناء خدمات رقمية موثوقة.

  • المطورون

    ربط حالات التحقق بحالات منتجك

    وجّه منتجك انطلاقًا من الحالة، أي النتيجة، وخزّن قيمة checkStatus بجانبها كشرح. اربط كل قيمة من قيم الحالة العشر بحالة واحدة في نظامك، واحصل على أحدث حالة من verification.status_updated أو من خلال الاستقصاء الدوري.

ابنِ منتجك.وسنتولى الباقي.

الهوية والامتثال من البداية إلى النهاية، وفق معايير عالمية وبأسعار تناسب المؤسسين.