التحقق من الردود

تستخدم حزمة SDK؟

تتحقق حزم SDK منذ الإصدار 2.0.1 من الردود الموقَّعة قبل أن تراها، وتتخلّص من أي ردّ يفشل. هذه الصفحة لكتابة عميلك الخاص.

توقّع أنيس الردود التي ينقل فيها الردّ مالًا، أو يسلّم البطاقات، أو يُثبت مفتاحك — وفي هذه الاستدعاءات كل ردّ موقَّع، نجاحًا كان أم رفضًا. وفي هذه الاستدعاءات يشترط العميل وجود التوقيع، ويتخلّص من أي ردّ لا يستطيع التحقق منه: لا يسجّله ثم يمضي، ولا يتصرف بناءً عليه. والردّ بلا توقيع ردّ لا يمكن التحقق منه — فشل، لا ردّ يُقبل. لا تكتب أبدًا «تحقّق إن وُجد توقيع»: فالمزوِّر يحذفه ببساطة. وردّ طلب الشراء الذي لا يمكن التحقق منه يُعامَل كأنه لم يصل قط — فالنتيجة مجهولة، ويُستأنف طلب الشراء بمعرّف العملية نفسه.

أي الردود موقَّعة

القرار يخصّ الاستدعاء الذي أجريته، لا ما يحمله الردّ.

توقّع أنيس كل ردّ — النجاح وكل رفض السبب
إضافة عنوان أو إزالته — بيئة الاختبار فقط — نقاط نهاية للاختبار، غير متاحة في الإنتاج يؤكد الردّ تغيير شبكة الوصول
تعليق تطبيقك وإلغاء مفتاح الردّ يؤكد إيقاف الوصول
تقديم طلب شراء يتحرك المال
قراءة طلب شراء الردّ هو نتيجة الطلب
إنشاء شحن أو قراءته يصف الردّ الشحن ورموزه أو إعادة المال
إنشاء الشحن المباشر أو قراءته أو تصحيحه يصف الردّ الدفع أو التسليم، أو يقبل تصحيح المستلم بردّ 202 موقّع مع Location وإقرار المعالجة ذي الحقول الثلاثة، دون بيانات الشحن المباشر أو طلب الشراء
تسجيل عنوان الإشعارات أو اختباره أو إعادة الإرسال يؤكد الردّ تغييرًا في إدارة التسليم
كشف بطاقة وكشف فاتورة الردّ يسلّم رموز البطاقات
قراءة دعوة وإرسال مفتاح عام وإثبات حيازة المفتاح وقراءة حالة التسجيل الردّ يُثبت مفتاحك
فحص توقيعك هذا الاستدعاء موجود لاختبار التوقيع

أما ردود كل استدعاء آخر فهي غير موقَّعة، نجاحًا كانت أم رفضًا: قراءة ملفّك، وقائمة المحافظ، وقراءة محفظة، واستدعاءات الكتالوج الخمسة (الفئات والفئات الفرعية وفئة فرعية وبطاقاتها وبطاقة واحدة)، وقائمة البطاقات المملوكة وقراءة بطاقة مملوكة. لا تحمل Signature ولا Signature-Input، وتحمل Content-Digest وX-Request-Id. ولا شيء تتحقق منه فيها — فحماية TLS تكفيها — فلا تشترط توقيعًا هناك. ومستند المفاتيح العامة غير موقَّع أيضًا.

ردود باقات العدادات وقوائم عملياتها ومنتجات الشحن المباشر ومواقعها وعروض أسعارها وقوائم عملياته وقراءة عنوان الإشعارات وقائمة أحداثها غير موقّعة. تظل استدعاءاتها موقّعة. وللإشعارات الواردة ملف تحقق خاص بها، موضح في التحقق من إشعارات Webhook.

استدعاءاتك أنت لا تتغيّر: كل استدعاء ما زلت توقّعه بنفسك، كما في توقيع الاستدعاءات.

بقية هذه الصفحة عن الردود الموقَّعة.

ما الذي توقّعه أنيس

تُوقَّع الردود باستخدام ECDSA P-256 وSHA-256، بالتسمية sig1، مع المعاملات created وkeyid وalg وtag="anis-response-v2" — ودون expires. الأجزاء الموقّعة، بهذا الترتيب:

