# 统一认证平台 - 账号同步 (M2M)

## 1. 概述

本文涵盖两类 M2M 能力：**映射同步**（`POST /apps/mapping/sync`，增删改本平台用户与您应用的映射关系）与 **按平台用户主键 ID 查询用户**（`GET /users/m2m/by-platform-id/{user_id}`）。二者均使用 `X-App-Access-Token`，请在服务端调用，勿下发前端。

映射同步支持批量调用。

**Base URL**: `{{API_BASE_URL}}`

## 2. 认证方式
此接口不使用签名算法，而是使用 **App Access Token**。
- **Header**: `X-App-Access-Token: <YOUR_TOKEN>`
- Token 可在平台管理界面的应用详情页查看。

## 3. 同步接口 (Sync)
创建、更新或删除用户映射关系。

- **URL**: `POST /apps/mapping/sync`
- **Content-Type**: `application/json`

### 逻辑
1. **增改模式 (UPSERT)**:
   - 根据 `mobile` 查找用户。
   - **新建用户**: 若用户不存在，必须提供 `name`（姓名）。`english_name`（英文名）可选，如未提供会自动生成并确保唯一性。
   - **已有用户**: **不允许修改** `name`、`mobile`、`english_name` 等用户基本信息。但可以修改映射信息（`mapped_key`、`mapped_email`、`is_active`）。
   - 建立或更新该用户与当前应用的映射 (`mapped_key`, `mapped_email`, `is_active`)。
2. **删除模式 (DELETE)**:
   - 仅删除该用户在当前应用下的映射关系。
   - **不删除**平台上的用户账号。
   - 必须提供 `mapped_key`，且须与平台上该映射记录中的外部账号 **一致**（用于校验）。

### Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| `mobile` | string | Yes | 用户手机号 (平台唯一标识)，须为 11 位中国大陆手机号（`1[3-9]` 开头） |
| `name` | string | Conditional | 用户姓名 (新建用户必填，已有用户不允许修改) |
| `english_name` | string | Optional | 英文名/拼音 (新建用户可选，如未提供会自动生成；已有用户不允许修改) |
| `mapped_key` | string | Yes | 外部系统用户 ID（映射账号，1～100 字符；可修改） |
| `mapped_email` | string | No | 外部系统邮箱 (可修改) |
| `is_active` | boolean | No | 映射状态 (默认 true，可修改) |
| `sync_action` | string | No | 操作类型: `UPSERT` (增改, 默认) 或 `DELETE` (删除映射) |

### 示例 1: 新增用户 (UPSERT)
```bash
curl -X POST "{{API_BASE_URL}}/apps/mapping/sync" \
     -H "Content-Type: application/json" \
     -H "X-App-Access-Token: eyJhbGci..." \
     -d '{
           "mobile": "13800138000",
           "name": "张三",
           "mapped_key": "user_1001",
           "mapped_email": "zhangsan@example.com",
           "sync_action": "UPSERT"
         }'
```
注意：`english_name` 可以不提供，系统会自动生成。

### 示例 2: 更新已有用户的映射信息 (UPSERT)
```bash
curl -X POST "{{API_BASE_URL}}/apps/mapping/sync" \
     -H "Content-Type: application/json" \
     -H "X-App-Access-Token: eyJhbGci..." \
     -d '{
           "mobile": "13800138000",
           "mapped_key": "user_1001_updated",
           "mapped_email": "zhangsan_new@example.com",
           "is_active": true,
           "sync_action": "UPSERT"
         }'
```
注意：已有用户不能修改 `name`、`mobile`、`english_name`，只能修改映射信息。

### 示例 3: 删除映射 (DELETE)
```bash
curl -X POST "{{API_BASE_URL}}/apps/mapping/sync" \
     -H "Content-Type: application/json" \
     -H "X-App-Access-Token: eyJhbGci..." \
     -d '{
           "mobile": "13800138000",
           "mapped_key": "user_1001_updated",
           "sync_action": "DELETE"
         }'
```
（`mapped_key` 须与当前平台上该用户在本应用下的映射账号一致。）

### Response (200)

```json
{
  "id": 123,
  "app_id": 1,
  "user_id": 456,
  "mapped_key": "user_1001",
  "mapped_email": "zhangsan@example.com",
  "user_mobile": "13800138000",
  "user_status": "ACTIVE",
  "is_active": true,
  "new_user_created": false,
  "generated_password": null
}
```

