REST API စနစ် - v1

ပြန်လည်ရောင်းချသူများအတွက် ဂိမ်းငွေဖြည့်နှင့် Voucher API

ဂိမ်း Top Up၊ ဂိမ်းငွေဖြည့်ခြင်းနှင့် Voucher ကုဒ်များအတွက် REST API တစ်ခုတည်း ဖြစ်ပါသည်။ ပစ္စည်းစာရင်း ဖတ်ခြင်း၊ ကစားသူ စစ်ဆေးခြင်း၊ အော်ဒါတင်ခြင်းမှသည် ရလဒ်ကို webhook သို့မဟုတ် status ပြန်စစ်ခြင်းဖြင့် ရယူခြင်းအထိ ပါဝင်ပါသည်။

ဤ API သည် SHOP2TOPUP ကို နောက်ကွယ်မှ လည်ပတ်စေသော host-to-host (H2H) ငွေဖြည့် API ဖြစ်ပါသည်။ HTTPS ပေါ်တွင် ရိုးရိုး JSON ဖြင့် အလုပ်လုပ်ပြီး Bearer အထောက်အထားစစ်ဆေးမှု၊ UUID idempotency key များ၊ ထုတ်ပြန်ထားသော rate limit များနှင့် စက်ဖြင့်ဖတ်နိုင်သည့် တည်ငြိမ်သော အမှားကုဒ်များ ပါဝင်ပါသည်။ ထို့ကြောင့် ဆိုင်၊ အွန်လိုင်းစတိုး သို့မဟုတ် bot တစ်ခုက client library မလိုဘဲ ဒစ်ဂျစ်တယ် ဂိမ်းခရက်ဒစ်ကို ပရိုဂရမ်ဖြင့် ရောင်းချနိုင်ပါသည်။ နှစ်ပေါင်း 5+ အဆက်မပြတ် လည်ပတ်ခဲ့ရာတွင် ဤ API တစ်ခုတည်းမှ အော်ဒါ 3,000,000+ ကို ပေးပို့ခဲ့ပြီး ဖြစ်ပါသည်။

ဈေးနှုန်း၊ ငွေပေးချေမှု နည်းလမ်းများနှင့် partner အကောင့် အလုပ်လုပ်ပုံကို သိလိုပါက ဤစာမျက်နှာတွင် ဖတ်ပါ: SHOP2TOPUP Reseller အစီအစဉ် အကျဉ်းချုပ်.

မည်သည့်အရာကိုမျှ လက်မှတ်မထိုးမီ ပထမဆုံး call

endpoint တိုင်းသည် ခေါင်းစီး (header) တစ်ခုသာ ပါဝင်သော သာမန် HTTPS တောင်းဆိုမှု ဖြစ်ပါသည်။ ထည့်သွင်းရမည့် SDK မရှိ၊ ပရောဂျက်ထဲ ကူးထည့်ရမည့် client library မရှိ၊ ထပ်ထည့်ရမည့် build အဆင့်လည်း မရှိပါ။ အောက်ပါ ခေါ်ဆိုမှုကို ကူးထည့်ပြီး key ကို အစားထိုးလိုက်ရုံဖြင့် terminal ထဲတွင် တကယ့် ပစ္စည်းစာရင်း တုံ့ပြန်ချက်ကို မြင်ရပါမည်။

တောင်းဆိုမှု နမူနာ - cURL
curl -s "https://shop2topup.com/api/endpoints/v1/catalog/categories?bigCategoryId=1" \
  -H "Authorization: Bearer YOUR_KEY_ID.YOUR_KEY_SECRET"
တုံ့ပြန်ချက် - 200 OK
{
  "success": true,
  "categories": [
    {
      "id": 12,
      "name": "Free Fire",
      "description": "Garena Free Fire diamonds",
      "big_category_id": 1,
      "big_category_name": "Mobile Games"
    }
  ]
}

အခြေခံ URL လိပ်စာ

https://shop2topup.com/api/endpoints/v1

စာတမ်းတွင် ဖော်ပြထားသော path အားလုံးသည် ဤအခြေခံ URL မှ စတင်ပါသည်။ တုံ့ပြန်ချက်များသည် JSON ဖြစ်ပြီး success ဟူသော boolean အကွက် အမြဲ ပါသဖြင့် client ထဲရှိ စစ်ဆေးချက် တစ်ခုတည်းဖြင့် အောင်မြင်သည့် လမ်းကြောင်းနှင့် ကျန်အရာအားလုံးကို ခွဲခြားနိုင်ပါသည်။

အမှား တုံ့ပြန်ချက် ပုံစံ

status ကုဒ်တိုင်းတွင် မအောင်မြင်သည့် တုံ့ပြန်ချက်များ၏ ပုံစံ တူညီပါသည်။ API သဘောတူညီချက်၏ အစိတ်အပိုင်းဖြစ်သော error.code ကို အခြေခံ၍ ခွဲခြားပါ။ error.message ကိုမူ လူဖတ်ရန် ရေးထားပြီး အချိန်မရွေး စကားလုံး ပြင်နိုင်သဖြင့် ၎င်းကို အခြေခံ၍ ဘယ်တော့မှ မခွဲခြားပါနှင့်။

အမှား တုံ့ပြန်ချက်
{
  "success": false,
  "error": {
    "code": "PRICE_INCREASED",
    "message": "Price has increased beyond expected",
    "action": "FIX_INPUT",
    "retryable": false,
    "retry_after": null,
    "details": {
      "expected_unit_price": "0.950000",
      "current_unit_price": "0.980000"
    }
  }
}

API တစ်ခုလုံးကို မျက်နှာပြင်တစ်ခုတည်းတွင်

endpoint 11 ခုဖြင့် ချိတ်ဆက်မှု တစ်ခုလုံး ပြည့်စုံပါသည်။ ပစ္စည်းစာရင်း ဖတ်ခြင်း၊ ပစ္စည်းဈေးနှုန်း ရယူခြင်း၊ ကစားသူ စစ်ဆေးခြင်း၊ အော်ဒါတင်ခြင်းနှင့် နောက်ပိုင်း စာရင်းတိုက်ခြင်းတို့ ပါဝင်ပါသည်။ အတန်းတိုင်းသည် parameter အားလုံး၊ နမူနာ တောင်းဆိုမှုနှင့် နမူနာ တုံ့ပြန်ချက် ပါဝင်သော ကိုးကားစာတမ်း အပြည့်အစုံသို့ တိုက်ရိုက် ချိတ်ထားပါသည်။

နည်းလမ်းလမ်းကြောင်းလုပ်ဆောင်ချက်အသေးစိတ်
GET/accountအကောင့်အချက်အလက် ရယူခြင်းအသေးစိတ် ဖတ်ရန်
GET/catalog/big-categoriesပင်မအမျိုးအစား စာရင်းအသေးစိတ် ဖတ်ရန်
GET/catalog/categoriesအမျိုးအစား စာရင်းအသေးစိတ် ဖတ်ရန်
GET/catalog/subcategoriesအမျိုးအစားခွဲ (ပစ္စည်း) စာရင်းအသေးစိတ် ဖတ်ရန်
GET/catalog/subcategory/:itemId/priceပစ္စည်း ဈေးနှုန်း ရယူခြင်းအသေးစိတ် ဖတ်ရန်
GET/catalog/category/:categoryId/requirementsအမျိုးအစား လိုအပ်ချက်များ ရယူခြင်းအသေးစိတ် ဖတ်ရန်
POST/player/validateကစားသူ စစ်ဆေးခြင်းအသေးစိတ် ဖတ်ရန်
POST/orders/createအော်ဒါ တင်ခြင်းအသေးစိတ် ဖတ်ရန်
GET/orders/:orderIdအော်ဒါ အခြေအနေ ရယူခြင်းအသေးစိတ် ဖတ်ရန်
POST/orders/batchအော်ဒါများကို အစုလိုက် ရယူအသေးစိတ် ဖတ်ရန်
GET/ordersအော်ဒါစာရင်းအသေးစိတ် ဖတ်ရန်

ထို့အပြင် အော်ဒါ status webhook များကိုလည်း ဤစာမျက်နှာ အောက်ပိုင်းတွင် အပြည့်အစုံ ဖော်ပြထားပါသည်။

အထောက်အထားစိစစ်ခြင်းနှင့် ဝင်ရောက်ခွင့် ထိန်းချုပ်ခြင်း

