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

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

أهم النقاط
- يؤدي تكرار 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)؟
من سجلّك الخاص، وقبل إرسال أي شيء. نمطٌ ثابت:
عندما يبدأ العميل عملية التحقق من الهوية، قم بإنشاء صف في قاعدة البيانات الخاصة بك لتلك المحاولة (طلب، خطوة إعداد، قرض).
استنتج
requestIdمن ذلك الصف، على سبيل المثالkyc-application-8841، وتخزينها في الصف.أرسل الطلب مع تلك القيمة المخزنة.
في أي محاولة إعادة، اقرأ القيمة من الصف. لا تقم أبدًا بحساب قيمة جديدة.
ثلاث قواعد تلي ذلك:
لا تستخدم عشوائيًا 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)، لذا ينطبق نفس المبدأ: مرر قيمة مشتقة من سجلك الخاص، وليس قيمة يتم إنشاؤها من جديد في كل مرة يتم فيها تحميل الشاشة.
ما هي الاستجابات التي يجب عليك إعادة تجربتها؟
وثائق الأخطاء (يفتح في علامة تبويب جديدة) واضحة، وهي مرتبطة بجدول قصير.
إجابة | إعادة المحاولة؟ | ما يجب القيام به |
|---|---|---|
| لا | تم. تتبع |
| نعم | انتظر |
| نعم | التراجع الأسي مع التذبذب، نفس الشيء |
تمت إعادة ضبط الاتصال، DNS فشل، مهلة زمنية | نعم | كما سبق. قد يكون الطلب قد نجح، وهذا هو السبب تحديدًا لـ |
| ليس بشكل أعمى | احتفظ بتفاصيل الطلب واتصل بالدعم إذا استمرت المشكلة. |
| لا | أصلح الحمولة. اقرأ |
| لا | افحص المفتاح وبيئته. |
| لا | يتطلب الإنتاج ملف تعريف تجاري معتمد. |
| لا | لك |
الحد الأقصى الموثق هو 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 's
metadataعندما SDK يقوم بتقديم الطلبات نيابةً عنك.محاولات أخرى
429،502،503،504وأعطال الشبكة فقط، مع إمكانية التراجع وRateLimit-Resetقيمة.نتائج مثل
declinedتمت إدارته بواسطةreasonCodeلا يتم ذلك عن طريق إعادة الإرسال.تمت إزالة التكرارات من معالج Webhook
X-Myaza-DeliveryأوverificationId.
يوجد عقد الطلب الكامل في مرجع التحقق من الإنشاء (يفتح في علامة تبويب جديدة) ، ويربط مركز المطورين باقي الأجزاء. API .
المصادر

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


