SmartPOS Developersເຂົ້າລະບົບ

ເອກະສານ API

Base URL: https://pos-v2.luayver.com. ຫົວຂໍ້ທີ່ໝາຍ “ໃຊ້ໄດ້ແລ້ວ” ເອີ້ນໃຊ້ໄດ້ຈິງໃນປັດຈຸບັນ; “ກຳລັງພັດທະນາ” ແມ່ນແຜນງານ ຍັງເອີ້ນໃຊ້ບໍ່ໄດ້.

ຄູ່ມືເລີ່ມຕົ້ນໃຊ້ງານ · ໃຊ້ໄດ້ແລ້ວ

ປະຕິບັດຕາມຂັ້ນຕອນລຸ່ມນີ້ ເພື່ອເຂົ້າລະບົບ, ກວດເບິ່ງຮ້ານ ແລະ API ທີ່ທ່ານໄດ້ຮັບອະນຸຍາດ, ແລະ ກຽມລະບົບຂອງທ່ານໃຫ້ພ້ອມເຊື່ອມຕໍ່. ຕົວຢ່າງໃຊ້ curl; ພາສາອື່ນໃຊ້ຫຼັກການດຽວກັນ.

  1. ຂໍບັນຊີນັກພັດທະນາ

    ບໍ່ມີການສະໝັກເອງ. ຕິດຕໍ່ຜູ້ດູແລລະບົບ SmartPOS ເພື່ອຂໍບັນຊີ ໂດຍແຈ້ງຊື່ບໍລິສັດ, ຮ້ານທີ່ຕ້ອງການເຊື່ອມ ແລະ ຂໍ້ມູນທີ່ລະບົບຂອງທ່ານຕ້ອງໃຊ້ (ເຊັ່ນ ອ່ານສິນຄ້າ, ສົ່ງອໍເດີ). ຜູ້ດູແລລະບົບຈະສົ່ງຊື່ຜູ້ໃຊ້ ແລະ ລະຫັດຜ່ານໃຫ້ທ່ານ.

  2. ເຂົ້າລະບົບໃນເວັບໄຊນີ້

    ເປີດໜ້າ ເຂົ້າລະບົບ ແລ້ວປ້ອນຊື່ຜູ້ໃຊ້ ແລະ ລະຫັດຜ່ານ. ໜ້າ ບັນຊີ ຈະສະແດງຮ້ານທີ່ໄດ້ຮັບອະນຸຍາດ ແລະ ລາຍການ API ທີ່ທ່ານເຊື່ອມໄດ້. ຖ້າຍັງບໍ່ມີລາຍການ ໃຫ້ແຈ້ງຜູ້ດູແລລະບົບ.

  3. ຂໍ token ຈາກໂປຣແກຣມຂອງທ່ານ

    ສົ່ງຊື່ຜູ້ໃຊ້ ແລະ ລະຫັດຜ່ານໄປທີ່ /api/v2/dev/auth/login. ຄຳຕອບມີ token (ຂຶ້ນຕົ້ນດ້ວຍ dvs_) ແລະ expiresAt. token ໃຊ້ໄດ້ 12 ຊົ່ວໂມງ; ເມື່ອໝົດອາຍຸ ໃຫ້ເຂົ້າລະບົບໃໝ່. ເກັບ token ໄວ້ຝັ່ງ server ເທົ່ານັ້ນ ຫ້າມໃສ່ໃນແອັບມືຖື ຫຼື ໜ້າເວັບ.

    curl -X POST https://pos-v2.luayver.com/api/v2/dev/auth/login \
      -H "content-type: application/json" \
      -d '{ "username": "acme.dev", "password": "…" }'
    
    # ຄຳຕອບ
    { "token": "dvs_…", "expiresAt": "2026-11-14T03:00:00.000Z" }
  4. ກວດເບິ່ງບັນຊີ, ຮ້ານ ແລະ API ທີ່ອະນຸຍາດ

    ສົ່ງ token ໃນ header Authorization: Bearer <token>. field shop_code ແມ່ນຮ້ານທີ່ທ່ານເຊື່ອມໄດ້; field apis ແມ່ນລາຍການ API ທີ່ອະນຸຍາດ (key, label, method, path). ໃຫ້ລະບົບຂອງທ່ານອ່ານ apis ທຸກຄັ້ງທີ່ເລີ່ມເຮັດວຽກ ເພາະຜູ້ດູແລລະບົບອາດປ່ຽນລາຍການໄດ້ໂດຍບໍ່ຕ້ອງເຂົ້າລະບົບໃໝ່.

    curl https://pos-v2.luayver.com/api/v2/dev/auth/me -H "authorization: Bearer dvs_…"
    
    # ຄຳຕອບ (ຕົວຢ່າງ)
    {
      "username": "acme.dev",
      "shop_code": "e2e",
      "shop_name": "ຮ້ານທົດສອບ",
      "scopes": ["products:read", "orders:write"],
      "apis": [
        { "key": "products:read", "label": "ອ່ານສິນຄ້າ ແລະ ລາຄາ", "method": "GET", "path": "/api/open/v1/products" },
        { "key": "orders:write", "label": "ສົ່ງອໍເດີເຂົ້າຮ້ານ (ເປັນບິນພັກ)", "method": "POST", "path": "/api/open/v1/orders" }
      ]
    }
  5. ກຽມການສົ່ງຊ້ຳຢ່າງປອດໄພ

    ທຸກຄຳຂໍທີ່ປ່ຽນຂໍ້ມູນ ຕ້ອງມີ header Idempotency-Key ທີ່ບໍ່ຊ້ຳກັນຕໍ່ການກະທຳໜຶ່ງ (ເຊັ່ນ UUID ຂອງອໍເດີໃນລະບົບທ່ານ). ຖ້າເຄືອຂ່າຍຂາດ ໃຫ້ສົ່ງໃໝ່ດ້ວຍ key ເດີມ; ຂໍ້ມູນຈະປ່ຽນພຽງຄັ້ງດຽວ. ເບິ່ງລາຍລະອຽດໃນຫົວຂໍ້ Idempotency-Key ລຸ່ມນີ້.

    curl -X POST https://pos-v2.luayver.com/api/open/v1/orders \
      -H "authorization: Bearer <API key>" \
      -H "Idempotency-Key: 7f3c2a90-…" \
      -H "content-type: application/json" -d '{ … }'
  6. ອອກຈາກລະບົບ

    ເມື່ອບໍ່ໃຊ້ token ແລ້ວ ໃຫ້ຍົກເລີກມັນ. ການປ່ຽນລະຫັດຜ່ານ, ປ່ຽນຮ້ານ ຫຼື ປິດບັນຊີ ໂດຍຜູ້ດູແລລະບົບ ຈະຍົກເລີກທຸກ token ຂອງບັນຊີທັນທີ.

    curl -X POST https://pos-v2.luayver.com/api/v2/dev/auth/logout -H "authorization: Bearer dvs_…"
  • ເສັ້ນທາງ /api/open/v1 ຍັງເອີ້ນໃຊ້ບໍ່ໄດ້: ຈະເປີດພ້ອມ API key (ເບິ່ງຫົວຂໍ້ ແອັບ ແລະ API key). ຕອນນີ້ ທ່ານສາມາດເຂົ້າລະບົບ, ອ່ານລາຍການ API ທີ່ອະນຸຍາດ ແລະ ຮັບເຫດການຜ່ານ webhook ໄດ້ແລ້ວ.
  • ທ່ານເອີ້ນໄດ້ສະເພາະ API ທີ່ຢູ່ໃນ apis ແລະ ສະເພາະຮ້ານ shop_code ຂອງທ່ານເທົ່ານັ້ນ.
  • ໜ້າ ສະຖານະ ສະແດງວ່າ API ໃຊ້ງານໄດ້ ແລະ ຕອບໄວເທົ່າໃດ.

