# 產生 Headers

## 簽名

包含 Creator Storefront / Admin API 以及 Pass Admin API，只要是透過 GraphQL 呼叫的 APIs，都需要使用以下方法產生簽名。

## 標頭

Creator Admin API、Pass Admin API 以及 Creator Storefront API 要透過 key/secret 取得使用權限，需於通訊時在 header 中加入指定的屬性以完成驗證，描述如下：

| header 屬性       | 類型     | 說明                                   | 如何取得                                             |
| --------------- | ------ | ------------------------------------ | ------------------------------------------------ |
| x-qubic-api-key | string | API KEY                              | [聯絡 Qubic 團隊](https://www.qubic.market/#contact) |
| x-qubic-ts      | string | 運算當下的時間戳記                            | `Date.now().toString()`                          |
| x-qubic-sign    | string | 運算後的簽名                               | 範例                                               |
| Authorization   | string | 選填，使用 Storefront API 存取授權資料時，需要提供此資訊 | 範例                                               |

產生 API Key 時可以選擇是否採用安全性更高的 API 通訊機制，請依照是否有勾選使用對應的 Header 格式。\
接下來會提供 [標準範例](#biao-zhun-fan-li) 和 [高安全性的範例](#gao-an-quan-xing-de-fan-li) msg 的部分，標準不包含 body 本身，而高安全性是有包含的

<figure><img src="https://2097780654-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FmSOr6YIdkV27v1xXHSUV%2Fuploads%2FLvnPHzFoa6quBuIdXyX2%2Fimage.png?alt=media&#x26;token=1a1e73bf-c5e5-4a78-8d84-db4fec11bfad" alt=""><figcaption></figcaption></figure>

## 標準範例

要被簽名的訊息不包含 request body

```
yarn add graphql-request graphql crypto-js      # yarn
npm install graphql-request graphql crypto-js   # npm
```

```typescript
import HmacSHA256 from "crypto-js/hmac-sha256.js";
import Base64 from "crypto-js/enc-base64.js";
import { request, gql } from "graphql-request";

const KEY = "YOUR_CREATOR_ADMIN_API_KEY";
const SECRET = "YOUR_CREATOR_ADMIN_API_SECRET";

const url = "https://creator.qubic.app/admin/graphql";

const urlObj = new URL(url);
const resource = `${urlObj.pathname}${urlObj.search}`; // output: /admin/graphql

const now = Date.now();
const msg = `${now}POST${resource}`;
const sig = HmacSHA256(msg, SECRET).toString(Base64);

const requestHeaders = {
  "x-qubic-api-key": KEY,
  "x-qubic-ts": now.toString(),
  "x-qubic-sign": sig,
};

const document = gql`
  query shop {
    shop {
      id
    }
  }
`;

const result = await request({
  url,
  document,
  requestHeaders,
});

console.log(result);
```

## 高安全性的範例

要被簽名的訊息中包含 request body

```
yarn add graphql-request graphql crypto-js      # yarn
npm install graphql-request graphql crypto-js   # npm
```

```typescript
import HmacSHA256 from "crypto-js/hmac-sha256.js";
import Base64 from "crypto-js/enc-base64.js";
import { request, gql, resolveRequestDocument } from "graphql-request";

const KEY = "YOUR_CREATOR_ADMIN_API_KEY";
const SECRET = "YOUR_CREATOR_ADMIN_API_SECRET";

const url = "https://creator.qubic.app/admin/graphql";

const urlObj = new URL(url);
const resource = `${urlObj.pathname}${urlObj.search}`; // output: /admin/graphql

const document = gql`
  query shop {
    shop {
      id
    }
  }
`;

const { operationName, query } = resolveRequestDocument(document);

const body = JSON.stringify({
  query,
  operationName,
});

const now = Date.now();
const msg = `${now}POST${resource}${body}`;
const sig = HmacSHA256(msg, SECRET).toString(Base64);

const requestHeaders = {
  "x-qubic-api-key": KEY,
  "x-qubic-ts": now.toString(),
  "x-qubic-sign": sig,
};

const result = await request({
  url,
  document,
  requestHeaders,
});

console.log(result);
```

## 單機版驗證簽名

這邊提供演算法例子，供參考用

### 標準簽名

```
yarn add crypto-js      # yarn
npm install crypto-js   # npm
```

```typescript
import HmacSHA256 from "crypto-js/hmac-sha256.js";
import Base64 from "crypto-js/enc-base64.js";

function sign(option) {
  const { now, method, resource, secret } = option;

  const msg = `${now}${method}${resource}`;
  const sign = HmacSHA256(msg, secret).toString(Base64);

  return { msg, sign };
}

const { msg, sign } = sign({
  now: 1689907490132,
  method: "POST",
  resource: "/admin/graphql",
  secret: "secret",
});

console.log(msg === "1689907490132POST/admin/graphql"); // true
console.log(sign === "d1tZksk8khiWQ+UTUY7m6u1Msb5Oyhfej+c384e5GM8="); // true
```

### 高安全性的簽名

```
yarn add crypto-js      # yarn
npm install crypto-js   # npm
```

```typescript
import HmacSHA256 from "crypto-js/hmac-sha256.js";
import Base64 from "crypto-js/enc-base64.js";

function signSec(option) {
  const { now, body, method, resource, secret } = option;

  const msg = `${now}${method}${resource}${body}`;
  const sign = HmacSHA256(msg, secret).toString(Base64);

  return { msg, sign };
}

const { msg, sign } = signSec({
  now: 1566549227549,
  body: "the_body",
  method: "PUT",
  resource: "/test/path?currency=USD",
  secret: "secret",
});

console.log(msg === "1566549227549PUT/test/path?currency=USDthe_body"); // true
console.log(sign === "xN/7FHzMvIVbJYESYPJlMwNHL9r3DBZ21lsjSn5W3Bo="); // true
```

## 常見問題

* 為何我一直收到 `{"error":{"code":404,"message":"resource not found"}}`？
  1. 請確認有將 [header 所需的資訊](#biao-tou)放入其中
  2. 請確認正在使用的 API key/secret 與 GraphQL endpoint 是匹配的
  3. 可以先試著寫[單機版程式驗證簽名](#chan-ji-ban-yan-zheng-qian-ming)是否正確


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://qubic.gitbook.io/docs/guides/use-graphql/generate-headers.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
