# 全量用户同步 (User Sync Pull) 开发指南

本文档旨在指导开发者如何调用统一认证平台 (UAP) 的全量用户同步接口。
开发者可以通过此接口，将 UAP 中的全量用户数据（仅基础信息）拉取到自己的业务系统中。

## 1. 接口概述

*   **API 地址**: `{{API_BASE_URL}}/apps/mapping/users`
    *   例如: `http://localhost:8000/api/v1/apps/mapping/users`
*   **请求方法**: `GET`
*   **认证方式**: Header 中携带 `X-App-Access-Token: <您的应用访问令牌>`

## 2. 认证准备

在调用接口前，请确保您已在 UAP 平台创建应用，并获取了 **Access Token**。
Access Token 通常在应用详情页面的 "密钥管理" 或 "应用信息" 区域查看。

## 3. 请求参数 (Query Parameters)

该接口支持分页查询，建议在大数据量时分批拉取。

| 参数名 | 类型 | 必填 | 默认值 | 说明 |
| :--- | :--- | :--- | :--- | :--- |
| `skip` | integer | 否 | 0 | 偏移量，表示跳过前 N 条记录 |
| `limit` | integer | 否 | 100 | 每页返回的记录数量 |

## 4. 响应结构

接口返回标准的 JSON 格式数据。

```json
{
  "total": 1250,        // 平台用户总数 (未删除)
  "items": [            // 用户列表
    {
      "mobile": "13800138000",   // 手机号 (唯一标识)
      "name": "张三",            // 中文名 (可能为空)
      "english_name": "zhangsan" // 英文名 (可能为空)
    },
    // ...
  ]
}
```

## 5. 调用示例

### 5.1 Curl

```bash
curl -X GET "{{API_BASE_URL}}/apps/mapping/users?skip=0&limit=100" \
     -H "X-App-Access-Token: YOUR_ACCESS_TOKEN_HERE"
```

### 5.2 Python (Requests)

```python
import requests
import time

API_URL = "{{API_BASE_URL}}/apps/mapping/users"
ACCESS_TOKEN = "YOUR_ACCESS_TOKEN_HERE"

def sync_all_users():
    skip = 0
    limit = 100
    total_synced = 0
    
    while True:
        print(f"正在拉取: skip={skip}, limit={limit}...")
        try:
            resp = requests.get(
                API_URL, 
                params={"skip": skip, "limit": limit},
                headers={"X-App-Access-Token": ACCESS_TOKEN},
                timeout=10
            )
            
            if resp.status_code != 200:
                print(f"请求失败: {resp.status_code} - {resp.text}")
                break
                
            data = resp.json()
            items = data.get("items", [])
            total = data.get("total", 0)
            
            # 处理数据：保存到本地数据库
            for user in items:
                # TODO: save_to_db(user)
                pass
            
            count = len(items)
            total_synced += count
            print(f"已获取 {count} 条数据。进度: {total_synced}/{total}")
            
            if count < limit or total_synced >= total:
                print("同步完成！")
                break
                
            skip += limit
            
            # 避免请求过于频繁
            time.sleep(0.1)
            
        except Exception as e:
            print(f"发生错误: {e}")
            break

if __name__ == "__main__":
    sync_all_users()
```

### 5.3 Java (OkHttp)

```java
OkHttpClient client = new OkHttpClient();

String url = "{{API_BASE_URL}}/apps/mapping/users?skip=0&limit=100";
Request request = new Request.Builder()
  .url(url)
  .addHeader("X-App-Access-Token", "YOUR_ACCESS_TOKEN_HERE")
  .build();

try (Response response = client.newCall(request).execute()) {
    if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

    System.out.println(response.body().string());
}
```

## 6. 常见错误码

*   **403 Forbidden**: 
    *   令牌无效或过期。
    *   令牌对应的应用已被禁用。
*   **422 Unprocessable Entity**: 参数格式错误（如 `skip` 为负数）。

