# Background Service Worker

## Tong quan

Background Service Worker la thanh phan chay ngam cua extension, chiu trach nhiem quan ly toan bo logic nen tang: nhan dien shop, lang nghe su kien trinh duyet, xu ly messaging, ket noi Socket.io, quan ly database PouchDB, va tu dong lam moi phien dang nhap.

**Entry point:** `src/background/index.js`

## Cau truc thu muc

```
src/background/
├── index.js                    # Entry point chinh
├── get.js                      # Lay cau hinh dich vu tu API
├── shopee/
│   ├── index.js                # Nhan dien shop Shopee + khoi tao dich vu
│   └── task.js                 # Tac vu dinh ky (flashsale sync, seller auth sync)
├── tiktok/
│   └── index.js                # Nhan dien shop TikTok
├── lazada/
│   └── index.js                # Nhan dien shop Lazada
├── bridge/
│   ├── event.js                # Xu ly event tu runtime.onMessage (legacy)
│   ├── global.js               # Xu ly message tu webext-bridge + keepAlive
│   └── listener/
│       ├── index.js            # Dang ky webRequest listeners
│       ├── utils.js            # Parse request headers/query
│       ├── shopee/
│       │   ├── product.js      # Bat header request san pham Shopee
│       │   ├── chat.js         # Loc tu cam trong chat Shopee
│       │   └── print.js        # Log in don Shopee
│       ├── tiktok/
│       │   └── print.js        # Log in don TikTok
│       └── lazada/
│           └── print.js        # Log in don Lazada
├── fetch/
│   └── metric/
│       ├── index.js            # Entry metric
│       ├── shopee.js           # Thu thap metric don hang Shopee
│       ├── tiktok.js           # (TODO) Metric TikTok
│       └── lazada.js           # (TODO) Metric Lazada
├── service/
│   ├── index.js                # getUserInfo, getAffiliateUrl tu storage
│   └── user.js                 # Lam moi phien dang nhap (session refresh)
├── socket/
│   ├── index.js                # Khoi tao ket noi socket (app + worker)
│   ├── app.js                  # Socket.io App connection
│   └── worker.js               # Socket.io Worker fetch service
└── store/
    ├── index.js                # In-memory store (request payload, fetch bucket)
    └── shop.js                 # ShopIdentify class cho Shopee/TikTok/Lazada
```

## Trinh tu khoi tao

Khi extension duoc cai dat hoac trinh duyet khoi dong, Service Worker bat dau thuc thi `src/background/index.js` theo trinh tu sau:

### Giai doan 1: Khoi tao ngay lap tuc (t = 0s)

```
loggerBackground.log('Service Worker started')
```

Ghi log thoi gian bat dau Service Worker.

### Giai doan 2: Khoi tao dich vu chinh (t = 1s)

Sau 1 giay (`delay(1000)`), ham `serviceStart()` duoc goi, khoi chay **dong thoi** cac dich vu sau (moi dich vu chay doc lap, khong cho nhau):

| Thu tu | Dich vu | Ham | Mo ta |
|--------|---------|-----|-------|
| 1 | Data Cleanup | `modelCleanerData()` | Xoa du lieu cu qua 30-45 ngay |
| 2 | Index Loader | `modelIndexLoader()` | Tao PouchDB indexes cho 12 model |
| 3 | Shopee Identify | `shopeeShopIdentify()` | Nhan dien shop Shopee dang dang nhap |
| 4 | TikTok Identify | `tiktokShopIdentify()` | Nhan dien shop TikTok dang dang nhap |
| 5 | Lazada Identify | `lazadaShopIdentify()` | Nhan dien shop Lazada dang dang nhap |
| 6 | Event Service | `eventService()` | Dang ky runtime.onMessage handler |
| 7 | Listener Service | `listenerService()` | Dang ky webRequest listeners |
| 8 | Bridge Service | `brideService()` | Dang ky webext-bridge handlers + keepAlive |
| 9 | Socket Service | `socketService()` | Ket noi Socket.io (App + Worker) |

Sau khi khoi tao xong, mot `setInterval` 60 giay duoc thiet lap de chay lai nhan dien shop (xem muc "Tac vu dinh ky").

### Giai doan 3: Session refresh va Shopee service (t = 60s)

Sau 60 giay (`delay(60_000)`), thuc hien:

