المطورون/التكامل

شحن رصيد الهاتف المحمول

يشحن هذا المنتج رقم هاتف مدفوعًا مسبقًا بشكل مباشر. يحصل عميلك على رصيد مكالمات أو بيانات على خطه، ولا يوجد كود لتسليمه. وتدفع القيمة من محفظتك لدى CardV، تمامًا كما في الطلبات الأخرى.

ذات صلة: المصادقة · القواعد العامة · Webhook

#كيف يعمل

Text
GET  /recharge/countries            الدول التي يمكنك الشحن فيها
GET  /recharge/operators?country=US  المشغّلون وأنواع الشحن والمبالغ
POST /recharge/quote                سعرك، وقيمة quote_token صالحة لمدة 300 ثانية
POST /recharge/orders               إرسال الطلب، ويُدفع من محفظتك
GET  /recharge/orders/{order_id}    الاستعلام عن الحالة، أو انتظار Webhook
  • تبدأ كل المسارات بـ /api/v1. أرسل الترويسات نفسها كما في كل استدعاء.
  • يجب توقيع استدعاءي POST. وقّعهما بالطريقة نفسها المتبعة مع POST/orders، لكن استخدم مسار كل منهما، مثل /api/v1/recharge/quote.
  • طلبات الشحن منفصلة عن طلبات بطاقات الهدايا. استخدم نقاط النهاية /recharge لقراءتها.
  • نوفّر الشحن المباشر فقط، ولا نوفّر منتجات PIN (كود يُدخله العميل بنفسه).

#الدول

يعرض GET/api/v1/recharge/countries الدول التي يمكنك الشحن فيها الآن.

JSON
{
  "count": 2,
  "results": [
    {"code": "MX", "name": "Mexico", "currency_codes": ["MXN"], "operator_count": 4, "offer_count": 37},
    {"code": "US", "name": "United States", "currency_codes": ["USD"], "operator_count": 6, "offer_count": 52}
  ]
}
  • code هو رمز الدولة وفق ISO 3166-1 alpha-2. أرسله في الحقل country في الاستدعاءات التالية.
  • currency_codes هي العملات المحلية التي يبيع بها المشغّلون في هذه الدولة.
  • تتغيّر القائمة عند إضافة مشغّلين أو توقّف توفّرهم. حمّلها من جديد كل بضع ساعات.

#المشغّلون

يعرض GET/api/v1/recharge/operators?country=US مشغّلي الاتصالات في دولة واحدة. أضف search=att للتصفية حسب اسم المشغّل.

JSON
{
  "count": 1,
  "results": [
    {
      "operator_key": "us-att",
      "name": "AT&T",
      "country": "US",
      "country_name": "United States",
      "logo_url": "https://b2b.cardv.net/api/v1/catalog-assets/3f5c...a1.png",
      "subtypes": ["airtime", "data"],
      "amount_model": "range",
      "currency_codes": ["USD"],
      "amounts": [
        {"min": "5.0000", "max": "100.0000", "currency": "USD", "subtype": "airtime", "label": "5.0000-100.0000 USD"},
        {"min": "15.0000", "max": "15.0000", "currency": "USD", "subtype": "data", "label": "15.0000 USD"}
      ],
      "offer_count": 3
    }
  ]
}
الحقلالمعنى
operator_keyالرقم الذي ترسله في عرض السعر وفي الطلب، مثل us-att. احفظه كنص.
subtypesما يمكنك شراؤه: airtime (رصيد مكالمات) أو data أو bundle (مكالمات وبيانات).
amount_modelfixed إذا كانت كل المبالغ قيمًا محددة، وrange إذا كان أي مبلغ منها نطاقًا.
amounts[]كل خيار متاح. إذا تساوى min وmax فهو مبلغ ثابت، وإلا فأي مبلغ بينهما.
amounts[].currencyالعملة المحلية لهذا الخيار. أرسلها في الحقل local_currency.
logo_urlصورة تستضيفها CardV، أو "".
  • المبالغ مبالغ محلية: أي ما يصل إلى خط الهاتف، بالعملة المحلية.
  • قيمة country غير معروفة أو بصيغة غير صحيحة تُرجع HTTP 400.

