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

# 鉴权指南

> 介绍 API Key / Secret Key 的安全管理方式和接口 HMAC-SHA256 签名规则；IP 白名单、SessionId 公钥等内容请参阅本组其他页面。

无论您是交易所、钱包还是平台方，只要拿到 DCS 交付的一对密钥，就可以用一套统一的签名规则调用所有 **DeCard 托管** 接口——本页帮您把鉴权一次配通。作为持牌、自有 BIN 的发卡机构，DCS 对每一次接口调用都要求可验证的来源与防重放保护。

<Note>
  该模型为每个用户维护独立的法币/数币账户与余额，**不涉及链上抵押品**。
</Note>

***

## 本组概览

本组汇总了您从接入开发到生产上线所需的技术配置与安全凭据：

| 子页                                                  | 用途                                             |
| :-------------------------------------------------- | :--------------------------------------------- |
| **鉴权指南（本页）**                                        | API Key / Secret Key 管理与接口 HMAC-SHA256 签名      |
| **[IP 白名单](./ip-whitelisting)**                     | 向 DCS 报备您的网络出口地址，用于接口调用放行与生产凭证安全提取             |
| **[SessionId 加密与公钥配置](./sessionid-keys)**           | DeCard 托管模式实际具备的加密与签名能力汇总                      |
| **[H5 KYC 与开卡引导页](./h5-kyc-guidance)**              | 嵌入式 KYC 与开卡引导 H5 流程                            |
| **[Web SDK 接入](../sdk/web-sdk)**                    | 前端集成 SDK                                       |
| **[Webhook 与 WebSocket 实时通知](./webhook-websocket)** | 事件回调（Webhook）与 **WebSocket 实时推送**（DeCard 托管特色） |

## 1. 密钥与请求头

### 您会从 DCS 拿到什么

| 字段          | 描述                               | 谁提供 |
| :---------- | :------------------------------- | :-- |
| `apiKey`    | 调用接口的全局唯一标识，用于身份识别与请求来源追踪        | DCS |
| `secretKey` | 用于计算请求签名的密钥，**请妥善保管，切勿泄露给任何第三方** | DCS |

`apiKey` 是一个全局唯一标识，方便身份识别与数据分析；为防止他人冒用您的 `apiKey` 发起请求，需配对 `secretKey` 按约定规则生成签名，并随请求一并提交给 DCS 验证。DCS 会通过安全渠道向您交付这对密钥，接入机构对接口的任何调用都应遵循约定的签名协议。