1. **`userSessionRefresh()`** - Kiem tra va lam moi token dang nhap AutoShopee
2. **`shopeeService()`** - Khoi tao dich vu Shopee (flashsale sync, seller auth sync, alarms)

```
delay(1000)  ──► serviceStart()  ──► [9 dich vu dong thoi]
                                  ──► setInterval(60s) shop identify

delay(60000) ──► userSessionRefresh()
             ──► shopeeService()
```

## Nhan dien shop (Shop Identification)

### Co che hoat dong

Extension nhan dien shop bang cach goi API cua tung nen tang de lay thong tin seller dang dang nhap tren trinh duyet hien tai. Thong tin duoc luu vao `ShopIdentify` instance trong memory va (tuy nen tang) persist vao storage.

### Shopee (`src/background/shopee/index.js`)

```
shopeeShopIdentify():
  1. Goi getShopeeSellerFallbackInfo() - lay shopId, username tu API/cookie Shopee
  2. Luu vao ShopeeShopIdentify (chi trong memory, khong sync storage)
```

### TikTok (`src/background/tiktok/index.js`)

```
tiktokShopIdentify():
  1. Goi getTiktokSellerInfo() - lay seller_id, shop_name tu TikTok Seller API
  2. Luu vao TiktokShopIdentify (sync ca memory + storage)
```

### Lazada (`src/background/lazada/index.js`)

```
lazadaShopIdentify():
  1. Goi getLazadaSellerInfo() - lay shopId, shopName tu Lazada Seller API
  2. Luu vao LazadaShopIdentify (sync ca memory + storage)
```

### ShopIdentify class (`src/background/store/shop.js`)

Moi nen tang co mot instance `ShopIdentify` luu tru:
- `shopId` - ID cua shop
- `shopName` - Ten shop/username
- `isSync` - Co tu dong persist vao storage hay khong

| Instance | isSync | Ghi chu |
|----------|--------|---------|
| `ShopeeShopIdentify` | `false` | Chi luu trong memory |
| `TiktokShopIdentify` | `true` | Persist vao `tiktokSetting` |
| `LazadaShopIdentify` | `true` | Persist vao `lazadaSetting` |

## Event Listeners

### 1. webRequest Listeners (`src/background/bridge/listener/`)

Dang ky qua `browserWebrequest.onBeforeSendHeaders.addListener` de bat HTTP request truoc khi gui di.

#### Shopee Product Request

| Listener | URL Pattern | Ham xu ly | Mo ta |
|----------|------------|-----------|-------|
| Product Get | `SHOPEE_URLS.PRODUCT_GET_PC` | `onFetchProductId` | Bat header cua request lay thong tin san pham |
| Search Items | `SHOPEE_URLS.SEARCH_SEARCH_ITEMS` | `onFetchSearchProduct` | Bat header cua request tim kiem san pham |
| Client Global | `SHOPEE_URLS.CLIENT_GLOBAL` | `onFetchClientAll` | Bat header cua tat ca request client |

**Muc dich:** Luu lai request headers (bao gom anti-bot token) de tai su dung khi extension can goi API Shopee truc tiep. Du lieu duoc luu vao `RequestProductPayload`, `RequestSearchPayload`, `RequestShopeeClient` (in-memory store).

**Co che ignore:** Neu header chua key `SHOPEE_HEADER_KEYS.IGNORE` thi bo qua request do (tranh bat lai request do chinh extension tao ra).

#### Print Order Listeners

| Listener | URL Pattern | Ham xu ly | Mo ta |
|----------|------------|-----------|-------|
| Shopee Print | `SHOPEE_URLS.SELLER_ORDER_PRINT_PDF` | `onSellerPrintOrderShopee` | Log khi seller in don Shopee |
| TikTok Print | `TIKTOK_URLS.SELLER_PRINT_PDF` | `onSellerPrintOrderTiktok` | Log khi seller in don TikTok |
| Lazada Print | `LAZADA_URLS.SELLER_PRINT_PDF` | `onSellerPrintOrderLazada` | Log khi seller in don Lazada |

**Muc dich:** Ghi nhan lich su in don hang vao PouchDB thong qua `pushXxxPrintLogJob()`. Chi ghi log khi setting `saveHistoryPrint` tuong ung duoc bat.

#### Chat Filter (hien tai tat)

