Documentation

وثائق ZolnaPay

دليل نظيف وشامل لقبول المدفوعات ودمج المنصة — من أول طلب إلى Webhooks.

REST · HTTPS HMAC webhooks AR / EN api.zolna.app/v1

جرّب الـ API مباشرة

طلبات عامة حقيقية من المتصفح — بدون مفتاح سري.

جاهز

النتائج من api.zolna.app مباشرة. للمدفوعات استخدم مفتاح sk_test_ من لوحة المطوّرين على الخادم.

{ "hint": "Select an endpoint and press Send" }

البدء السريع

أربع خطوات واضحة لأول عملية تجريبية.

1

أنشئ مشروعاً

من لوحة التاجر، ثم أنشئ مفتاح اختبار.

2

أنشئ دفعة

استدعِ POST /payments بالمبلغ بالسنتات.

3

أكّد أو افتح Checkout

تأكيد برمجي، أو جلسة مستضافة جاهزة.

4

اربط Webhook

استقبل payment.succeeded فوراً على خادمك.

# Create a test payment
curl -X POST https://api.zolna.app/v1/payments \
  -H "Authorization: Bearer sk_test_..." \
  -H 'Content-Type: application/json' \
  -d '{"amountCents":2000,"currency":"usd","customerEmail":"buyer@example.com"}'
import { ZolnaPay } from '@zolnapay/sdk';

const zp = new ZolnaPay({ secretKey: process.env.ZOLNAPAY_SECRET_KEY });
const payment = await zp.payments.create({
  amountCents: 2000,
  currency: 'usd',
  customerEmail: 'buyer@example.com',
});
import os, requests

r = requests.post(
  "https://api.zolna.app/v1/payments",
  headers={"Authorization": f"Bearer {os.environ['ZOLNAPAY_SECRET_KEY']}"},
  json={"amountCents": 2000, "currency": "usd", "customerEmail": "buyer@example.com"},
)
print(r.json())

المصادقة

مفتاح سري للخادم، أو JWT لجلسة لوحة التاجر.

POST/auth/register

إنشاء حساب تاجر. يُرسل رمز تفعيل للبريد.

الحقلالنوع
namestringمطلوب
emailstringمطلوب
passwordstring (≥10)مطلوب
localear | enاختياري
curl -X POST https://api.zolna.app/v1/auth/register \
  -H 'Content-Type: application/json' \
  -d '{"name":"Sara","email":"sara@brand.com","password":"SuperSecret123","locale":"ar"}'
POST/auth/verify-email

تفعيل البريد برمز من 6 أرقام — يعيد جلسة جاهزة.

POST/auth/login

كلمة المرور ثم رمز البريد، أو TOTP إن وُجد. Google يتجاوز رمز البريد.

POST /v1/auth/login
{ "email": "...", "password": "..." }

POST /v1/auth/login/email-code
{ "ticket": "...", "code": "123456" }
مهم: لا تضع المفتاح السري في المتصفح. استخدمه من الخادم فقط.

مفاتيح API

أنشئها من صفحة المطورين. الاختبار فوري، والإنتاج بعد تفعيل المشروع.

sk_test_…

مفتاح اختبار — بلا أموال حقيقية.

sk_live_…

مفتاح إنتاج — بعد اعتماد الحساب.

GET/api-keys

قائمة مفاتيح المشروع الحالي.

POST/api-keys

إنشاء مفتاح. السر يُعرض مرة واحدة فقط.

{ "type": "secret", "mode": "test" }
X-Merchant-Id · عند تعدد المشاريع، أرسل معرّف المشروع في هذه الترويسة.

المدفوعات

أنشئ، أكّد، واسترد. المبالغ دائماً integer بالسنتات.

POST/payments

إنشاء PaymentIntent. يدعم Idempotency-Key.

الحقلالنوع
amountCentsintegerمطلوب
currencystringاختياري
customerEmailstringاختياري
descriptionstringاختياري
curl -X POST https://api.zolna.app/v1/payments \
  -H "Authorization: Bearer $KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-1001' \
  -d '{"amountCents":5000,"currency":"usd","customerEmail":"a@x.com"}'
POST/payments/:id/confirm

تأكيد الدفع بوسيلة: card / test_card / stripe · mobile_money · paypal · bank_transfer · crypto_btc · crypto_usdt · saved

{
  "paymentMethod": {
    "type": "paypal",
    "email": "buyer@example.com"
  }
}

