منصة B2B للسلع الرقمية

إعادة محاولة الطلبات بأمان في واجهات B2B 2026

FoxReload لا تملك ترويسة Idempotency-Key. النمط الآمن — تحقّق من حالة الطلب قبل إنشاء طلب جديد. شرح إلغاء التكرار واستراتيجيات التخزين.

إعادة محاولة الطلبات بأمان في واجهات B2B 2026 — نمط التحقق من الحالة قبل إعادة المحاولة

مفاتيح Idempotency هي التقنية التي تجعل أي طلب POST في واجهة B2B آمناً لإعادة المحاولة. من دونها، يتحوّل كل انتهاء مهلة شبكية على العميل إلى سؤال "هل أُنشئ الطلب أم لا؟" — وفي 30% من الحالات تكون الإجابة "كلاهما". واجهة FoxReload لا تدعم ترويسة Idempotency-Key. تشرح هذه المقالة النمط البديل الصحيح — التحقق من الحالة قبل إعادة المحاولة — إلى جانب استراتيجيات إلغاء التكرار من جانب العميل.

1. لماذا لا تملك واجهة FoxReload مفاتيح Idempotency

نقطة نهاية الطلبات في FoxReload عند POST /api/orders لا تقبل ترويسة Idempotency-Key. كل استدعاء يُنشئ طلباً جديداً. هذا يعني:

  • إعادة محاولة واحدة بعد خلل شبكي قد تُنشئ طلبين
  • يُخصم رصيدك مرتين
  • تُسلَّم مجموعتان من الأكواد

الحل بالكامل على جانب العميل.

2. نمط التحقق من الحالة قبل إعادة المحاولة

قبل إعادة محاولة POST /api/orders الذي أرجع انتهاء مهلة أو خطأً غامضاً، تحقّق مما إذا كان الطلب موجوداً بالفعل:

async function safeCreateOrder(
  items: OrderItem[],
  apiKey: string,
): Promise<Order> {
  // Step 1: Record intent in your own DB before calling the API
  const clientRef = randomUUID();
  await db.pendingOrders.insert({ clientRef, items, createdAt: new Date() });

  try {
    const res = await fetch('https://public-api.foxreload.com/api/orders', {
      method: 'POST',
      headers: { 'X-API-Key': apiKey, 'Content-Type': 'application/json' },
      body: JSON.stringify({ items }),
      signal: AbortSignal.timeout(30_000),
    });
    if (!res.ok) throw new Error(`HTTP ${res.status}`);
    const order = await res.json();
    await db.pendingOrders.update(clientRef, { orderId: order.id });
    return order;

  } catch (err) {
    // Step 2: On failure, check if the order was created
    const existing = await db.pendingOrders.findByRef(clientRef);
    if (existing?.orderId) {
      // Order was created; poll its status
      return pollOrder(existing.orderId, apiKey);
    }

    // Step 3: Check recent FoxReload orders for a match
    const recent = await fetchRecentOrders(apiKey); // GET /api/orders?limit=10
    const match = findMatchingOrder(recent, items);
    if (match) {
      await db.pendingOrders.update(clientRef, { orderId: match.id });
      return match;
    }

    // Step 4: Only retry if confirmed not created
    throw err; // caller can retry after delay
  }
}

3. تخزين إلغاء التكرار من جانب العميل

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

التخزين الكمون TTL التكلفة / مليون سجل
Postgres UNIQUE 5–8ms $0.10
Redis SETNX <2ms 24h $0.40
DynamoDB ConditionExpression 8–12ms 24h $1.25
Memcached CAS <1ms 24h $0.30

بالنسبة لمعظم التكاملات، يكون Postgres مع قيد UNIQUE على client_ref كافياً ويمنحك مساراً تدقيقياً دائماً.

4. مقارنة مناهج إلغاء التكرار

المنهج يمنع التكرار المسار التدقيقي كتابة DB إضافية؟
Idempotency-Key (غير متاح في FoxReload) نعم على الخادم لا
التحقق من الحالة قبل إعادة المحاولة نعم قاعدة بياناتك نعم
بوابة SETNX من جانب العميل نعم (ضمن TTL) Redis نعم
إعادة محاولة عمياء (لا تفعل ذلك أبداً) لا لا لا

يضيف منهج التحقق من الحالة كتابة DB واحدة لكل محاولة طلب. عند أي حجم أقل من ملايين الطلبات يومياً، يكون هذا مقبولاً تماماً.

5. مقارنة خلفيات تخزين إلغاء التكرار

// Postgres approach (recommended for audit)
await db.query(`
  INSERT INTO order_intents (client_ref, items_hash, created_at)
  VALUES ($1, $2, NOW())
  ON CONFLICT (client_ref) DO NOTHING
`, [clientRef, hashItems(items)]);

6. ماذا لو واجهت تسابقاً بين طلبين متزامنين؟

إذا حاول عاملان إنشاء الطلب نفسه في آنٍ واحد، فإن قيد UNIQUE في قاعدة البيانات على client_ref سيرفض أحدهما على مستوى DB قبل أن يصل أيٌّ منهما إلى FoxReload. هذا هو الحل الأنظف:

CREATE TABLE order_intents (
  client_ref UUID PRIMARY KEY,
  order_id UUID,
  items_hash TEXT NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  resolved_at TIMESTAMPTZ
);

يتابع المُدخِل الأول وحده استدعاء الواجهة. أما الثاني فيقرأ السجل الموجود ويراقب النتيجة.

CTA

واجهة FoxReload لا تملك مفاتيح Idempotency — طبّق التحقق من الحالة قبل إعادة المحاولة ومخزن client_ref في نظامك الخاص. مرجع واجهة الطلبات الكامل متاح بعد التهيئة — اطلب الوصول.

الأسئلة الشائعة

هل تدعم FoxReload ترويسة Idempotency-Key؟
لا. FoxReload لا تملك ترويسة Idempotency-Key. إذا أرسلت POST /api/orders مرتين فستُنشئ طلبين منفصلين وسيُخصم رصيدك مرتين. النمط الصحيح هو التحقق من حالة الطلب قبل إعادة المحاولة.
ماذا أفعل إذا انتهت مهلة POST /api/orders؟
استدعِ GET /api/orders?limit=10 وابحث عن طلب يطابق العنصر المتوقع وطابع الوقت. إن وُجد، استخدم هذا الطلب — لا تُنشئ طلباً جديداً. إن لم يُوجد، فمن الآمن إعادة محاولة POST.
كيف أُطبّق إلغاء التكرار من جانب العميل؟
قبل استدعاء POST /api/orders، اكتب سجلاً معلقاً في قاعدة بياناتك بـ client_ref فريد. عند أي فشل، استعلم عن قاعدة بياناتك بحثاً عن client_ref. إن كان order_id مرتبطاً به، تابع حالته؛ وإلا فأعِد محاولة POST.
ما خطر الطلب المزدوج؟
كل طلب يخصم من رصيد FoxReload لديك ويُسلّم الأكواد للعملاء. الطلب المكرر يعني إنفاقاً مزدوجاً وتسليماً مزدوجاً. من دون مفتاح Idempotency، يبقى التحقق من الحالة قبل إعادة المحاولة هو الحماية الوحيدة.
احصل على وصول واجهة FoxReload

مقالات ذات صلة