အထောက်အထား စစ်ဆေးရန် HTTP ခေါင်းစီး (header) တစ်ခုသာ လိုပါသည်။ တောင်းဆိုမှုတိုင်းတွင် Authorization header ပါရမည်ဖြစ်ပြီး ၎င်းထဲ၌ key ID နှင့် secret ပေါင်းထားသော Bearer အထောက်အထား ပါဝင်ပါသည်။ ထိုအထောက်အထားကို Reseller panel ရှိ API Access စာမျက်နှာမှ ထုတ်ပေးပါသည်။ key ID က အကောင့်ကို ခွဲခြားပေးပြီး secret က ထိုအကောင့်ကို သင်ပိုင်ကြောင်း သက်သေပြပါသည်။ secret ကို ဆာဗာဘက်တွင် HMAC စစ်ဆေးမှုဖြင့် အတည်ပြုပါသည်။

secret ကို ဖန်တီးချိန်တွင် တစ်ကြိမ်သာ ပြသပြီး နောက်ပိုင်း ပြန်ကြည့်၍ မရတော့ပါ။ သင့်စနစ်တွင် သုံးနေပြီးသား secret manager ထဲ သိမ်းပြီး environment variable အဖြစ် ထည့်သွင်းပါ။ source control ထဲသို့ မရောက်ပါစေနှင့်။ ပျောက်သွားလျှင် ပြန်ရယူ၍ မရသဖြင့် key အသစ်ဖြင့် လဲလှယ်ရပါမည်။

OAuth redirect၊ session cookie နဲ့ refresh token မရှိပါ။ အချိန်သတ်မှတ်ပြီး လုပ်ဆောင်ပေးရမည့်အရာလည်း မရှိပါ။ ဒါကြောင့် အလိုအလျောက် ချိတ်ဆက်လုပ်ဆောင်ရာမှာ cron job သို့မဟုတ် queue worker က အထောက်အထားတစ်ခုတည်းကို သက်တမ်းတိုးရန်မလိုဘဲ နှစ်ပေါင်းများစွာ အသုံးပြုနိုင်ပါသည်။ သက်တမ်းကုန်ချိန်မရှိသဖြင့် မနက် 3 နာရီမှာ ထပြီး သက်တမ်းတိုးပေးရသည့် အခြေအနေလည်း မရှိပါ။

key တစ်ခုတွင် IP allowlist တွဲထားနိုင်ပါသည်။ allowlist တွင် လိပ်စာ ထည့်ထားသည်နှင့် အခြားလိပ်စာများမှ တောင်းဆိုမှုများကို လုပ်ငန်းဆိုင်ရာ logic မစမီ IP_NOT_ALLOWED နှင့် HTTP 403 ဖြင့် ငြင်းပယ်ပါသည်။ ထို့ကြောင့် အထောက်အထား ပေါက်ကြားသွားသော်လည်း သင့်ဆာဗာများ ပြင်ပတွင် အသုံးမဝင်ပါ။ key လဲလှယ်ခြင်းသည် migration မဟုတ်ဘဲ deploy တစ်ခုသာ ဖြစ်ပါသည်။ key အသစ် ဖန်တီးပါ၊ deploy လုပ်ပါ၊ ပြီးလျှင် key အဟောင်းကို ဖျက်ပါ။

key တစ်ခုသည် Reseller အကောင့်တစ်ခုနှင့် သက်ဆိုင်ပြီး ထိုအကောင့်၏ Wallet မှ ငွေကို သုံးပါသည်။ ထို့ကြောင့် secret ကို browser၊ မိုဘိုင်း bundle သို့မဟုတ် အများမြင် repository ထဲ ဘယ်တော့မှ မထည့်ပါနှင့်။ API ကို သင့် backend မှ ခေါ်ပြီး front end ကို backend နှင့် ဆက်သွယ်စေပါ။ ဤစာတမ်းတွင် ဖော်ပြထားသမျှသည် ဆာဗာမှ ဆာဗာသို့ ခေါ်ဆိုသူကို ယူဆထားပါသည်။

တောင်းဆိုမှု ခေါင်းစီး
Authorization: Bearer <keyId>.<secret>

call တစ်ခုတည်းဖြင့် key စစ်ဆေးခြင်း

GET /account ဖြင့် credential တစ်ခုကို health check လုပ်နိုင်ပါသည်။ တစ်ကြိမ်ခေါ်ရုံဖြင့် အချက်သုံးချက်ကို တစ်ပြိုင်နက် သိရပါမည်။ key ဖြင့် authenticate ဖြစ်မဖြစ်၊ အကောင့် အသုံးပြုခွင့် ရှိမရှိနှင့် မှာမည့် အော်ဒါအတွက် Wallet လက်ကျန်ငွေ လုံလောက်မလောက် တို့ ဖြစ်သည်။ စနစ် boot ချိန်တွင်လည်းကောင်း၊ batch run တိုင်း မစမီလည်းကောင်း ခေါ်ပါ။

အထောက်အထားစိစစ်ခြင်းနှင့် အကောင့်ဆိုင်ရာ လမ်းညွှန်ကို ဖတ်ရှုပါ

အစမှအဆုံး ချိတ်ဆက်ပုံ အပြည့်အစုံ

အလုပ်လုပ်သော integration တစ်ခုကို အဆင့် 4 ဆင့်ဖြင့် ပြီးစီးနိုင်ပါသည်။ အောက်ပါ နမူနာများသည် cURL၊ Node နှင့် PHP ဖြင့် live API ပေါ်တွင် အဆင့်အားလုံးကို run ပြထားပါသည်။ ကိုယ်ပိုင် credential ကို အစားထိုးလိုက်လျှင် ရေးထားသည့်အတိုင်း run နိုင်ပါသည်။

  1. 1

    ပစ္စည်းစာရင်းကို ဖတ်ပါ

    ပင်မအမျိုးအစားမှ အမျိုးအစား၊ ထို့နောက် အမျိုးအစားခွဲအထိ အဆင့်ဆင့် ဖတ်သွားပါ။ ပြီးလျှင် ရောင်းတော့မည့် ပစ္စည်း၏ လက်ရှိဈေးနှုန်းကို ယူပါ။ အမျိုးအစား ဖွဲ့စည်းပုံကို cache လုပ်ထားပါ၊ ဈေးနှုန်းကိုမူ ရောင်းခါနီးတိုင်း အသစ်ပြန်ယူပါ။

  2. 2

    ကစားသူကို စစ်ဆေးပါ

    ငွေမဖြတ်မီ အကောင့်အမှတ်အသားကို အသုံးပြုပြီး ဂိမ်းအတွင်းအမည်နှင့် Region ကို ရှာဖွေအတည်ပြုပါ။ စာရိုက်မှားခြင်းနှင့် Region မကိုက်ညီခြင်းတို့ကို ဤအဆင့်တွင် စစ်ဆေးတွေ့ရှိနိုင်ပါသည်။

  3. 3

    အော်ဒါ ဖန်တီးပါ

    UUID တစ်ခု ထုတ်ပြီး သိမ်းဆည်းထားပါ၊ ထို့နောက် ၎င်းကို order_id အဖြစ် ပို့ပါ။ ဤတန်ဖိုးသည် သင်၏ idempotency key ဖြစ်ပြီး အော်ဒါဖန်တီးသည့် တောင်းဆိုမှုကို ထပ်ပို့ရန် တစ်ခုတည်းသော လုံခြုံသည့် နည်းလမ်း ဖြစ်ပါသည်။

  4. 4

    ပေးပို့မှု အတည်ပြုပါ

    အော်ဒါ status webhook ကို စောင့်ပါ။ ကိုယ်သတ်မှတ်ထားသော timeout ကျော်သည်အထိ pending ဖြစ်နေဆဲ အော်ဒါများအတွက် status ကို ကိုယ်တိုင် ဖတ်စစ်ပါ။

cURL - လုပ်ငန်းစဉ် အပြည့်အစုံကုဒ်ပြရန်
export S2T_KEY="YOUR_KEY_ID.YOUR_KEY_SECRET"
export S2T_BASE="https://shop2topup.com/api/endpoints/v1"

# 1. Find the item you want to sell.
curl -s "$S2T_BASE/catalog/subcategories?categoryId=12" \
  -H "Authorization: Bearer $S2T_KEY"

# 2. Read the exact price you will be charged for it.
curl -s "$S2T_BASE/catalog/subcategory/999/price" \
  -H "Authorization: Bearer $S2T_KEY"

# 3. Confirm the player exists BEFORE any money moves.
curl -s -X POST "$S2T_BASE/player/validate" \
  -H "Authorization: Bearer $S2T_KEY" \
  -H "Content-Type: application/json" \
  -d '{"sub_category_id": 999, "player_id": "123456789", "server": "Asia"}'

# 4. Create the order. order_id is YOUR uuid and YOUR idempotency key.
curl -s -X POST "$S2T_BASE/orders/create" \
  -H "Authorization: Bearer $S2T_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "order_id": "01912345-6789-7abc-8def-0123456789ab",
    "sub_category_id": 999,
    "quantity": 1,
    "requirements": { "player_id": "123456789", "server": "Asia" },
    "expected_unit_price": "0.950000"
  }'

