⚡API آپمویPartner API v1.1

مستندات API فروش اشتراک آپموی

نسخهٔ ۱ · آدرس پایه: https://api.upmovi.com/v1 (آدرس معادل: https://api.upmovi.ir/v1)

این API برای سایت‌های همکار (مثل سایت شارژ) ساخته شده تا بتوانند اشتراک سایت فیلم را بفروشند و کاربر را روی سایت فیلم ثبت‌نام کنند. پرداخت کاربر در سایت شما انجام می‌شود؛ بعد از پرداخت موفق، یک درخواست به این API می‌فرستید تا اشتراک روی شمارهٔ موبایل او فعال شود.

جریان پیشنهادی

  1. کاربر در سایت شما وارد پنل می‌شود و صفحهٔ پلن‌ها را باز می‌کند.
  2. سایت شما GET /plans را صدا می‌زند و پلن‌ها و قیمت‌های روز را نشان می‌دهد (دکمهٔ «به‌روزرسانی» هم همین را دوباره می‌خواند).
  3. کاربر پلن را انتخاب می‌کند، یک operation_key (UUID) می‌سازید و در دیتابیس خودتان ذخیره می‌کنید، و پرداخت انجام می‌شود.
  4. اگر پرداخت موفق بود: POST /orders با همان operation_key.
  5. در پاسخ، تاریخ پایان اشتراک و (اگر حساب تازه ساخته شده) رمز عبور برمی‌گردد. رمز فقط همین یک‌بار نمایش داده می‌شود؛ آن را به کاربر نشان دهید یا پیامک کنید.
  6. اگر درخواست قطع شد یا پاسخی نگرفتید، همان درخواست را با همان operation_key دوباره بفرستید (امن است) یا GET /orders/{operation_key} را بخوانید.

احراز هویت

همهٔ درخواست‌ها باید این هدر را داشته باشند:

Authorization: Bearer <API_KEY>
Accept: application/json

قواعد کلی

مورد توضیح
قالب ورودی و خروجی JSON؛ برای POST هدر Content-Type: application/json بفرستید
پول تومان، عدد صحیح (IRT)
زمان UTC به قالب 2026-12-15T23:59:59Z
موبایل 09123456789؛ ارقام فارسی، +98... و 98... هم پذیرفته و نرمال می‌شود
محدودیت ۱۲۰ درخواست در دقیقه برای هر کلید؛ ۲۰ تلاش ناموفق در دقیقه برای هر IP
کش پاسخ‌ها no-store هستند

پاسخ موفق: {"ok": true, "data": {...}} — پاسخ خطا: {"ok": false, "error": {"code": "...", "message": "..."}}

۱) فهرست پلن‌ها — GET /plans

قیمت‌ها همیشه از خود سایت فیلم خوانده می‌شوند (با تخفیف فعال). پیشنهاد: هنگام نمایش به کاربر دوباره بخوانید یا حداکثر چند دقیقه کش کنید.

{
  "ok": true,
  "data": {
    "currency": "IRT", "unit": "toman",
    "version": "a1b2c3d4e5f60789",
    "generated_at": "2026-11-15T06:00:00Z",
    "plans": [
      {
        "id": 10, "name": "1-Month Subscription", "name_fa": "اشتراک 1 ماهه",
        "duration_days": 30,
        "original_price": 272000, "final_price": 190000, "discount_percent": 30,
        "discount_until": null, "is_popular": false, "badge": null, "features": null
      }
    ]
  }
}

۲) بررسی حساب — GET /accounts?mobile=09...

{ "ok": true, "data": { "exists": true, "mobile": "09123456789", "user_id": 123,
  "status": "active", "has_password": true, "active_until": "2026-12-15T23:59:59Z" } }

اگر حساب نباشد: {"exists": false, "mobile": "..."}. برای نمایش پیام «اشتراک فعلی شما تا ... است» یا «حساب جدید ساخته می‌شود» مفید است.

۳) ثبت سفارش پرداخت‌شده — POST /orders

فقط بعد از پرداخت موفق صدا بزنید.