#عرض السعر

يُرجع POST/api/v1/recharge/quote سعرك لعملية شحن واحدة. ويجب توقيع هذا الاستدعاء.

JSON
{
  "country": "US",
  "operator_key": "us-att",
  "amount": "10.00",
  "local_currency": "USD",
  "subtype": "airtime"
}
الحقلإلزامي؟المعنى
countryنعمرمز الدولة من قائمة الدول.
operator_keyنعممن قائمة المشغّلين.
amountنعمالمبلغ المحلي كنص. في المبلغ الثابت: إحدى القيم المدرجة. في النطاق: بين min وmax.
local_currencyموصى بهرمز ISO 4217 لعملة amount، من amounts[].currency. أرسله إذا كان المشغّل يعرض أكثر من عملة.
subtypeلاairtime (الافتراضي) أو data أو bundle.

الرد:

JSON
{
  "country": "US",
  "country_name": "United States",
  "operator": {"operator_key": "us-att", "name": "AT&T", "logo_url": ""},
  "subtype": "airtime",
  "local_amount": "10.0000",
  "local_currency": "USD",
  "merchant_price": "9.6200",
  "merchant_currency": "USD",
  "expires_at": "2026-09-30T08:20:30.123456+00:00",
  "quote_token": "eyJ2ZXJzaW9uIjox...:1uXyZa:8c1f..."
}
  • merchant_price هو ما تدفعه من محفظتك، بعملة merchant_currency.
  • تثبّت قيمة quote_token هذا السعر لمدة 300 ثانية، حتى expires_at. أرسلها مع الطلب دون تغيير.
  • ترتبط هذه القيمة بحسابك وبالدولة والمشغّل والنوع والمبلغ نفسها.
  • تأكد من أن local_currency هي العملة التي تتوقعها قبل إرسال الطلب.
  • عرض السعر لا يحجز أي مبلغ، ويمكنك طلب عرض سعر جديد في أي وقت.

#إرسال طلب شحن

يشحن POST/api/v1/recharge/orders الهاتف، ويدفع القيمة من محفظتك. ويجب توقيع هذا الاستدعاء.

JSON
{
  "external_order_id": "SHOP-RC-20260930-0001",
  "country": "US",
  "operator_key": "us-att",
  "amount": "10.00",
  "local_currency": "USD",
  "subtype": "airtime",
  "account": "12125550100",
  "quote_token": "eyJ2ZXJzaW9uIjox...:1uXyZa:8c1f..."
}
الحقلإلزامي؟المعنى
external_order_idنعمرقم طلبك، ولا يتكرر بين كل طلباتك، بما فيها طلبات بطاقات الهدايا.
country، operator_key، amount، local_currency، subtypeنعمالقيم نفسها التي أرسلتها في عرض السعر.
accountنعمرقم الهاتف المراد شحنه: أرقام فقط، مع رمز الدولة، دون + أو مسافات.
quote_tokenنعممن عرض السعر، قبل انتهاء صلاحيته.

أمثلة على أرقام الهواتف: 12125550100 (الولايات المتحدة)، و525512345678 (المكسيك). تأكد من أن الرقم تابع للمشغّل الذي اخترته، فالشحن المرسل إلى رقم خاطئ لا يمكن التراجع عنه.

تتحقق CardV من عرض السعر، وتخصم merchant_price من محفظتك فورًا، ثم تبدأ الشحن في الخلفية. الطلب الجديد يُرجع HTTP 201:

JSON
{
  "idempotent_replay": false,
  "order": {
    "order_id": "O-00005678",
    "external_order_id": "SHOP-RC-20260930-0001",
    "status": "accepted",
    "status_title": "Recharge accepted",
    "poll_after_seconds": 12,
    "account": "12***00",
    "local_amount": "10.0000",
    "local_currency": "USD",
    "merchant_price": "9.6200",
    "merchant_currency": "USD",
    "...": "more fields"
  }
}
  • احفظ order.order_id.
  • يُرجَع رقم الهاتف مخفيًا جزئيًا، ولا يُرجَع كاملًا أبدًا.