| 字段 | 说明 |
|------|------|
| `id` | 映射记录主键 |
| `app_id` | 应用数据库主键 |
| `user_id` | 平台用户 ID，可用于下文 §4「按 ID 查询用户」 |
| `mapped_key` / `mapped_email` | 当前映射账号与邮箱 |
| `user_mobile` | 用户手机号 |
| `user_status` | 用户状态概要 |
| `is_active` | 映射是否启用（DELETE 后为 `false`） |
| `new_user_created` | 本次是否新建平台用户 |
| `generated_password` | 新建用户时平台生成的初始密码，常为空 |

## 4. 按平台用户 ID 查询用户（M2M）

当业务侧已保存统一认证平台的用户主键（例如映射同步响应中的 `user_id`、或简易认证校验里的平台用户 ID），可用本接口查询该用户在平台上的档案。**路径中的 `user_id` 是平台 `users` 表主键，不是外部系统的 `mapped_key`。** 按手机号或条件搜索请使用 `GET /users/search`。

- **Method**: `GET`
- **URL**: `/users/m2m/by-platform-id/{user_id}`
- **认证**: `X-App-Access-Token: <YOUR_TOKEN>`（与应用详情中的永久 M2M Token 一致；**不是** `POST /auth/app-token` 返回的 Bearer JWT）

**约束摘要**

- 仅接受**应用**凭证。若请求同时携带有效的用户 `Authorization: Bearer`（且会先被解析为用户身份），将返回 **403**「仅支持应用凭证访问」——服务端调用时请勿附带用户 Bearer，或仅发送 `X-App-Access-Token`。
- 仅当用户 `status=ACTIVE` 且 `is_deleted=0` 时返回 **200**，否则 **404**。

### 4.1 请求参数

| 位置 | 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|------|
| Path | `user_id` | integer | 是 | 平台用户主键 ID |
| Header | `X-App-Access-Token` | string | 是 | 应用 M2M 永久访问令牌 |

### 4.2 请求示例

```bash
curl -X GET "{{API_BASE_URL}}/users/m2m/by-platform-id/456" \
     -H "X-App-Access-Token: eyJhbGci..."
```

### 4.3 响应说明（200）

响应体为**用户对象**（开放模型），**不包含密码**。

| 字段 | 类型 | 说明 |
|------|------|------|
| `id` | integer | 平台用户主键 |
| `mobile` | string | 手机号 |
| `name` | string \| null | 姓名 |
| `english_name` | string \| null | 英文名 |
| `organization_id` | integer \| null | 所属组织 ID |
| `organization_name` | string \| null | 所属组织名称 |
| `status` | string | 状态；本接口成功时为 `ACTIVE` |
| `role` | string \| null | 如 `ORDINARY_USER` |
| `is_deleted` | integer | 软删除标记；成功时为 `0` |
| `created_at` | string (datetime) | 创建时间 |
| `updated_at` | string (datetime) | 更新时间 |

### 4.4 响应示例（200 JSON）

```json
{
  "id": 456,
  "mobile": "13800138000",
  "name": "张三",
  "english_name": "zhangsan",
  "organization_id": 10,
  "organization_name": "研发部",
  "status": "ACTIVE",
  "role": "ORDINARY_USER",
  "is_deleted": 0,
  "created_at": "2025-01-10T08:00:00",
  "updated_at": "2025-06-01T12:00:00"
}
```

### 4.5 常见错误

| HTTP | 含义 |
|------|------|
| 401 | 缺少或错误的 `X-App-Access-Token` |
| 403 | 未以应用凭证访问（例如仅用户 JWT） |
| 404 | 用户不存在，或已删除 / 非 `ACTIVE` |

## 5. 错误码（映射同步接口）

以下针对 **`POST /apps/mapping/sync`**：

- `400 Bad Request`: 
  - 参数错误（如手机号格式非法、缺少 `mapped_key`、新建用户未提供 `name`）
  - 已有用户尝试修改 `name`、`mobile` 或 `english_name`
  - 姓名/英文名已存在（新建用户时）
  - 映射关系冲突（`mapped_key` 或 `mapped_email` 已被占用）
  - `DELETE` 时 `mapped_key` 与平台记录不一致，或历史数据缺少外部账号
- `403 Forbidden`: Token 无效。