إن رجع requires_action: لـ Stripe استخدم clientSecret ثم /complete. للتحويل البنكي/الكريبتو ارفع إثباتاً عبر /public/payments/:id/proof.

POST/payments/:id/complete

مزامنة الدفع بعد 3DS — عام لصفحة Checkout.

GET/public/payments/:id

قراءة عامة آمنة للدافع (المبلغ والحالة وaction) بدون مصادقة.

POST/public/payments/:id/proof

رفع إثبات تحويل بنكي أو كريبتو (multipart). الحالة تصبح pending_review حتى يقرر الأدمن.

curl -X POST https://api.zolna.app/v1/public/payments/$PAY_ID/proof \
  -F method=bank_transfer \
  -F bankCode=bankak \
  -F senderName=Ali \
  -F reference=TRX123 \
  -F file=@receipt.jpg
GET/payments

أحدث عمليات المشروع.

GET/payments/export

تصدير CSV للمدفوعات (حتى 90–365 يوماً) للتسوية المحاسبية.

POST/payments/:id/refund

استرداد كامل أو جزئي لعملية ناجحة (Stripe إن وُجدت). يدعم Idempotency-Key.

curl -X POST https://api.zolna.app/v1/payments/$PAY_ID/refund \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Idempotency-Key: refund-order-1001' \
  -H 'Content-Type: application/json' \
  -d '{"amountCents":500,"reason":"partial"}'
POST/webhooks/stripe

Webhook وارد من Stripe. فعّل التوقيع عبر webhook_secret في أدمن → المعالجات.

payment_intent.succeeded · payment_intent.payment_failed · charge.dispute.created · charge.dispute.updated · charge.dispute.closed

وسائل الدفع

بطاقة، موبايل موني، PayPal، تحويل بنكي، BTC وUSDT — تُفعَّل من الأدمن وإعدادات التاجر.

PayPal / Card / MM

في test: PayPal ينجح فوراً، البطاقة عبر test/Stripe، وموبايل موني بعد توثيق SMS.

Bank / BTC / USDT

تُرجع requires_action مع تعليمات الإيداع، ثم إثبات → pending_review → قبول الأدمن.

GET/public/checkout/config?mode=test

يعيد الوسائل المفعّلة + مفتاح Stripe إن وُجد.

GET/admin/payment-proofs

قائمة إثباتات بانتظار المراجعة. القرار عبر POST /admin/payment-proofs/:id/decide مع {"decision":"approve"|"reject"}.

Checkout

صفحة دفع مستضافة على checkout.zolna.app.

POST/checkout/sessions

تُنشئ جلسة وتعيد رابط توجيه جاهز.

curl -X POST https://api.zolna.app/v1/checkout/sessions \
  -H "Authorization: Bearer $KEY" \
  -H 'Content-Type: application/json' \
  -d '{"amountCents":2000,"currency":"usd","customerEmail":"buyer@example.com"}'

الاشتراكات

منتج ← خطة ← اشتراك، مع تجديد تلقائي.

POST/products

إنشاء منتج قابل للفوترة.

POST/plans

خطة شهرية أو سنوية.

POST/subscriptions

بدء اشتراك على خطة.

POST/subscriptions/:id/cancel

إلغاء فوري أو عند نهاية الفترة.

GET/public/subscriptions/manage?token=...

صفحة إدارة عامة للعميل: فواتير + حالة + إلغاء عند نهاية الفترة.

Disputes

نزاعات محلية + نزاعات Stripe الواردة مع رفع أدلة ومزامنة القرار.

GET/disputes

عرض نزاعات التاجر الحالية، بما فيها stripeDisputeId و dueBy.

POST/disputes/:id/evidence

رفع أدلة محلياً، ومع Stripe أيضاً إن كان النزاع وارداً من Stripe.

GET/admin/disputes

لوحة نزاعات الأدمن للمراجعة والحسم.

Audit

أحداث مالية وتشغيلية append-only في /admin/audit.

GET/admin/audit

يشمل الآن تفاصيل before/after لأحداث مثل: payment.refunded · payout.requested · payout.approved · payout.rejected · subscription.canceled · subscription.paused · subscription.dunning_* · stripe.dispute_* · dispute.decided.

Hardening

Rate limits + Stripe webhook idempotency.

POST/auth/login · /auth/register · /payments/:id/confirm · /refunds · /payouts

