> ## Documentation Index
> Fetch the complete documentation index at: https://sdk.qfapi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# ECR 整合技術規格

> 用於連接 POS 與 QFPay ECR 系統的整合通訊協定與加密規格說明。

<Note>
  **支援的終端機型號**

  * **Landi A8 / A8S**：支援所有支付方式
  * **PAX A920**：僅支援 QR Code 支付
</Note>

***

## 1. POS-KEY

POS-KEY 為交易資料加密金鑰，由 Haojin App 產生。

系統預設為 **啟用加密**。\
商戶可於商戶平台（MMS）開啟 / 關閉加密或重新產生 POS-KEY，並需於 Haojin App 重新整理裝置後才會生效。

### 重新產生 POS-KEY

Haojin App → 我的 → 設定 → POS-Key → 產生

### 查詢 POS-KEY

商戶平台 → 設定 → 裝置設定 → POS Key 管理

***

## 2. 加密方式（Encryption）

* 所有交易資料皆使用 **AES-128 / CBC / PKCS5Padding**
* 加密金鑰：POS-KEY
* IV：`qfpay202306_hjsh`
* 加密後再進行 Base64 編碼

***

## 3. 請求資料格式（Request Payload）

| 參數                  | 必填 | 型態      | 說明                       |
| ------------------- | -- | ------- | ------------------------ |
| `amt`               | 是  | Double  | 交易金額（例：10.1 = HKD 10.10） |
| `func_type`         | 是  | String  | 功能指令代碼                   |
| `channel`           | 是  | String  | 錢包 / 支付方式                |
| `out_trade_no`      | 否  | String  | 商戶交易參考號                  |
| `camera_id`         | 否  | Integer | 0=後鏡頭（預設），1=前鏡頭          |
| `payment_timeout`   | 否  | Integer | 支付逾時時間（秒）                |
| `wait_card_timeout` | 否  | Integer | 等待刷卡時間（預設 120 秒）         |

***

### 3.1 付款（Payment）

<Note>
  * QR Code 模式：MPM / CPM 依最近一次使用自動切換
  * `camera_id` 可指定前 / 後鏡頭
  * 刷卡交易：`wait_card_timeout` 為最大等待時間
  * 錢包交易：`payment_timeout` 為整筆交易等待時間
  * **PayMe 最長僅支援 120 秒**
  * `scan_type`：
    * `QRCODE_PAY`
    * `SCAN_PAY`
  * `moveToBack`：
    * `0`：不返回（預設）
    * `1`：交易完成後自動返回首頁
</Note>

```json theme={null}
{
  "content": {
    "amt": 100,
    "camera_id": 0,
    "channel": "card_payment",
    "func_type": 1001,
    "moveToBack": 1,
    "out_trade_no": "456799999999",
    "wait_card_timeout": 120,
    "scan_type": "SCAN_PAY"
  },
  "digest": "76b9186077cdc2bc5d78ae921309811d"
}
```

***

### 3.2 退款（Refund / Void）

| 欄位                  | 必填 | 型別      | 說明                |
| ------------------- | -- | ------- | ----------------- |
| `orderId`           | 是  | String  | QFPay 交易編號（syssn） |
| `refund_amount`     | 否  | String  | 退款金額（預設最大可退金額）    |
| `allow_modify_flag` | 否  | Integer | 0=不可修改（預設），1=可修改  |

<Warning>
  Visa / Mastercard / 銀聯卡 / 美國運通卡\
  **當日退款必須全額退款，不支援當日部分退款。**
</Warning>

```json theme={null}
{
  "content": {
    "allow_modify_flag": 1,
    "func_type": 1002,
    "moveToBack": 1,
    "orderId": "order_id",
    "refund_amount": "0.05"
  },
  "digest": "9C8E9FB05C7C24B6CA04EBFA1263EF41"
}
```

***

### 3.3 列印收據

```json theme={null}
{
  "content": {
    "orderId": "12345678",
    "func_type": 3001
  },
  "digest": "79fd145311d54d03e4e685d50f15dd7f"
}
```

***

### 3.4 列印交易摘要

```json theme={null}
{
  "content": {
    "func_type": 3002
  },
  "digest": "79fd145311d54d03e4e685d50f15dd7f"
}
```

***

### 3.5 交易查詢

支援參數 `out_trade_no`

```json theme={null}
{
  "content": {
    "orderId": "12345678",
    "func_type": 4001
  },
  "digest": "99CE8BF9C7304AC964522D10F51660B4"
}
```

***

### 3.6 取消付款 / 退款請求

```json theme={null}
{
  "content": {
    "func_type": 5001
  },
  "digest": "99CE8BF9C7304AC964522D10F51660B4"
}
```

***

## 4. 簽名產生機制（Signature Generation）

### 計算流程

```js theme={null}
// original payload
content = {"amt":100,"channel":"card_payment","func_type":1001,"out_trade_no":"456799999999"}

// sort keys in ascending order
format_content = {amt=100,channel='card_payment',func_type=1001,out_trade_no='456799999999'}

// if value is empty, use '' (empty string)

// signature
digest = md5(format_content + pos_key)
```