> 沙盒环境的 `apiKey`/`secretKey` 请联系 DCS 团队获取；生产环境必须走 [生产环境密钥的安全提取](#3-生产环境密钥的安全提取)。

### 每个请求必带的头

接入机构对接口的每次调用，都需在 HTTP 头中携带以下各头：

| Header             | 必填       | 说明                                                                      |
| :----------------- | :------- | :---------------------------------------------------------------------- |
| `Content-Type`     | REQUIRED | 请求体为 JSON 时固定 `application/json`。缺失时返回 HTTP 400，业务码 `SYS_ILLEGAL_PARAM` |
| `X-DAPI-API-KEY`   | REQUIRED | DCS 交付的 `apiKey`                                                        |
| `X-DAPI-TIMESTAMP` | REQUIRED | 请求时间戳（毫秒），用于防重放                                                         |
| `X-DAPI-NONCE`     | REQUIRED | 随机数，取值范围 `[10000, 99999]`，保证请求一次性有效                                     |
| `X-DAPI-SIGN`      | REQUIRED | 按下文规则计算的 HMAC-SHA256 签名（十六进制小写）                                         |

<Warning>
  `secretKey` 仅用于本地计算签名，**切勿**在请求头中明文传输。
</Warning>

缺少 `Content-Type: application/json` 的典型响应：

```json theme={null}
{"code":"SYS_ILLEGAL_PARAM","message":"illegal param","messageDetail":null,"data":null,"success":false}
```

> 该 `success=false` 来自 Content-Type 缺失时的框架级错误响应，不代表所有业务响应都稳定包含 `success`。正常集成仍应以 `code` 判断成败，不要依赖 `success` 字段。

***

## 2. 接口签名（HMAC-SHA256）

### 签名规则

使用 **HmacSHA256** 算法，以 `secretKey` 为密钥，对拼接串签名：

```
X-DAPI-SIGN = HmacSHA256( apiKey + timestamp + nonce + payload , secretKey )
```

输出为十六进制小写字符串。

**拼接串各段说明：**

| 段           | 取值                                                         |
| :---------- | :--------------------------------------------------------- |
| `apiKey`    | 与 `X-DAPI-API-KEY` 一致                                      |
| `timestamp` | 与 `X-DAPI-TIMESTAMP` 一致（毫秒时间戳）                             |
| `nonce`     | 与 `X-DAPI-NONCE` 一致                                        |
| `payload`   | **GET** 请求：URL 编码后的查询参数（query string）；**其他方法**：原始请求体（body） |

```text theme={null}
if method is GET:
    payload = url.encodedQuery()     // 例如 externalUserId=<externalUserId>&cardMantissa=1670
else:
    payload = body                   // 原始 JSON 请求体字符串
```

> 签名算法固定为 HmacSHA256，请一律使用该算法。

### 防重放（谁做：DCS 校验 / 接入机构生成）

* **TIMESTAMP**：取值为 **13 位毫秒级时间戳**（如 `Date.now()`，非 10 位秒级）。格式不对会返回 `DAPI_TIMESTAMP_FORMAT_ERROR`。DCS 只处理**有效期 5 秒**内的请求，超出即返回 `DAPI_TIMESTAMP_EXPIRED`——请用当前时间重新生成并重算签名，并确保本地时钟同步。
* **NONCE**：每次请求生成一个 `[10000, 99999]` 的随机数，保证请求一次性有效，请勿复用。

> 鉴权失败时，请先检查时间戳、nonce 和签名原文；具体错误码以接口实际返回及 DCS 针对本产品提供的字典为准。

### 签名实现示例

**JavaScript（Postman Pre-request Script）**

```javascript theme={null}
const CryptoJS = require('crypto-js');

const apiSecret = '<your-secret-key>';
const apiKey    = '<your-api-key>';

// GET 用查询参数；其他方法用请求体，二选一拼接
const queryParams  = '<your-query-param>';   // 例如 externalUserId=<externalUserId>&cardMantissa=1670
const requestBody  = '<your-request-body>';  // POST/PUT 时的原始 body
const nonce        = 10010;
const timestamp    = Date.now().toString();

const dataToSign = apiKey + timestamp + nonce + queryParams + requestBody;
const signature  = CryptoJS.HmacSHA256(dataToSign, apiSecret).toString(CryptoJS.enc.Hex);
```

**Java**

```java theme={null}
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;

public final class HmacSignature {
    private static final String HMAC_SHA256 = "HmacSHA256";

    public static String getSignature(String apiSecret, String data) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(apiSecret.getBytes(), HMAC_SHA256);
        Mac mac = Mac.getInstance(HMAC_SHA256);
        mac.init(keySpec);
        byte[] hmac = mac.doFinal(data.getBytes());
        return Hex.encodeHexString(hmac);
    }
}
```

### 完整请求示例（GET）

```bash theme={null}
curl --location 'https://{domain}/card/v2/detail?externalUserId=<externalUserId>&cardId=<cardId>' \
  --header 'Content-Type: application/json' \
  --header 'X-DAPI-API-KEY: <your-api-key>' \
  --header 'X-DAPI-SIGN: <calculated-signature>' \
  --header 'X-DAPI-TIMESTAMP: <millis-timestamp>' \
  --header 'X-DAPI-NONCE: <random-10000-99999>'
```

> 此例中 `payload = externalUserId=<externalUserId>&cardId=<cardId>`（GET 的查询参数）。验证您的实现时，先用 DCS 提供的同一组 `apiKey/timestamp/nonce/payload` 复算出相同的 `X-DAPI-SIGN`，再上线。

<Warning>
  示例中所有 `externalUserId`、`apiKey`、`X-DAPI-SIGN`、`TIMESTAMP`、`NONCE` 均为占位符，请勿当作真实值；DeCard 托管模式涉及大量终端用户隐私数据，调试日志同样不应记录真实凭据与 PII。
</Warning>

### 统一响应结构

所有接口返回统一结构：

```json theme={null}
{
  "code": "SYS_SUCCESS",
  "message": "",
  "messageDetail": {
    "message": "",
    "title": "",
    "type": "",
    "icon": "",
    "action": "",
    "linkTitle": "",
    "linkUrl": ""
  },
  "data": ""
}
```

| 字段              | 类型     | 说明                                                                                                                                       |
| :-------------- | :----- | :--------------------------------------------------------------------------------------------------------------------------------------- |
| `code`          | string | 业务状态码，成功为 `SYS_SUCCESS`；失败为具体错误码                                                                                                         |
| `message`       | string | 简要信息，成功时通常为空                                                                                                                             |
| `messageDetail` | object | 结构化展示对象，含 `message` / `title` / `type` / `icon` / `action` / `linkTitle` / `linkUrl`，可用于前端引导展示；成功时各字段通常为空。**请勿据此判断成败**，业务成败一律以 `code` 为准 |
| `data`          | object | 业务数据                                                                                                                                     |

> 判断成功请以 `code == "SYS_SUCCESS"` 为准。响应结构**不含** `success` 布尔字段，请勿依赖该字段。

***

## 3. 生产环境密钥的安全提取

为避免生产环境的 `apiKey`/`secretKey` 在交付途中泄露，**生产密钥不直接发给您**，而是走一次性安全提取流程。

> 沙盒环境无需此流程，直接联系 DCS 团队获取即可。

### 流程（谁做）

1. **接入机构提供**：一个安全邮箱地址 + 一个用于提取的请求 IP。
   * 邮箱用于接收提取指引；该 IP 会被加入「提取密钥」白名单。
2. **DCS 发送**：安全邮箱收到一封邮件，内含一个**仅一次有效**的临时安全链接。
3. **接入机构提取**：把 `extractUrl` 与 `extractSecretKey` 拼接后，**在指定 IP 的机器上执行**，即可领取 `apiKey`/`secretKey`。

### 邮件中的字段

| 字段                 | 类型     | 描述          |
| :----------------- | :----- | :---------- |
| `expireTime`       | string | 提取安全码的有效期   |
| `extractSecretKey` | string | 密钥提取安全码     |
| `extractUrl`       | string | 密钥提取 URL    |
| `howToUse`         | string | 使用方式说明      |
| `notes`            | string | 提示：链接仅可提取一次 |

**成功响应**

```json theme={null}
{
  "code": "SYS_SUCCESS",
  "message": null,
  "messageDetail": null,
  "data": {
    "expireTime": "2024-10-21T16:52+08:00[Asia/Shanghai]",
    "extractSecretKey": "<one-time-extract-secret>",
    "extractUrl": "https://{domain}/internal/open-api/v1/secret-extract/",
    "howToUse": "Please concatenate the url with the secret-key and execute it on the specified machine.",
    "notes": "This link is only valid for one AKSK extraction, if the content is not properly accessed, the AKSK may have been compromised, please contact us promptly."
  }
}
```

**失败响应**

```json theme={null}
{
  "code": "ERROR-CODE",
  "message": "simple describe, see error-code list",
  "messageDetail": null,
  "data": null
}
```

> 此处仅展示失败响应结构。具体错误码请以接口实际返回及 DCS 针对本产品提供的字典为准，本版不引用其他产品的错误码表。

<Warning>
  **若未能成功领取密钥**：说明链接可能已在有效期内被使用、密钥存在泄露风险。请立即联系 DCS 商务，重新走邮件流程换发。

  该提取 IP 与日常接口调用 IP 可以不同，请分别向 DCS 说明用途；IP 白名单的提交方式见 [IP 白名单](./ip-whitelisting)。
</Warning>

***

## 下一步 / 相关

鉴权配通后，前往 [快速开始](../getting-started/quickstart) 跑通第一张卡，或先在 [前置准备](../getting-started/first-steps) 确认开通与回调已就绪。

其他接入资源：

* **[IP 白名单](./ip-whitelisting)**：向 DCS 报备您的网络出口地址，用于接口调用放行与生产凭证安全提取。
* **[SessionId 加密与公钥配置](./sessionid-keys)**：DeCard 托管模式实际具备的加密与签名能力汇总。
* **[H5 KYC 与开卡引导页](./h5-kyc-guidance)**：嵌入式 KYC 与开卡引导流程。
* **[Web SDK 接入](../sdk/web-sdk)**：前端集成 SDK。
* **[Webhook 与 WebSocket 实时通知](./webhook-websocket)**：事件回调（Webhook）与 **WebSocket 实时推送**（DeCard 托管特色）。