ການຢືນຢັນຕົວຕົນ (Session) · ໃຊ້ໄດ້ແລ້ວ

ບັນຊີນັກພັດທະນາ ແຍກຈາກບັນຊີ POS ເພື່ອຄວາມປອດໄພ: ຜູ້ດູແລລະບົບເປັນຜູ້ສ້າງບັນຊີ ແລະ ກຳນົດຮ້ານທີ່ທ່ານເຊື່ອມໄດ້. ເຂົ້າລະບົບດ້ວຍຊື່ຜູ້ໃຊ້ ແລະ ລະຫັດຜ່ານ ແລ້ວສົ່ງ token ໃນ header Authorization: Bearer <token>. token ຂອງ POS ໃຊ້ຢູ່ບ່ອນນີ້ບໍ່ໄດ້ ແລະ token ນັກພັດທະນາ ໃຊ້ກັບ POS ບໍ່ໄດ້.

MethodPathAuthລາຍລະອຽດ
POST/api/v2/dev/auth/login
{ "username": "acme.dev", "password": "…" }
ບໍ່ຕ້ອງການເຂົ້າລະບົບ; ຕອບກັບ token (ຂຶ້ນຕົ້ນດ້ວຍ dvs_) ແລະ ເວລາໝົດອາຍຸ
GET/api/v2/dev/auth/meBearerຂໍ້ມູນບັນຊີ ແລະ ຮ້ານທີ່ໄດ້ຮັບອະນຸຍາດ
POST/api/v2/dev/auth/logoutBearerອອກຈາກລະບົບ ແລະ ຍົກເລີກ token
GET/api/v2/healthບໍ່ຕ້ອງການສະຖານະຂອງ API ແລະ ຖານຂໍ້ມູນ