طلبات متكررة تتجاوز الحد ترجع 429 rate_limited مع رؤوس X-RateLimit-*.

POST/webhooks/stripe

كل event.id يُخزَّن في inbound_webhook_events. إعادة التسليم ترجع duplicate: true دون إعادة المعالجة (مع إعادة محاولة للأحداث الفاشلة أو العالقة).

GETscripts/e2e-smoke-finance.py

Smoke E2E: دفع → webhook idempotency → نزاع → استرداد → سحب → audit.

POSTmanage.py retry_webhooks

Cron كل دقيقة يعيد تسليم webhooks التجار الفاشلة بتأخير تصاعدي حتى 7 محاولات.

GET/files/:path?exp=&sig=

ملفات KYC/الأدلة خاصة: الرفع يعيد رابطاً موقّعاً، والمسار العام /media/private|uploads مرفوض (403).

POST/payouts

طلب السحب يتطلب تأكيد بريدي (stage: step_up ثم stepUpCode) قبل الحجز.

GETscripts/backup-postgres.sh

نسخ احتياطي يومي لقاعدة Postgres مع احتفاظ 14 يوماً في /var/backups/zolnapay.

GET/health

يشمل الآن redis وbackup وadminUrl. صفحة الحالة تعرضها مباشرة.

POST/payment-methods/mobile-money/start

يرسل SMS عبر SMS_PROVIDER (simulation / twilio / http). Live MM charge يبقى معطلاً حتى تكامل المزود.

المحفظة

متاح · معلّق · محجوز — بشفافية كاملة.

GET/balance
{
  "availableCents": 125000,
  "pendingCents": 4200,
  "reservedCents": 0,
  "currency": "usd"
}
GET/balance/transactions

سجل الحركات المالية.

POST/payouts

طلب سحب من الرصيد المتاح.

Webhooks

أحداث فورية عبر HTTPS مع توقيع HMAC.

POST/webhook-endpoints

أضف عنوان HTTPS. السر يُعرض مرة واحدة.

{ "url": "https://example.com/webhooks/zolna", "mode": "test" }
GET/events

كتالوج عام لأنواع الأحداث — بدون مصادقة.

  • payment.succeeded · payment.failed · payment.refunded · payment.disputed
  • subscription.created · renewed · canceled · paused · resumed
  • invoice.paid · invoice.payment_failed · payout.paid · payout.failed
Zolna-Signature · تحقق عبر t=…,v1=HMAC_SHA256.

الأخطاء

شكل موحّد لكل الاستجابات الفاشلة.

{ "message": "invalid_credentials" }
  • invalid_credentials
  • email_not_verified
  • merchant_not_live
  • amount_required
  • forbidden_role

JavaScript SDK

نفس عقد الـ API بحزمة خادم بسيطة — مع أنواع TypeScript.

جرّب من SDK على الخادم بمفتاح sk_test_ من صفحة المطورين. لا تضع المفتاح السري في المتصفح.

import { ZolnaPay } from '@zolnapay/sdk';

const zp = new ZolnaPay({
  secretKey: process.env.ZOLNAPAY_SECRET_KEY,
  baseUrl: 'https://api.zolna.app/v1',
});

const session = await zp.checkout.sessions.create({
  amountCents: 2000,
  currency: 'usd',
});

await zp.payments.confirm(session.id, {
  type: 'card',
  card: { number: '4242424242424242', expMonth: 12, expYear: 2030, cvc: '123' },
});

const customers = await zp.customers.list();
await zp.subscriptions.pause(subId);
await zp.subscriptions.resume(subId);

الموارد: payments · checkout · paymentLinks · paymentMethods · balance · subscriptions · payouts · customers · disputes · team · webhooks · apiKeys

الاختبار

ادمج بثقة قبل استقبال أموال حقيقية.

بطاقة اختبار

4242 4242 4242 4242

أي تاريخ مستقبلي وأي CVC.

صحة الخدمة

GET /v1/health

والحالة الحية على status.zolna.app

POST/payments/:id/confirm

أمثلة وسائل بديلة في test:

{ "paymentMethod": { "type": "bank_transfer", "bankCode": "bankak" } }
{ "paymentMethod": { "type": "crypto_btc" } }
{ "paymentMethod": { "type": "crypto_usdt" } }
{ "paymentMethod": { "type": "paypal", "email": "buyer@example.com" } }