فیلد الزامی توضیح
operation_key بله UUID یکتا برای هر خرید (همان را در تکرار هم بفرستید)
mobile بله موبایل خریدار
plan_id بله شناسهٔ پلن از /plans
amount بله تومانی که کاربر پرداخته؛ نباید کمتر از final_price فعلی پلن باشد (وگرنه 409 amount_too_low)
reference خیر کد پیگیری پرداخت در سایت شما (برای گزارش)
password خیر فقط برای حساب تازه: اگر بفرستید همان رمز ثبت می‌شود، وگرنه رمز تصادفی ۱۰ حرفی ساخته و برگردانده می‌شود
{
  "operation_key": "5f7480c7-1be9-4f13-9f6a-69633840dab5",
  "mobile": "09123456789", "plan_id": 10, "amount": 190000, "reference": "TRK-889123"
}

پاسخ موفق (201 بار اول):

{ "ok": true, "data": {
  "operation_key": "5f7480c7-1be9-4f13-9f6a-69633840dab5",
  "already_applied": false, "order_id": 3000000257,
  "user": { "id": 3000000555, "mobile": "09123456789", "created": true, "has_password": true },
  "subscription": { "plan_id": 10, "end_date": "2026-12-15T23:59:59Z" },
  "password": "k7Hq2mXpWc"
} }

۴) وضعیت سفارش — GET /orders/{operation_key}

{ "ok": true, "data": { "operation_key": "...", "order_id": 3000000257, "user_id": 3000000555,
  "plan_id": 10, "status": "paid", "amount": 190000, "applied": true, "end_date": "2026-12-15T23:59:59Z" } }

اگر سفارش نبود 404 not_found. برای بازبینی بعد از timeout یا خطای ۵۰۰ استفاده کنید.

خطاها

HTTP code معنی
401 unauthorized کلید نیست یا اشتباه است
403 ip_not_allowed IP سرور شما در لیست مجاز نیست
403 account_not_active حساب این موبایل فعال نیست
404 plan_not_found پلن وجود ندارد یا برای فروش نیست
404 not_found سفارشی با این operation_key نیست
409 amount_too_low مبلغ کمتر از قیمت فعلی است؛ دوباره /plans را بخوانید
409 order_rejected operation_key برای درخواست دیگری استفاده شده یا سفارش قبلی ناقص است
422 validation_failed / invalid_mobile / invalid_operation_key ورودی نامعتبر
429 rate_limited / too_many_requests درخواست زیاد؛ کمی صبر کنید
500 server_error خطای سرور؛ با همان operation_key دوباره بفرستید یا وضعیت را بخوانید

نکات مهم برای پیاده‌سازی

نمونه کد

curl

curl -s https://api.upmovi.com/v1/plans \
  -H "Authorization: Bearer $API_KEY" -H "Accept: application/json"

curl -s -X POST https://api.upmovi.com/v1/orders \
  -H "Authorization: Bearer $API_KEY" -H "Content-Type: application/json" \
  -d '{"operation_key":"5f7480c7-1be9-4f13-9f6a-69633840dab5","mobile":"09123456789","plan_id":10,"amount":190000,"reference":"TRK-889123"}'

PHP

function upmoviApi(string $method, string $path, ?array $body = null): array
{
    $ch = curl_init('https://api.upmovi.com/v1' . $path);
    curl_setopt_array($ch, [
        CURLOPT_CUSTOMREQUEST  => $method,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT        => 25,
        CURLOPT_HTTPHEADER     => [
            'Authorization: Bearer ' . getenv('UPMOVI_API_KEY'),
            'Accept: application/json',
            'Content-Type: application/json',
        ],
        CURLOPT_POSTFIELDS     => $body === null ? null : json_encode($body),
    ]);
    $raw = curl_exec($ch);
    $code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);
    return ['status' => $code, 'json' => json_decode((string) $raw, true)];
}

$plans = upmoviApi('GET', '/plans');
$order = upmoviApi('POST', '/orders', [
    'operation_key' => $savedUuid, 'mobile' => $mobile,
    'plan_id' => 10, 'amount' => 190000, 'reference' => $trackingCode,
]);
if (in_array($order['status'], [200, 201], true)) {
    $password = $order['json']['data']['password'] ?? null; // فقط برای حساب تازه
}

چک‌لیست راه‌اندازی