```javascript
if (false) {  // Hien tai da tat
  browserWebrequest.onBeforeRequest.addListener(
    onSendChatMessage,
    { urls: [SHOPEE_URLS.CHAT_WEBCHAT] },
    ['blocking', 'requestBody'],
  );
}
```

Khi bat, se chan tin nhan chat Shopee chua tu cam (bad word). Danh sach tu cam lay tu `appSetting.badWord`.

### 2. Runtime Message Listener (`src/background/bridge/event.js`)

Dang ky qua `chrome.runtime.onMessage` (legacy messaging, khong phai webext-bridge).

Xu ly 3 loai event:

| Event | Ham xu ly | Mo ta |
|-------|-----------|-------|
| `EVENT_SHOPEE_GET_HEADER_SHOPEE` | `handleShopeeHeaderEvent` | Tra ve danh sach headers da bat (theo `by`: 'product' hoac 'search') |
| `EVENT_GET_SCRIPT_URL` | `handleScriptUrlEvent` | Chuyen doi script path thanh chrome.runtime URL |
| `EVENT_FETCH_API_AUTOSHOPEE` | `handleFetchApiEvent` | Proxy API call qua fetch adapter (bypass CORS) |

**`handleFetchApiEvent`** su dung Axios voi `fetchAdapter` de thuc hien HTTP request tu Service Worker (noi khong co XMLHttpRequest).

### 3. Tab Update Listener

Dang ky trong `brideService()`:

```javascript
tabOnUpdate(onBridgerTabChange);
```

Khi tab thay doi (URL, trang thai), gui message `EVENT_TAB_ON_CHANGE` den content script cua tab do thong qua webext-bridge.

### 4. KeepAlive Connection

```javascript
chrome.runtime.onConnect.addListener((port) => {
  if (port.name === 'keepAlive') { ... }
});
```

Content scripts ket noi port `keepAlive` de giu Service Worker song (tranh bi Chrome MV3 tat sau 5 phut khong hoat dong). Nhan message `ping` tu content scripts.

## Bridge Message Handlers (webext-bridge)

Dang ky trong `brideService()` (`src/background/bridge/global.js`) qua `onMessage()` cua webext-bridge.

| Event Name | Ham xu ly | Mo ta |
|------------|-----------|-------|
| `EVENT_SHOPEE_LISTEN_FETCH` | `onBridgeShopeeListenFetch` | Nhan du lieu fetch listener tu content script, day vao FetchListenerBucket. Dong thoi xu ly select variation de luu stock san pham |
| `EVENT_SHOPEE_GET_PRODUCT` | `onBridgeShopeeGetProduct` | Tra ve thong tin san pham Shopee tu cache (CacheShopeeProduct) |
| `EVENT_GET_SCRIPT_URL` | `onBridgeGetScriptUrl` | Chuyen doi script path thanh chrome.runtime URL |
| `EVENT_OPEN_POPUP` | `onBridgeOpenPopup` | Mo popup/options page tai path chi dinh |
| `EVENT_GET_USER_INFO` | `onBridgeGetUserInfo` | Tra ve thong tin user tu storage (token, plan, userData) |
| `EVENT_GET_AFFILIATE_PLATFORM` | `onBridgeGetAffiliatePlatform` | Lay affiliate URL cho nen tang chi dinh (shopee/tiki/lazada) |
| `EVENT_GET_LOCAL_SETTING` | `onBridgeGetLocalSetting` | Doc gia tri setting tu storage theo key |
| `EVENT_SHOPEE_SAVE_PRODUCT` | `onBridgeShopeeSaveProduct` | Luu thong tin san pham Shopee vao cache |
| `EVENT_SHOPEE_GET_HEADER_SHOPEE` | `onBridgeShopeeGetHeaderShopee` | Tra ve headers da bat (product hoac search) |
| `EVENT_SHOPEE_GET_AFFILIATE_CHAT` | `onBridgeShopeeGetAffiliateChat` | Render noi dung chat affiliate |

### Xu ly Fetch Listener chi tiet

`onBridgeShopeeListenFetch` nhan du lieu tu content script Shopee client:

1. **Loc URL:** Bo qua cac URL trong `listUrlBucketIgnore` (API v1, notification, login, ...)
2. **Day vao bucket:** Luu URL + JSON response vao `FetchListenerBucketShopee`
3. **Flush tu dong:** Khi bucket dat limit (mac dinh 100), tu dong gui du lieu len worker API
4. **Xu ly select variation:** Neu URL la `pdp/cart_panel/select_variation_pc` hoac `pdp/get_pc_vsku`, trích xuất thong tin stock san pham va luu vao 3 lop cache: `ShopeeProductStock` (memory) -> `CacheShopeeStock` (ttl-localstorage) -> `KVShopeeProductStock` (KV storage)

### Background -> Content Script Messages

Tu background gui den content script qua webext-bridge (`src/app/bridge/background/content.js`):

| Event Name | Ham | Mo ta |
|------------|-----|-------|
| `EVENT_TAB_FETCH_URL` | `bridgeTabFetchShopeeUrl` | Yeu cau content script fetch URL (bypass CORS) |
| `EVENT_TAB_ON_CHANGE` | `bridgeTabOnChange` | Thong bao tab thay doi den content script |

## Socket.io Connection

### Khoi tao (`src/background/socket/index.js`)

Socket duoc khoi tao dua tren cau hinh tu server (`getConfigService()`):

```
socketService():
  1. Doc setting: useShopManager, workerFetchService
  2. Lay configService tu API (fetchExtensionInfo)
  3. Neu configService.connectApp = true -> ket noi Socket App
  4. Neu !useShopManager && workerFetchService && configService.fetchUrl -> ket noi Socket Worker
```

### Socket App (`src/background/socket/app.js`)

- **URL:** Lay tu `socketUrl` (config env), mac dinh `wss://ws.autoshopee.com`
- **Transport:** WebSocket only
- **Reconnect:** 5 lan, cach 2 giay
- **Xac thuc:** Gui `extension:auth` event voi payload chua token, username, userId, version, manifest
- **Muc dich:** Dong bo trang thai, thong bao real-time, dieu khien tu xa

### Socket Worker (`src/background/socket/worker.js`)

- **URL:** Lay tu `workerSocketUrl` (config env)
- **Transport:** WebSocket only
- **Reconnect:** 5 lan, cach 2 giay

Class `WorkerFetchUrlService` quan ly viec fetch URL theo yeu cau cua server:

**Luong hoat dong:**

```
1. Ket noi socket worker
2. Kiem tra seller dang nhap (getShopeeSellerFallbackInfo)
3. Neu chua dang nhap -> WORKER_NO_READY_LOGIN, dung lai
4. Neu da dang nhap -> set workerName = username, workerId = shopId
5. Gui worker-set-indentify len server
6. Gui worker-ready-up thong bao san sang nhan job

Khi nhan job (fetch-url-job-recived):
  1. Kiem tra worker dang connected + active + ready
  2. Tim tab dang mo trang Shopee (getTabIdReadyFetch)
  3. Neu khong co tab -> setWorkerDown, thu lai sau 10s
  4. Gui yeu cau fetch URL den content script qua bridge
  5. Kiem tra crawler detection
  6. Neu bi phat hien bot -> setWorkerDown, thu lai sau 60s
  7. Gui ket qua ve server qua handlderJobFetch
```

**Socket Worker Events:**

| Event | Huong | Mo ta |
|-------|-------|-------|
| `connect` | Server -> Client | Ket noi thanh cong, gui identify + ready up |
| `disconnected` | Server -> Client | Mat ket noi, set worker down |
| `fetch-url-job-recived` | Server -> Client | Nhan job fetch URL |
| `fetch-url-worker-id` | Server -> Client | Nhan job fetch URL theo worker ID |
| `worker-set-indentify` | Client -> Server | Gui thong tin worker (name, id, version, ...) |
| `worker-ready-up` | Client -> Server | Thong bao worker san sang |
| `worker-ready-down` | Client -> Server | Thong bao worker khong san sang |

## PouchDB va Model Loader

### Khoi tao Indexes (`modelIndexLoader`)

Khi Service Worker bat dau, `modelIndexLoader()` tao PouchDB indexes cho 12 model:

