# Feature Spec: 兑换码 RedemptionCode(Ops · ECR-015) > Status: `Active`(Loop continuous · Approved · coding) > Parent: WAVE0-FROZEN · Predecessor: ECR-014 Closed > Capability: `CommerceEntitlement` · BC: `Membership_Orders` > 授权:`docs/WAVE0/LOOP_AUTHORIZATION.md` ## Non-goals 真支付 · Entitlement 细权 · ask_pack 兑换 · UGC ## L2 | Entity | 不变式 | |--------|--------| | `RedemptionBatch` | label · plan_code∈membership_plans · quantity 1..100 | | `RedemptionCode` | code 唯一;status unused→redeemed\|disabled;redeemed 不可再兑 | ## L3 API | Method | Path | Auth | 语义 | |--------|------|------|------| | POST | `/admin/redemption-batches` | `admin.membership.codes.write` | 批量生成 | | GET | `/admin/redemption-batches` | `admin.membership.codes.read` | 批次列表 | | GET | `/admin/redemption-batches/:id/codes` | `admin.membership.codes.read` | 码列表 | | POST | `/admin/redemption-codes/:id/disable` | `admin.membership.codes.write` | 作废 unused | | POST | `/membership/redeem` | DeviceAuth+已注册 | 兑码→延长会员 | ## L4 AC | ID | Then | |----|------| | AC-F-01 | POST batch quantity=3 → 3 unused codes | | AC-F-02 | C端 redeem → membership active;码=redeemed | | AC-F-03 | 再兑同一码 → 400 | | AC-F-04 | disable unused → status=disabled;兑 → 400 | | AC-S-01 | 无 write → POST batch 403 | | AC-S-02 | 未登录兑码 → 401 | | AC-P-01 | GET batches < 500ms | | AC-O-01 | 生成 AuditLog `redemption.batch.create` | | AC-O-02 | 兑换可追溯 redeemed_by | contract_diff: `docs/CONTRACT_DIFF/ECR-015.yaml`