# 如何使用 JSON 訊息？

BotBonnie 提供特殊的**JSON 訊息**格式，可以利用此種訊息格式，串接您的服務，由您的伺服器動態提供不同的訊息內容。僅需提供您的 `JSON API URL`，在呼叫您的 API 時，BotBonnie 會自動帶入以下資料：

* 在 Request Body 帶入**用戶識別資料**
* 在 Request Header 帶入 `X-Hub-Signature` 做安全性驗證

而您的 API 需回傳 BotBonnie 特定訊息 JSON 格式。

## 1. JSON 訊息範例

* [訊息範例請參考支援的訊息格式](https://docs.botbonnie.com/jiao-xue-fan-li/ru-he-shi-yong-json-xun-xi/zhi-yuan-de-xun-xi-ge-shi)

## 2. 用戶識別資料

BotBonnie 會在 Request POST body 自動帶入**用戶識別資料**，可搭配[帳號串接](https://docs.botbonnie.com/jiao-xue-fan-li/zhang-hao-bang-ding)使用。

| 參數名稱                                                     | 類型      | 描述                              |
| -------------------------------------------------------- | ------- | ------------------------------- |
| **bot\_id**                                              | String  | 機器人的 ID                         |
| <p><strong>bot\_uid</strong></p><p>(deprecated)</p>      | String  | 用戶 ID (加密)                      |
| **bot\_raw\_uid**                                        | String  | 用戶 ID (未加密)                     |
| **bot\_pid**                                             | String  | 粉絲頁 ID                          |
| **bot\_channel**                                         | Number  | 渠道代號  （`0`：Facebook / `1`：LINE） |
| <p><strong>bot\_isLinked</strong></p><p>(deprecated)</p> | Boolean | 用戶目前是否已經帳號連結 （`true` / `false`） |

## 3. 取得額外資料

當您的 JSON API 需要使用者的相關資料時，可以在 JSON API 網址中加上相關參數，BotBonnie 會在 Request POST body 中將相關的資訊一併傳送至您的伺服器。

```
https://yourdomian.com?fields=user,userParams
```

您可以在 `JSON API URL` 上攜帶額外網址參數來獲取 BotBonnie 提供的額外資訊。 目前支援的網址參數類型如下：

| 參數名稱         | 類型     | 支援的種類                                                     |
| ------------ | ------ | --------------------------------------------------------- |
| **`fields`** | String | `user`: 提供當下的用戶資料 `user_params`: 提供儲存於 BotBonnie 端的自訂用戶參數 |

範例的 Body 如下：

```
{ 
  "bot_id": "bot-xxxxx",
  "bot_uid": "3xxxxxxxxxxxd",
  "bot_raw_uid": "2xxxxxxxxxxxx0",
  "bot_pid": "1234779123812",
  "bot_channel": 0,
  "bot_isLinked": true,
  "user": {
    "id": "3xxxxxxxxxxxd",
    "rawId": "2xxxxxxxxxxxx0",
    "created": 1505360797321,
    "name": "陳邦妮",
    "gender": "female",
    "last_name": "陳",
    "pic": "https://scontent.xx.fbcdn.net/v/t31.0-1/p960x960/1800025_10202073294786135_45024857_o.jpg?oh=85252db7049dbf99de251175d03a6d46&oe=5A604B50",
    "locale": "zh_TW",
    "first_name": "邦妮",
    "timezone": 8 
  },
  "userParams": {
    "input": "你好",
    ...
  }
  ...
}
```

#### user

所有與用戶相關的資訊

| 鍵值           | 數值                                                                                  | 必定存在 |
| ------------ | ----------------------------------------------------------------------------------- | ---- |
| `id`         | <p>BotBonnie 認定之用戶 ID (加密)<br>ex: <code>3e69e881732e38b290e39a28b87403bd</code></p> | o    |
| `rawId`      | <p>BotBonnie 認定之用戶 ID (未加密)<br>ex: <code>2452158751517100</code></p>                | o    |
| `created`    | BotBonnie 建立此用戶的時間，unixtime 以毫秒表示 ex: `1505360797321`                               | o    |
| `name`       | 用戶全名 ex: `陳邦妮`                                                                      |      |
| `last_name`  | 用戶姓氏 ex: `陳`                                                                        |      |
| `first_name` | 用戶名稱 ex: `邦妮`                                                                       |      |
| `gender`     | 用戶性別 `male` or `female`                                                             |      |
| `pic`        | 用戶大頭照網址                                                                             |      |
| `locale`     | 用戶所在地區 ex: `zh_TW`                                                                  |      |
| `timezone`   | 用戶時區 ex: `8`                                                                        |      |

#### userParams

企業儲存於用戶身上額外的參數

| 鍵值      | 數值                | 必定存在 |
| ------- | ----------------- | ---- |
| `input` | 觸發此 JsonAPI 的用戶輸入 |      |

## 4. 來源安全性驗證

BotBonnie 會在 Request Header 帶入 `X-Hub-Signature` 確保來源安全性。

`X-Hub-Signature` 是為了驗證 POST 請求是來自 BotBonnie 伺服器，而不是來自惡意用戶。我們使用 SHA1 將 `API Secret` 與原始請求做雜湊，您可以在您的伺服器做來源驗證。

### 4.1 如何取得 `API Secret` ？

BotBonnie 提供每個 bot 專屬的 `API Secert`。可進入 bot 主控台，點選「設定 > 進階設定」，即可取得此 bot 的 `API Secert`。

### 4.2 如何驗證 `X-Hub-Signature` ？

假設您有一個基本的伺服器監聽 webhooks 。

```javascript
var express = require('express')
var bodyParser = require('body-parser')
var crypto = require('crypto')

// Express error-handling middleware function.
// Read more: http://expressjs.com/en/guide/error-handling.html
function abortOnError(err, req, res, next) {
  if (err) {
    console.log(err)
    res.status(400).send({ error: "Invalid signature." })
  } else {
    next()
  }
}

var app = express();
var listener = app.listen(process.env.PORT ? process.env.PORT : 3000)

// body-parser is the first Express middleware.
app.use(bodyParser.json({ verify: verifyRequest }))

// Add an error-handling Express middleware function 
// to prevent returning sensitive information.
app.use(abortOnError)

app.post('/webhook/', function (req, res) {
  res.status(200).send("done!")
})
```

使用 `API Secret` 與原始請求做驗證。

```javascript
// Calculate the X-Hub-Signature header value.
function getSignature(buf) {
  var hmac = crypto.createHmac("sha1", process.env.BOTBONNIE_API_SECRET)
  hmac.update(buf, "utf-8")
  return "sha1=" + hmac.digest("hex")
}

// Verify function compatible with body-parser to retrieve the request payload.
// Read more: https://github.com/expressjs/body-parser#verify
function verifyRequest(req, res, buf, encoding) {
  var expected = req.headers['x-hub-signature']
  var calculated = getSignature(buf)
  console.log("X-Hub-Signature:", expected, "Content:", "-" + buf.toString('utf8') + "-")
  if (expected !== calculated) {
    throw new Error("Invalid signature.")
  } else {
    console.log("Valid signature!")
  }
}
```
