توقيع الاستدعاءات
هل تستخدم حزمة SDK؟
حزم SDK تقوم بكل هذا نيابةً عنك. هذه الصفحة لمن يكتب عميله الخاص، أو لفهم سبب رفضٍ ما.
كل استدعاء، باستثناء تسجيل المفتاح والمفاتيح العامة لأنيس، يُوقَّع باستخدام HTTP Message Signatures (RFC 9421)،
بخوارزمية ECDSA P-256 مع SHA-256. أنت توقّع نصًّا محددًا بدقة — نصّ التوقيع — يُبنى من أجزاء الاستدعاء.
تعيد أنيس بناء النصّ نفسه مما استلمته، وتتحقق من توقيعك مقابله. إذا اختلف بايت واحد يُرفض الاستدعاء بالرمز
invalid_credentials، دون أي إشارة إلى البايت المختلف، وذلك عن قصد.
الأنواع الثلاثة للاستدعاءات الموقّعة
المسار هو الذي يحدد الأجزاء التي توقّعها — راجع صفحة كل مسار في مرجع API.
| النوع | يستخدمه | الأجزاء الموقّعة، بهذا الترتيب تحديدًا |
|---|---|---|
| قراءة | كل قراءة GET مصادَق عليها |
@method @authority @path @query x-anis-date |
| تغيير | الكشف والتشخيص وتغييرات الوصول والشبكات وPATCH لمستلم الشحن المباشر وتغييرات إدارة الإشعارات |
@method @authority @path @query content-digest nonce x-anis-date |
| طلب شراء | إنشاء طلب بطاقات أو شحن عداد أو الشحن المباشر | @method @authority @path @query content-digest nonce idempotency-key x-anis-date |
يأتي idempotency-key قبل x-anis-date، لا بعده.
الترويسات التي ترسلها
| الترويسة | في | القيمة |
|---|---|---|
X-Anis-Date |
كل استدعاء موقّع | الوقت بصيغة ISO-8601 بتوقيت UTC: 2026-09-19T08:00:00Z |
Content-Digest |
استدعاءات التغيير وطلبات الشراء | sha-256=:<base64 of SHA-256 of the exact body bytes>: |
Nonce |
استدعاءات التغيير وطلبات الشراء | قيمة عشوائية جديدة لكل استدعاء (تستخدم حزم SDK 128 بتًا عشوائيًا بترميز base64url) |
Idempotency-Key |
المشتريات | معرّف العملية الخاص بك: UUID بأحرف صغيرة مع الشرطات |
Signature-Input |
كل استدعاء موقّع | المعاملات المبيّنة أدناه |
Signature |
كل استدعاء موقّع | sig1=:<base64 of the 64-byte signature>: |
المعاملات
sig1=("@method" "@authority" "@path" "@query" "x-anis-date");created=1789804800;expires=1789804860;keyid="3f2a9c14-8d6e-4b21-9f07-5c8ab2d61e43";alg="ecdsa-p256-sha256"
- التسمية (label) هي دائمًا
sig1، في كلٍّ منSignature-InputوSignature. createdوexpiresبالثواني وفق توقيت Unix. لا تتحقق أنيس من المدة بينهما: فهي ترفض قيمةcreatedالتي تتقدّم على ساعتها بأكثر من 30 ثانية تقريبًا أو تتأخر عنها بأكثر من 5 دقائق، وترفضexpiresالذي مضى وقته. اجعلexpiresيساويcreatedمضافًا إليه 60 ثانية أو أقل (كما تفعل حزم SDK) — انظر قسم «الساعة» أدناه.keyidهو معرّف المفتاح الذي حصلت عليه عند تسجيل المفتاح: UUID بأحرف صغيرة مع الشرطات.algهو دائمًاecdsa-p256-sha256. لا يوجد ما يُتفاوض عليه.- في استدعاءات التغيير وطلبات الشراء، أضف
;nonce="<the Nonce header>"في النهاية، ويجب أن يساوي قيمة ترويسةNonce. في استدعاء القراءة يجب ألا يكون موجودًا. أي عدم تطابق يُرفض بالرمزmalformed_signed_requestقبل أن يُتحقق من التوقيع أصلًا.
لإخفاقات التوقيع أحد ردّين، عن قصد. الاستدعاء غير سليم البنية — ترويسة توقيع مفقودة أو لا يمكن قراءتها، أو أجزاء
موقّعة ليست ما يحتاجه المسار أو ليست بترتيبه، أو بصمة محتوى لا يمكن قراءتها أو لا تصف المحتوى المُرسَل — يُرفض
بالرمز malformed_signed_request (400)، قبل أن تنظر أنيس في أي مفتاح. أما
الاستدعاء السليم البنية الذي لا يصحّ توقيعه — نصّ توقيع خاطئ، أو توقيع بصيغة DER، أو وقت قديم، أو مفتاح غير معروف
أو غير نشط — فيكون ردّه invalid_credentials (401).
نصّ التوقيع
سطر واحد لكل جزء موقّع بالشكل "name": value، وينتهي كل سطر بمحرف سطر جديد — ثم سطر أخير لـ
"@signature-params"، دون محرف سطر جديد بعده. مثال لطلب شراء:
"@method": POST
"@authority": partners.anis.ly
"@path": /v1/wallets/2f1c8a94-6d37-4e52-b8a1-0c9e5d3f7b26/orders
"@query": ?
"content-digest": sha-256=:3AuIAnFFepkxwk6edx9OofFKHz5L8cSdZNVmztycemo=:
"nonce": b2F1dGgtbm9uY2UtMDAx
"idempotency-key": 9b2e4f17-3c6a-4d58-b0e1-7a5c8d2f6b34
"x-anis-date": 2026-09-19T08:00:00Z
"@signature-params": ("@method" "@authority" "@path" "@query" "content-digest" "nonce" "idempotency-key" "x-anis-date");created=1789804800;expires=1789804860;keyid="3f2a9c14-8d6e-4b21-9f07-5c8ab2d61e43";alg="ecdsa-p256-sha256";nonce="b2F1dGgtbm9uY2UtMDAx"
| الجزء | القيمة |
|---|---|
@method |
الطريقة (method) بأحرف كبيرة |
@authority |
اسم المضيف — مع المنفذ إن لم يكن المنفذ الافتراضي للبروتوكول — بأحرف صغيرة |
@path |
المسار تمامًا كما أُرسل. كل مسار يتكوّن من كلمات ثابتة ومعرّفات UUID، لذا لا يحتاج أبدًا إلى ترميز النسبة المئوية (percent-encoding) |
@query |
? متبوعة بسلسلة الاستعلام تمامًا كما أُرسلت. عند غياب الاستعلام يُوقَّع ? |
content-digest, nonce, idempotency-key, x-anis-date |
قيمة الترويسة تمامًا كما أُرسلت |
وقّع بايتات نصّ التوقيع بترميز UTF-8 باستخدام ECDSA P-256 وSHA-256. أرسل التوقيع بصيغته ذات 64 بايتًا — r ثم
s، كلٌّ منهما 32 بايتًا — وليس بصيغة DER أبدًا.
المزالق
- عند غياب الاستعلام يُوقَّع
?، لا سلسلة فارغة. - يُوقَّع الاستعلام تمامًا كما أُرسل — دون إعادة ترتيب، أو إعادة ترميز، أو إعادة بناء من القيم بعد تحليلها. مؤشر التصفح (paging cursor) يُعاد تمامًا كما استلمته.
- اسم المضيف بأحرف صغيرة. المضيف المكتوب بأحرف كبيرة وصغيرة مختلطة يُنتج نصًّا موقّعًا لا تعيد أنيس بناءه أبدًا.
- كل استدعاء تغيير يحسب البصمة لما يرسله بالضبط. الكشف لا يرسل محتوى على الإطلاق — ولا حتى
{}— لذا فبصمته هي بصمة صفر بايت:sha-256=:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=:. أما الفحص الذاتي للتوقيع فيرسل{}بالضبط:sha-256=:RBNvo1WzZ4oRRq0W9+hknpT7T8If536DEMBg9hyq/4o=:. وطلب الشراء يحسب البصمة لمحتواه بصيغة JSON — احسب البصمة بعد أن يصبح المحتوى نهائيًا، وأرسل تلك البايتات نفسها بالضبط. - التوقيع 64 بايتًا، وليس DER أبدًا. تُنتج .NET وWebCrypto الصيغة ذات 64 بايتًا. أما
openssl_signفي PHP ومكتبةcryptographyفي Python فتُنتجان DER وتحتاجان إلى تحويل؛ والتوقيع الذي يتراوح طوله بين 70 و72 بايتًا هو DER.
الساعة
تقبل أنيس التوقيع الذي لا تتجاوز قيمة created فيه نحو 30 ثانية تقدّمًا على ساعتها أو 5 دقائق تأخّرًا عنها، والذي لم
يحن بعدُ وقت expires فيه. تحمل ردود أنيس الموقَّعة وقتها الخاص، ولا يقبل العميل الردّ الموقَّع إلا إذا كان ضمن 60 ثانية من ساعته هو
(انظر التحقق من الردود).
لهذا ينبغي ألا يتجاوز عمر التوقيع 60 ثانية: مع نافذة أطول، قد تتسبب ساعة خادم متأخرة بضع دقائق في قبول طلب شراء وإتمامه، ثم في التخلّص من الردّ الذي يحمل رموز البطاقات باعتباره قديمًا جدًا. أبقِ ساعة خادمك متزامنة.
عندما لا يجتاز التوقيع التحقق
استدعِ فحص توقيعك. يُبلغك بالطريقة (method) والعنوان والمسار والاستعلام التي بنت أنيس عليها نصّ التوقيع، وبالمفتاح الذي وجدته. قارنها بنصّ التوقيع لديك، سطرًا بسطر.
وقبل أن يستدعي عميلك أنيس أصلًا، اختبره على أمثلة اختبار التوقيع: ففيها نصّ التوقيع الدقيق لكل نوع من الاستدعاءات الموقّعة.