23dff69c62
- 新增 license_codes 码池表 + model.LicenseCode;licenses 加 tier 档位列 - LicenseService.Redeem:单事务 FOR UPDATE 校验码未用 → 时长叠加(可叠加,0=永久) → 写 type/tier/max_devices → 绑设备(超限整笔回滚) → 标记已用 → 即时失效 phase 缓存 路由仍 POST /license/activate,客户端零破坏 - util.GenerateRedeemCode/NormalizeCode:JIUKU-XXXX-XXXX 短码(crypto/rand) - cmd/gencode:平台批量生成兑换码并落库;删除 cmd/issue、cmd/genkey - 退役 ed25519 + HMAC:删 util/license_key、GenerateKey、License 全部 config 字段 及生产启动私钥校验;trial 改直接建行(无需私钥、去 Fatal) - tier 档位钩子默认 standard,分档消费模式后续设计 - 测试:Redeem 全场景(叠加/过期重置/永久/一码一次/无效/设备上限回滚) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
20 lines
943 B
Go
20 lines
943 B
Go
package model
|
|
|
|
import "time"
|
|
|
|
type License struct {
|
|
Base
|
|
ShopID uint64 `gorm:"not null;index" json:"shop_id"`
|
|
LicenseKey string `gorm:"size:768;uniqueIndex" json:"license_key"`
|
|
Type string `gorm:"type:enum('trial','monthly','annual','lifetime');default:'trial'" json:"type"`
|
|
// Tier 当前权益档位(标准/pro/max…),随兑换码写入;当前默认 'standard',暂不据此做能力差异。
|
|
Tier string `gorm:"size:32;not null;default:'standard'" json:"tier"`
|
|
ExpiresAt *time.Time `json:"expires_at"`
|
|
IsActive bool `gorm:"default:true" json:"is_active"`
|
|
MaxDevices int `gorm:"default:3" json:"max_devices"`
|
|
Features JSON `gorm:"type:json" json:"features,omitempty"`
|
|
// Deprecated: device binding is now tracked in license_devices table.
|
|
DeviceID string `gorm:"size:255" json:"device_id,omitempty"`
|
|
ActivatedAt *time.Time `json:"activated_at,omitempty"`
|
|
}
|