| Model | Module |
|-------|--------|
| TikTok Shop | `models/tiktok/shop` |
| TikTok Product | `models/tiktok/product` |
| Shopee Shop | `models/shopee/shop` |
| Shopee Product | `models/shopee/product` |
| Shopee Seller Shop | `models/shopee/seller/shop` |
| Shopee Seller Product | `models/shopee/seller/product` |
| Shopee Seller Flashsale | `models/shopee/seller/flashsale` |
| Shopee Marketing Sender | `models/shopee/marketing/sender` |
| Group Product | `models/group` |
| Product Mapping | `models/mapping` |
| Usage (Shopee + TikTok) | `models/usage` |
| Order PDF (Shopee + TikTok + Lazada) | `models/orderPdf` |

### Don dep du lieu cu (`modelCleanerData`)

Chay khi Service Worker khoi dong, xoa du lieu cu:

| Model | Thoi gian xoa |
|-------|---------------|
| `UsageShopee` | > 30 ngay |
| `UsageTiktok` | > 30 ngay |
| `ShopeeOrderPdfPrintJob` | > 45 ngay |
| `LazadaOrderPdfPrintJob` | > 45 ngay |
| `TiktokOrderPdfPrintJob` | > 45 ngay |

## Lam moi phien dang nhap (Session Refresh)

File: `src/background/service/user.js`

`userSessionRefresh()` chay sau 60 giay khi Service Worker khoi dong:

```
1. Doc thong tin user tu storage (token, username, password)
2. Neu chua dang nhap (khong co token/username/password) -> bo qua
3. Goi getUserInfo() API de kiem tra token con hop le
4. Neu API tra ve loi 403 (token het han):
   a. Goi loginUser() voi username + password + profileId
   b. Neu dang nhap thanh cong:
      - Luu token moi vao userSetting.userToken
      - Luu userData moi vao userSetting.userData
      - Luu userId moi vao userSetting.userId
      - Luu extensionPlan (neu co)
   c. Neu dang nhap that bai -> log loi
5. Neu API thanh cong (token con hop le) -> khong lam gi
```

## Tac vu dinh ky

### Nhan dien shop (moi 60 giay)

Sau khi `serviceStart()` hoan tat, mot `setInterval` 60 giay chay lai:
- `shopeeShopIdentify()`
- `tiktokShopIdentify()`
- `lazadaShopIdentify()`

**Muc dich:** Cap nhat thong tin shop khi nguoi dung chuyen tai khoan hoac dang nhap/dang xuat tren cac nen tang.

### Shopee Alarms (`src/background/shopee/index.js`)

Dang ky qua `chrome.alarms` (chi chay sau khi `userSessionRefresh` thanh cong):

| Alarm | Chu ky | Ham xu ly | Mo ta |
|-------|--------|-----------|-------|
| `task:shopee:flashsale` | 15 phut | `shopeeFlashsaleSync()` | Dong bo flash sale tu dinh va tu lich |
| `task:shopee:seller` | 10 phut | `shopeeSellerAuthSync()` | Dong bo thong tin seller (cookies, profile) len server |

### Shopee Flashsale Sync (`src/background/shopee/task.js`)

```
shopeeFlashsaleSync():
  1. Doc setting: shopeeFlashsaleCampaignAuto, shopeeFlashsaleSchedulerAuto
  2. Lay shopId tu getShopeeSellerFallbackInfo()
  3. Neu isAutoCampaign = true -> createScheduleFlashsaleFromCampaignShopId(shopId)
  4. Neu isAutoScheduler = true -> createFlashsaleFromSchedulerShopId(shopId)
```

### Shopee Seller Auth Sync (`src/background/shopee/task.js`)

```
shopeeSellerAuthSync():
  1. Lay cookies Shopee seller (getShopeeSellerCookies)
  2. Lay thong tin seller (shopId, username, phone, email, image)
  3. Ma hoa payload bang enCryptApiData
  4. Gui len server qua shopeeShopSyncFromBackground
```

## Cau hinh dich vu tu xa (`src/background/get.js`)

`getConfigService()` goi API `fetchExtensionInfo()` de lay cau hinh tu server:

| Config | Kieu | Mo ta |
|--------|------|-------|
| `connectApp` | boolean | Bat/tat ket noi Socket App |
| `connectWorker` | boolean | Bat/tat ket noi Socket Worker |
| `fetchUrl` | boolean | Bat/tat tinh nang fetch URL worker |
| `fetchListenerActive` | boolean | Bat/tat fetch listener bucket |
| `fetchListenerLimit` | number | Gioi han so luong item trong bucket truoc khi flush |

