NON-PRODUCTION

Mission — tài liệu ghép client

Nhiệm vụ của user trên lobby (không phải HTTP game). Client gọi POST /api/v2/rpc trên game-api-gateway, body mã hóa AES giống daily bonus / gold digger. Có 4 kỳ: ngày, tuần, tháng, và sự kiện (khoảng thời gian cố định).

1. Tổng quan

MụcGiá trị
Gatewaygame-api-gateway · POST /api/v2/rpc
AuthJWT game trong header, middleware GameJWTVerify
Prefix method/mission — /list, /detail, /claim
TimezoneServer UTC+7
Claim1 lần / snapshot. Thưởng gửi chip mail, không cộng chip ngay trên response.
Server tự lọc mission theo VIP / country của user. Client không gửi user_id — lấy từ JWT. description và progress_text đã localize theo country publisher. Client không dịch thêm. Progress online được flush khi user mở list / detail / claim.

2. Period types

Mỗi mission có period_type. Dùng để chia tab. Không hardcode label — map từ value dưới đây.

valueKỳReset / hết hạn
dailyHàng ngàyfrom_time = 0h hôm nay UTC+7, to_time = +24h
weeklyHàng tuầnĐầu tuần → +7 ngày (UTC+7)
monthlyHàng thángĐầu tháng → cuối tháng (UTC+7)
eventSự kiện đặc biệtKhoảng cố định CMS chỉ định. Dùng from_time / to_time trên từng mission
Countdown trên card = to_time - now (unix seconds). Khi hết hạn, list lần sau sẽ không còn mission đó. Không giả định mọi mission reset lúc 0h — weekly / monthly / event sống lâu hơn 1 ngày.

3. Auth & envelope

Giống mọi RPC lobby: decrypt data → JSON {"method","data"} → handler → encrypt {"code","msg"}.

POST /api/v2/rpc
Authorization: Bearer <access_token>
Content-Type: application/json

decrypt → {
  "method": "/mission/list",
  "data": {}
}

success → HTTP 200, encrypted { "code": 0, "msg": { ... } }
error   → HTTP 500, encrypted { "code": ..., "msg": ... }

Popup lỗi dùng code = 1000 và msg là chuỗi i18n (khi parse được error từ server).

4. List missions đang chạy

method: /mission/list

data có thể rỗng {} (trả tất cả period) hoặc lọc 1 tab:

data:
{}
// hoặc
{ "period_type": "daily" }     // daily | weekly | monthly | event
                               // sai / lạ → list rỗng cho filter đó, không lỗi
msg:
{
  "missions": [
    {
      "snapshot_id": 1001,
      "name": "Play 10 games",
      "description": "Chơi 10 ván hôm nay",
      "period_type": "daily",
      "from_time": 1756227600,
      "to_time": 1756314000,
      "progress": 4,
      "target": 10,
      "percent": 40,
      "progress_text": "",
      "completed": false,
      "claimed": false,
      "reward_amount": 1000,
      "icon_url": "https://cdn.example.com/missions/play-10.png"
    }
  ]
}
FieldÝ nghĩa
snapshot_idID snapshot đang chạy. Dùng khi detail / claim. Không dùng template id.
nameTitle hiển thị (CMS soạn).
descriptionMô tả đã localize theo country publisher của user. Client không dịch thêm.
period_typedaily / weekly / monthly / event. Chia tab.
from_time / to_timeUnix seconds. Kỳ của mission này. Dùng countdown / “còn lại”.
progressTiến độ thô (số ván / chip / giây online / tiền nạp…).
targetMốc cần đạt. Hiện progress / target (vd. 4 / 10).
percent0–100, đã cap. Progress bar.
progress_textDòng phụ server đã localize. Rỗng "" với mission thường. Ranking: ngày nhận thưởng tuần sau, kèm tag Unity rich text <color=#e3b602>…</color>. Hiện nguyên chuỗi, không tự ghép ngày.
completedtrue khi đủ target.
claimedĐã nhận thưởng.
reward_amountChip sẽ nhận nếu claim bây giờ. Chip cố định hoặc cashback % progress hiện tại.
icon_urlURL icon mission (CMS soạn, khuyến nghị 50×50, mỗi chiều tối đa 200px). Có thể rỗng "" — khi đó client dùng icon mặc định lưu local, không ẩn card.
icon_url rỗng / thiếu = không có ảnh CMS. Client luôn có 1 icon default (asset local), chỉ thay bằng URL khi chuỗi không rỗng.
Nút Claim chỉ hiện khi completed === true và claimed === false. Claim xong set claimed = true local hoặc gọi lại list.
Ranking mission: progress_text không rỗng, ví dụ Automatically receive the reward on <color=#e3b602>15-09</color> (ngày = đầu tuần sau, format DD-MM, đã dịch theo country). Render rich text; không parse tay ngày.
List trả mọi mission đang active (daily hôm nay + weekly tuần này + monthly tháng này + event còn hạn), không chỉ daily. Muốn 4 tab: gọi 1 lần data: {} rồi group theo period_type (khuyến nghị), hoặc gọi 4 lần với từng period_type.

