# Id Card Two Factor Auth

> 身份证二要素实名认证，验证身份证号与姓名是否匹配，返回性别、生日、户籍地址等信息。需要实名核验、身份认证时使用。

- Skill: `qq5855144/id-card-two-factor-auth` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add qq5855144/id-card-two-factor-auth`
- Raw SKILL.md: https://api.skillmd.com/api/skills/qq5855144/id-card-two-factor-auth/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- License: MIT
- Author: qq5855144 (https://skillmd.com/u/qq5855144)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/qq5855144/id-card-two-factor-auth

---


## 能力概述

通过身份证号和姓名进行二要素实名认证，验证两者是否匹配，并返回用户性别、生日、身份证注册地等信息。后台配备多冗余渠道，可通过系统监控自动切换，保障服务高可用性与高成功率。

- **Endpoint**：`GET https://app-bo4w33bsdqm9-api-oLpZ74noWOMa-gateway.appmiaoda.com/idcard`
- **认证方式**：platform_managed（`X-Gateway-Authorization: Bearer ${INTEGRATIONS_API_KEY}`）
- **核心参数**：`idcard`（身份证号）、`name`（姓名）
- **响应格式**：JSON，业务结果在 `showapi_res_body` 中，`code=0` 表示匹配

**响应示例（匹配）：**

```json
{
  "showapi_res_error": "",
  "showapi_res_id": "68e872ddfb638ca67cdbd345",
  "showapi_res_code": 0,
  "showapi_fee_num": 1,
  "showapi_res_body": {
    "ret_code": 0,
    "code": 0,
    "msg": "匹配",
    "order": "845563287741872",
    "province": "贵州省",
    "city": "黔东南苗族侗族自治州",
    "county": "剑河县",
    "address": "详细地址",
    "sex": "M",
    "birthday": "1979-11-08"
  }
}
```

---

## 生成期用法（Agent 直接调用）

```typescript
const apiKey = process.env["INTEGRATIONS_API_KEY"]!; // platform_managed，密钥由平台注入

/**
 * 调用身份证二要素实名认证接口，验证身份证号与姓名是否匹配。
 * @param idcard 身份证号，例如：522629197911080415
 * @param name 姓名，例如：张三（内部会自动进行 URL 编码）
 * @returns showapi_res_body 业务响应体
 */
async function verifyIdCardTwoFactor(
  idcard: string,
  name: string
): Promise<{
  ret_code: number;
  code: number;
  msg: string;
  order: string;
  province: string;
  city: string;
  county: string;
  address: string;
  sex: string;
  birthday: string;
}> {
  const params = new URLSearchParams({ idcard, name });
  const response = await fetch(
    `https://app-bo4w33bsdqm9-api-oLpZ74noWOMa-gateway.appmiaoda.com/idcard?${params.toString()}`,
    {
      method: "GET",
      headers: {
        "Content-Type": "application/json; charset=utf-8",
        "X-Gateway-Authorization": `Bearer ${apiKey}`,
      },
    }
  );

  if (!response.ok) throw new Error(`HTTP error: ${response.status}`);

  const json = await response.json();
  if (json.showapi_res_code !== 0) {
    throw new Error(`API error: ${json.showapi_res_error}`);
  }

  const body = json.showapi_res_body;
  if (body.ret_code !== 0) {
    throw new Error(`业务错误 ret_code=${body.ret_code}: ${body.msg}`);
  }

  return body;
}

// 使用示例
const result = await verifyIdCardTwoFactor("522629197911080415", "张三");
console.log(`验证结果：${result.msg}，code=${result.code}`);
// code=0：匹配；code=1：不匹配；code=2：无此身份证号码
```

---

## 生成后用法（应用内通过 Edge Function 调用）

### Edge Function（`edge-functions/id-card-two-factor-auth.ts`）

```typescript
// edge-functions/id-card-two-factor-auth.ts
import { serve } from "https://deno.land/std/http/server.ts";

serve(async (req: Request): Promise<Response> => {
  if (req.method !== "POST") {
    return new Response("Method Not Allowed", { status: 405 });
  }

  // --- 解析客户端请求 ---
  let idcard: string;
  let name: string;
  try {
    const body = await req.json();
    idcard = body.idcard;
    name = body.name;
    if (!idcard) throw new Error("Missing idcard");
    if (!name) throw new Error("Missing name");
  } catch {
    return new Response(JSON.stringify({ error: "Invalid request body" }), {
      status: 400,
      headers: { "Content-Type": "application/json" },
    });
  }

  // --- 注入平台密钥（严禁暴露给前端）---
  const apiKey = Deno.env.get("INTEGRATIONS_API_KEY");
  if (!apiKey) {
    return new Response(JSON.stringify({ error: "Server configuration error" }), {
      status: 500,
      headers: { "Content-Type": "application/json" },
    });
  }

  // --- 调用上游接口（注意：姓名需 URL 编码）---
  const params = new URLSearchParams({ idcard, name });
  const upstream = await fetch(
    `https://app-bo4w33bsdqm9-api-oLpZ74noWOMa-gateway.appmiaoda.com/idcard?${params.toString()}`,
    {
      method: "GET",
      headers: {
        "Content-Type": "application/json; charset=utf-8",
        "X-Gateway-Authorization": `Bearer ${apiKey}`,
      },
    }
  );

  // 透传配额超限/余额不足错误
  if (upstream.status === 429 || upstream.status === 402) {
    const errText = await upstream.text();
    return new Response(errText, {
      status: upstream.status,
      headers: { "Content-Type": "application/json" },
    });
  }

  if (!upstream.ok) {
    return new Response(
      JSON.stringify({ error: `Upstream error: ${upstream.status}` }),
      { status: 502, headers: { "Content-Type": "application/json" } }
    );
  }

  const data = await upstream.json();
  return new Response(JSON.stringify(data), {
    status: 200,
    headers: { "Content-Type": "application/json" },
  });
});
```

### 前端调用代码（Web / MiniProgram 通用）

**推荐方式（supabase client 可用时）：**

```typescript
/**
 * 通过 Edge Function 调用身份证二要素实名认证。
 * @param idcard 身份证号
 * @param name 姓名
 * @returns showapi_res_body 业务响应体
 */