## In-memory Store (`src/background/store/index.js`)

| Store | Kieu | Mo ta |
|-------|------|-------|
| `RequestProductPayload` | `GetListPayload` | Luu headers cua request lay san pham Shopee |
| `RequestSearchPayload` | `GetListPayload` | Luu headers cua request tim kiem Shopee |
| `RequestShopeeClient` | `GetListPayload` | Luu headers cua request client Shopee |
| `FetchListenerBucketShopee` | `FetchListenerBucket` | Buffer du lieu fetch listener, tu dong flush len server |
| `ShopeeProductStock` | `Map` | Cache stock san pham theo key `productId-shopId` |

## Xu ly loi

Tat ca dich vu trong `serviceStart()` va `delay(60_000)` deu duoc wrap trong `.catch()` rieng biet. Dieu nay dam bao:

- **Mot dich vu loi khong anh huong dich vu khac** - moi service chay doc lap
- **Log co cau truc** - Moi loi duoc ghi voi format thong nhat:
  ```javascript
  loggerBackground.error({
    msg: 'BACKGROUND_SERVICE_ERROR',
    service: 'ten_dich_vu',
    error,
  });
  ```
- **Khong crash Service Worker** - Bat ky loi nao cung duoc bat va ghi log thay vi de Service Worker dung

### Worker Fetch Error Recovery

`WorkerFetchUrlService` co co che tu phuc hoi:

| Loi | Hanh dong | Thoi gian phuc hoi |
|-----|-----------|-------------------|
| Khong tim thay tab Shopee | `setWorkerDown('NO_TAB_ID')` | 10 giay |
| Bi phat hien crawler/bot | `setWorkerDown('CRAWLER_DETECTED')` | 60 giay |
| Mat ket noi socket | `isConnected = false, isActive = false` | Tu dong reconnect (5 lan, 2s/lan) |

## So do tong the

```
┌─────────────────────────────────────────────────────────────┐
│                    SERVICE WORKER                            │
│                                                              │
│  t=0s   Log khoi dong                                        │
│                                                              │
│  t=1s   serviceStart()                                       │
│         ├── modelCleanerData()     Xoa du lieu cu            │
│         ├── modelIndexLoader()     Tao PouchDB indexes       │
│         ├── shopeeShopIdentify()   Nhan dien Shopee          │
│         ├── tiktokShopIdentify()   Nhan dien TikTok          │
│         ├── lazadaShopIdentify()   Nhan dien Lazada          │
│         ├── eventService()         runtime.onMessage          │
│         ├── listenerService()      webRequest listeners       │
│         ├── brideService()         webext-bridge + keepAlive  │
│         ├── socketService()        Socket.io (App + Worker)   │
│         └── setInterval(60s)       Lap lai nhan dien shop     │
│                                                              │
│  t=60s  userSessionRefresh()       Lam moi token              │
│         shopeeService()            Alarms + Flashsale sync    │
│           ├── alarm: 15 phut       Flashsale sync             │
│           └── alarm: 10 phut       Seller auth sync           │
│                                                              │
│  Lien tuc:                                                   │
│         webRequest ──► Bat headers, log in don                │
│         webext-bridge ──► Xu ly message tu content/popup      │
│         Socket.io ──► Nhan job fetch URL, dong bo             │
│         keepAlive ──► Giu Service Worker song                 │
└─────────────────────────────────────────────────────────────┘
```

## Metric thu thap (TODO)

File `src/background/fetch/metric/` chua logic thu thap so lieu don hang. Hien tai chi Shopee da implement (`fetchMetricOrderShopee`), TikTok va Lazada chua duoc implement.

**Shopee Metric:**

| Truong | Mo ta |
|--------|-------|
| `unpaid` | Don chua thanh toan |
| `unprocessed` | Don chua xu ly |
| `processed` | Don da xu ly |
| `cancel` | Don yeu cau huy |
| `return` | Don hoan tra chua xu ly |

## Affiliate URL (`src/background/service/index.js`)

Class `AffiliateGenerator` quan ly viec tao affiliate link cho 3 nen tang (Shopee, Tiki, Lazada):
- Gioi han toi da 5 lan tao link trong 1 phien
- Sau 5 lan, ngung tao trong 2 gio
- URL duoc giai ma tu API qua `deCryptApiData`