# الجزء يكون موجودًا عندما
1 "@status" دائمًا
2 "content-digest" دائمًا
3 "x-request-id" دائمًا
4 "signature-input";req تكون قد وقّعت الاستدعاء (غائب في ردود تسجيل المفتاح) — وقيمته هي Signature-Input الخاص بك أنت
5 "signature";req تكون قد وقّعت الاستدعاء — قيمة ترويسة Signature الخاصة بالاستدعاء كما وصلت بالضبط (sig1=:…:)؛ غائبة في الردود العامة وردود تسجيل المفتاح
6 "location" يحمل الردّ Location
7 "retry-after" يحمل الردّ Retry-After
8 "idempotency-replayed" يحمل الردّ Idempotency-Replayed: true
9 "cache-control" يحمل الردّ Cache-Control: no-store

هذا المثال توضيحي ويستخدم قيمًا بديلة لمعرّف المفتاح وتوقيع الاستدعاء. يُبنى نصّ التوقيع كما يُبنى في الاستدعاء: سطر واحد لكل جزء، ثم "@signature-params" دون محرف سطر جديد بعده.

"@status": 200
"content-digest": sha-256=:epGQsVay09pY/GXv6MpAjMbsZ7VvobF1nAdylVo/mMk=:
"x-request-id": 01J9R2K8T4V6XQ0M3B7C5D9E1F
"signature-input";req: sig1=("@method" "@authority" "@path" "@query" "x-anis-date");created=1789804800;expires=1789804860;keyid="…";alg="ecdsa-p256-sha256"
"signature";req: sig1=:<request signature bytes in base64>:
"@signature-params": ("@status" "content-digest" "x-request-id" "signature-input";req "signature";req);created=1789804800;keyid="partner-signing/v1-active";alg="ecdsa-p256-sha256";tag="anis-response-v2"

يقع ;req خارج علامات الاقتباس، بالشكل نفسه في سطره وفي @signature-params.

خطوات الفحص، بالترتيب

  1. وجود Signature وSignature-Input كليهما — في استدعاء موقَّع الردّ يكون دائمًا؛ والتسمية هي sig1؛ وalg هو ecdsa-p256-sha256.
  2. يطابق المحتوى ترويسة Content-Digest الخاصة به — ويُفحص ذلك قبل التوقيع. التوقيع يغطي ترويسة البصمة لا المحتوى، لذا فالعميل الذي يفحص التوقيع أولًا يقبل محتوى مستبدَلًا كلما أُعيدت كتابة البصمة هي الأخرى.
  3. أعد بناء قائمة الأجزاء الموقّعة مما يحمله الردّ (الجدول أعلاه)، واشترط أن تذكر Signature-Input في الردّ تلك القائمة بالضبط. لا تثق أبدًا بالقائمة التي يعلنها الردّ: فالردّ الموقّع توقيعًا صحيحًا على قائمة أقصر يترك محتواه دون حماية.
  4. تقع قيمة created ضمن 60 ثانية من ساعتك — فالردّ ليس له expires، ودون هذا الحدّ يمكن إعادة إرسال ردّ ملتقَط إليك إلى ما لا نهاية.
  5. يسمّي keyid مفتاحًا من المفاتيح المنشورة لأنيس (أدناه). ارفض kid المدرج في revoked[] بالسبب key_compromised مهما كانت التواريخ، ودون جلب المستند مجددًا. ارفض مفتاحًا بحالة retired إذا كانت created > retiredAt بالسبب key_retired، وأي مفتاح — active أو next أو retired — إذا كانت created < notBefore بالسبب key_not_yet_valid.
  6. التوقيع 64 بايتًا، ويجتاز التحقق على نصّ التوقيع المُعاد بناؤه.

أي شيء غير ذلك: تخلّص من الردّ. وتغطي أمثلة اختبار الردود كل فحص من هذه الفحوص.

غياب tag="anis-response-v2" أو اختلافه يُرفض بالسبب profile_unexpected؛ واختلاف قائمة الأجزاء أو ترتيبها يُرفض بالسبب covered_components_mismatch.

المفاتيح العامة لأنيس

GET /.well-known/partner-signing-keys.json — المسار الوحيد الذي لا يحتاج إلى توقيع، وردّه نفسه غير موقَّع — ينشر كل مفتاح قد يوقّع ردًّا، بما في ذلك المفتاح التالي قبل تدوير المفاتيح، والمفتاح السابق بعده. لكلٍّ منها kid، وهو ما يسمّيه keyid في الردّ. تعامل مع kid على أنه اسم مُبهم (opaque).

يحمل كل مفتاح في keys[] حالة status (active أو next أو retired) ووقت notBefore. يحمل المفتاح المُنهى أيضًا retiredAt: وقت توقفه عن التوقيع، وهو الأسبق بين انتهاء صلاحيته ووقت notBefore لخلفه. يبقى مدرجًا ما دام الوقت الحالي قبل retiredAt مضافًا إليه 90 يومًا — طوال المدة التي يمكن فيها الاعتراض على ردّ وقّعه.

