# 技术调研：闪送配送服务

## Google 路线距离

采用 Google Routes API v2 的 `POST https://routes.googleapis.com/directions/v2:computeRoutes`。请求头使用 `X-Goog-Api-Key` 和 `X-Goog-FieldMask: routes.distanceMeters,routes.duration`，请求体使用取件、收件经纬度、`DRIVE`、`TRAFFIC_AWARE`。参考 Google 官方 [Compute Routes](https://developers.google.com/maps/documentation/routes/reference/rest/v2/TopLevel/computeRoutes)、[计算路线](https://developers.google.com/maps/documentation/routes/compute_route_directions) 和 [字段掩码](https://developers.google.com/maps/documentation/routes/choose_fields)。

服务端只从字典 `sys_google_routes_key` 读取独立密钥，不复用可能由现有匿名接口返回的浏览器密钥 `sys_googlemap_key`，也不在响应或日志中输出服务端密钥。该密钥需启用 Routes API 并限制服务端来源。连接/读取超时、HTTP 非成功、JSON 无路线或距离不大于 0 均降级。

## 降级与精度

外部路线不可用时使用 Haversine 公式计算球面直线距离，四舍五入为整数米并标记 `STRAIGHT_LINE`；路线成功标记 `ROUTE`。闪送计价与现有外卖订单保持同一业务规则：按当前时间匹配运价时段，起送距离内收起送价格，超出不足 0.5 公里不加价、0.5 至不足 1 公里按 1 公里计、至少 1 公里按实际超出距离计。距离与单价除法使用 `BigDecimal`，里程费用使用 `HALF_UP` 四舍五入为整数新台币；路线预计时长只用于履约展示，不参与金额计算。

## 并发与安全

- 创建由 `(user_id, client_request_id)` 唯一键最终保证幂等。
- 抢单和状态变更使用条件 UPDATE，不先查后改。
- App 身份只来自 `JwtUtil.getusid(token)`，骑手额外校验 `userType=2`。
- 平台接口使用 `@PreAuthorize`；凭证仅接受 HTTP(S) URL。
- 待抢订单通过专用视图脱敏，不直接序列化数据库实体。