# 5. Read the order back until it leaves "pending".
curl -s "$S2T_BASE/orders/01912345-6789-7abc-8def-0123456789ab" \
  -H "Authorization: Bearer $S2T_KEY"
အစမှအဆုံး လုပ်ငန်းစဉ် (Node.js နမူနာ)ကုဒ်ပြရန်
// Node 18+ — no dependencies, global fetch and global crypto.
const BASE = 'https://shop2topup.com/api/endpoints/v1';
const KEY = process.env.S2T_KEY; // "<keyId>.<secret>", server-side only.

async function call(path, init = {}) {
  const res = await fetch(BASE + path, {
    ...init,
    headers: {
      Authorization: `Bearer ${KEY}`,
      'Content-Type': 'application/json',
      ...(init.headers || {}),
    },
  });

  if (res.status === 429) {
    const wait = Number(res.headers.get('Retry-After') || 5);
    await new Promise((r) => setTimeout(r, wait * 1000));
    return call(path, init);
  }

  const body = await res.json();
  if (!res.ok || body.success === false) {
    throw Object.assign(new Error(body?.error?.code || 'HTTP_' + res.status), {
      code: body?.error?.code,
      status: res.status,
    });
  }
  return body;
}

async function sell({ itemId, categoryId, playerId, server }) {
  // 1 + 2. Catalog and current price.
  const { subcategories } = await call(
    `/catalog/subcategories?categoryId=${categoryId}`,
  );
  const item = subcategories.find((s) => s.item_id === itemId);
  const { price } = await call(`/catalog/subcategory/${itemId}/price`);

  // 3. Player check before charging.
  const { player } = await call('/player/validate', {
    method: 'POST',
    body: JSON.stringify({
      sub_category_id: itemId,
      player_id: playerId,
      server,
    }),
  });

  // 4. Create the order. Persist orderId BEFORE the call so a crash mid-flight
  //    can be replayed with the same uuid instead of double-charging.
  const orderId = crypto.randomUUID();
  await saveIntent(orderId, itemId, playerId);

  const { order } = await call('/orders/create', {
    method: 'POST',
    body: JSON.stringify({
      order_id: orderId,
      sub_category_id: itemId,
      quantity: 1,
      requirements: { player_id: playerId, server },
      expected_unit_price: price.unit_price,
    }),
  });

  // 5. Confirm. A webhook usually beats the poll; the poll is the safety net.
  let status = order.status;
  while (status === 'pending') {
    await new Promise((r) => setTimeout(r, 20000));
    status = (await call(`/orders/${orderId}`)).order.status;
  }

  return { orderId, status, itemName: item?.name, playerName: player.player_name };
}
PHP - လုပ်ငန်းစဉ် အပြည့်အစုံကုဒ်ပြရန်
<?php
// PHP 8 — plain cURL, no SDK required.
const S2T_BASE = 'https://shop2topup.com/api/endpoints/v1';

function s2t(string $path, ?array $body = null): array
{
    $ch = curl_init(S2T_BASE . $path);
    $headers = [
        'Authorization: Bearer ' . getenv('S2T_KEY'),
        'Content-Type: application/json',
    ];

    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER     => $headers,
        CURLOPT_TIMEOUT        => 30,
    ]);

    if ($body !== null) {
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
    }

    $raw    = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    $data = json_decode($raw, true) ?: [];

    if ($status >= 400 || ($data['success'] ?? false) === false) {
        throw new RuntimeException($data['error']['code'] ?? 'HTTP_' . $status);
    }

    return $data;
}

// 1 + 2. Catalog, then the exact price for the item.
$catalog = s2t('/catalog/subcategories?categoryId=12');
$price   = s2t('/catalog/subcategory/999/price');

// 3. Player check before charging.
$player = s2t('/player/validate', [
    'sub_category_id' => 999,
    'player_id'       => '123456789',
    'server'          => 'Asia',
]);

// 4. Create the order with your own uuid as the idempotency key.
$orderId = sprintf(
    '%04x%04x-%04x-7%03x-%04x-%04x%04x%04x',
    random_int(0, 0xffff), random_int(0, 0xffff),
    random_int(0, 0xffff), random_int(0, 0x0fff),
    random_int(0x8000, 0xbfff),
    random_int(0, 0xffff), random_int(0, 0xffff), random_int(0, 0xffff)
);

$order = s2t('/orders/create', [
    'order_id'            => $orderId,
    'sub_category_id'     => 999,
    'quantity'            => 1,
    'requirements'        => ['player_id' => '123456789', 'server' => 'Asia'],
    'expected_unit_price' => $price['price']['unit_price'],
]);

// 5. Read it back until it settles.
do {
    sleep(20);
    $latest = s2t('/orders/' . $orderId);
} while ($latest['order']['status'] === 'pending');

echo $latest['order']['status'];

အောက်ပါ အချက်နှစ်ချက်ကို မပြောင်းလဲဘဲ လိုက်လုပ်သင့်ပါသည်။ create call မခေါ်မီ အော်ဒါ UUID ကို သိမ်းဆည်းထားပါ၊ ခေါ်ပြီးမှ မသိမ်းပါနှင့်။ cache ထဲရှိ ဈေးနှုန်းကို မယုံဘဲ ဈေးနှုန်းကို အသစ်ပြန်ဖတ်ပါ။ ဤအလေ့အကျင့် နှစ်ခုကြောင့် ငွေနှစ်ခါဖြတ်ခြင်းနှင့် PRICE_INCREASED ငြင်းပယ်ခံရခြင်း အားလုံးနီးပါး မဖြစ်တော့ပါ။

Webhooks: အော်ဒါအခြေအနေ ပြန်လည်အကြောင်းကြားချက်များ

HTTPS endpoint တစ်ခုကို မှတ်ပုံတင်ထားလျှင် အော်ဒါရလဒ် ထွက်လာသည်နှင့် ပလက်ဖောင်းက ထိုလိပ်စာသို့ ချက်ချင်း ပို့ပေးပါသည်။ သင့်ဆိုင်ဘက်က အခြေအနေကို ထပ်ခါထပ်ခါ လှမ်းမေးနေစရာ မလိုတော့ဘဲ အကြောင်းကြားချက် ရောက်လာချိန်တွင် တုံ့ပြန်ရုံသာ ဖြစ်ပါမည်။ အကြောင်းကြားချက်တိုင်းကို လက်မှတ်ထိုးထားသဖြင့် ဒေတာကို အသုံးမပြုမီ Shop2Topup ထံမှ အမှန်တကယ် ပို့ထားကြောင်း စစ်ဆေးအတည်ပြုနိုင်သည်။

ဖြစ်ရပ်များ

ဖြစ်ရပ်ပို့သည့်အချိန်
order.completedအော်ဒါထဲမှ ယူနစ်တစ်ခု ပို့ပြီးပါပြီ။ အော်ဒါတစ်ခုလုံး၏ အခြေအနေကို data.status တွင် ကြည့်ပါ။
order.refundedအော်ဒါထဲမှ ယူနစ်တစ်ခုကို Wallet သို့ ငွေပြန်အမ်းပြီးပါပြီ။ ယူနစ်အားလုံး ငွေပြန်အမ်းပြီးမှသာ data.status သည် refunded ဖြစ်ပါမည်။
webhook.testhandler ကို စစ်ဆေးရန် Panel မှ လက်မှတ်ထိုးထားသော စမ်းသပ်ပေးပို့မှုတစ်ခုကို စတင်ခဲ့သည်။

ပေးပို့ရာတွင် ပါဝင်သော ခေါင်းစီးများ

ခေါင်းစီးတန်ဖိုး
Content-Typeapplication/json
X-Shop2Topup-Signaturesha256=<hex> ပုံစံ၊ မူရင်းအတိုင်းရှိသော တောင်းဆိုမှု ကိုယ်ထည် (body) ကို HMAC-SHA256 ဖြင့် တွက်ထားသည့် တန်ဖိုး
X-Shop2Topup-Eventပို့လိုက်သည့် ဖြစ်ရပ်၏ အမည်ဖြစ်သည်။ ဥပမာ အော်ဒါ ပြီးစီးပြီဆိုလျှင် order.completed ဟု ပါလာမည်။
User-Agentshop2topup-webhook/1.0

အကြောင်းကြားချက်တွင် ပါဝင်သော ဒေတာ