المفتاح المخترق لا يظهر في keys[] ولا يوقّع. يظهر في revoked[] مع kid وcompromisedAt لمدة 90 يومًا بعد وقت الاختراق. تعلن أنيس عن الاختراق خلال 24 ساعة بالبريد الإلكتروني وفي المستند. انظر مسودة الأدلة والنزاعات.

يحمل كل مفتاح purpose بالقيمة answer أو webhook. الحقل اختياري في المخطط للتوافق، لكن أنيس ترسله دائمًا. استخدم مفاتيح answer لردود API ومفاتيح webhook للإشعارات الواردة. للإشعار مفتاح وملف توقيع منفصلان؛ فلا تقبل المفتاح لمجرد ظهوره في القائمة.

  • احتفظ بالمستند لمدة لا تتجاوز 5 دقائق. اجلبه مجددًا بعد ذلك، حتى يتوقف الوثوق بمفتاح تسحبه أنيس خلال دقائق. تحسب الذاكرة المؤقتة المشتركة بين العمليات الدقائق الخمس من وقت جلب المستند أول مرة، لا من وقت نسخه إليها. ومع تحديث أنيس لقائمتها، يتوقف العميل الذي يتبع هذه القواعد عن الوثوق بمفتاح مسحوب خلال 7 دقائق تقريبًا.
  • قيمة kid مجهولة: اجلب المستند مجددًا — مرة واحدة على الأكثر كل 30 ثانية لكل عنوان أنيس يستخدمه عميلك (وتُحسب محاولة الجلب الفاشلة). تتشارك الفحوص المتزامنة عملية جلب واحدة. خلال هذه الثواني الثلاثين يُرفض الردّ الذي يسمّي مفتاحًا مجهولًا بالسبب unknown_key دون جلب المستند. ولا تكون قيمة kid المدرجة في revoked[] سببًا للجلب أبدًا.
  • ارفض المستند بأكمله إذا حمل أيُّ مفتاح عنصرًا خاصًا (d) — لا ذلك المفتاح وحده. المستند الذي يُسرّب مفتاحًا خاصًا لا يُوثق به إطلاقًا.
  • كل إحداثية طولها 32 بايتًا بالضبط. ارفض أي مفتاح بشكل مختلف.

يُجيب هذا المسار بالحالة HTTP ‏503 والرمز dependency_unavailable حين يتعذّر قراءة قائمة المفاتيح أو لم تُحدِّثها أنيس منذ 9 دقائق. احتفظ بنسختك المؤقتة حتى انتهاء صلاحيتها الأصلية — 5 دقائق على الأكثر من وقت جلبها — وأعِد المحاولة مع زيادة الانتظار تدريجيًا. لا تمدّد محاولة الجلب الفاشلة تلك الصلاحية؛ وبعد انتهائها لا يمكنك التحقق من الردود الموقَّعة حتى تجلب مستندًا حديثًا.

الردّ الوحيد غير الموقَّع في استدعاء موقَّع

إذا تعذّر التوقيع لدى أنيس نفسها، فإن الاستدعاء الموقَّع يُردّ عليه بـ 503 دون توقيع. هو ردّ في استدعاء موقَّع لا تستطيع التحقق منه، فتعامل معه كأي ردّ كهذا: أعد محاولة استدعاء القراءة، واستأنف طلب الشراء بمعرّف العملية نفسه. (أما الاستدعاءات التي لا توقَّع ردودها أبدًا فلا تعتمد على توقيع أنيس، ولا يمسّها ذلك.)

إذا لم يكن لدى أنيس مفتاح يُسمح لها بالتوقيع به، فإن كل استدعاء موقَّع يُجيب بالحالة 503 دون توقيع. وإذا تعذّر عليها قراءة قائمة مفاتيحها منذ 9 دقائق، يُجيب مستند المفاتيح بالحالة 503 أيضًا. وتستمر الاستدعاءات التي لا توقَّع ردودها في العمل طوال ذلك.

عرض العناوين المسموح بها: بيئة الاختبار فقط — نقاط نهاية للاختبار، غير متاحة في الإنتاج. ردّ القراءة غير موقّع؛ ويجب التحقق من توقيع ردود الإضافة والإزالة، بما فيها الرفض. هذه المسارات الثلاثة مستبعدة دائمًا من حزم SDK.

إذا تعذّر توفير مفتاح الإشعارات، تستمر وثيقة المفاتيح في نشر مفاتيح الردود وتحذف مفتاح الإشعارات وحده. يستمر التحقق من ردود API؛ وارفض الإشعارات حتى تتمكن من جلب مفتاح إشعارات صالح.