应用奖励兑换码(CDK,原通用码券)
认证中心的应用奖励兑换码服务与用户软件授权激活码相互独立。每个码批次归属于一个应用;接入方使用本应用 API Key 时,不能查询或核销其他应用的码。奖励由接入方根据核销快照完成实际发放,不等于平台软件使用权益。
管理能力
管理后台的「应用奖励兑换码」(旧入口名「通用码券」)支持:
- 激活码、兑换码、CDK、礼包码、试用码和自定义码;
- 按批次生成最多 1000 个随机码,加密保存原码并仅以尾号展示;
- 为批次配置
entitlement_key和不超过 16 KiB 的 JSON 权益数据,并可保存为按应用隔离的权益模板; - 配置开始时间、截止时间、单码总兑换次数、单个主体兑换次数;
- 在「批次 / 单码 / 核销记录 / 权益模板」四个视角查询和管理;批次可以编辑、整批作废或恢复,单码可以停用或恢复;
- 未发生核销的批次或单码可永久删除。已有核销记录的对象保留审计历史,只允许作废,避免把已经发生的业务事实抹掉;
- 记录每次核销的应用、外部主体、幂等键、业务元数据和时间。
修改批次权益只影响修改后的新核销。每次成功核销都会保存当时的权益快照,因此旧请求的幂等重试仍返回原来的权益,不会因管理员后来编辑批次而改变。
当前管理接口仍使用平台范围的 authorizations:write,没有独立的 CDK 只读、写入或原码导出权限。管理页按应用筛选不是授权隔离;上文的应用边界指接入方 API Key 接口。独立权限及历史角色映射由 #23 跟踪,须经明确批准和迁移验收后再实施,不自动扩大既有角色权限。
subject_id 由接入方定义,可以是游戏角色 ID、游戏账号 ID、软件账号 ID 或设备主体。若奖励是账号共享的,应传账号 ID;若奖励属于单角色,应传经过游戏服校验的角色 ID。
应用配置
应用需要启用以下 API Key 权限:
codes:read:调用校验接口;codes:redeem:调用原子核销接口。
API Key 只能保存在接入方服务端,不得打包进游戏或软件客户端。两个接口不接受浏览器 Cookie 或 OAuth 用户令牌。
认证中心不会直接修改第三方客户端或游戏账号。客户端只负责收集兑换码并提交给自己的业务服务端;业务服务端核销成功后,必须根据白名单中的 entitlement_key 和经过校验的 payload,在自己的数据库、库存、会员或邮件系统中完成实际发放。
校验接口
POST /api/v1/codes/validate
X-API-Key: <应用 API Key>
Content-Type: application/json
{
"code": "CDK-...",
"subject_id": "role-123"
}
HTTP 200 只表示请求成功,必须检查 data.valid。可能的 reason 包括 not_found、disabled、not_started、expired、exhausted 和 subject_limit。校验不会预占或消费兑换次数,不能代替核销。
核销接口
POST /api/v1/codes/redeem
X-API-Key: <应用 API Key>
Content-Type: application/json
{
"code": "CDK-...",
"subject_id": "role-123",
"idempotency_key": "cdk:role-123:request-uuid",
"metadata": {
"server_id": "area-1"
}
}
成功响应示例:
{
"code": 0,
"message": "success",
"data": {
"redemption_id": "...",
"duplicate": false,
"code_type": "cdk",
"entitlement_key": "starter_pack_v1",
"payload": {
"mail_template": "starter",
"items": [{"id": 1001, "count": 5}]
},
"batch_id": "...",
"batch_name": "新手礼包",
"starts_at": "...",
"expires_at": null
}
}
同一业务请求重试时必须复用相同的 idempotency_key。认证中心会返回原核销结果并将 duplicate 置为 true;同一幂等键若改用其他码或主体,会返回 HTTP 409。
游戏服接入流程
- 客户端把
{code, role_id}发给游戏服的cdk/redeemRPC。 - 游戏服从已认证会话获取用户 ID,并验证
role_id确实属于该用户。 - 游戏服生成并持久化请求 ID,以该值构造稳定的
idempotency_key,调用认证中心核销接口。 - 游戏服只按
entitlement_key查找本地白名单奖励规则;payload用于经过严格校验的参数,不直接执行任意操作。 - 游戏服使用
redemption_id作为发奖唯一键,在本地事务或发件箱中创建奖励邮件。超时重试认证中心时复用原幂等键,发奖重试时复用原redemption_id。 - 客户端重新拉取账号权益、背包或邮件列表并刷新界面;不要只在客户端本地加数值,因为那既不可信也无法跨设备生效。
这样即使认证中心成功核销后游戏服短暂崩溃,重试也能取得相同结果且不会重复发奖。
数据与安全边界
- 原码使用 SHA-256 哈希核验,并通过现有
DATA_KEY_FILE的 AES-GCM 密钥加密保存;日志和核销记录不保存原码。 - 核销会锁定目标码记录,在一个数据库事务中检查有效期及次数并写入使用记录。
- 应用 ID 由 API Key 推导,不接受请求体指定,避免跨应用核销。
metadata最大 4 KiB,权益 JSON 最大 16 KiB;管理端批次名称、权益键、备注和次数均有边界校验。- 上线前应使用 HTTPS、轮换已泄露的 API Key,并限制认证中心入口仅允许可信游戏服访问。