5. Mission detail

method: /mission/detail

Một mission theo snapshot_id lấy từ list. Shape mission giống từng phần tử trong list (kèm target, progress_text).

data:
{ "snapshot_id": 1001 }

msg:
{
  "mission": {
    "snapshot_id": 1001,
    "name": "Weekly ranking",
    "description": "Top bảng xếp hạng tuần này",
    "period_type": "weekly",
    "from_time": 1756227600,
    "to_time": 1756832400,
    "progress": 12000,
    "target": 1,
    "percent": 100,
    "progress_text": "Automatically receive the reward on <color=#e3b602>15-09</color>",
    "completed": true,
    "claimed": false,
    "reward_amount": 5000,
    "icon_url": "https://cdn.example.com/missions/ranking.png"
  }
}

6. Claim reward

method: /mission/claim

data:
{ "snapshot_id": 1001 }

msg success:
{ "snapshot_id": 1001, "reward_amount": 1000 }

7. Gợi ý UI

  1. Vào lobby / event → gọi /mission/list với {}.
  2. Chia 4 tab theo period_type: Daily / Weekly / Monthly / Event. Tab không có mission thì ẩn hoặc empty state.
  3. Card: icon = icon_url (rỗng → icon default local), title = name, sub = description, bar = percent, số = progress / target, chip = reward_amount.
  4. Nếu progress_text không rỗng: hiện dòng đó (rich text) thay vì tự viết “nhận thưởng ngày …”. Ranking thưởng tuần sau, không claim tay.
  5. Tap card → /mission/detail với snapshot_id để refresh progress trước khi hiện popup chi tiết.
  6. Countdown = to_time (unix). Weekly / monthly / event nên hiện “còn X ngày/giờ”.
  7. Completed chưa claim: CTA Claim. Đã claim: badge Claimed, disable.
  8. Sau claim: cập nhật card hoặc list lại. Có thể poll mail / chip nếu UI đang hiện số dư.
  9. Đừng cache list sang ngày khác — daily đổi mỗi 0h UTC+7; weekly/monthly/event đổi theo to_time.
Không hardcode target type, tên, hay mốc. CMS đổi nội dung / kỳ / thưởng. Client chỉ tin field list trả về.

8. Error codes

Tình huốngHành vi client
JWT hết hạn / decrypt failcode -3 — login lại
Thiếu tokencode -4
snapshot_id invalid / body list / detail không parse đượccode -2 invalid input
Đã claimpopup i18n ERROR_EVENT_REWARD_RECEIVED
Chưa hoàn thànhpopup i18n ERROR_NOT_TIME
Snapshot không tồn tại / đã hết hạn (claim)popup i18n ERROR_DATA_NOT_FOUND
Detail snapshot không còn / id lạcode -1 — đóng popup, gọi lại list
Lỗi kháccode -1 unknown

9. Checklist