卡密管理
dujiao-shop 支持 3 种交付形式,商品的 auto_secret_kind 字段决定:
auto_secret_kind | 形态 | 库存来源 |
|---|---|---|
text | 文本字符串(典型激活码 / 密钥) | 卡密池(card_secrets 表),手工导入 |
file | 文件(zip / pdf / 任意类型,≤ 1 GB) | 文件数 = 库存数 |
codex_pool | OpenAI/ChatGPT 账号 | 号池(详见 Codex 号池) |
文本卡密
1. 创建批次
后台 → 卡密管理 → 添加批次:
| 字段 | 说明 |
|---|---|
| 批次名 | 内部标识,如 618-misc-2026 |
| 关联商品 | 可选,留空表示所有商品都能消费这个批次 |
| 备注 | 给自己看,如"618 大促采购第一批" |
2. 导入卡密
进批次详情:
- 粘贴:每行一条,直接 Ctrl+V
- 上传 CSV:第 1 列是卡密字串,其余列忽略
导入后会显示去重统计(同批次内重复 / 已存在于库的 / 新增数)。
3. 看消耗
- 可用:未卖出
- 已售:
sold = true(关联sold_order_no) - 预占:
reserved_order_id > 0(订单 pending,15 分钟内未付款会自动归还)
4. 退卡 / 作废
订单退款时,默认情况下卡密不归还(防止恶意"先付款拿卡再退款")。 若你确认是合规退款,手动到批次详情 → 卡密列表 → 该条 → "释放"。
文件卡密
1. 设置商品
商品编辑 → auto_secret_kind = file。
2. 上传文件
商品详情页底部 → "上传卡密文件" 区域 → 拖入 / 点选:
- 单文件 ≤ 1 GB(
credentials.max_size配置) - 任意类型,服务器不解压不检查内容
- 文件落到
credentials.root(默认./credentials/),数据库只存映射关系,Web 不可直接访问
3. 库存逻辑
库存 = 已上传文件数 - 已售出文件数。一个买家拿到 1 个文件。
4. 买家下载
订单详情页 → "下载卡密文件" 按钮。下载链接带 JWT 签名,30 分钟有效,过期可点"重新生成"。
卡密池设计要点
- 预占 (reservation) 在下单事务中原子完成,防超卖:sql
-- 文本卡密 UPDATE card_secrets SET reserved_order_id = ? WHERE batch_id = ? AND sold = false AND reserved_order_id = 0 LIMIT ?; - 付款回调 触发
sold = true+sold_order_no = ? - 超时取消 触发
reserved_order_id = 0 - 全程对齐"先预占再决断"的语义,跟号池一致
排查
| 现象 | 原因 |
|---|---|
| 商品页显示"库存不足"但批次里有卡密 | 批次没关联此商品,或卡密都 reserved 没归还 |
| 退款后买家又下单拿到同一张卡 | 你手动释放了卡密 → 这是预期行为 |
| 文件上传后商品库存没变 | 刷新页面 / 检查文件是否真的传完 |