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

# 位置验证 API：地理围栏与 IP 距离

> Didit 可在验证期间确认用户的实际位置：支持设备定位、地理围栏、IP 与证件距离比对及欺骗攻击检测。每次检测仅需 $0.05。

Didit 的位置验证步骤通过单次读取设备位置（浏览器或原生 SDK）或网络连接的 IP 位置，并将其与允许和禁止区域、IP 位置以及证件上的地址进行比对核验，从而确认用户在验证时所处的实际位置。
在工作流和 API 中，该功能对应 `GEOLOCATION` 功能，其配置项为 `geolocation_*` 键，其核验结果显示在会话决策的 `geolocation_checks[]` 中。

## 适用场景

* 您仅在特定司法管辖区持有牌照（例如博彩、经纪、借贷），必须证明用户在申请时位于允许的区域内。
* 您必须将用户拦截在禁止区域之外，例如受制裁地区或您不提供服务的州/省份。
* 您需要额外的欺诈防范信号：设备位置与 IP 位置或身份证件地址相距甚远、模拟位置、VPN 或模拟器。
* 您不需要用户的行动轨迹或历史记录，仅需获取会话期间采集的单次读取位置。

## 工作原理

**1. 提示与权限**

用户会看到需要获取其位置的原因，并了解该位置仅在本次验证中读取一次。
随后其浏览器或手机会请求位置权限。
Didit 会将用户同意的提示信息（版本、语言和时间）作为 `consent` 记录在结果中。

**2. 每次尝试获取一次位置**

客户端会保留最佳读取结果，直到精度达到要求或单次尝试超时（默认 20 秒）。
每次尝试都包含一个有效期为 5 分钟且与会话绑定的单次使用挑战，以确保捕获的提交内容无法被重放。

**3. 核验**

Didit 会评估精度、新鲜度、近似位置权限、欺骗攻击信号、区域、与 IP 位置和证件地址的距离、VPN、代理、Tor 和模拟器的发现项，以及用户此前的核验记录。

**4. 结果**

