استطلاع حالة الطلب وطبقة الإشعارات للسلع الرقمية
الإجابة المختصرة
لا ترسل FoxReload أي webhooks. لمعرفة متى يكتمل الطلب، استطلع GET /api/orders/{order_id} حتى تكون status إما "completed" أو "cancelled" أو "failed". عند الاكتمال، يحتوي items[].externalData على الأكواد المُسلّمة. للمتاجر عالية الحجم التي تريد سلوكًا قائمًا على الأحداث، ابنِ عامل استطلاع في الخلفية يحوّل تغيّرات الحالة إلى أحداث داخلية.
مهم — لا تدعم FoxReload الـ webhooks، ولا ترويسة
X-FoxReload-Signature، ولا أحداث استدعاءorder.*. لا يوجد بيئة اختبار (sandbox) — استخدمisMock: trueعند إنشاء الطلب للطلبات التجريبية. لا توجد مفاتيح idempotency — إذا ترك خطأ شبكي حالة طلب غير مؤكّدة، فتحقق منGET /api/orders/{id}قبل إنشاء طلب جديد لتجنّب الشراء المزدوج.
الخلاصة الأساسية — الاستطلاع هو النمط الصحيح لـ FoxReload. معظم الطلبات تكتمل بشكل متزامن خلال ثوانٍ. أما الحالات الأبطأ، فإن حلقة استطلاع في الخلفية مع تراجع أُسّي تمنحك معالجة غير متزامنة موثوقة دون webhooks.
لمن هذا الدليل
- المطورون الذين يدمجون FoxReload API ويحتاجون إلى التعامل مع تنفيذ الطلبات غير المتزامن
- مشغّلو المتاجر الذين يبنون خطوط تسليم أكواد مؤتمتة
- المهندسون الذين يريدون تسليمًا قائمًا على الأحداث لكنهم يعملون مع API قائم على الاستطلاع
كيف يعمل تنفيذ الطلبات في FoxReload
1. POST /api/orders/
Body: {"items": [{"itemId": "product_01k...", "quantity": 1}]}
→ Response: {"id": "order_01k...", "status": "processing", ...}
2. Poll GET /api/orders/{order_id}
→ {"id": "order_01k...", "status": "processing", ...} (not yet)
→ {"id": "order_01k...", "status": "completed",
"items": [{"externalData": ["XXXXX-YYYYY-ZZZZZ"]}]} (done)
عندما يكون status == "completed"، اقرأ items[i].externalData — وهي مصفوفة من الأكواد المُسلّمة أو تأكيدات الشحن. إذا واجه عنصر خطأً، فتحقق من items[i].error.
الاستطلاع مقابل الـ Webhooks
| العامل | الاستطلاع (FoxReload) | الـ Webhooks (غير متاح) |
|---|---|---|
| مدعوم من FoxReload | نعم | لا |
| زمن الاستجابة | يعتمد على فترة الاستطلاع (عادة <3 ثوانٍ) | غير متاح |
| التنفيذ | حلقة بسيطة | غير قابل للتطبيق |
| معالجة الحجم العالي | يُوصى بعامل في الخلفية | غير متاح |
حالات الطلب النهائية
| الحالة | المعنى | الإجراء |
|---|---|---|
completed |
تم تنفيذ الطلب؛ الأكواد في items[].externalData |
سلّم الأكواد للعميل |
cancelled |
أُلغي الطلب قبل التنفيذ | استرد للعميل؛ لا تُسلّم |
failed |
فشل التنفيذ | نبّه فريق العمليات؛ استرد إن تم أخذ الدفعة |
processing / paid / active |
لا يزال قيد التقدم | واصل الاستطلاع |
تنفيذ استطلاع أساسي
import time
import requests
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://public-api.foxreload.com"
HEADERS = {"X-API-Key": API_KEY, "Content-Type": "application/json"}
def poll_order(order_id: str, max_attempts: int = 30) -> dict:
terminal = {"completed", "cancelled", "failed"}
delay = 1.0
for attempt in range(max_attempts):
resp = requests.get(f"{BASE_URL}/api/orders/{order_id}", headers=HEADERS)
resp.raise_for_status()
order = resp.json()
if order["status"] in terminal:
return order
time.sleep(delay)
delay = min(delay * 1.5, 15) # exponential backoff, cap at 15s
raise TimeoutError(f"Order {order_id} did not reach terminal status")
def get_codes(order: dict) -> list[str]:
codes = []
for item in order.get("items", []):
codes.extend(item.get("externalData", []))
return codes
# Usage
order = poll_order("order_01k...")
if order["status"] == "completed":
codes = get_codes(order)
deliver_to_customer(codes)
elif order["status"] == "failed":
alert_ops(order)
الحجم العالي — عامل استطلاع في الخلفية
للمتاجر التي تعالج طلبات كثيرة في الدقيقة، شغّل عاملًا مخصصًا في الخلفية بدلًا من الاستطلاع المعطِّل داخل الطلب:
Order creation API call
→ Store order_id in DB with status = 'pending'
→ Return response to customer ("Order placed, processing")
Background worker (runs every 2–5 seconds):
→ Query DB: SELECT * FROM orders WHERE status = 'pending'
→ For each: GET /api/orders/{order_id}
→ If status changed:
- Update DB
- If completed: deliver codes to customer (email / bot / order page)
- If failed: alert ops
هذا يفصل إنشاء الطلب عن الاستطلاع ويتوسّع بنظافة. عاملك هو طبقة الإشعارات — لا تشارك FoxReload في دفع الأحداث.
بناء طبقة الإشعارات الداخلية الخاصة بك
إذا أردت سلوكًا قائمًا على الأحداث داخل نظامك الخاص، فأطلق أحداثًا داخلية من عامل الاستطلاع:
# After polling detects a status change:
if new_status == "completed":
internal_queue.publish("order.completed", {
"order_id": order_id,
"codes": get_codes(order),
"customer_id": customer_id,
})
# Separate consumer:
@queue.consumer("order.completed")
def on_order_completed(event):
send_code_to_customer(event["customer_id"], event["codes"])
هذا بالكامل ضمن بنيتك التحتية الخاصة. لا تشارك FoxReload في تدفّق الأحداث هذا.
تجنّب الطلبات المزدوجة (لا مفاتيح Idempotency)
لا تدعم FoxReload مفاتيح idempotency. إذا جعل خطأ شبكي من غير الواضح ما إذا أُنشئ الطلب، فـ تحقق دائمًا قبل إنشاء طلب جديد:
def safe_create_order(item_id: str, qty: int, your_ref: str) -> dict:
# 1. Check if an order with your internal reference already exists
existing = find_order_by_reference(your_ref) # your DB lookup
if existing:
return poll_order(existing["foxreload_order_id"])
# 2. Create new order
resp = requests.post(
f"{BASE_URL}/api/orders/",
headers=HEADERS,
json={"items": [{"itemId": item_id, "quantity": qty}]}
)
resp.raise_for_status()
order = resp.json()
save_order_reference(your_ref, order["id"]) # persist before polling
return poll_order(order["id"])
خزّن مرجعك الداخلي ومعرّف طلب FoxReload معًا قبل الاستطلاع.
التعامل مع الطلبات العالقة
إذا بقي الطلب في processing بعد اتفاقية مستوى الخدمة لديك:
- واصل الاستطلاع مع تراجع — بعض عمليات التنفيذ بطيئة بشكل مشروع
- بعد عتبة اتفاقية مستوى الخدمة لديك (مثلًا 10 دقائق)، نبّه فريق العمليات مع معرّف الطلب
- لا تُلغِ وتُعِد الإنشاء تلقائيًا — تحقق مع دعم FoxReload أولًا لتجنّب الشراء المزدوج
قائمة التحقق
- POST /api/orders/ مع مصادقة
X-API-Keyونوع محتوىapplication/json - خزّن معرّف الطلب فور الإنشاء
- استطلع GET /api/orders/{order_id} مع تراجع أُسّي
- تعامل مع كل الحالات النهائية — completed و cancelled و failed
- استخرج الأكواد من items[].externalData عند الاكتمال
- تحقق من items[].error بحثًا عن إخفاقات كل عنصر في الطلبات المكتملة
- قبل إعادة الإنشاء عند خطأ شبكي، تحقق مما إذا كان الطلب موجودًا بالفعل
- للحجم العالي — عامل استطلاع في الخلفية مع إطلاق أحداث داخلية
- نبّه عند الطلبات العالقة في processing بعد اتفاقية مستوى الخدمة
- اختبر بطلبات isMock: true قبل الانطلاق الفعلي