若啟用加密：

1. 先將 `content` 進行 AES 加密
2. 再以加密結果計算 `digest`

***

## 5. 欄位定義

### 5.1 `func_type`

| 數值   | 說明     |
| ---- | ------ |
| 1001 | 交易     |
| 1002 | 退款     |
| 3001 | 列印收據   |
| 3002 | 列印交易摘要 |
| 4001 | 交易查詢   |
| 5001 | 取消請求   |

***

### 5.2 `channel`

CPM = 消費者出示碼\
MPM = 商戶出示碼

| 值              | 說明                | PayType         |
| -------------- | ----------------- | --------------- |
| card\_payment  | Visa / Mastercard | 802808          |
| wx             | 微信支付              | 800208 / 800201 |
| alipay         | 支付寶               | 800108 / 800101 |
| payme          | PayMe             | 805808 / 805801 |
| union          | 銀聯閃付              | 800708 / 800701 |
| fps            | FPS               | 802001          |
| octopus        | 八達通               | 803708          |
| unionpay\_card | 銀聯卡               | 806708          |
| amex\_card     | 美國運通              | 806808          |

***

## 6. 回應格式

```json theme={null}
{
  "respcd": "6000",
  "data": "{...}",
  "respmsg": "xxxxxxxxxx",
  "resperr": "xxxxxxxxxx"
}
```

### 回應代碼

| 代碼   | 說明               |
| ---- | ---------------- |
| 4003 | 請求被拒絕            |
| 5001 | 解密失敗             |
| 4004 | 請求方法錯誤（請使用 POST） |
| 4005 | 其他錯誤             |
| 4006 | 參數錯誤             |
| 6000 | 請求成功             |
| 6001 | 使用者取消            |
| 6002 | 請求失敗             |

***

## 7. USB 傳輸方式

1. 以 USB 連接 POS 與收銀機
2. 依 USB 協議封裝資料
3. 回傳資料需解析後再進行 AES 解密

***

## 8. HTTP / HTTPS 通訊協議

* 預設 Port：`9001`
* 使用 `POST`
* Header：

| 欄位           | 值                |
| ------------ | ---------------- |
| Content-Type | application/json |

如需設定 HTTPS，請參閱 [ECR HTTPS 整合文件](/zh-hant/integration/in-store/pos-api/ecr-https)。

### API 路徑

| 操作     | 路徑                           |
| ------ | ---------------------------- |
| 發起交易   | `/api/pos/trade`             |
| 發起退款   | `/api/pos/cancel`            |
| 列印收據   | `/api/pos/print_receipt`     |
| 列印交易摘要 | `/api/pos/transaction_info`  |
| 查詢交易結果 | `/api/pos/query_transaction` |
| 取消交易請求 | `/api/pos/cancel_request`    |

***

## 9. TCP 協議

* 預設 Port：9002
* 使用 Socket
* 所有內容皆為 AES 加密

***

## 10. USB 封包結構

| 欄位              | 說明             | 長度       |
| --------------- | -------------- | -------- |
| Start indicator | 0x2f6e         | 2 Bytes  |
| version         | 0x01           | 1 Byte   |
| payload type    | 0x10/0x20/0x30 | 1 Byte   |
| ref number      | 0x01\~0x7f     | 1 Byte   |
| payload length  | 總長度            | 2 Bytes  |
| data length     | 資料長度           | 2 Bytes  |
| data segment    | 主體資料           | Variable |
| End indicator   | 0x2f6e         | 2 Bytes  |

<Warning>
  `0x2f6e` 為 ASCII 字串 `/n` 的十六進制表示，不是換行字元。
</Warning>

***

### Timeout

回應逾時：**1000ms**

***

### 串列埠設定

| 設定           | 值    |
| ------------ | ---- |
| Baud rate    | 9600 |
| Stop bit     | 1    |
| Parity       | 0    |
| Data bits    | 8    |
| Flow control | Off  |

***

### USB-to-Serial 支援

| 晶片         | 支援  |
| ---------- | --- |
| PL2303 HXD | 支援  |
| CH340      | 不支援 |
| FT232      | 不支援 |

<Note>
  此限制僅適用於 USB 模式整合。\
  若使用 HTTP / TCP 整合方式，則不受晶片限制。
</Note>

***

### 封包範例

明文： `{“content”:”{"amt":100,"channel":"wx","funcType":1,"mode":1}”,“digest”:“2f0c4683e25a7b9407265033070e9034”}`

Hex: `2f6e011001007f00747b22636f6e74656e74223a227b5c22616d745c223a3130302c5c226368616e6e656c5c223a5c2277785c222c5c2266756e63547970655c223a312c5c226d6f64655c223a317d222c22646967657374223a223266306334363833653235613762393430373236353033333037306539303334227d2f6e`
