الوصول (الوضع B) — دليل تكامل الشريك
سلّم هذا الملف لأي تطبيق طرف ثالث / تطبيق شقيق يفتح المحتوى عندما يدفع المشتري على الوصول في الكنز.
الوصول = المشتري يدفع على الكنز. الشريك يفعّل منتجه.
ليس الوضع A («ادفع بالكنز» على موقعك) — راجع ادفع بالكنز.
خطوات البائع (المنتج): إنشاء عرض وصول من لوحة التحكم — إدراج الوصول والشراكة.
ما تحتاجه من قائمة البائع
| الحقل | الغرض |
|---|---|
external_ref | رمز الخطة / SKU لديك (يُرسل في الـ webhook والتحقق) |
partner_api_secret (aks_…) | توقيع HMAC للـ webhook + رأس X-Elknz-Access-Secret |
webhook_url | المسار الأساسي للتفعيل |
claim_url (اختياري) | يفتحه المشتري في تبويب جديد بعد الدفع مع ?claim=… (لا يغادر صفحة الكنز بالكامل) |
البائع يضبطها على عرض الوصول (لوحة التحكم). يمكن تدوير السر عبر واجهة البائع عند الحاجة.
التكامل الموصى به (Webhook أولاً)
Buyer pays on elknz.com/access/…
→ ELKNZ wallet debit
→ POST your webhook access.paid | access.renewed | access.expired
→ You upsert entitlement by elknz_user_id + external_ref
Buyer opens your app later
→ You call POST /api/access/verify-entitlement (no key paste)
→ Unlock if valid: true
Fallback: buyer pastes elk_… → POST /api/access/verify-key
Optional UX: buyer opens claim_url in a new tab → POST /api/access/claimتعامل مع تكرار event_id كأنه مُعالَج مسبقاً. عند access.expired ألغِ الصلاحية.
المضيفات
| البيئة | قاعدة الـ API |
|---|---|
| الإنتاج | https://api.elknz.com |
| محلي | https://api.elknz.com أو http://127.0.0.1:1233 |
كل المسارات أدناه تحت {API_BASE}/api/access/....
1) الـ Webhooks (الأساسي)
الرؤوس
| الرأس | المعنى | ||
|---|---|---|---|
Content-Type | application/json | ||
X-Elknz-Event | access.paid \ | access.renewed \ | access.expired |
X-Elknz-Timestamp | ثوانٍ Unix وقت التوقيع | ||
X-Elknz-Signature | sha256= + HMAC-SHA256 سداسي عشري لـ جسم الطلب الخام باستخدام partner_api_secret |
الجسم (مثال)
{
"event": "access.paid",
"event_id": "access.paid:ACC-…:…",
"status": "paid",
"purchase_number": "ACC-…",
"access_key": "elk_…",
"listing_id": 1,
"external_ref": "sku_or_plan",
"billing_mode": "one_time",
"interval": null,
"amount": 9.99,
"currency": "USD",
"elknz_user_id": 42,
"elknz_username": "buyer1",
"period_start": "…",
"period_end": null,
"paid_at": "…"
}تحقق من التوقيع قبل الوثوق بالجسم. يفضّل التفعيل من elknz_user_id + external_ref (تجنّب لصق المفتاح قدر الإمكان).
2) التحقق من الاستحقاق (بدون مفتاح)
POST /api/access/verify-entitlement
X-Elknz-Access-Secret: aks_…
Content-Type: application/json
{
"external_ref": "sku_or_plan",
"elknz_user_id": 42
}يمكنك إرسال elknz_username بدل (أو مع) elknz_user_id. وlisting_id اختياري إذا أُعيد استخدام نفس external_ref.
الاستجابة:
{
"valid": true,
"purchase_number": "ACC-…",
"listing_id": 1,
"external_ref": "sku_or_plan",
"billing_mode": "recurring",
"interval": "month",
"status": "active",
"period_end": "…",
"elknz_user_id": 42,
"amount_paid": 9.99,
"currency": "USD"
}عند الرفض: valid: false مع reason (unknown_listing، unknown_buyer، no_purchase، expired، period_ended، …).
3) تبادل المطالبة (اختياري)
إذا وُجد claim_url على العرض، بعد الدفع/التجديد يُصدر الكنز رمزاً لمرة واحدة وقصير العمر (~10 دقائق، ACCESS_CLAIM_TTL_MINUTES) وتفتح واجهة المشتري:
{claim_url}?claim=clm_…
في تبويب متصفح جديد. يبقى المشتري على الكنز ويمكنه فتح رابط جديد لاحقاً من لوحة التحكم ← الوصول ← شراء ووصولي.
خادمك:
POST /api/access/claim
X-Elknz-Access-Secret: aks_…
Content-Type: application/json
{ "claim": "clm_…" }نفس شكل استجابة الاستحقاق.
| القاعدة | السلوك |
|---|---|
| لمرة واحدة | التبادل الناجح يضبط claim_consumed_at. إعادة الاستخدام → valid: false وreason: claim_used |
| قصير العمر | بعد الانتهاء → reason: claim_expired |
| إعادة الإصدار | المشتري يستدعي POST /api/access/purchases/{purchase_id}/claim-link (مصادَق) لإنشاء رمز جديد وإبطال أي رمز سابق غير مستخدم |
| الأفضل Webhook | المطالبة اختيارية؛ الـ webhook وverify-entitlement هما الأساس |
مثال استجابة رابط المطالبة للمشتري:
{
"purchase_id": 12,
"claim_redirect_url": "https://partner.example/claim?claim=clm_…",
"claim_expires_at": "…",
"claim_status": "ready",
"ttl_minutes": 10
}4) التحقق بالمفتاح (احتياطي)
POST /api/access/verify-key
X-Elknz-Access-Secret: aks_…
Content-Type: application/json
{ "access_key": "elk_…" }مطلوب عندما يكون للعرض سر شريك. نفس شكل الاستجابة.
الوضع A مقابل الوضع B
| الوصول (الوضع B) | المحفظة (الوضع A) | |
|---|---|---|
| الدفع | على كتالوج الكنز | على موقعك |
| الاشتراك اليوم | نعم (تجديد الوصول) | نعم (اشتراكات) |
| المال | خصم المشتري → احتجاز البائع | خصم المشتري → محفظة التاجر |
| التفعيل | Webhook / استحقاق / مفتاح / مطالبة | webhook payment.succeeded لديك |
لا تدمج المنتجين. استخدم الوصول عندما يعيش العرض على الكنز؛ والوضع A عندما يجب أن يكون الدفع على نطاقك.