مستندات API

با REST API در LisansX می‌توانید فهرست محصولات و موجودی را به سایت خود منتقل کنید، سفارش ثبت کنید و کدهای تحویل را فوراً دریافت کنید. احراز هویت، نقاط پایانی (endpoints) و نمونه‌های PHP، Node.js و Python در ادامه آمده است.

کلید API فقط به نمایندگان ارائه می‌شود. همه می‌توانند مستندات را مطالعه کنند؛ برای ارسال درخواست، یک بسته نمایندگی فعال لازم است. کلید شما پس از تأیید درخواست نمایندگی‌تان ایجاد می‌شود.

احراز هویت

هر درخواست با سه هدر امضا می‌شود. از آنجا که امضا شامل مهر زمانی، متد HTTP، مسیر و بدنه خام به‌صورت هم‌زمان است، درخواست در مسیر قابل تغییر یا ارسال مجدد نیست.

هدرمقدار
X-Api-Keyکلید API شما
X-Timestampثانیه Unix — باید در محدوده ±300 ثانیه از زمان سرور باشد
X-Signatureامضای hex تولیدشده با فرمول زیر
signingKey = sha256_hex(api_secret)
signature  = hmac_sha256_hex(signingKey, timestamp + "\n" + METHOD + "\n" + path + "\n" + rawBody)
  • path: مسیر به‌همراه رشتهٔ کوئری، در صورت وجود (/api/v1/products?limit=50). پارامترهای کوئری نیز بخشی از امضا هستند — دقیقاً همان آدرسی را که درخواست می‌کنید امضا کنید.
  • rawBody: عین همان JSON که ارسال می‌کنید؛ برای درخواست‌های GET یک رشتهٔ خالی.
  • پس از امضای بدنه، آن را دوباره سریال‌سازی نکنید — حتی کوچک‌ترین تفاوت امضا را نامعتبر می‌کند.

نقاط پایانی

متدمسیرتوضیحات
GET /api/v1/products همهٔ محصولات در حال فروش، با قیمت‌های نمایندگی شما
GET /api/v1/products/{id} جزئیات یک محصول و وضعیت موجودی
POST /api/v1/order ایجاد سفارش — در صورت موفقیت، کدهای تحویل بازگردانده می‌شوند
GET /api/v1/order/{order_no} وضعیت سفارش و کدهای تحویل‌شده
GET /api/v1/balance موجودی فعلی شما

محدودیت درخواست دقیقه‌ای برای هر حساب نمایندگی تعیین می‌شود. در صورت عبور از محدودیت، 429 rate_limited بازگردانده می‌شود. همهٔ پاسخ‌های خطا در قالب {"success": false, "error": "...", "message": "..."} هستند.

نمونه‌های یکپارچه‌سازی

آمادهٔ کپی و استفاده

<?php
final class LisansXClient
{
    public function __construct(
        private string $baseUrl,
        private string $apiKey,
        private string $apiSecret
    ) { $this->baseUrl = rtrim($baseUrl, '/'); }

    public function request(string $method, string $path, ?array $body = null): array
    {
        $method  = strtoupper($method);
        $bodyRaw = $body !== null ? json_encode($body, JSON_UNESCAPED_UNICODE) : '';
        $ts      = (string)time();

        // کلید امضا = مقدار hex هش SHA-256 مربوط به secret خام
        $signingKey = hash('sha256', $this->apiSecret);
        $signature  = hash_hmac('sha256', $ts . "\n" . $method . "\n" . $path . "\n" . $bodyRaw, $signingKey);

        $ch = curl_init($this->baseUrl . $path);
        curl_setopt_array($ch, [
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_CUSTOMREQUEST  => $method,
            CURLOPT_TIMEOUT        => 30,
            CURLOPT_HTTPHEADER     => [
                'X-Api-Key: '   . $this->apiKey,
                'X-Timestamp: ' . $ts,
                'X-Signature: ' . $signature,
                'Content-Type: application/json',
            ],
        ]);
        if ($body !== null) curl_setopt($ch, CURLOPT_POSTFIELDS, $bodyRaw);

        $raw = curl_exec($ch);
        return json_decode((string)$raw, true) ?: ['success' => false, 'error' => 'invalid_response'];
    }
}

// --- نحوه استفاده ---
$api = new LisansXClient('https://lisansx.net', 'YOUR_API_KEY', getenv('LISANSX_SECRET'));

$products = $api->request('GET', '/api/v1/products');
$order    = $api->request('POST', '/api/v1/order', ['product_id' => 1, 'qty' => 1]);

if (!empty($order['success'])) {
    foreach ($order['data']['codes'] as $code) {
        echo "Teslim edilen kod: $code\n";
    }
} else {
    error_log('LisansX hatasi: ' . ($order['message'] ?? 'bilinmiyor'));
}

خطاهای رایج

401 invalid_signature
ممکن است مرحلهٔ استخراج کلید امضا به‌صورت sha256(secret) را از قلم انداخته باشید.
401 invalid_timestamp
ساعت سرور شما همگام نیست. آن را با NTP همگام‌سازی کنید.
403 ip_not_allowed
محدودیت IP تعریف شده است و درخواست شما از IP‌ای ارسال می‌شود که در فهرست نیست.
409 replayed_request
همان درخواست POST امضاشده برای بار دوم دریافت شد (محافظت در برابر تکرار). هر درخواست را با مهر زمانی جدید امضا کنید؛ اگر در همان ثانیه دو سفارش برای یک محصول ثبت می‌کنید، یک فیلد یکتای "nonce" به بدنه اضافه کنید (مثلاً شمارهٔ سفارش خودتان).
429 rate_limited
از محدودیت دقیقه‌ای فراتر رفته‌اید؛ درخواست‌های خود را در طول زمان پخش کنید.
409 out_of_stock
محصول موجود نیست یا به تعداد درخواستی موجود نیست (فیلد available تعداد باقی‌مانده را نشان می‌دهد). سفارشی ایجاد نمی‌شود و مبلغی از موجودی کسر نمی‌شود. پیش از دریافت پرداخت از مشتری خود، موجودی را با GET /api/v1/products/{id} بررسی کنید؛ وب‌هوک stock.changed هنگام اتمام یا بازگشت موجودی محصول، فوراً به شما اطلاع می‌دهد.
409 price_changed
اگر "max_unit_price" اختیاری را همراه سفارش ارسال کرده باشید و قیمت واحد فعلی از آن بیشتر باشد، سفارشی ایجاد نمی‌شود؛ unit_price قیمت فعلی را نشان می‌دهد.
402 delivery_failed
سفارش ایجاد شد اما محصول تحویل داده نشد (مثلاً در لحظهٔ آخر در منبع تمام شد). مبلغ به‌طور خودکار به موجودی شما بازگردانده می‌شود.
پیام در Telegram ثبت درخواست پشتیبانی