每项发现都会触发一个[警告](https://docs.didit.me/zh/core-technology/location-verification/warnings-location-verification.md)，其配置的操作（`NO_ACTION`、`REVIEW` 或 `DECLINE`）决定步骤状态。
以最严格的操作为准。

## 位置来源

您可以通过 `geolocation_position_source` 选择位置的获取来源。

| 值 | 处理逻辑 |
| - | - |
| `device_and_ip` | 核对设备位置与发送请求的连接 IP 位置是否匹配。 |
| `device_only` | 仅使用设备位置，绝不与 IP 位置进行比对。 |
| `ip_only` | 从不向用户请求权限。改为评估连接的 IP 位置（城市级别，50 公里半径），不应用精度、新鲜度或近似位置权限规则。 |
| 未设置 | 向设备请求位置，并将该位置与会话的设备与 IP 分析步骤所观测到的 IP 位置进行比对。对 VPN、代理或 Tor 发现项执行操作的节点会查询该连接，其表现与 `device_and_ip` 一致。 |

在向设备请求位置的节点上，未获取到位置的尝试将被视为拒绝或失败：绝不会用 IP 位置来替代。

## 配置默认值与限制

所有键均为选填项。
完整列表请参阅[工作流功能配置参考](https://docs.didit.me/zh/management-api/workflows/feature-configs.md#位置验证)。

| 配置项 | 默认值 | 限制范围 |
| - | - | - |
| `geolocation_max_accuracy_radius_m` | 250 m | 10 至 50,000 m |
| `geolocation_max_age_seconds` | 120 s | 5 至 3,600 s |
| `geolocation_timeout_seconds` | 20 s | 5 至 120 s |
| `geolocation_max_attempts` | 3 | 1 至 5 |
| `geolocation_accuracy_mode` | `precise` | `precise` 或 `approximate_allowed` |
| `geolocation_low_accuracy_behavior` | `ask_again` | `ask_again` 或 `fail` |
| `geolocation_allow_qr_handoff` | 开启 | 开启或关闭 |
| `geolocation_allow_skip` | 关闭 | 开启或关闭 |
| `geolocation_refusal_path` | `retry_then_handoff` | `retry_then_handoff`、`continue_without_location`、`end_session` |
| `is_geolocation_geofencing_enabled` | 关闭 | 开启或关闭 |
| `geolocation_ip_distance_km` | 200 km | 0 或更大，`null` 表示关闭比对 |
| `geolocation_document_distance_km` | 关闭 | 0 或更大 |
| `geolocation_travel_tolerance_enabled` | 关闭 | 常规区域 10 至 500 km（默认 100），1 至 90 天（默认 14） |
| `geolocation_consecutive_mismatch_count` | 关闭 | 2 至 10 |

### 预设

`geolocation_preset` 会为您未明确设置的每项操作设定默认值。
`licensing` 会拒绝处于允许区域外、禁止区域内、使用 VPN 或 Tor 以及来自模拟器的位置，并对代理进行审核。
`fraud_screening` 应用相同的核验项，但会将 `licensing` 会拒绝的所有情况转为人工审核。
您明确设置的操作始终优先。

## 地理围栏

开启 `is_geolocation_geofencing_enabled` 并列出 `geolocation_areas`。
区域可以是一个完整的国家/地区、某个国家/地区的行政区划（ISO 3166-2）、一个圆形（1 至 500 公里）或一个多边形（3 至 200 个顶点）。
只有位于允许区域内的位置才能通过，且禁止区域的优先级始终高于允许区域。
区域列表最多可包含 50 个区域，且至少需要一个允许区域。

Didit 会评估位置的整个精度圆范围，而不仅仅是其中心点：

* 精度圆完全位于所有允许区域之外时，判定为 `LOCATION_OUTSIDE_GEOFENCE`。
* 精度圆穿过决定判定的边界时，判定为 `LOCATION_GEOFENCE_UNDETERMINED`，绝不会直接判定为“在区域外”。
* 精度圆完全位于禁止区域内时，判定为 `LOCATION_IN_BLOCKED_AREA`，并在允许区域判定的基础上额外触发该警告。

国家/地区或行政区划的边界止于与其他陆地接壤处，而非海岸线。
系统会向用户展示服务可用的区域，但绝不会向其透露哪些区域被禁止。
区域规则同样适用于 `ip_only` 步骤，依据 IP 位置进行评估。
旧版的 `geolocation_geofencing_by_country` 设置依然有效，但不能与 `geolocation_areas` 同时使用。

## 距离检查

| 检查 | 测量范围 | 设置 |
| - | - | - |
| IP 距离 | 设备位置与 IP 位置之间的距离（扣除两者的不确定性半径后；0 表示两者重叠）。 | `geolocation_ip_distance_km`, `geolocation_ip_distance_action` |
| 证件距离 | 位置与地址之间的距离（经过粗略地理编码，因此属于弱信号）。 | `geolocation_document_distance_km`, `geolocation_document_distance_basis`, `geolocation_document_distance_action` |
| 连续不匹配 | 用户先前进行的、处于允许区域外、受阻区域内或离地址过远的检查（相同 `vendor_data`）。 | `geolocation_consecutive_mismatch_count` |

`geolocation_document_distance_basis` 用于选择地址：`document`（先选择身份证件，再选择地址证明）、`proof_of_address` 或 `declared`（会话创建时的 `expected_details.address`）。
启用 `geolocation_travel_tolerance_enabled` 后，如果用户在最近 `geolocation_travel_max_days` 天内曾在其地址附近出现，则当前远离该地址不会被标记。
旅行容差绝不豁免 VPN、伪造的位置、受阻区域或位于允许区域之外的位置。

## 欺骗与完整性信号

* **模拟提供程序**：Android 和 iOS 会在位置属于模拟而非实测时进行上报。
* **设备证明**：原生 SDK 可以附加设备证明。证明失败一律拒绝。缺失证明会被记录，且默认不采取任何操作。浏览器无法提供证明，会被记录为 `unsupported`，而非失败。
* **VPN、代理和 Tor**：在共享位置的网络连接中发现。当您对其中某项的操作不是 `NO_ACTION` 时，若仍有剩余尝试次数，系统会要求用户将其关闭后重试。
* **模拟器**：仅由原生应用上报。检测到模拟器会在该次尝试时直接结束该步骤，因为重试无法更改设备。
* **重放**：在其他会话中出示的质询一律拒绝。

## 结果

该步骤中被接受的尝试具有一个 `outcome`：

| Outcome | 含义 |
| - | - |
| `verified` | 符合所有规则的位置。 |
| `low_accuracy` / `accuracy_undetermined` | 半径超出限制，或设备未上报半径。 |
| `stale` | 位置距当前时间已超过 `geolocation_max_age_seconds`。 |
| `approximate` | 在需要精确位置时仅授予了大致位置权限。 |
| `denied` / `restricted` | 用户拒绝，或系统阻止了位置信息获取。 |
| `unavailable` / `timeout` | 设备未获取到位置，或获取超时。 |
| `mock_detected` | 系统报告该位置为模拟位置。 |
| `outside_geofence` / `in_blocked_area` | 位置超出所有允许区域，或位于受阻区域内。 |
| `anonymizer_detected` | 发现 VPN、代理、Tor 出口节点或模拟器，且您的工作流配置了针对该情况的操作。 |
| `skipped` | 用户未共享位置便继续操作。 |
| `replay_rejected` | 质询属于另一个会话。 |
| `unsupported_client` | 应用或 SDK 版本过旧，无法显示该步骤。 |

若仍有剩余尝试次数，当出现精度不足、位置陈旧、大致位置、拒绝授权或区域不符的结果时，系统会要求用户重试，且仅最后一次尝试会触发警告。
检测到模拟位置，或您的工作流会对模拟器采取操作时，会在上报该情况的该次尝试中直接结束该步骤。

## 用户体验

### 同意与权限

在用户接受须知并响应系统提示之前，不会读取任何信息。
该须知会说明：位置信息仅在此次验证中读取一次，不会记录其行动轨迹。
拒绝授权的用户将根据 `geolocation_refusal_path` 进行处理：

* `retry_then_handoff`：在仍有剩余尝试次数时再次请求，若仍未授权则引导在手机上继续。
* `continue_without_location`：允许在不提供位置的情况下继续，并将拒绝授权记录为结果。
* `end_session`：首次拒绝即直接结束该步骤和会话。此选项要求 `geolocation_permission_denied_action` 设置为 `REVIEW` 或 `DECLINE`，且该会话绝不会通过。

启用 `geolocation_allow_skip` 后，用户可以随时在不提供位置的情况下继续，该步骤将按 `geolocation_unavailable_action` 进行判定。

### 浏览器

托管流程会向浏览器请求位置，并在网站位置权限被关闭时提供针对 Chrome 和 Safari 的逐步指导。
浏览器无法区分精确授权与大致授权，因此网页结果绝不会触发 `LOCATION_APPROXIMATE_ONLY`，也绝不上报模拟提供程序、模拟器或设备证明。
电脑无法共享精确位置，因此该流程会提供一个二维码，以便在用户的手机上继续相同的验证（`geolocation_allow_qr_handoff`，默认开启），手机端完成后电脑端会自动进入下一步。
当您将该流程嵌入到 iframe 中时，请在 `allow` 属性中包含 `geolocation`，请参阅[嵌入式 iframe](https://docs.didit.me/zh/integration/web-sdks/incontext-iframe.md)。
若页面阻止了地理位置权限策略，将被视为网站自身的决定，而非用户的拒绝。

### 原生 SDK

iOS 和 Android SDK 会向操作系统请求权限，并可附加设备证明与模拟位置标记。
在 iOS 上，需在 `Info.plist` 中添加 `NSLocationWhenInUseUsageDescription`；在 Android 上，SDK 会声明 `ACCESS_FINE_LOCATION` 和 `ACCESS_COARSE_LOCATION`，且仅在工作流包含该步骤时在运行时进行请求。
请参阅[原生 SDK](https://docs.didit.me/zh/integration/native-sdks/overview.md)。
在 iOS 或 Android 上授予大致位置权限会触发 `LOCATION_APPROXIMATE_ONLY`，除非 `geolocation_accuracy_mode` 为 `approximate_allowed`。
早于该步骤发布的应用或 SDK 构建版本将以 `unsupported_client` 结束，以避免会话卡滞。

## 决策返回的内容

[会话决策](https://docs.didit.me/zh/sessions-api/retrieve-session.md)和 `status.updated` Webhook 包含两个列表：

* `geolocation_checks[]`：每个位置步骤对应一项，包含该步骤已接受的尝试及其 `warnings`。
* `geolocation_attempts[]`：每个位置步骤的每一次尝试，按时间由旧到新排列。

有关每个字段的详细信息，请参阅[位置验证报告](https://docs.didit.me/zh/core-technology/location-verification/report-location-verification.md)。
坐标、精度、城市和国家/地区属于终端用户的个人数据，因此工作流的响应属性可以限制您的决策返回哪些 `geolocation_checks` 字段。

## 定价

位置验证的费用为**每次核验 \$0.05**，且不包含在免费额度中。
无论核验结果如何，Didit 都会对会话中的每个位置步骤计费一次，因为该核验已运行并返回了结果。
同一步骤内的重试不收费。
重新提交并再次完成该步骤将再次计费。

## 沙盒

沙盒会话在相同的托管流程中运行相同的步骤，设备或浏览器仍会报告真实位置。
沙盒会话绝不会调用 IP 查询服务，因此 IP 比对仅使用会话中已有的信息。
用量记录的价格为 0，因此沙盒会话绝不产生费用。
此步骤没有魔法输入。

## 相关内容

* [位置验证报告](https://docs.didit.me/zh/core-technology/location-verification/report-location-verification.md) - `geolocation_checks[]` 和 `geolocation_attempts[]` 的每个字段。
* [位置验证警告](https://docs.didit.me/zh/core-technology/location-verification/warnings-location-verification.md) - 每个 `LOCATION_*` 代码及其操作。
* [工作流功能配置](https://docs.didit.me/zh/management-api/workflows/feature-configs.md#位置验证) - 每个 `geolocation_*` 键。
* [设备与 IP 分析](https://docs.didit.me/zh/core-technology/ip-analysis/overview.md) - 会话的 IP 地理位置与 VPN 检查。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.