# game-config-service 游戏配置服务

## 服务职责

game-config-service 第一阶段负责接收旧项目/外部采集任务已经得到的游戏配置和 RTP/反奖快照，把它们保存为带版本的 active 配置视图。新架构当前不在本服务内自己跑采集器，采集结果必须通过导入接口进入服务，再供 game-router、risk-rtp-service、settlement-service 查询使用。

## 当前实现

- 标准 Go 服务分层：`cmd`、`internal/bootstrap`、`internal/config`、`internal/domain`、`internal/handler/http`、`internal/model`、`internal/repository/postgres`、`internal/service`、`internal/api`、`api/openapi`、`configs`。
- HTTP 框架：Hertz，经 `common/pkg/httpserver` 提供 `/health` 和 `/ready`。
- 仓储：第一阶段为内存仓储，包名保留 `repository/postgres`，接口按 PostgreSQL + Redis 缓存后续替换设计。
- 幂等：`import_idempotency_key` 命中且 payload 一致时返回业务视图 `code=IDEMPOTENT_HIT`；同一幂等键不同 payload 返回 409。
- active 语义：同一 `game_code` 导入 active=true 的配置或 snapshot 时，会把旧 active 版本置为 inactive。

## 本地命令

```bash
cd /Users/amumu/Desktop/beifen/golang新架构/游戏服务/game-config-service
go test ./...
go build ./cmd/game-config-service
PORT=8080 go run ./cmd/game-config-service
```

成熟度检查：

```bash
cd /Users/amumu/Desktop/beifen/golang新架构
./scripts/check-go-service-maturity.sh
```

## 接口

### POST /games/configs

新增或更新游戏配置版本。用于导入旧项目游戏前端、数值、赔付表等采集后标准化结果。

请求示例：

```json
{
  "provider": "pg",
  "game_code": "fortune-tiger",
  "config_version": "2026-06-06T10:00:00Z",
  "rtp_bucket": "pg:fortune-tiger:96.5",
  "payout_table_hash": "sha256:payout-table-v1",
  "source_snapshot_id": "collector-snapshot-001",
  "active": true,
  "imported_by": "collector-sync",
  "import_idempotency_key": "config-import-001"
}
```

关键字段：

| 字段 | 说明 |
| --- | --- |
| provider | 游戏供应商，如 `pg` |
| game_code | 游戏编码 |
| config_version | 配置版本，后续注单和结算必须携带 |
| rtp_bucket | RTP/反奖分桶，用于风控 RTP 和结算读取 |
| payout_table_hash | 赔付表哈希，保证 settlement-service 使用的数值来源可追踪 |
| source_snapshot_id | 采集来源快照 ID |
| active | 是否提升为当前可读版本 |
| import_idempotency_key | 导入幂等键 |

### GET /games/configs/{game_code}

查询当前 active 游戏配置。game-router 可用它选择游戏版本，settlement-service 可用 `config_version` 和 `payout_table_hash` 固化结算依据。

### POST /games/rtp-snapshots

导入采集 RTP/反奖快照。该接口表达旧项目“数值反奖数据是采集来的”这一约束：采集任务先在外部生成 snapshot，本服务只接收标准化结果。

请求示例：

```json
{
  "provider": "pg",
  "game_code": "fortune-tiger",
  "config_version": "2026-06-06T10:00:00Z",
  "rtp_bucket": "pg:fortune-tiger:96.5",
  "payout_table_hash": "sha256:payout-table-v1",
  "source_snapshot_id": "collector-snapshot-001",
  "sample_size": 200000,
  "observed_rtp_bps": 9650,
  "active": true,
  "imported_by": "collector-sync",
  "import_idempotency_key": "rtp-import-001"
}
```

`observed_rtp_bps` 使用基点表示，`9650` 表示 `96.50%`。

### GET /games/rtp-snapshots/{game_code}

查询当前 active RTP snapshot。risk-rtp-service 可读取 `rtp_bucket`、`observed_rtp_bps`、`sample_size`、`source_snapshot_id`，用于后续 RTP 策略和结果选择。

## 采集数据导入流程

```text
旧项目/外部采集任务
-> 生成 source_snapshot_id
-> 标准化 game config 与 RTP snapshot
-> POST /games/configs
-> POST /games/rtp-snapshots
-> active=true 时替换该 game_code 当前读取版本
-> game-router / risk-rtp-service / settlement-service 查询 active 视图
```

第一阶段只做内存存储和清晰契约，不负责采集、文件解析、MinIO/R2 原始包管理。后续落地时，原始采集包可进对象存储，本服务保存版本元数据、赔付表哈希、active 指针和 Redis 缓存。

## 后续服务读取方式

- game-router：调用 `GET /games/configs/{game_code}`，根据 `active=true` 的 `config_version` 路由到对应游戏版本。
- risk-rtp-service：调用 `GET /games/rtp-snapshots/{game_code}`，读取 `rtp_bucket`、`observed_rtp_bps`、`sample_size` 和 `source_snapshot_id`。
- settlement-service：调用 `GET /games/configs/{game_code}`，使用 `payout_table_hash` 与注单上的 `config_version` 校验结算依据，避免使用无版本反奖数据。

## 测试覆盖

- 配置版本 upsert 与 active 查询。
- 配置导入幂等命中。
- 配置导入幂等冲突。
- RTP snapshot 幂等导入和运行时读取字段。
- inactive-only 查询返回 not found。
- 标准服务目录架构测试。