ການສົ່ງຊ້ຳຢ່າງປອດໄພ (Idempotency-Key) · ໃຊ້ໄດ້ແລ້ວ

ທຸກຄຳຂໍທີ່ປ່ຽນຂໍ້ມູນ ສົ່ງ header Idempotency-Key (ຄ່າບໍ່ຊ້ຳກັນຕໍ່ການກະທຳໜຶ່ງ). ການສົ່ງຊ້ຳດ້ວຍ key ເດີມ ຈະໄດ້ຄຳຕອບເດີມ ແລະ ຂໍ້ມູນປ່ຽນພຽງຄັ້ງດຽວ.

  • 425 — ຄຳຂໍທຳອິດຍັງດຳເນີນການຢູ່: ລໍຖ້າແລ້ວສົ່ງໃໝ່
  • 409 idempotency_applied — ການກະທຳນີ້ສຳເລັດແລ້ວ: ຢ່າສົ່ງໃໝ່
  • 422 — key ເດີມ ແຕ່ເນື້ອໃນຄຳຂໍຕ່າງກັນ

ລະຫັດຂໍ້ຜິດພາດ · ໃຊ້ໄດ້ແລ້ວ

ເມື່ອຄຳຂໍບໍ່ສຳເລັດ API ຕອບເປັນ JSON { "error": "<ລະຫັດ>" } ພ້ອມ HTTP status ລຸ່ມນີ້.

  • 400 invalid_input — ຂໍ້ມູນທີ່ສົ່ງມາບໍ່ຖືກຮູບແບບ; field issues ບອກວ່າຜິດບ່ອນໃດ
  • 401 invalid_credentials — ຊື່ຜູ້ໃຊ້ ຫຼື ລະຫັດຜ່ານບໍ່ຖືກ, ຫຼື ບັນຊີຖືກປິດ
  • 401 unauthorized — ບໍ່ມີ token, token ໝົດອາຍຸ ຫຼື ຖືກຍົກເລີກ: ໃຫ້ເຂົ້າລະບົບໃໝ່
  • 429 too_many_attempts — ປ້ອນລະຫັດຜ່ານຜິດຫຼາຍເທື່ອ: ລໍຖ້າ 15 ນາທີ ແລ້ວລອງໃໝ່
  • 5xx — ຂໍ້ຜິດພາດຝັ່ງ server: ລໍຖ້າຈັກໜ່ອຍ ແລ້ວສົ່ງໃໝ່ດ້ວຍ Idempotency-Key ເດີມ

ແອັບ ແລະ API key · ກຳລັງພັດທະນາ

ລົງທະບຽນແອັບ, ຮັບ key ແບບທົດສອບ (sk_test_) ແລະ ແບບໃຊ້ງານຈິງ (sk_live_), ກຳນົດຂອບເຂດສິດ (scope) ແລະ ເຈົ້າຂອງຮ້ານເປັນຜູ້ອະນຸຍາດ. ເສັ້ນທາງ API ສາທາລະນະ: /api/open/v1.

Webhook ແລະ ເຫດການ · ໃຊ້ໄດ້ແລ້ວ