async function verifyIdCard(idcard: string, name: string) {
  const { data, error } = await supabase.functions.invoke("id-card-two-factor-auth", {
    body: { idcard, name },
  });
  if (error) throw error;
  if (data.showapi_res_code !== 0) {
    throw new Error(`API 错误：${data.showapi_res_error}`);
  }
  const body = data.showapi_res_body;
  if (body.ret_code !== 0) {
    throw new Error(`业务错误 ret_code=${body.ret_code}: ${body.msg}`);
  }
  return body;
}
```

**备用方式（无法使用 supabase client 时）：**

```typescript
/**
 * 通过原生 fetch 调用身份证二要素实名认证 Edge Function。
 * @param idcard 身份证号
 * @param name 姓名
 * @returns showapi_res_body 业务响应体
 */
async function verifyIdCard(idcard: string, name: string) {
  const res = await fetch(
    `${import.meta.env.VITE_SUPABASE_URL}/functions/v1/id-card-two-factor-auth`,
    {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ idcard, name }),
    }
  );

  if (res.status === 429) {
    const err = await res.json();
    throw new Error(`配额已用尽：${err.message ?? res.statusText}`);
  }
  if (res.status === 402) {
    const err = await res.json();
    throw new Error(`余额不足：${err.message ?? res.statusText}`);
  }
  if (!res.ok) throw new Error(`请求失败：${res.status}`);

  const json = await res.json();
  if (json.showapi_res_code !== 0) {
    throw new Error(`API 错误：${json.showapi_res_error}`);
  }
  const body = json.showapi_res_body;
  if (body.ret_code !== 0) {
    throw new Error(`业务错误 ret_code=${body.ret_code}: ${body.msg}`);
  }
  return body;
}
```

---

## 参数说明

### 请求参数

| 参数名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| `idcard` | string | 是 | 身份证号，例如：522629197911080415 |
| `name` | string | 是 | 姓名，例如：张三（请求时需 URL 编码，避免中文乱码） |

### 返回字段说明

**外层公共字段：**

| 字段路径 | 类型 | 说明 |
|----------|------|------|
| `showapi_res_code` | number | 外层响应状态码，0 表示接口调用成功 |
| `showapi_res_error` | string | 错误信息，空字符串表示无错误 |
| `showapi_res_id` | string | 响应唯一 ID |
| `showapi_fee_num` | number | 本次请求计费次数 |
| `showapi_res_body` | object | 核心业务响应体 |

**业务字段（`showapi_res_body`）：**

| 字段路径 | 类型 | 说明 |
|----------|------|------|
| `ret_code` | number | 业务结果码，0=成功（计费），其余=失败（不计费） |
| `code` | number | 验证标示，见下方验证标示说明 |
| `msg` | string | 验证结果说明，与 `code` 对应 |
| `order` | string | 本次验证的流水号（唯一标识） |
| `sex` | string | 性别：M=男性，F=女性（由身份证号解析） |
| `birthday` | string | 用户生日，格式 YYYY-MM-DD（由身份证号解析） |
| `province` | string | 身份证注册地-省份 |
| `city` | string | 身份证注册地-城市 |
| `county` | string | 身份证注册地-区县 |
| `address` | string | 身份证注册地-详细地址（省+市+区县） |

**验证标示（`code`）含义：**

| code 值 | 含义 |
|---------|------|
| 0 | 身份证号与姓名匹配 |
| 1 | 身份证号与姓名不匹配 |
| 2 | 无此身份证号码（身份证号不存在） |
| 3 | 身份证号与姓名匹配，但照片比对失败 |
| 4 | 请求参数不能为空 |
| 12 | 身份证号码格式不合法 |
| 14 | 姓名格式异常（如含特殊字符、长度不符合规范） |
| 15 | 暂不支持该地域的身份证校验 |
| 100 | 渠道异常，请稍后再试（系统自动切换渠道中） |
| 101 | 验证信息重复输入，需间隔 60 秒以上再次核验 |
| 102 | 接口维护中，暂时无法提供服务 |
| 103 | 24 小时内相同姓名或身份证号的核验次数超限 |

---

## 注意事项

- **密钥安全**：`INTEGRATIONS_API_KEY` 仅可在 Edge Function 服务端读取，严禁暴露到前端。
- **计费**：每次成功调用（`ret_code=0`）计费 1 次，原价 ¥2.20/次，折扣价 ¥1.80/次。`ret_code≠0` 的失败调用不计费，请在业务层做好参数校验，避免无效调用。
- **参数编码**：姓名参数中含中文，发起 GET 请求时须进行 URL 编码（`URLSearchParams` 会自动处理），避免乱码导致验证失败。
- **频率限制**：同一信息（姓名+身份证号）60 秒内不可重复验证；24 小时内同一姓名或身份证号核验次数有限制（超限返回 `code=103`）。
- **渠道切换**：返回 `code=100`（渠道异常）时，系统会自动切换冗余渠道，建议稍后重试，无需手动干预。
- **地域限制**：部分地域暂不支持校验（返回 `code=15`），以接口实际响应为准。
- **错误处理**：务必处理 429（配额超限）和 402（余额不足）两种 HTTP 状态码，在前端给出明确提示。