အကြောင်းကြားချက်တိုင်း၏ ထိပ်ဆုံးအဆင့်တွင် တူညီသော အကွက်သုံးခု အမြဲ ပါဝင်ပါသည်။ ၎င်းတို့မှာ event၊ timestamp နှင့် data ဖြစ်ပြီး data ၏ ပုံစံသည် အခြေအနေ စစ်ဆေးသည့် API က ပြန်ပေးသော အော်ဒါ အချက်အလက်နှင့် တစ်ထပ်တည်း တူညီသည်။ Voucher ကုဒ်များကို ပြီးစီးပြီဖြစ်သော အော်ဒါတွင်သာ ထည့်ပေးသည်။ player_name မှာ null ဖြစ်နိုင်ပြီး အော်ဒါကို ယူနစ်များအဖြစ် ခွဲထားသည့်အခါတိုင်း sub_transaction_summary ပါလာပါမည်။

POST ဖြင့် ပေးပို့သည့် ဒေတာ - order.completed
{
  "event": "order.completed",
  "timestamp": "2026-03-11T14:30:00.000Z",
  "data": {
    "order_id": "01912345-6789-7abc-8def-0123456789ab",
    "status": "completed",
    "player_id": "123456789",
    "player_name": "ProGamer99",
    "subcategory_name": "FF 100 Diamonds",
    "quantity": 1,
    "charged_amount": "0.950000",
    "currency": "USD",
    "created_at": "2026-03-11T14:28:00.000Z",
    "completed_at": "2026-03-11T14:30:00.000Z",
    "vouchers": [
      {
        "code": "XXXX-YYYY-ZZZZ",
        "serial_number": "SN-9928371",
        "expiry_date": "2027-03-11"
      }
    ],
    "sub_transaction_summary": {
      "total": 1,
      "completed": 1,
      "failed": 0,
      "pending": 0,
      "processing": 0,
      "retrying": 0,
      "refunded": 0
    }
  }
}

လက်မှတ် စစ်ဆေးခြင်း

ပေးပို့မှုတိုင်းတွင် X-Shop2Topup-Signature ခေါင်းစီး ပါဝင်ပါသည်။ ၎င်း၏တန်ဖိုးသည် sha256= ဖြင့် စပြီး နောက်တွင် သင့် webhook လျှို့ဝှက်ကီးဖြင့် ပို့လာသော မူရင်း ဒေတာကို တွက်ထားသော HMAC-SHA256 hex တန်ဖိုး ဆက်လိုက်ပါသည်။ JSON အဖြစ် ခွဲဖတ်ခြင်း မပြုမီ ပို့လာသည့် မူရင်း byte များအတိုင်း စစ်ဆေးပြီး ကြာချိန် ပုံသေဖြစ်သော နှိုင်းယှဉ်နည်းဖြင့် တိုက်စစ်ပါ။ ဒေတာကို အရင်ခွဲဖတ်ပြီးမှ လက်မှတ်စစ်သော handler ကို ပြန်လည်စီထုတ်ထားသည့် ဒေတာဖြင့် လှည့်စားနိုင်သည်။

လက်မှတ်စစ်ပြီး လက်ခံကြောင်း ပြန်ကြားခြင်း (Node.js နမူနာ)
// Express — verify the signature against the RAW body, not the parsed object.
const crypto = require('crypto');

app.post(
  '/shop2topup/webhook',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const signature = req.get('X-Shop2Topup-Signature') || '';
    const expected =
      'sha256=' +
      crypto
        .createHmac('sha256', process.env.S2T_WEBHOOK_SECRET)
        .update(req.body)
        .digest('hex');

    const a = Buffer.from(expected);
    const b = Buffer.from(signature);
    if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
      return res.status(401).end();
    }

    const payload = JSON.parse(req.body.toString('utf8'));

    // Answer fast, then do the work. The delivery times out after 10 seconds.
    res.status(200).end();
    enqueueSettlement(payload.data.order_id, payload.event);
  },
);

ပေးပို့မှုနှင့် ပြန်လည်ပေးပို့မှု

callback ကို တစ်ကြိမ်သာ ပို့ပြီး endpoint က 10 စက္ကန့်အတွင်း ပြန်ဖြေရပါမည်။ အလိုအလျောက် ထပ်ပို့ခြင်းနှင့် exponential backoff မရှိပါ၊ ယင်းမှာ တမင် စီစဉ်ထားခြင်း ဖြစ်သည်။ status endpoint သည် အတည်ဆုံး မှတ်တမ်းဖြစ်သောကြောင့် အော်ဒါအခြေအနေ ပြန်တိုက်စစ်ခြင်းကို မမြင်ရသည့် retry အချိန်ဇယားအပေါ် မမှီခိုဘဲ ကိုယ်တိုင် ထိန်းချုပ်သည့် poll ဖြင့် လုပ်သင့်ပါသည်။ 200 ကို ချက်ချင်း ပြန်ပေးပြီး ကျန်အလုပ်ကို ကိုယ်ပိုင် queue ပေါ်တွင် ဆက်လုပ်ပါ။

ထပ်ရောက်လာလည်း တစ်ကြိမ်သာ လုပ်ဆောင်သော handler များ

handler ကို order_id ဖြင့် key ချထားပြီး တူညီသည့် callback ထပ်ရောက်လာလျှင် ဘာမှ ထပ်မလုပ်စေပါနှင့်။ တစ်ကြိမ်သာ ပို့သော်လည်း ကိုယ်ပိုင် infrastructure က message တစ်ခုတည်းကို worker နှစ်ခုထံ တစ်ခါတစ်ရံ ပေးမိတတ်ပါသည်။ ဖောက်သည်ကို နှစ်ခါ credit ပေးမိသည့် အော်ဒါသည် နောက်ကျမှ credit ပေးသည့် အော်ဒါထက် များစွာ ပိုဆိုးသည့် bug ဖြစ်သည်။

မှတ်ပုံတင်ခြင်းနှင့် secret များ

အကြောင်းကြားချက် လက်ခံမည့် URL ကို မှတ်ပုံတင်ခြင်း၊ လက်မှတ်ပါသော စမ်းသပ် ပေးပို့မှုတစ်ခု ပြုလုပ်ခြင်းနှင့် လက်မှတ်ထိုးရန် လျှို့ဝှက်ကီးကို အသစ်လဲခြင်းတို့ကို အများသုံး API မှတစ်ဆင့် မပြုလုပ်ရဘဲ သင် အကောင့်ဝင်ထားသော Reseller စီမံခန့်ခွဲမှုစာမျက်နှာထဲတွင်သာ ပြုလုပ်ရပါသည်။ HTTPS မဖြစ်မနေ လိုအပ်ပြီး သီးသန့်ကွန်ရက် လိပ်စာများကို လက်မခံပါ။

Reseller စီမံခန့်ခွဲမှုစာမျက်နှာရှိ API အသုံးပြုခွင့် ကဏ္ဍကို ဖွင့်ပါ

တောင်းဆိုနှုန်း ကန့်သတ်ချက်များနှင့် အမှား ကိုင်တွယ်ပုံ

Limit များကို အကောင့်အလိုက် ထုတ်ပြန်ထားပြီး rolling window ဖြင့် ကန့်သတ်ပါသည်။ catalog ဖတ်ယူမှု များသည့် အလုပ်များကို အများဆုံး ခွင့်ပြုထားသည်။ status endpoint များကိုမူ တမင် တင်းကျပ်စွာ ထားပါသည်၊ ၎င်းတို့မှာ polling loop အတွက် မဟုတ်ဘဲ အော်ဒါအခြေအနေ ပြန်တိုက်စစ်ရန် အရန်နည်းလမ်းအဖြစ်သာ ရှိသောကြောင့် ဖြစ်သည်။