SmartPOS ສົ່ງເຫດການຂອງຮ້ານທ່ານ ໄປຫາ URL (https) ຂອງທ່ານ ທັນທີທີ່ເກີດຂຶ້ນ (ພາຍໃນປະມານ 15 ວິນາທີ). ຕ້ອງມີສິດ webhooks:manage ຈາກຜູ້ດູແລລະບົບ. ຈັດການ webhook ໄດ້ໃນໜ້າ Webhook ຂອງເວັບໄຊນີ້ ຫຼື ຜ່ານ API ລຸ່ມນີ້.

  1. ເຫດການທີ່ມີ

    sale.completed — ຂາຍສຳເລັດ (ບິນໃໝ່, ມີລາຍການສິນຄ້າ ແລະ ຍອດລວມ). sale.voided — ຍົກເລີກບິນ. price.changed — ປ່ຽນລາຄາຂາຍສິນຄ້າ (ລາຄາເກົ່າ ແລະ ໃໝ່). webhook.ping — ເຫດການທົດສອບຈາກປຸ່ມ ທົດສອບ.

    POST https://your-app.example/webhook
    webhook-id: 3f1c…            (ລະຫັດເຫດການ: ໃຊ້ກັນການຮັບຊ້ຳ)
    webhook-timestamp: 1763020800
    webhook-signature: v1,K5o…=
    
    {
      "id": "3f1c…",
      "type": "sale.completed",
      "occurred_at": "2026-11-13T08:00:00.000Z",
      "data": {
        "receipt_no": "T1-000123", "doc_no": "INV-2026-0042", "branch_id": "…",
        "sold_at": "2026-11-13T08:00:00.000Z", "currency": "LAK", "total": 150000,
        "items": [{ "product_id": "…", "variant_id": null, "name": "ນ້ຳດື່ມ", "qty": 2,
                    "unit_price": 5000, "discount": 0, "line_total": 10000 }]
      }
    }
  2. ກວດລາຍເຊັນທຸກຄັ້ງ

    ລາຍເຊັນເປັນແບບ Standard Webhooks: HMAC-SHA256 ຂອງ "webhook-id.webhook-timestamp.body" ດ້ວຍ secret (ສ່ວນຫຼັງ whsec_ ຖອດລະຫັດ base64). ໃຊ້ body ດິບທີ່ໄດ້ຮັບ ກ່ອນແປງເປັນ JSON. ປະຕິເສດຖ້າລາຍເຊັນບໍ່ກົງ ຫຼື timestamp ຫ່າງຈາກເວລາປັດຈຸບັນເກີນ 5 ນາທີ. ຫຼື ໃຊ້ library standardwebhooks ທີ່ມີໃຫ້ຫຼາຍພາສາ.

    // Node.js
    import { createHmac, timingSafeEqual } from "node:crypto";
    
    function verify(secret, headers, rawBody) {
      const key = Buffer.from(secret.replace("whsec_", ""), "base64");
      const id = headers["webhook-id"], ts = headers["webhook-timestamp"];
      if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
      const want = "v1," + createHmac("sha256", key).update(`${id}.${ts}.${rawBody}`).digest("base64");
      const got = headers["webhook-signature"].split(" ").find((s) => s.length === want.length) ?? "";
      return got.length === want.length && timingSafeEqual(Buffer.from(got), Buffer.from(want));
    }
  3. ຕອບກັບໃຫ້ໄວ ແລະ ຮັບຊ້ຳໄດ້

    ຕອບ HTTP 2xx ພາຍໃນ 10 ວິນາທີ ແລ້ວຈຶ່ງປະມວນຜົນພາຍຫຼັງ. ຖ້າບໍ່ໄດ້ 2xx ລະບົບຈະສົ່ງໃໝ່ຫຼັງ 1, 5, 30, 120 ແລະ 720 ນາທີ; ຫຼັງຈາກນັ້ນ ຈະໝາຍວ່າ ສົ່ງບໍ່ສຳເລັດ ແລະ ທ່ານກົດ ສົ່ງໃໝ່ ໄດ້ໃນໜ້າ Webhook. ເຫດການດຽວກັນອາດມາຮອດຫຼາຍກວ່າໜຶ່ງເທື່ອ: ໃຫ້ກວດ webhook-id ແລະ ຂ້າມອັນທີ່ເຄີຍປະມວນຜົນແລ້ວ.

MethodPathAuthລາຍລະອຽດ
GET/api/v2/dev/webhooksBearerລາຍການ webhook, ເຫດການທີ່ມີ ແລະ ປະຫວັດການສົ່ງ 50 ລາຍການລ່າສຸດ
POST/api/v2/dev/webhooks
{ "url": "https://your-app.example/webhook", "events": ["sale.completed", "price.changed"] }
Bearerເພີ່ມ webhook; ຕອບກັບ secret (whsec_…) ພຽງຄັ້ງດຽວ
DELETE/api/v2/dev/webhooks/:idBearerລົບ webhook
POST/api/v2/dev/webhooks/:id/pingBearerສົ່ງເຫດການທົດສອບ webhook.ping ທັນທີ ແລະ ຕອບຜົນການສົ່ງ
POST/api/v2/dev/webhooks/deliveries/:id/resendBearerສົ່ງລາຍການທີ່ບໍ່ສຳເລັດໃໝ່ (webhook-id ເດີມ)
  • 403 scope_missing — ບັນຊີຍັງບໍ່ມີສິດ webhooks:manage
  • 403 no_shop — ຍັງບໍ່ໄດ້ກຳນົດຮ້ານໃຫ້ບັນຊີ
  • 409 too_many_webhooks — ຮ້ານໜຶ່ງມີ webhook ໄດ້ສູງສຸດ 5 ອັນ
  • ປະຫວັດການສົ່ງ ເກັບໄວ້ 30 ວັນ

ຮ້ານທົດສອບ (Sandbox) · ກຳລັງພັດທະນາ

ນັກພັດທະນາແຕ່ລະຄົນຈະໄດ້ຮ້ານທົດສອບແຍກຕ່າງຫາກ ທີ່ມີສິນຄ້າຕົວຢ່າງ; key ທົດສອບບໍ່ສາມາດເຂົ້າເຖິງຮ້ານຈິງໄດ້.