#إعادة المحاولة بأمان

يحميك external_order_id من شحن الهاتف مرتين.

ما ترسلهما تحصل عليه
رقم طلب جديدHTTP 201. طلب جديد، ويُخصم المبلغ من محفظتك.
رقم الطلب نفسه وعملية الشحن نفسهاHTTP 200 و"idempotent_replay": true. الطلب الموجود، دون أي خصم.
رقم الطلب نفسه لكن بعملية شحن مختلفةHTTP 400 على external_order_id. لا يحدث شيء.

"عملية الشحن نفسها" تعني الدولة والمشغّل والنوع والمبلغ ورقم الهاتف نفسها. تتعرّف CardV على الطلب المكرر قبل التحقق من عرض السعر، لذلك تُرجع الطلب الأول حتى لو انتهت صلاحية quote_token.

  • بعد انتهاء المهلة أو خطأ 5xx أو انقطاع الاتصال، أرسل المحتوى نفسه برقم الطلب نفسه. ووقّعه من جديد بطابع زمني وقيمة nonce جديدين.
  • لا تنشئ رقم طلب جديدًا لمجرد أن الرد لم يصلك. فقد يؤدي ذلك إلى شحن الهاتف مرتين.

#قراءة طلبات الشحن

يُرجع GET/api/v1/recharge/orders/{order_id} طلبًا واحدًا. ويمكنك استخدام رقم طلب CardV (O-00005678).

JSON
{
  "order_id": "O-00005678",
  "external_order_id": "SHOP-RC-20260930-0001",
  "status": "processing",
  "order_status": "processing",
  "status_title": "Recharge processing",
  "status_message": "The recharge request is being processed. Delivery is not confirmed yet.",
  "next_step": "Keep this order open and wait for confirmation before placing another recharge.",
  "poll_after_seconds": 12,
  "country": "US",
  "operator": {"operator_key": "us-att", "name": "AT&T", "logo_url": ""},
  "subtype": "airtime",
  "account": "12***00",
  "local_amount": "10.0000",
  "local_currency": "USD",
  "merchant_price": "9.6200",
  "merchant_currency": "USD",
  "attempts": [{"attempt_no": 1, "status": "processing", "error_message": "", "submitted_at": "2026-09-30T08:16:02.511201Z", "completed_at": null}],
  "created_at": "2026-09-30T08:16:01.004211Z",
  "updated_at": "2026-09-30T08:16:02.611978Z",
  "...": "more fields"
}
  • رقم طلب غير معروف، أو طلب يخص حسابًا آخر، يُرجع HTTP 404.
  • status_title وstatus_message وnext_step نصوص باللغة الإنجليزية يمكنك عرضها على موظفيك.
  • poll_after_seconds هي المدة التي تنتظرها قبل الاستعلام التالي. والقيمة 0 تعني أن الطلب اكتمل.

#قائمة طلبات الشحن

يعرض GET/api/v1/recharge/orders طلبات الشحن الخاصة بك، من الأحدث إلى الأقدم.

HTTP
GET /api/v1/recharge/orders?status=processing&limit=50&offset=0
JSON
{"count": 3, "limit": 50, "results": ["..."]}
  • عوامل التصفية: status، وsearch (رقم طلب CardV أو رقم طلبك أو اسم المشغّل).
  • القيمة الافتراضية لـ limit هي 20، والحد الأقصى 100. أي قيمة أكبر تُخفَّض إلى 100.
  • إذا كانت limit أو offset سالبة أو ليست رقمًا، تحصل على HTTP 400.

#الحالة

Text
accepted ──► processing ──► succeeded
                  │
                  ├──► manual_review ──► succeeded أو refunded
                  │
                  └──► failed ──► refunded   (أُعيد المبلغ إلى محفظتك)