လမ်းကြောင်းတောင်းဆိုမှုများအချိန်ကာလရေတွက်သည့် အခြေခံ
GET /catalog/* (5 ခုလုံး)500060 စက္ကန့်အကောင့်အလိုက်
POST /orders/create500060 စက္ကန့်အကောင့်အလိုက်
GET /orders/:orderId360 စက္ကန့်အကောင့် + အော်ဒါ ID အလိုက်
POST /orders/batch260 စက္ကန့်အကောင့်အလိုက်
GET /orders260 စက္ကန့်အကောင့်အလိုက်
GET /account6060 စက္ကန့်အကောင့်အလိုက်
POST /player/validateနေ့စဉ် ကစားသူ စစ်ဆေးမှု ခွဲတမ်း24 နာရီအကောင့်တစ်ခုချင်းအလိုက် (X-RateLimit ခေါင်းစီးများ မပါဝင်ပါ)

ကုန်ပစ္စည်းစာရင်း၊ အော်ဒါနှင့် အကောင့်ဆိုင်ရာ ခေါ်ဆိုမှုများသည် တုံ့ပြန်မှုတိုင်းတွင် X-RateLimit-Limit၊ X-RateLimit-Remaining နှင့် X-RateLimit-Reset တို့ကို ထည့်ပေးပါသည်။ ထို့ကြောင့် စနစ်တကျ ရေးထားသော ပရိုဂရမ်သည် လက်ရှိ အခြေအနေကို ခန့်မှန်းနေစရာ မလိုပါ။ ကန့်သတ်ခံရပြီးမှ မဟုတ်ဘဲ မတိုင်မီကပင် ကျန်ရှိသည့် အရေအတွက်ကို စောင့်ကြည့်၍ ခေါ်ဆိုမှုနှုန်းကို လျှော့ချပါ။ ကစားသူ စစ်ဆေးခြင်းမှာမူ ခြွင်းချက်ဖြစ်သည်။ ၎င်းကို နေ့စဉ် ကစားသူ စစ်ဆေးခွင့် အရေအတွက်ဖြင့်သာ တွက်ချက်ပြီး X-RateLimit ခေါင်းစီးများကို မပို့ပါ။ ထိုအရေအတွက်ကို 429 တုံ့ပြန်မှု၏ body ထဲတွင် ဖော်ပြပေးပါသည်။

နှုန်းကန့်သတ်ခံရသည့် တုံ့ပြန်ချက် - 429
HTTP/1.1 429 Too Many Requests
Retry-After: 45
X-RateLimit-Limit: 2
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1765000000

{
  "success": false,
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Rate limit exceeded. Try again after retry_after seconds.",
    "action": "RETRY_LATER",
    "retryable": true,
    "retry_after": 45,
    "details": {
      "limit": 2,
      "remaining": 0,
      "retry_after": 45,
      "window_seconds": 60
    }
  }
}

အစပိုင်းတွင် တွေ့ရမည့် error များနှင့် ပြင်ဆင်နည်း

မအောင်မြင်သည့် request တိုင်းတွင် HTTP status နှင့်အတူ မပြောင်းလဲသည့် error ကုဒ်တစ်ခု ပြန်ပေးပါသည်။ အောက်ပါတို့မှာ integration အသစ်တစ်ခု ပထမအပတ်အတွင်း ကြုံရလေ့ရှိသည့် error များဖြစ်ပြီး တစ်ခုချင်းစီကို ဖြေရှင်းမည့် ပြင်ဆင်ချက်နှင့် တွဲဖော်ပြထားသည်။

ကုဒ်အခြေအနေ ကုဒ်အဓိပ္ပာယ်ပြင်ဆင်နည်း
INVALID_API_KEY401API Key မမှန်ကန်ပါပေးထားသော API Key သည် စနစ်တွင် လက်ရှိအသုံးပြုနိုင်သည့် မည်သည့် API Key နှင့်မျှ မကိုက်ညီပါ။Key ID နှင့် secret နှစ်ခုလုံး မှန်ကန်ကြောင်း စစ်ဆေးပါ။ လိုအပ်ပါက API Access ပန်နယ်မှ ကီးကို အသစ်ပြန်ထုတ်ပါ။action: FIX_INPUT · retryable: false · retry_after: null
IP_NOT_ALLOWED403IP လိပ်စာသည် ခွင့်ပြုစာရင်းတွင် မပါဝင်ပါတောင်းဆိုမှု ပေးပို့သည့် IP လိပ်စာသည် API Key ၏ ခွင့်ပြုစာရင်းတွင် မပါဝင်ပါ။API Access ကဏ္ဍရှိ ခွင့်ပြုစာရင်းထဲသို့ သင့်ဆာဗာ၏ IP ကို ထည့်ပါ၊ သို့မဟုတ် IP ကန့်သတ်ချက်များကို ဖယ်ရှားပါ။action: FIX_INPUT · retryable: false · retry_after: null
MISSING_REQUIRED_FIELD400လိုအပ်သော field မပါဝင်ပါတောင်းဆိုမှု၏ body တွင် မဖြစ်မနေ ပါရမည့် အကွက်တစ်ခု မပါဝင်ပါ။ ကစားသူဆိုင်ရာ လိုအပ်ချက်များအတွက် ပျောက်နေသော အကွက်အမည်ကို details.field တွင် ဖော်ပြပါသည်။သက်ဆိုင်ရာ endpoint ၏ အသုံးပြုနည်းကို စစ်ဆေးပါ။ ကစားသူအချက်အလက်အတွက် လိုအပ်သော အကွက်များကို GET /catalog/category/:categoryId/requirements တွင် ကြည့်ပြီး လိုအပ်သည့် အကွက်အားလုံးကို ပေးပို့ပါ။action: FIX_INPUT · retryable: false · retry_after: null
INVALID_UUID_FORMAT400UUID ပုံစံ မမှန်ကန်ပါအော်ဒါအတွက် ပေးပို့ထားသော order_id သည် မှန်ကန်သော UUID ပုံစံ မဟုတ်ပါ။မှန်ကန်သည့် UUID ပုံစံတစ်ခုခု (v1, v4, v7 စသည်) ကို သုံးပါ။ ပုံစံ: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx။action: FIX_INPUT · retryable: false · retry_after: null
PLAYER_NOT_FOUND400ကစားသူ ရှာမတွေ့ပါဤ Player ID မရှိကြောင်း ဂိမ်းဘက်မှ အတည်ပြုထားပါသည်။ အတည်ပြုချက် ရရှိမှသာ ဤကုဒ်ကို ပြန်ပေးသည်။ ID ကို စစ်ဆေး၍ မရသည့်အခါ PLAYER_CHECK_UNAVAILABLE ကို ပြန်ရပါမည်။Player ID မှန်မမှန် စစ်ဆေးပါ။ ဂိမ်းအတွက် zone_id လိုအပ်ခြင်း ရှိမရှိကိုလည်း ကြည့်ပါ။action: FIX_INPUT · retryable: false · retry_after: null
PLAYER_CHECK_UNAVAILABLE503ဤဂိမ်းအတွက် Player ID များကို ယခု စစ်ဆေး၍ မရပါလောလောဆယ် ဤဂိမ်း၏ Player ID များကို စစ်ဆေး၍ မရပါ။ Player ID ကို ပယ်ချထားခြင်း မဟုတ်ပါ။retry_after စက္ကန့် စောင့်ပြီးနောက် တူညီသော request ကို ထပ်ပို့ပါ။ ID မှားနေသည်ဟု ဖောက်သည်ကို မပြောပါနှင့်။action: RETRY_LATER · retryable: true · retry_after: 60
REGION_MISMATCH400ဤကစားသူ၏ Region တွင် ဤပစ္စည်းကို လက်ခံ၍ မရပါကစားသူ၏ Region သို့ ဤပစ္စည်းကို ပေးပို့၍ မရပါ။ အမှားတုံ့ပြန်ချက်တွင် player_region နှင့် player_name တို့ ပါဝင်ပါသည်။ကစားသူ၏ Region နှင့် ကိုက်ညီသော ပစ္စည်းကို ရွေးပါ။action: CHOOSE_OTHER · retryable: false · retry_after: null
INSUFFICIENT_BALANCE400Wallet လက်ကျန်ငွေ မလုံလောက်ပါဤအော်ဒါ ပြီးစီးရန် Wallet ထဲတွင် ငွေ မလုံလောက်ပါ။အော်ဒါ မတင်မီ Reload စာမျက်နှာမှ Wallet ကို Top Up လုပ်ပါ။action: TOP_UP · retryable: false · retry_after: null
OUT_OF_STOCK400ပစ္စည်း Stock ပြတ်နေပါသည်တောင်းဆိုထားသော ပစ္စည်းသည် လောလောဆယ် Stock ပြတ်နေပါသည်။နောက်မှ ထပ်စမ်းကြည့်ပါ၊ သို့မဟုတ် အခြားပစ္စည်းကို ရွေးပါ။action: RETRY_LATER · retryable: true · retry_after: null
PRODUCT_UNAVAILABLE409ဤပစ္စည်းကို ယာယီ ဝယ်၍ မရပါပစ္စည်းရှိသော်လည်း လောလောဆယ် ရောင်းချ၍ မရပါ။နောက်မှ ထပ်စမ်းကြည့်ပါ၊ သို့မဟုတ် အခြားပစ္စည်းကို ရွေးပါ။action: RETRY_LATER · retryable: true · retry_after: null
DUPLICATE_ORDER409အော်ဒါ ID ထပ်နေပါသည်ဤ UUID ဖြင့် အော်ဒါရှိပြီးသားဖြစ်ပါသည်။ UUID တူညီသည့် အော်ဒါကို ထပ်မံမဖန်တီးစေရန် ကာကွယ်ထားခြင်းဖြစ်ပါသည်။အော်ဒါအသစ်အတွက် UUID အသစ် ထုတ်ပါ။ ထပ်ပို့စဉ် ဤ error ရပါက ပထမအကြိမ် ပို့ထားသော အော်ဒါကို လက်ခံရရှိပြီး ဖြစ်သည်။ အော်ဒါအသစ် ထပ်မတင်ဘဲ GET /orders/{orderId} ဖြင့် ထိုအော်ဒါကို ဖတ်ပါ။action: CHECK_ORDER · retryable: false · retry_after: null
PRICE_INCREASED400ဈေးနှုန်း မျှော်မှန်းထားသည်ထက် တက်သွားပါသည်လက်ရှိ တစ်ခုချင်း ဈေးနှုန်းသည် တောင်းဆိုမှုတွင် ပါသော expected_unit_price ထက် မြင့်နေပါသည်။GET /catalog/subcategory/:id/price ဖြင့် နောက်ဆုံးဈေးနှုန်းကို ရယူပြီး expected_unit_price ကို ပြင်ဆင်ပါ။action: FIX_INPUT · retryable: false · retry_after: null
RATE_LIMIT_EXCEEDED429တောင်းဆိုမှု အကြိမ်ရေ ကန့်သတ်ချက် ကျော်သွားပါပြီဤ endpoint အတွက် သတ်မှတ်ထားသည့် အသုံးပြုခွင့်အကြိမ်ရေကို ကျော်လွန်သွားပါပြီ။ ကုန်ပစ္စည်းစာရင်း၊ အော်ဒါနှင့် အကောင့်ဆိုင်ရာ တောင်းဆိုမှုအုပ်စုများအတွက် တစ်မိနစ်အလိုက် ကန့်သတ်ချက်ကို သတ်မှတ်ထားပြီး တုံ့ပြန်ချက်တိုင်းတွင် X-RateLimit-Limit၊ X-RateLimit-Remaining နှင့် X-RateLimit-Reset တို့ကို ပေးပို့ပါသည်။ details တွင်လည်း limit၊ remaining (0)၊ retry_after နှင့် window_seconds တို့ကို ထပ်မံဖော်ပြထားပါသည်။ POST /player/validate အတွက်မူ နေ့စဉ် ကစားသူအချက်အလက် စစ်ဆေးခွင့်အကြိမ်ရေဖြင့် တွက်ချက်ပါသည်။ ထို့ကြောင့် X-RateLimit header များကို မပေးပို့ဘဲ 429 တုံ့ပြန်ချက်၏ error အတွင်း၌ limit၊ current၊ remaining၊ reset_at နှင့် reset_in_seconds တို့ကို ဖော်ပြထားပါသည်။ မည်သည့်ကန့်သတ်ချက်ကြောင့် ဖြစ်ပေါ်သည်ဖြစ်စေ စောင့်ဆိုင်းရမည့်အချိန်ကို စက္ကန့်ဖြင့် error.retry_after နှင့် Retry-After header တွင် ဖော်ပြထားပါသည်။ထပ်မံမပို့မီ retry_after သို့မဟုတ် Retry-After header တွင် ဖော်ပြထားသည့် စက္ကန့်အရေအတွက်အတိုင်း စောင့်ပါ။ တစ်မိနစ်အလိုက် ကန့်သတ်ထားသည့် endpoint များတွင် ကန့်သတ်ချက်မပြည့်စေရန် X-RateLimit-Remaining ကို ကြည့်ပြီး ကျန်ရှိသည့် အကြိမ်ရေကို စစ်ဆေးပါ။action: RETRY_LATER · retryable: true · retry_after: စောင့်ဆိုင်းရန် ကျန်ရှိသည့် စက္ကန့်
INTERNAL_ERROR500Server အတွင်းပိုင်း အမှားServer တွင် မမျှော်လင့်ထားသော အမှားတစ်ခု ဖြစ်ပေါ်ခဲ့ပါသည်။retry_after စက္ကန့် ကြာပြီးမှ တောင်းဆိုမှုကို ထပ်ပို့ပါ။ POST /orders/create ဆိုလျှင် ယခင် order_id ကိုပင် ပြန်သုံးပါ၊ သို့မှသာ အော်ဒါကို နှစ်ကြိမ် ဖန်တီးမိခြင်း လုံးဝ မဖြစ်နိုင်ပါ။ ပြဿနာ မပြေလည်သေးပါက အကူအညီအဖွဲ့ကို ဆက်သွယ်ပါ။action: RETRY_LATER · retryable: true · retry_after: 30
error ကုဒ် 42 ခုလုံးနှင့် ပြင်ဆင်နည်းများကို ကိုးကားစာမျက်နှာတွင် ကြည့်ပါ

ချိတ်ဆက်ရာတွင် မေးလေ့ရှိသော မေးခွန်းများနှင့် အဖြေများ

ဤ API ကို ချိတ်ဆက်နေစဉ် ဆော့ဖ်ဝဲရေးသူများ တကယ်မေးလေ့ရှိသည့် မေးခွန်းများ ဖြစ်ပါသည်။ အထောက်အထားစစ်ဆေးခြင်း၊ ထပ်ပို့ခြင်း၊ တစ်ကြိမ်သာ လုပ်ဆောင်စေခြင်း (idempotency)၊ နှုန်းကန့်သတ်ခြင်း၊ အကြောင်းကြားချက်များနှင့် မအောင်မြင်မှု ကိုင်တွယ်ခြင်းတို့ ပါဝင်သည်။

ပြန်လည်ရောင်းချသူ API သည် တောင်းဆိုမှုများကို မည်သို့ အထောက်အထား စိစစ်ပါသလဲ။

Authorization: Bearer <keyId>.<secret> ဟူသော HTTP ခေါင်းစီး တစ်ခုတည်းဖြင့် စိစစ်ပါသည်။ ကီးအတွဲကို ပြန်လည်ရောင်းချသူ panel ရှိ API Access စာမျက်နှာမှ ထုတ်ယူရပြီး လျှို့ဝှက်ချက်ကို ဖန်တီးချိန်တွင် တစ်ကြိမ်သာ ပြသပါသည်။ ဆာဗာက ခေါ်ဆိုမှုတိုင်းတွင် ၎င်းကို HMAC ဖြင့် စစ်ဆေးသည်။ OAuth ပြန်လွှဲပို့ခြင်း၊ ဆက်ရှင် ကွတ်ကီးနှင့် သက်တမ်းတိုးရမည့် တိုကင် မရှိသဖြင့် ပထမဆုံး တောင်းဆိုမှုမှ စ၍ နောက်ပိုင်း တောင်းဆိုမှုတိုင်းအထိ ထိုခေါင်းစီး တစ်ခုတည်းကိုပင် သုံးနိုင်ပါသည်။

ခေါ်ဆိုမည့် ပရိုဂရမ်တွင် မည်သည့် base URL နှင့် API ဗားရှင်းကို သတ်မှတ်ရပါသလဲ။

base URL တစ်ခုသာ ရှိပြီး ၎င်းမှာ တိုက်ရိုက်အသုံးပြုရသည့် စနစ်ပင် ဖြစ်ပါသည်။ စမ်းသပ်ရန် သီးခြားဆာဗာ မရှိသဖြင့် ထိုဆာဗာဖြင့် တည်ဆောက်ပြီး နောက်မှ လဲလှယ်ရမည့် အဆင့်လည်း မရှိပါ။ ပရိုဂရမ်ကို အထက်ပါ v1 base URL သို့ ချိတ်ဆက်ပြီး တောင်းဆိုမှုတိုင်းတွင် Authorization: Bearer <keyId>.<secret> ကို ထည့်ပို့ပါ။ အခြားအရာများ မလုပ်မီ ကီးနှင့် ခေါင်းစီးပုံစံ မှန်ကန်ကြောင်း သေချာစေရန် အကောင့်အချက်အလက်ကို ပြန်ပေးသည့် GET /account ဖြင့် စတင်ပါ။ ငွေ ရွေ့လျားစေသော ခေါ်ဆိုမှုမှာ POST /orders/create တစ်ခုတည်းသာ ဖြစ်သည်။ ထို့ကြောင့် ၎င်းကို နောက်ဆုံးမှ ခေါ်ပါ၊ အသေးဆုံး ပမာဏဖြင့် စမ်းပါ၊ ပရိုဂရမ်ကို စမ်းသပ်ပြင်ဆင်နေဆဲ ကာလတွင် မျှော်မှန်းထားသော ယူနစ်ဈေးနှုန်းကို expected_unit_price အဖြစ် တွဲပို့ပါ။

POST /orders/create ခေါ်ဆိုရာတွင် ထပ်ပို့မိလည်း အော်ဒါ နှစ်ခု မဖြစ်စေရန် ကာကွယ်ပေးသည့် ကီးကို မည်သည့် အကွက်တွင် ထည့်ရပါသလဲ။

order_id ဖြစ်ပါသည်။ ၎င်းမှာ သင့်ဘက်တွင် ကိုယ်တိုင်ထုတ်ပြီး အော်ဒါဖန်တီးသည့် တောင်းဆိုမှုထဲ ထည့်ပို့ရသော UUID တစ်ခုဖြစ်သည်။ ရှိပြီးသား order_id ဖြင့် ထပ်ပို့ပါက API သည် ဒုတိယအော်ဒါ မဖွင့်ဘဲ HTTP 409 နှင့် DUPLICATE_ORDER ကို ပြန်ပေးပါသည်။ ထို့ကြောင့် ပြန်ပို့ရုံဖြင့် ငွေ နှစ်ကြိမ် ဖြတ်ခံရခြင်း ဘယ်တော့မှ မဖြစ်ပါ။ မူလအော်ဒါကို GET /orders/:orderId ဖြင့် ပြန်ကြည့်နိုင်ပါသည်။ ပထမအကြိမ် မပို့မီ UUID ကို ထုတ်ပြီး သိမ်းထားပါ။ အချိန်ကုန်သွားပြီးမှ ထုတ်သော UUID သည် ပြန်ပို့ရန် ကီး မဟုတ်ဘဲ ကီးအသစ်သာ ဖြစ်သွားမည်ဖြစ်ပြီး အဓိပ္ပာယ်တူသော order_id နှစ်ခုကို ဆာဗာက ပေါင်းပေးမည် မဟုတ်ပါ။

တောင်းဆိုမှု အချိန်ကုန်သွားခဲ့ပါသည်။ အော်ဒါ ဖန်တီးပြီးသွားပြီလား။

ခန့်မှန်းမနေဘဲ အော်ဒါအခြေအနေကို ဖတ်ကြည့်၍ သိနိုင်ပါသည်။ ပို့ခဲ့သည့် UUID အတိုင်း GET /orders/:orderId ကို ခေါ်ပါ။ အော်ဒါ ပြန်ထွက်လာပါက လက်ခံပြီးမှ အချိန်ကုန်သွားခြင်း ဖြစ်သဖြင့် ထပ်မပို့ပါနှင့်။ ORDER_NOT_FOUND ရရှိပါက ငွေ ဘာမှ မဖြတ်ခဲ့သဖြင့် ထို UUID အတိုင်းပင် အော်ဒါဖန်တီးသည့် တောင်းဆိုမှုကို ဘေးကင်းစွာ ထပ်ပို့နိုင်ပါသည်။

webhook မှ ပြန်ခေါ်လာသော တောင်းဆိုမှုရှိ လက်မှတ်ကို မည်သို့ စစ်ဆေးရပါသလဲ။

မူရင်း တောင်းဆိုမှု body ပေါ်တွင် HMAC ကို ပြန်တွက်ပြီး X-Shop2Topup-Signature ခေါင်းစီးနှင့် တိုက်စစ်ပါ။ ထိုခေါင်းစီးတွင် sha256=<hex> ပါဝင်သည်။ လက်ခံရရှိသည့် ဘိုက်များကို အတိအကျ ယူ၍ webhook လျှို့ဝှက်ချက်ဖြင့် HMAC-SHA256 တွက်ပါ၊ ရှေ့တွင် sha256= ထည့်ပါ၊ ထို့နောက် အချိန်ကွာခြားမှုမှ အချက်အလက် မပေါက်ကြားစေသော နှိုင်းယှဉ်နည်းဖြင့် တိုက်စစ်ပါ။ JSON ကို ခွဲခြမ်းဖတ်ပြီး ပြန်ရေးထားသော ပုံစံနှင့် ဘယ်တော့မှ မနှိုင်းယှဉ်ပါနှင့်။ ထိုသို့ ပြန်ပြောင်းလိုက်လျှင် ဘိုက်များ ပြောင်းသွားသဖြင့် ဘယ်သောအခါမှ ကိုက်ညီမည် မဟုတ်ပါ။ မကိုက်ညီပါက 401 ဖြင့် ငြင်းပယ်ပါ။ မှန်ကန်သော ပေးပို့မှုကို 10 စက္ကန့်အတွင်း 200 ဖြင့် ပြန်ဖြေပြီး ငွေစာရင်းရှင်းလင်းသည့် အလုပ်ကို နောက်မှ ကိုယ်ပိုင် တန်းစီစနစ်ပေါ်တွင် ဆက်လုပ်ပါ။

ခေါ်ဆိုမှု နှုန်းကန့်သတ်ချက်ကို ကျော်သွားလျှင် ဘာဖြစ်ပါသလဲ။

RATE_LIMIT_EXCEEDED ကုဒ်နှင့် Retry-After ခေါင်းစီး ပါဝင်သော HTTP 429 တုံ့ပြန်မှုကို ရရှိပါမည်။ တုံ့ပြန်မှု body တွင် ထိုစက္ကန့်အရေအတွက်ကိုပင် retry_after အဖြစ် ထပ်ဖော်ပြထားပြီး limit၊ remaining နှင့် window_seconds တို့ကိုလည်း ထည့်ပေးထားပါသည်။ ထိုစက္ကန့်အရေအတွက်အတိုင်း အတိအကျ စောင့်ပြီးမှ တစ်ကြိမ်သာ ပြန်ခေါ်ပါ။ ချက်ချင်း ပြန်မခေါ်ပါနှင့်။ ရေတွက်မှုသည် ချိတ်ဆက်မှုအလိုက် မဟုတ်ဘဲ အကောင့်အလိုက် ဖြစ်သောကြောင့် တူညီသော ခေါ်ဆိုမှုကို ကီး အများအပြားတွင် ခွဲ၍လည်း မပို့ပါနှင့်။

ကစားသူ အကောင့်ကို စစ်ဆေးသည့် POST /player/validate က မည်သည့် အချက်အလက် အကွက်များကို ပြန်ပေးပါသလဲ။

Response ၏ data Object ထဲတွင် player_name ကို ပြန်ပေးပြီး ဂိမ်းက ထုတ်ပြပါက zone_id နှင့် region ကိုပါ ထည့်ပေးပါသည်။ အော်ဒါဖန်တီးခြင်း အဆင့်ကပင် Player ကို ရှာဖွေ၍ Region စစ်ဆေးပြီး Region မကိုက်သော တောင်းဆိုမှုကို Wallet မှ ငွေမဖြတ်မီ REGION_MISMATCH (HTTP 400) ဖြင့် ငြင်းပယ်ပါသည်။ ထို့ကြောင့် လက်ကျန်ငွေကို ကာကွယ်ပေးသည်မှာ ဤ Call မဟုတ်ပါ။ ဝယ်သူ Top Up လုပ်တော့မည့် အကောင့်ကို ပြသရန်နှင့် ID ရိုက်မှားသည်ကို အတည်မပြုမီ ဖမ်းမိရန် player_name ကို ပြန်ဖတ်ခြင်းသည် လက်တွေ့ကျသော တစ်ခုတည်းသော နည်းလမ်း ဖြစ်သောကြောင့် ခေါ်ပါ။ အမည်ကို ဂိမ်းထံမှသာ ယူပြီး ဝယ်သူ ရိုက်ထည့်သည့်အရာမှ မည်သည့်အခါမျှ မယူပါ။

လိုအပ်ချက်များ တုံ့ပြန်ချက်ကို အော်ဒါ တောင်းဆိုချက်ထဲသို့ မည်သို့ ထည့်ရမည်နည်း။

field_name ကို အခြေခံ၍ စီစဉ်ပါ။ GET /catalog/category/:categoryId/requirements မှ ပြန်ရသော ကွက်လပ်တစ်ခုစီသည် POST /orders/create သို့ ပို့မည့် requirements ထဲတွင် ကွက်လပ်တစ်ခုအဖြစ် ပါဝင်ရပါမည်။ ကွက်လပ်တိုင်းတွင် data_type ပါသဖြင့် ဖောင်ဘက်က မည်သည့်ပုံစံ ပြရမည်ကို သိပြီး ဆာဗာဘက်က မည်သည့် အမျိုးအစားသို့ ပြောင်းရမည်ကို သိနိုင်ပါသည်။ single_select နှင့် multi_select ကွက်လပ်များတွင် ခွင့်ပြုထားသော တန်ဖိုးများ ပါလာသဖြင့် စာသား လွတ်လပ်စွာ ရိုက်ရသည့် ကွက်အစား ထိုတန်ဖိုးများထဲမှသာ ရွေးခိုင်းပါ။ စာရင်းကို အော်ဒါတိုင်းတွင် ပြန်မဖတ်ဘဲ အမျိုးအစား တစ်ခုချင်းအလိုက် သိမ်းထားပါ။ အော်ဒါ ဖန်တီးမှုက MISSING_REQUIRED_FIELD ဖြင့် ပြန်လာပါက စာရင်းကို ထပ်မံ ဖတ်ပါ။

ဈေးနှုန်းတက်ကြောင်း PRICE_INCREASED ပြန်လာပါက ကိုယ့်စနစ်က မည်သို့ ကိုင်တွယ်သင့်သနည်း။

ဈေးနှုန်းကို ပြန်ဖတ်ပါ၊ ဆုံးဖြတ်ပါ၊ ထို့နောက်မှ ပြန်ပို့ပါ။ body တူတူကို ဘယ်တော့မှ ထပ်မပို့ပါနှင့်။ PRICE_INCREASED (HTTP 400) ဆိုသည်မှာ လက်ရှိ တစ်ယူနစ်ဈေးနှုန်းသည် သင်ပို့ထားသော expected_unit_price ထက် မြင့်နေသည်ဟု ဆိုလိုပါသည်။ ထို့ကြောင့် အော်ဒါဖန်တီးမှုကို ငြင်းပယ်ခဲ့ပြီး ငွေ တစ်ပြားမှ မဖြတ်ခဲ့ပါ။ error အသေးစိတ်တွင် expected_unit_price နှင့် current_unit_price နှစ်ခုလုံး ပါပြီး ဈေးနှုန်းအဟောင်းဖြင့် မစဉ်းစားဘဲ ထပ်ပို့လျှင် အကြိမ်တိုင်း ငြင်းပယ်ခံရပါမည်။ GET /catalog/subcategory/:itemId/price ကို ဖတ်၍ ဈေးနှုန်းအသစ် အဆင်ပြေသေးလား ဆုံးဖြတ်ပါ။ ထို့နောက် expected_unit_price ကို ပြင်ပြီး order_id တူတူဖြင့် အော်ဒါဖန်တီးမှုကို ပြန်ပို့ပါ။ ငြင်းပယ်ခံရသော တောင်းဆိုမှုက ထို order_id ကို ဘယ်တော့မှ မသုံးစွဲပါ။ expected_unit_price ကို ချန်ထားလျှင် ဤဈေးနှုန်းစစ်ဆေးမှု လုံးဝ ပိတ်သွားပါမည်။ အလိုအလျောက် ချိတ်ဆက်မှုတစ်ခုအတွက် ထိုသို့ လိုလားခဲပါသည်။

တစ်စိတ်တစ်ပိုင်းသာ ပို့ပြီးသော အော်ဒါကို order response တွင် ဘယ်လို ပြသလဲ။

status ကို partial အဖြစ် ပြန်ပေးပြီး ခွဲခြမ်းမှုကို sub_transaction_summary တွင် အသေးစိတ် ဖော်ပြထားပါသည်။ ထို object က unit များကို completed (ပြီးစီးပြီ)၊ refunded (ငွေပြန်အမ်းပြီး) သို့မဟုတ် pending (စောင့်ဆိုင်းဆဲ) အဖြစ် ရေတွက်ပြီး ထိုသုံးမျိုး ပေါင်းလျှင် total နှင့် အမြဲ ညီပါသည်။ sub_transactions တွင်မူ unit တစ်ခုချင်းကို ၎င်း၏ status ဖြင့် စာရင်းပြထားပါသည်။ မပို့ရသေး၊ ငွေလည်း ပြန်မအမ်းရသေးသော unit သည် pending အဖြစ် ဆက်ရှိနေပါမည်။ pending ကို နောက်ဆုံးအခြေအနေ မဟုတ်ဟု မှတ်ယူပြီး ဆက်စောင့်ပါ။ completed၊ partial နှင့် refunded ကိုမူ နောက်ဆုံးအခြေအနေအဖြစ် မှတ်ယူပါ။ failed (မအောင်မြင်)၊ processing နှင့် retrying ရေတွက်ချက်များကို လိုက်ဖက်မှုအတွက်သာ ထားရှိပြီး အမြဲ 0 ဖြစ်ပါသည်။ order.completed နှင့် order.refunded callback များတွင်လည်း ထိုအကျဉ်းချုပ် ပါသဖြင့် အတည်ပြုပြီးသော payload ဖြင့် ထပ်မဖတ်ဘဲ အော်ဒါကို စာရင်းပိတ်နိုင်ပါသည်။

allowlist တွင် မပါသော လိပ်စာမှ ပို့သည့် တောင်းဆိုမှုကို မည်သို့ ပြန်ဖြေသလဲ။

လုပ်ငန်းဆိုင်ရာ စစ်ဆေးမှုများ မစတင်မီ HTTP 403 နှင့် IP_NOT_ALLOWED ကုဒ်ကို ပြန်ပေးပါသည်။ API Key တွင် IP ခွင့်ပြုစာရင်း ဗလာမဟုတ်လျှင် ဤစစ်ဆေးမှု အမြဲ အလုပ်လုပ်သဖြင့် ကီး ပေါက်ကြားသွားလျှင်ပင် ကိုယ့်ဘက်မှ အပြင်ထွက်သော လိပ်စာများမှလွဲ၍ မည်သည့်နေရာတွင်မျှ အသုံးမဝင်ပါ။ မက်ဆေ့ချ် စာသားကို မမှီဘဲ error.code အပေါ် အခြေခံ၍ ခွဲခြားပါ။ အသုံးပြုနေသော စနစ်တွင် IP_NOT_ALLOWED ရုတ်တရက် ပေါ်လာပါက ကီး ပျက်သွားသည်ဟု မယူဆပါနှင့်။ NAT ဂိတ်ဝေးအသစ် သို့မဟုတ် worker ကွန်ရက်ခွဲအသစ်ကဲ့သို့ အပြင်ထွက်လိပ်စာ ပြောင်းသွားခြင်းဟု မှတ်ယူပါ။ အပြင်ထွက်လိပ်စာ အမှန်တကယ် မတည်ငြိမ်မှသာ ခွင့်ပြုစာရင်းကို ဗလာထားပါ။

အော်ဒါတစ်ခု ပြီးစီးရန် အချိန် ဘယ်လောက်ကြာသလဲ။

ပြီးစီးမှုကို ချက်ချင်းဖြစ်သည်ဟု မယူဆဘဲ asynchronous အဖြစ်သာ သဘောထားပါ။ POST /orders/create သည် အော်ဒါကို လက်ခံပြီး Wallet မှ ငွေဖြတ်ပြီးသည်နှင့် ပုံမှန်အားဖြင့် pending (စောင့်ဆိုင်းဆဲ) status ဖြင့် ပြန်လာပါသည်။ ထို့နောက် ပေးပို့ခြင်းကို သီးခြား worker များက ဆောင်ရွက်ပြီး နောက်ဆုံးအခြေအနေကို webhook ဖြင့် သို့မဟုတ် နောက်တစ်ကြိမ် status ဖတ်သည့်အခါ သိရပါမည်။ ဝယ်သူဘက်မှ လာသော HTTP request ကို နောက်ဆုံးအခြေအနေအထိ စောင့်ခိုင်းမထားပါနှင့်။ request ကို လက်ခံ၍ ဝယ်သူကို ပြန်ဖြေပြီးမှ စာရင်းရှင်းခြင်းကို သီးခြား ဆောင်ရွက်ပါ။

အကောင့်ဖွင့်၊ API Key ထုတ်ပြီး live စတင်ပါ

အကောင့်ဖွင့်ပြီးနောက် API ကို ခေါ်ရန် အတည်ပြုချက်စောင့်ရသည့် တန်းစီခြင်း မရှိသလို စောင့်ဆိုင်းရသည့် ကာလလည်း မရှိပါ။ Reseller အကောင့်ဖွင့်၊ API Access စာမျက်နှာတွင် Key ထုတ်ပြီး Wallet ကို Top Up လုပ်ပါ။ ပထမဆုံး အော်ဒါကို ထိုနေ့ချင်းမှာပင် ပို့နိုင်ပါသည်။

ဤပရောဂျက်၏ developer မဟုတ်ပါက လုပ်ငန်းပိုင်းဆိုင်ရာ အချက်များကို ဤနေရာတွင် ဖတ်နိုင်ပါသည်: SHOP2TOPUP Reseller အစီအစဉ် စာမျက်နှာ.

ပြန်လည်ရောင်းချသူများအတွက် ဂိမ်းငွေဖြည့်ခြင်းနှင့် Voucher ကုဒ် API၊ REST အသုံးပြုနည်း လမ်းညွှန်