# game-gateway 游戏网关服务

## 服务定位

游戏网关服务是玩家进入游戏前端的统一入口。第一阶段已经从单文件健康检查骨架升级为标准 Go 服务分层，负责商户玩家身份校验、生成游戏 session、返回 launch URL，并为后续接入 game-router 和 game-session-service 预留边界。

当前实现使用内存 repository，可本地运行和测试。生产落地时，session 建议迁移到 Redis，launch/audit 记录建议落到 PostgreSQL。

## 核心职责

- 提供 `POST /game/login` 和 `POST /game/launch`，创建或复用游戏启动 session。
- 支持 `merchant_id`、`player_id`、`game_code`、`provider`、`currency`、`trace_id`。
- 支持 launch 幂等键 `idempotency_key`，同一键同一请求指纹返回原 session，不重复创建。
- 为 session 设置 TTL，过期后 `GET /game/session/{session_id}` 返回 `SESSION_EXPIRED`。
- 生成面向游戏前端的 `launch_url`，保留域名前缀 `domain_prefix` 和前端地址 `GAME_LAUNCH_BASE_URL` 配置。
- 输出统一 HTTP JSON 响应。

## 禁止事项

- 不能直接扣款或加款。
- 不能直接结算。
- 不能直接读取或写入钱包、账本表。
- 不能直接读取后台管理密钥。
- 不能把游戏结果绕过注单和结算链路返回。

## 目录结构

```text
游戏服务/game-gateway
├── api/openapi/game-gateway.openapi.yaml
├── cmd/game-gateway/main.go
├── configs/config.example.yaml
└── internal
    ├── api
    ├── architecture
    ├── bootstrap
    ├── config
    ├── domain
    ├── handler/http
    ├── model
    ├── repository/memory
    └── service
```

## HTTP 接口

### POST /game/login

用于商户玩家登录并创建游戏入口 session。第一阶段与 `/game/launch` 共用同一条业务边界。

```bash
curl -s http://127.0.0.1:8090/game/login \
  -H 'Content-Type: application/json' \
  -H 'X-Request-ID: req-login-001' \
  -d '{
    "trace_id": "trace_001",
    "merchant_id": "merchant_001",
    "player_id": "player_001",
    "game_code": "fortune-tiger",
    "provider": "pg",
    "currency": "CNY",
    "idempotency_key": "launch_001"
  }'
```

响应中的 `data`：

```json
{
  "code": "OK",
  "session_id": "game_session_xxx",
  "trace_id": "trace_001",
  "merchant_id": "merchant_001",
  "player_id": "player_001",
  "game_code": "fortune-tiger",
  "provider": "pg",
  "currency": "CNY",
  "launch_idempotency_key": "launch_001",
  "launch_url": "https://play.example.com/gateway/launch?session_id=game_session_xxx",
  "domain_prefix": "g",
  "status": "ACTIVE",
  "expires_at": "2026-06-06T10:30:00Z"
}
```

### POST /game/launch

用于显式创建游戏启动 session。请求体字段与 `/game/login` 一致。

```bash
curl -s http://127.0.0.1:8090/game/launch \
  -H 'Content-Type: application/json' \
  -d '{
    "trace_id": "trace_001",
    "merchant_id": "merchant_001",
    "player_id": "player_001",
    "game_code": "fortune-tiger",
    "provider": "pg",
    "currency": "CNY",
    "idempotency_key": "launch_001"
  }'
```

幂等规则：

- 同一 `idempotency_key` + 同一 `merchant_id/player_id/game_code/provider/currency` 返回原 session，业务码为 `IDEMPOTENT_HIT`。
- 同一 `idempotency_key` 但请求指纹不同，返回 HTTP 409。
- 未传 `idempotency_key` 时，服务用 `merchant_id/player_id/provider/game_code/currency/trace_id` 派生 launch key。

### GET /game/session/{session_id}

```bash
curl -s http://127.0.0.1:8090/game/session/game_session_xxx
```

用于游戏前端或后续 game-router 调用前校验 session。session 未过期返回 `ACTIVE`，过期返回 HTTP 410 和 `SESSION_EXPIRED`。

## 配置

配置样例位于 `游戏服务/game-gateway/configs/config.example.yaml`。当前通过环境变量读取：

```text
SERVICE_NAME=game-gateway
PORT=8090
GAME_SESSION_TTL_SECONDS=1800
GAME_LAUNCH_BASE_URL=https://play.example.com/gateway/launch
GAME_DOMAIN_PREFIX=g
GAME_ROUTER_URL=http://game-router:8080
GAME_SESSION_SERVICE_URL=http://game-session-service:8080
GAME_SESSION_REDIS_DSN=redis://127.0.0.1:6379/2
GAME_AUDIT_POSTGRES_DSN=postgres://game_gateway:game_gateway@127.0.0.1:5432/game_gateway?sslmode=disable
```

## Redis / PostgreSQL 建议

第一阶段内存 repository 字段已经按后续存储落地设计：

- Redis session key：`game_session:{session_id}`，value 保存 `merchant_id/player_id/game_code/provider/currency/trace_id/status/expires_at/launch_url`，TTL 等于 `GAME_SESSION_TTL_SECONDS`。
- Redis 幂等 key：`game_launch_idem:{idempotency_key}`，value 保存 `session_id` 和请求指纹，TTL 不短于 session TTL。
- PostgreSQL audit 表建议记录 `session_id`、`launch_idempotency_key`、`merchant_id`、`player_id`、`game_code`、`provider`、`currency`、`trace_id`、`launch_url`、`status`、`created_at`、`expires_at`、`updated_at`。
- PostgreSQL 对 `launch_idempotency_key` 建唯一索引，防止多副本并发重复创建。

## 与周边服务关系

- `merchant-gateway`：商户 API 入口。商户玩家创建、商户签名、后台 API key 仍在 merchant-gateway 边界内；game-gateway 接收已标准化的商户玩家上下文。
- `game-session-service`：后续集中会话服务。game-gateway 第一阶段本地创建 session，后续可把 `CreateSessionIfAbsent` 和 `FindSession` 切到 game-session-service 或 Redis-backed session。
- `game-router`：后续游戏路由服务。game-gateway 创建并校验 session 后，可携带 `session_id/provider/game_code/config_version` 请求 game-router 获取子游戏实例 endpoint。
- `bet-order-service` / `settlement-service` / `wallet-service` / `ledger-service`：资金和注单链路。game-gateway 不直接调用这些服务改账，只负责入口 session。

## 本地命令

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

## 健康检查

```bash
curl http://127.0.0.1:8090/health
curl http://127.0.0.1:8090/ready
```

## 成熟度检查

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

game-gateway 已从 `scripts/go-service-placeholder.allowlist` 移除，后续如果退回单文件健康检查骨架，成熟度脚本会报错。