الحالةهل اكتمل؟ما الذي تفعله
acceptedلاانتظر. خُصم المبلغ من المحفظة، ولم يبدأ الشحن بعد.
processingلاانتظر. قد يستغرق الأمر عدة دقائق. لا ترسل الطلب مرة أخرى.
manual_reviewلاتتحقق CardV من النتيجة مع المشغّل. انتظر.
succeededنعمشُحن الهاتف. أبلغ عميلك.
failedليس بعدلم تتم عملية الشحن. انتظر refunded.
refundedنعمعاد المبلغ إلى محفظتك. يمكنك إرسال طلب جديد.
  • استعلم بعد poll_after_seconds، ثم باعد بين الاستعلامات: 30 ثانية، ثم 60 ثانية، ثم كل 5 دقائق. والتزم بحد الطلبات.
  • اعتبر أي حالة غير معروفة "لم يكتمل بعد".
  • ما دام الطلب لم يكتمل، لا ترسل عملية شحن أخرى إلى الرقم نفسه برقم طلب جديد. فإذا نجح الطلب الأول أيضًا، سيُشحن الهاتف مرتين.

#Webhook والاسترداد

ترسل طلبات الشحن رسائل Webhook نفسها التي ترسلها الطلبات الأخرى: order.succeeded وorder.failed وorder.refunded. تحتوي رسالة Webhook على رقم طلب CardV ورقم طلبك، وقائمة items فارغة. بعد وصول الرسالة، اقرأ الطلب باستخدام GET/api/v1/recharge/orders/{order_id}.

الاسترداد تلقائي. عندما يؤكد المشغّل فشل العملية، تعيد CardV قيمة merchant_price كاملة إلى محفظتك، وتصبح حالة الطلب refunded. يمكنك رؤية المبلغ المسترد في صفحة الحركات بالبوابة. عملية الشحن الناجحة لا يمكن استردادها أو إلغاؤها.

#الأخطاء

تتبع الأخطاء القواعد العامة. عرض السعر أو الطلب المرفوض يُرجع HTTP 400 ولا يُخصم أي مبلغ.

المفتاحأين يظهرما الذي تفعله
detailعرض السعر، الطلبالدولة أو المشغّل أو النوع أو المبلغ غير متاح. راجع قائمة المشغّلين.
amountعرض السعر، الطلبليس رقمًا، أو صفر، أو خارج النطاق.
local_currencyعرض السعر، الطلبليس رمز ISO 4217 من 3 أحرف.
accountالطلبرقم الهاتف مفقود.
quote_tokenالطلبمفقود أو منتهي الصلاحية أو معدّل أو غير مطابق. راجع code، ثم اطلب عرض سعر جديدًا.
balanceالطلباشحن محفظتك من البوابة.
riskالطلببلغت أحد حدود الطلبات. تواصل مع CardV.
external_order_idالطلبمستخدم لطلب مختلف. راجع إعادة المحاولة بأمان.
walletالطلبلا توجد محفظة نشطة. تواصل مع CardV.

تأتي أخطاء quote_token مع الحقل code:

JSON
{"code": "quote_expired", "quote_token": "This quote expired. Refresh the price and confirm again."}
codeالمعنى
quote_requiredلم تُرسَل قيمة quote_token.
quote_expiredمضى عليها أكثر من 300 ثانية. اطلب عرض سعر جديدًا.
quote_invalidمعدّلة، أو تخص عملية شحن مختلفة. اطلب عرض سعر جديدًا.
price_changedتغيّر سعرك منذ عرض السعر. اطلب عرضًا جديدًا وأكّد السعر الجديد.

HTTP 403 يعني مشكلة في بيانات الاعتماد أو التوقيع أو عنوان IP أو الموافقة. راجع المصادقة.

هل لديك سؤال حول التكامل؟ راسلنا على [email protected] مع ذكر Merchant ID ومعرّف الطلب أو الاستدعاء.