---
# System prepended metadata

title: 0.登入功能相關 API
tags: [NeutecLife App]

---

---
tags: NeutecLife App
---

# 0.登入功能相關 API

:::info
目錄：
<a href="https://hackmd.io/FStSBTFdRhac3tsDr8OyiA">0.登入功能相關 API 文件</a>
<a href="https://hackmd.io/coOyibBDRYqJpluQIQFYmg">1.首頁功能相關 API 文件</a>
<a href="https://hackmd.io/-A3kGYJ8SHyjegBROlwJow">2-1.分類列表：分類列表頁、借書＆歸還 API 文件</a>
<a href="https://hackmd.io/boCGrFpsR0CciLYEXS-kxw">2-2.分類列表：借物 API 文件</a>
<a href="https://hackmd.io/jBWDb0OaT_KV-_ducdzqsQ">2-3.分類列表：會議室＆英文課 API 文件</a>
<a href="https://hackmd.io/FhZ89ZDxSbOK8oYslEXuCA">3.最新消息 API 文件</a>
<a href="https://hackmd.io/SSAxobFGQEC8lyHiu485iQ">4.通知 API 文件</a>
<a href="https://hackmd.io/Fz8d0LtbS2iwhuI3QmmzYQ">5.我的 API 文件</a>



> [time=Jan 4, 2024]
* `更新`  Document init
> [time=Apr 19, 2024]
* `更新` 登入機制、錯誤代碼
> [time=Jun 12, 2024]
* `更新` 統一型態：不使用0與1代表Bool，將number修正為int型態
> [time=Jul 2, 2024]
* `更新` [logout API](#logout)去除email參數
* `新增` [websocket訂閱機制](#websocket主動推送資料訂閱機制)
> [time=Jul 10, 2024]
* `新增` [forgotPasswordCheckToken API](#forgotPasswordCheckToken) 忘記密碼信件Token驗證 forgotPassword checkToken
> [time=Jul 26, 2024]
* `更新` App登入流程圖，加入斷線重連動線
> [time=Jul 29, 2024]
* `更新` 日期格式統一採用 yyyy/M/d
> [time=Jul 31, 2024]
* `更新` loginPage 移除 accountInfo module 並新增 handshake module
> [time=Aug 8, 2024]
* `更新` [login](#login) 與 [checkAuthToken](#checkAuthToken) 新增測試參數testTimeout與testHttpStatusCode
* `更新` [forgotPassword](#forgotPassword) 欄位desc修改為toast，並新增isPositive欄位
> [time=Nov 4, 2024]
* `新增` 所有websocket API皆可額外帶入timeout參數
> [time=Dec 2, 2024]
* `更新` 錯誤代碼
> [time=Feb 2, 2025]
* `更新` 在登出後，app端需刪除favorite資料
> [time=Feb 2, 2025]
* `更新` updatePassowrd API拆成兩份，分別由forceUpdatePasswordPage與updatePasswordPage個別操作
> [time=Jul 23, 2025]
* `新增` getVersion API，判斷App是否需要被更新
> [time=Jul 23, 2025]
* `更新` 所有 Http POST 類型 API Timeout 統一 3 秒
> [time=Aug 26, 2025]
* `更新` getVersion API request新增參數osVersion，response新增參數images
----
:::

#### Remark
```
所有websocket API皆可額外帶入timeout參數做測試用途：

參數名稱：timeout
值：0-9 代表延遲回應的秒數，可模擬網路不穩回應變慢的情況
   99 代表Server端出現未知的錯誤，可模擬Server端某功能出現異常的情況

‼️ 所有 Http POST 類型 API Timeout 統一 3 秒。‼️
 ```


## API 列表
<a href='https://hackmd.io/_uploads/SkXLEFBFlx.png' target='_blank'>點我看原圖</a>
![NeutecLife_登入流程_0814.drawio](https://hackmd.io/_uploads/SkXLEFBFlx.png)
<a href='https://hackmd.io/_uploads/SkXLEFBFlx.png' target='_blank'>點我看原圖</a>

----
## 0.登入功能相關 API
### ✅ login
URL:`https://{domain name}/api/guest/login/user`

Method: `POST Content`

Descirption: `員工登入（透過帳密登入）`

**Request** 

| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| email       | string   | Y       | 員工帳號email |
| password    | string   | Y       | 員工密碼 |
| deviceUuid  | string   | Y       | 手機唯一編號 |
| pushToken   | string   |         | 推播Token (來自Pushy的Token)<br><b>關聯 [updatePushToken API](#%E2%9C%85-updatePushToken)，此值來源僅能透過app所儲存的值</b> |
| testTimeout | int      |         | dev與uat環境測試專用，代表sleep秒數 |
| testHttpStatusCode | int   |     | dev與uat環境測試專用，代表header送出的http status code |

Server端密碼規則：
password = SHA256(員工輸入密碼+員工編號)


```json=
{
    "email":"someone@neutec.com.tw",
    "password":"[員工所輸入的密碼]",
    "pushToken":"5b5efd0e700729a1b7f9fe",
    "deviceUuid":"0000000-08urjfk21-009822321-i8jf1kd9ol2"
}
```

**Response 帳密登入成功**

| Parameter   | Type   | Require | Description |
| ----------- | ------ | ------- | ----------- |
| status      | int | Y       |  [狀態代碼](#狀態代碼) |
| errorMsg    | string |         |  錯誤訊息 |
| data        | string | Y       |  資訊內容 |
| desc        | string | Y       |  狀態描述 |
| authToken   | string | Y       |  自動登入Token（將儲存於手機端） |
| wssToken    | string | Y       |  一次性websocket Token (60秒時效性) |

```json=
{
    "status": 200,
    "data":{
        "desc": "登入成功",
        "authToken": "14c879a1-f45c-4103-aeae-49b7d2b6a668",
        "wssToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjUxLCJlbWFpbCI6InNlYW4uY2hhbmdBUFBAbmV1dGVjLmNvbS50dyIsImlhdCI6MTcyMTcxODQ4MCwiZXhwIjoxNzIxNzE4NTQwfQ.RFV2MidWTKZ2Y35NIo7GKmgeNFml_fhhPPy4cb3yHhM"
    }
}
```
</br>

**Response 帳密驗證失敗（所有失敗一律1006）**

| Parameter   | Type   | Require | Description |
| ----------- | ------ | ------- | ----------- |
| status      | int | Y       |  [狀態代碼](#狀態代碼) |
| errorMsg    | string |         |  錯誤訊息 |
| data        | string | Y       |  資訊內容 |
| desc        | string | Y       |  狀態描述 |
| authToken   | string | Y       |  自動登入Token（將儲存於手機端） |
| wssToken    | string | Y       |  一次性websocket Token (60秒時效性) |

```json=
{
    "status": 1006,
    "errorMsg": "您輸入的帳號或密碼錯誤，請重新輸入"
}
```
</br>

**連線失敗，得不到Response**
```
顯示「連線逾時，請稍後再試」
```

<img src='https://hackmd.io/_uploads/BJwqZ4E5ex.png' width='200'>

</br>
</br>

### ✅ logout
URL:`https://{domain name}/api/user/logout/user`

Method: `POST Content`

Descirption: `登出動作`

#### Remark
```
1. 登出採用POST API進行，Server在接收到登出指令後，將自動斷開websocket
2. APP送出登出後，不論response是否為200，立即在手機端將authToken移除
3. APP送出登出後，移除favorite本地端資料
4. Server端收到Logout時，先從已登入的Session中尋找該使用者。若找不到，需要再從整個member中尋找。隨後清空該使用者的authToken與pushToken
```
**Request** 

| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| authToken   | string   | Y       | 登入時取得的authToken |

```json=
{
    "authToken": "14c879a1-f45c-4103-aeae-49b7d2b6a668",
}
```

</br>

**Response 登出成功**

| Parameter   | Type   | Require | Description |
| ----------- | ------ | ------- | ----------- |
| status      | int    | Y       |  [狀態代碼](#狀態代碼) |
| data        | string | Y       |  資訊內容 |
| desc        | string | Y       |  狀態描述 |


```json=
{
    "status": 200,
    "data": {
        "desc": "登出成功"
    }
    
}
```
</br>

**Response 登出失敗(所有失敗一律1005)**

| Parameter   | Type   | Require | Description |
| ----------- | ------ | ------- | ----------- |
| status      | int    | Y       |  [狀態代碼](#狀態代碼) |
| errorMsg    | string |         |  錯誤訊息 |


```json=
{
    "status": 1005,
    "errorMsg": "目前無法完成操作，請聯絡SPWA相關人員"
    
}
```
</br>

### ✅ getVersion
URL:`https://{domain name}/api/guest/getVersion`


Method: `POST Content`

Descirption: `取得App版本資訊`
#### Remark for 後台
```
後台建置一個控制介面，需要儲存的欄位：
1. App版本 text
2. 下載連結 text
3. 作業系統類型 select
4. 更新步驟圖片上傳，最多10張圖片

[後台計算版本方式] 
API將會根據osVersion給予相對應的圖片組 
ex: 當app帶入osVersion=16.8.2，請將版本換算成16*65535+8*1000+2*1得到1,056,562，並尋找資料庫中與之最接近的版本。
假設遇到正負相同差異量(例如資料庫中有16.8.1與16.8.3，App傳來的是16.8.2)，將會取較小的(16.8.1)圖組。
```

<br>

#### Remark for App
![NeutecLife版本更新流程.drawio (1)](https://hackmd.io/_uploads/ry_IlR89xx.png)

<br>

**Request** 

| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| os          | int      | Y       | 手機作業系統 (0:iOS 1:Android) |
| osVersion   | string   | Y       | 手機作業系統版本號 |

```json=
{
    "os": 0,
    "osVersion": "16.8.2"
}
```

<br>

**Response 成功**

| Parameter   | Type   | Require | Description |
| ----------- | ------ | ------- | ----------- |
| status      | int    | Y       |  [狀態代碼](#狀態代碼) |
| data        | object | Y       |  資訊內容 |
| version     | string | Y       |  App版本 |
| downloadUrl | string | Y       |  App下載連結 |
| os          | int    | Y       |  作業系統類型 (0:iOS 1:Android) |
| images      | array  | Y       |  更新步驟圖片組 (最少1張、最多10張圖片) |


```json=
{
    "status": 200,
    "data": {
        "version": "1.0.0",
        "downloadUrl": "itms-apps://itunes.apple.com",
        "os": 0,
        "images": ["ios_16.8.2_image_1.png","ios_16.8.2_image_2.png","ios_16.8.2_image_5.png"]
    }
    
}
```

</br>

**Response 失敗-伺服器異常(所有失敗一律1005)**

| Parameter   | Type   | Require | Description |
| ----------- | ------ | ------- | ----------- |
| status      | int    | Y       |  [狀態代碼](#狀態代碼) |
| errorMsg    | string | Y       |  錯誤訊息 |

```json=
{
    "status": 1005,
    "errorMsg": "目前無法完成操作，請聯絡SPWA相關人員"
}
```

</br>


### ✅ updatePushToken
URL:`https://{domain name}/api/guest/updatePushToken/user`

Method: `POST Content`

Descirption: `更新pushToken使用`

**Request** 

| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| authToken   | string   | Y       | 自動登入Token |
| deviceUuid  | string   | Y       | 手機辨識碼    |
| pushToken   | string   | Y       | 推播Token(來自Pushy的Token)    |
| testTimeout | int      |         | dev與uat環境測試專用，代表sleep秒數 |
| testHttpStatusCode | int   |     | dev與uat環境測試專用，代表header送出的http status code |

```json=
{
    "authToken":"14c879a1-f45c-4103-aeae-49b7d2b6a668",
    "deviceUuid":"0000000-08urjfk21-009822321-i8jf1kd9ol2",
    "pushToken":"971b7c7a47c7ecf2643702"
}
```

 </br>
    
**Response 成功**

| Parameter   | Type   | Require | Description |
| ----------- | ------ | ------- | ----------- |
| status      | int    | Y       |  [狀態代碼](#狀態代碼) |
| errorMsg    | string |         |  錯誤訊息 |
| data        | string | Y       |  資訊內容 |
| desc        | string | Y       |  狀態描述 |
| wssToken    | string | Y       |  一次性websocket Token |

```json=
{
    "status": 200,
    "data": {
        "desc": "成功"
    }
    
}
```
    
</br>

**Response 更新失敗(所有失敗一律1005)**

| Parameter   | Type   | Require | Description |
| ----------- | ------ | ------- | ----------- |
| status      | int    | Y       |  [狀態代碼](#狀態代碼) |
| errorMsg    | string |         |  錯誤訊息 |

```json=
{
    "status": 1005,
    "errorMsg": "目前無法完成操作，請聯絡SPWA相關人員"
}
```
```
App端介接失敗不顯示任何訊息
```
</br>

##### iOS App updatePushToken機制流程圖
![NeutecLife - updatePushToken流程_iOS.drawio (2)](https://hackmd.io/_uploads/SyunTNKjxx.png)

<br>

##### Android App updatePushToken機制流程圖
![NeutecLife - updatePushToken流程_Android.drawio (2)](https://hackmd.io/_uploads/r1qaaNKjee.png)

### ✅ checkAuthToken
URL:`https://{domain name}/api/guest/checkAuthToken/user`

Method: `POST Content`

Descirption: `自動登入機制，檢查authToken的合法性＋取得一次性wssToken`

#### Remark
```
一但驗證失敗，App立即在手機端移除authToken並開啟登入頁
```

**Request** 

| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| authToken   | string   | Y       | 自動登入Token<font color=#FF0000><br>(開發環境維持1分鐘效力) |
| deviceUuid  | string   | Y       | 手機辨識碼    |
| testTimeout | int      |         | dev與uat環境測試專用，代表sleep秒數 |
| testHttpStatusCode | int   |     | dev與uat環境測試專用，代表header送出的http status code |

```json=
{
    "authToken":"14c879a1-f45c-4103-aeae-49b7d2b6a668",
    "deviceUuid":"0000000-08urjfk21-009822321-i8jf1kd9ol2",
}
```

 </br>
    
**Response 驗證成功**

| Parameter   | Type   | Require | Description |
| ----------- | ------ | ------- | ----------- |
| status      | int    | Y       |  [狀態代碼](#狀態代碼) |
| errorMsg    | string |         |  錯誤訊息 |
| data        | string | Y       |  資訊內容 |
| desc        | string | Y       |  狀態描述 |
| wssToken    | string | Y       |  一次性websocket Token |

```json=
{
    "status": 200,
    "data": {
        "desc": "驗證成功",
        "wssToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjUxLCJlbWFpbCI6InNlYW4uY2hhbmdBUFBAbmV1dGVjLmNvbS50dyIsImlhdCI6MTcyMTcxODQ4MCwiZXhwIjoxNzIxNzE4NTQwfQ.RFV2MidWTKZ2Y35NIo7GKmgeNFml_fhhPPy4cb3yHhM"
    }
    
}
```
    
</br>

**Response 驗證失敗(所有失敗一律1011)**

| Parameter   | Type   | Require | Description |
| ----------- | ------ | ------- | ----------- |
| status      | int    | Y       |  [狀態代碼](#狀態代碼) |
| errorMsg    | string |         |  錯誤訊息 |

```json=
{
    "status": 1011,
    "errorMsg": "Authentication failed."
}
```
</br>

### ✅ forgotPassword
URL:`https://{domain name}/api/guest/forgotPassword/user`

Method: `POST Content`

Descirption: `忘記密碼送出申請。`
#### Remark
```
員工送出申請後，將會在後台「忘記密碼」功能區中出現該筆資料。
後台將會發送帶有「修改密碼URL」的email給申請者。
當點下修改密碼URL後，原密碼才會被改成新的亂數值密碼，並顯示新密碼在Web畫面中，告知申請者可用此新密碼開啟App重新登入。
```
**Request** 

| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| email       | string   | Y | 員工帳號  |
| deviceUuid  | string   | Y | 手機識別碼(API暫時沒有使用)  |


```json=
{
    "email":"someone@meutec.com.tw",
    "deviceUuid":"0000000-08urjfk21-009822321-i8jf1kd9ol2"
}
```

**Response for 成功**
| Parameter   | Type   | Require | Description |
| ----------- | ------ | ------- | ----------- |
| status      | int    | Y       |  [狀態代碼](#狀態代碼) |
| data        | string | Y       |  資訊內容 |
| isPositive  | bool   | Y       | 回應訊息是否為積極行為，true:icon顏色為藍色, false:icon顏色為白色 |
| toast       | string | Y       |  狀態描述 |


```json=
{
    "status": 200,
    "data":{
        "isPositive":true,
        "toast":"申請送出成功"
    }
}
```
</br>

**Response for 失敗 - 找不到email or 找不到UDID**
| Parameter   | Type   | Require | Description |
| ----------- | ------ | ------- | ----------- |
| status      | int    | Y       |  [狀態代碼](#狀態代碼) |
| errorMsg    | string |         |  錯誤訊息 |

```json=
{
    "status": 1007,
    "errorMsg":"查無此信箱，請聯絡SPWA相關人員"
}
```
</br>

**Response for 失敗 - 伺服器異常（除了1007外所有失敗一律1005）**
| Parameter   | Type   | Require | Description |
| ----------- | ------ | ------- | ----------- |
| status      | int    | Y       |  [狀態代碼](#狀態代碼) |
| errorMsg    | string |         |  錯誤訊息 |

```json=
{
    "status": 1005,
    "errorMsg":"目前無法完成操作，請聯絡SPWA相關人員"
}
```

</br>

**App端網路不穩orServer端異常，得不到Response狀況**
```
若得不到Server回應，將顯示「連線逾時，請稍後再試」
```
![截圖 2025-09-02 下午4.36.00](https://hackmd.io/_uploads/ByBch749gx.png)

</br>

<br>

### ✅ forgotPasswordCheckToken (Web專用)
URL:`https://{domain name}/api/guest/forgotPasswordCheckToken/user`


Method: `GET Content`

Descirption: `忘記密碼送出到Email後，點擊更新為預設密碼連結。`
#### Remark
```

點下修改密碼URL後，原密碼才會被改成新的亂數值密碼，並顯示新密碼在Web畫面中，告知申請者可用此新密碼開啟App重新登入。
```
**Request** 

| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| token       | string   | Y | 忘記密碼申請紀錄Token (Token長度固定為八碼)  |


```json=
{
    "token":"fI5qr31m"
}
```

**Response**
| Parameter   | Type   | Require | Description |
| ----------- | ------ | ------- | ----------- |
| status      | int | Y       |  [狀態代碼](#狀態代碼) |
| errorMsg    | string |         |  錯誤訊息 |
| data        | string | Y       |  資訊內容 |
| password        | string | Y       |  信件中顯示的密碼 |


```json=
{
    "status": 200,
    "data":{
        "password":"R42JIarg"
    }
}
```
</br>


### ✅ hankshake (握手websocket方法)
URL:`wss://{domain name}/api/guest/authorize/user?wssToken=3d/XB7HDQe3/dI2vI3tHZxF3e2Yz7XwDZdyB0Y4WQ7U`

Method: `wss`

Descirption: websocket握手機制 （將wssToken放入get參數）
<font color=red>uat環境測試階段，wssToken時效性僅一分鐘，若沒有持續發送對話將會自動斷線。</font>

#### Remark
```
wssToken取得方式：
1. 手動登入流程：可從login API取得
2. 自動登入流程：可從checkAuthToken API取得

若wssToken驗證失敗：
1. Server端socket server將會自動斷線
2. App端將再次透過checkAuthToken更新wssToken

注意事項：
1. 握手並驗證wssToken成功後，由App端決定要求哪些頁面的資料，
   Server端只會主動回傳handshake這個module回來。
   
2. 若isForceUpdatePassword為true，App端需要返回首頁並開啟修改密碼頁。

3. uat環境測試階段，wssToken時效性僅一分鐘，若沒有持續發送對話將會自動斷線。
```
手動登入流程：<a href="#✅-login">查看login API</a>
自動登入流程：<a href="#✅-checkAuthToken">查看checkAuthToken API</a>





**Response for wssToken驗證成功**
| Parameter | Type   | Require | Description |
| --------- | ------ | ------- | ----------- |
| requestId | string | Y       | 對話id (Server端直接帶入空值)  |
| status    | int    | Y       | [狀態代碼](#狀態代碼) |
| page      | string | Y       | 手機畫面名稱  |
| info      | array  | Y       | 手機畫面資訊 |
| module    | string | Y       | 手機畫面區塊名稱 |
| status    | int    | Y       | [狀態代碼](#狀態代碼) |
| type      | string | Y       | 資料處理型態 |
| num       | int    | Y       | 資料筆數 |
| data      | array  | Y       | 資料內容 |
| isAuthorize| bool  | Y       | 是否已被授權可以取得socket資料 |
| isForceUpdatePassword| bool | Y  | 是否進入第一次修改密碼頁面<br>兩種情況需強制進入修改密碼頁：<br>1.第一次登入<br>2.忘記密碼審核成功後 |
| datetime  | string | Y       | 資料發佈時間 |

```json=
{
  "requestId":"",
  "status": 200,
  "page": "loginPage",
  "info": [
    {
      "module": "handshake",
      "status": 200,
      "type": "list",
      "num": 1,
      "data": [
        {
          "isAuthorize":true,
          "isForceUpdatePassword":true
        }
      ],
      "datetime":"2024/1/17 10:00:01"
    }
  ]
}
```
</br>

**Response for wssToken驗證失敗**
| Parameter | Type   | Require | Description |
| --------- | ------ | ------- | ----------- |
| requestId | string | Y       | 對話id (Server端直接帶入空值)  |
| status    | int    | Y       | [狀態代碼](#狀態代碼) |
| errorMsg  | string |         | 錯誤訊息 |
| page      | string | Y       | 手機畫面名稱  |
| datetime  | string | Y       | 資料發佈時間 |


```json=
{
  "requestId":"",
  "status": 1011,
  "errorMsg": "Authentication failed.",
  "page": "loginPage",
  "dateTime" : "2024/1/17 10:00:01"
}
```
</br>

### ✅ forceUpdatePasswordPage-updatePassword (強制修改密碼)

URL: `wss://{domain name}/`

Method: `wss`

Descirption: `第一次登入後(或忘記密碼後)的強制修改密碼使用，此時只需要輸入新密碼`

Server端密碼規則：
password = SHA256(員工輸入密碼+員工編號)

**Request** 

| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId   | string   | Y       | 對話id  |
| page        | string   | Y       | 手機畫面名稱 |
| module      | string   | Y       | 功能區塊名稱 |
| type        | string   | Y       | 資料處理型態 |
| data        | string   | Y       | 資料 |
| newPassword | string   | Y       | 新密碼 |

```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "forceUpdatePasswordPage",
  "module": "updatePassword",
  "type": "update",
  "data": {
      "newPassword":"Abcd1234"
  }
}
```

**Response 成功**

| Parameter | Type   | Require | Description |
| --------- | ------ | ------- | ----------- |
| requestId | string | Y       | 對話id  |
| status    | int    | Y       | [狀態代碼](#狀態代碼) |
| page      | string | Y       | 手機畫面名稱  |
| info      | array  | Y       | 手機畫面資訊 |
| module    | string | Y       | 手機畫面區塊名稱 |
| status    | int    | Y       | [狀態代碼](#狀態代碼) |
| type      | string | Y       | 資料處理型態 |
| num       | int    | Y       | 資料筆數 |
| data      | array  | Y       | 資料內容 |



```json=
{
  "requestId":"64d94767-c926-6156-44a5-8bf08a3691d4",
  "status": 200,
  "page": "forceUpdatePasswordPage",
  "info": [
    {
      "module": "updatePassword",
      "status":200,
      "type": "list",
      "num": 1,
      "data": [
        { 
          "desc":"修改成功"
        }
      ],
      "datetime":"2024/1/17 10:13:10"
    }
  ]
}
```
</br>

**Response 失敗**

| Parameter | Type   | Require | Description |
| --------- | ------ | ------- | ----------- |
| requestId | string | Y       | 對話id  |
| status    | int    | Y       | [狀態代碼](#狀態代碼) |
| errorMsg  | string |         | 錯誤訊息 |


```json=
{
  "requestId":"64d94767-c926-6156-44a5-8bf08a3691d4",
  "status": 200,
  "page": "forceUpdatePasswordPage",
  "info": [
    {
      "module": "updatePassword",
      "status":1102,
      "errorMsg": "新密碼驗證失敗"
    }
  ]
}
```
</br>


### ✅ updatePasswordPage-updatePassword (設定頁的修改密碼)

URL: `wss://{domain name}/`

Method: `wss`

Descirption: `使用者進入設定頁時，主動要求做密碼變更時使用，此時需要輸入舊密碼以供驗證`

Server端密碼規則：
password = SHA256(員工輸入密碼+員工編號)

**Request** 

| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId   | string   | Y       | 對話id  |
| page        | string   | Y       | 手機畫面名稱 |
| module      | string   | Y       | 功能區塊名稱 |
| type        | string   | Y       | 資料處理型態 |
| data        | string   | Y       | 資料 |
| oriPassword | string   | Y       | 原本的密碼 |
| newPassword | string   | Y       | 新密碼 |

```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "updatePasswordPage",
  "module": "updatePassword",
  "type": "update",
  "data": {
      "oriPassword":"654321",
      "newPassword":"Abcd1234"
  }
}
```

**Response 成功**

| Parameter | Type   | Require | Description |
| --------- | ------ | ------- | ----------- |
| requestId | string | Y       | 對話id  |
| status    | int    | Y       | [狀態代碼](#狀態代碼) |
| page      | string | Y       | 手機畫面名稱  |
| info      | array  | Y       | 手機畫面資訊 |
| module    | string | Y       | 手機畫面區塊名稱 |
| status    | int    | Y       | [狀態代碼](#狀態代碼) |
| type      | string | Y       | 資料處理型態 |
| num       | int    | Y       | 資料筆數 |
| data      | array  | Y       | 資料內容 |



```json=
{
  "requestId":"64d94767-c926-6156-44a5-8bf08a3691d4",
  "status": 200,
  "page": "updatePasswordPage",
  "info": [
    {
      "module": "updatePassword",
      "status":200,
      "type": "list",
      "num": 1,
      "data": [
        { 
          "desc":"修改成功"
        }
      ],
      "datetime":"2024/1/17 10:13:10"
    }
  ]
}
```
</br>

**Response 失敗**

| Parameter | Type   | Require | Description |
| --------- | ------ | ------- | ----------- |
| requestId | string | Y       | 對話id  |
| status    | int    | Y       | [狀態代碼](#狀態代碼) |
| errorMsg  | string |         | 錯誤訊息 |



```json=
{
  "requestId":"64d94767-c926-6156-44a5-8bf08a3691d4",
  "status": 200,
  "page": "updatePasswordPage",
  "info": [
    {
      "module": "updatePassword",
      "status":1101,
      "errorMsg": "舊密碼驗證失敗"
    }
  ]
}
```
```json=
{
  "requestId":"64d94767-c926-6156-44a5-8bf08a3691d4",
  "status": 200,
  "page": "updatePasswordPage",
  "info": [
    {
      "module": "updatePassword",
      "status":1102,
      "errorMsg": "新密碼驗證失敗"
    }
  ]
}
```
</br>


---
### subscribe

URL: `wss://{domain name}/`

Method: `wss`

Descirption: `Server端將主動推送已訂閱頁面中有異動的資料`
#### Remark
```
1. 任一page皆能接受subscribe這個module
2. 當App端送出請求module為all時，意即代表訂閱該頁面。

ex:當App進入書籍列表頁時，必須先要一次bookPage的所有資料，
Server端將直接訂閱bookPage，直到App離開此畫面並發出解除訂閱為止。
```

**Request for 列出已訂閱清單** 

| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId   | string   | Y       | 對話id  |
| page        | string   | Y       | 手機畫面名稱 |
| module      | string   | Y       | 功能區塊名稱 |
| type        | string   | Y       | 資料處理型態 |
| data        | string   | Y       | 資料 |

```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "homePage",
  "module": "subscribe",
  "type": "list",
  "data": {
  }
}
```

<br>

**Response for 列出訂閱清單**

| Parameter | Type   | Require | Description |
| --------- | ------ | ------- | ----------- |
| requestId | string | Y       | 對話id  |
| status    | int    | Y       | [狀態代碼](#狀態代碼) |
| page      | string | Y       | 手機畫面名稱  |
| info      | array  | Y       | 手機畫面資訊 |
| module    | string | Y       | 手機畫面區塊名稱 |
| status    | int    | Y       | [狀態代碼](#狀態代碼) |
| type      | string | Y       | 資料處理型態 |
| num       | int    | Y       | 資料筆數 |
| data      | array  | Y       | 資料內容，列出目前已訂閱的項目清單 |

```json=
{
  "requestId":"64d94767-c926-6156-44a5-8bf08a3691d4",
  "status": 200,
  "page": "homePage",
  "info": [
    {
      "module": "subscribe",
      "status":200,
      "type": "list",
      "num": 4,
      "data": [
          "homePage", 
          "functionListPage", 
          "minePage",
          "bookPage"
      ],
      "datetime":"2024/1/17 10:13:10"
    }
  ],
  "datetime":"2024/1/17 10:13:10"
}
```

</br>

**Request for 解除訂閱** 

| Parameter   | Type     | Require | Description |
| ----------- | -------- | ------- | ----------- |
| requestId   | string   | Y       | 對話id  |
| page        | string   | Y       | 手機畫面名稱 |
| module      | string   | Y       | 功能區塊名稱 |
| type        | string   | Y       | 資料處理型態 |
| data        | string   | Y       | 資料 |
| pageName    | string   | Y       | 欲解除訂閱的頁面名稱 |

```json=
{
  "requestId": "64d94767-c926-6156-44a5-8bf08a3691d4",
  "page": "homePage",
  "module": "subscribe",
  "type": "delete",
  "data": {
      "pageName":"bookPage"
  }
}
```

<br>

**Response for 解除訂閱成功**

| Parameter | Type   | Require | Description |
| --------- | ------ | ------- | ----------- |
| requestId | string | Y       | 對話id  |
| status    | int    | Y       | [狀態代碼](#狀態代碼) |
| page      | string | Y       | 手機畫面名稱  |
| info      | array  | Y       | 手機畫面資訊 |
| module    | string | Y       | 手機畫面區塊名稱 |
| status    | int    | Y       | [狀態代碼](#狀態代碼) |
| type      | string | Y       | 資料處理型態 |
| num       | int    | Y       | 資料筆數 |
| data      | array  | Y       | 資料內容，列出目前已訂閱的項目清單 |

```json=
{
  "requestId":"64d94767-c926-6156-44a5-8bf08a3691d4",
  "status": 200,
  "page": "homePage",
  "info": [
    {
      "module": "subscribe",
      "status":200,
      "type": "list",
      "num": 3,
      "data": [
          "homePage", 
          "functionListPage", 
          "minePage"
      ],
      "datetime":"2024/1/17 10:13:10"
    }
  ],
  "datetime":"2024/1/17 10:13:10"
}
```
</br>

---
</br>

<iframe src="https://hackmd.io/zqx1OcNuTKSHCI89YIHMOw?view" width="100%" height="500"></iframe>

<!--
### 狀態代碼

| status | description |
| -----  |-------------|
| 200    | Success |
| 1001   | Not found this page or module. |
| 1003   | Not found this DATA. |
| 1004   | DATA parameter error. |
| 1005   | Data processing error. |
| 1006   | 您輸入的帳號或密碼錯誤，請重新輸入 |
| 1008   | Your account has been logged in another device. |
| 1009   | Touch too fast. |
| 1010   | Unknow error. |
| 1011   | 身份驗證失敗，請重新登入 |
| 1012   | Blacklist. |
| 1013   | Not found this lastId. |
| 1014   | 已超過書籍借用2本上限 |
| 1015   | 此書籍正在借閱中，借閱失敗 |
| 1016   | 書籍有人排隊預約，展延失敗 |
| 1017   | 時段衝突，此時段已有人預約 |
| 1018   | 物品已進入借用狀態，無法取消 |
| 1030   | 已有他人在此時段預約\r請重新選擇起訖時間 |
| 1031   | 會議時段衝突\r請重新選擇循環時段 |

<br>

### socket對話資料處理型態
| type   | description |
| -----  |-------------|
| select | App端請求「顯示用」資料。<br>ex:需要顯示書籍列表時。 |
| insert | App端請求「新增」動作。<br>ex:使用者按下借用按鈕時。 |
| update | App端請求「更新」動作。<br>ex:使用者更換快速入口項目時。 |
| delete | App端請求「刪除」動作。<br>ex:使用者按下取消收藏按鈕時。 |
| list   | Server端請求刷新整個區塊資料，或僅告知事件已處理完成。<br>ex:需要顯示書籍列表時。 |
| add    | Server端請求新增資料到區塊中。<br>ex:當後台新增了一筆通知時。 |
| modify | Server端請求更新畫面中的某筆資料。<br>ex:當後台修改了某一筆已發出通知的錯字時。 |
| remove | App端請求「刪除」動作。<br>ex:大樓消防演練通知會在演練結束後自動在App端移除消失。  |


-->