package public import ( "encoding/json" "fmt" "reflect" "strings" "time" ) type License struct { LicenseUUID string `json:"licensever,omitempty"` //license 唯一编号 ProductName string `json:"productname,omitempty"` //产品名称 MachineID string `json:"machineid,omitempty"` //机器ID ExpiresAt int64 `json:"expiresat,omitempty"` //过期时间 IssuedAt int64 `json:"issuedat,omitempty"` //签发时间 CustomKV map[string]string `json:"customkv,omitempty"` } func GenerateLicense(uuid string, productName string, machineID string, expires int64, kv map[string]string) *License { return &License{ LicenseUUID: uuid, ProductName: productName, MachineID: machineID, ExpiresAt: expires, IssuedAt: time.Now().Unix(), CustomKV: kv, } } func VerifyLicense(productName string, machine string, licenseBytes []byte, isVerify bool) (*License, error) { l := new(License) if err := json.Unmarshal(licenseBytes, l); err != nil { return nil, err } if isVerify { err := l.Valid(productName, machine) if err != nil { return nil, err } } return l, nil } func (c *License) Valid(productName string, machine string) error { var vErr error now := time.Now().Unix() //比较产品名称 if c.CompareProductName(productName) == false { vErr = ErrNoMatchProName } //比较过期时间 if c.VerifyExpiresAt(now, false) == false { // delta := time.Unix(now, 0).Sub(time.Unix(c.ExpiresAt, 0)) expStr := time.Unix(c.ExpiresAt, 0).Format("2006-01-02 15:04:05") vErr = ErrLicenseExpired.SetErrText(fmt.Sprintf("license is expired after %s", expStr)) } //比较签发时间 if c.VerifyIssuedAt(now, false) == false { vErr = ErrBeforeIssued } //比较机器是否与license匹配 if c.CompareMachine(machine) == false { vErr = ErrNoMatchMachineID } return vErr } //已经过期返回0,未过期返回剩余的秒数 func (c *License) GetExpiresAt() int64 { now := time.Now().Unix() delta := time.Unix(c.ExpiresAt, 0).Sub(time.Unix(now, 0)) if delta <= 0 { // return 0 } return int64(delta.Seconds()) } func (c *License) GetEndTime() string { return time.Unix(c.ExpiresAt, 0).String() } //比较产品名 func (c *License) CompareProductName(productName string) bool { return strings.Compare(c.ProductName, productName) == 0 } //比较过期时间 func (c *License) VerifyExpiresAt(now int64, req bool) bool { if c.ExpiresAt == 0 { return !req } return now <= c.ExpiresAt } //比较签发时间 func (c *License) VerifyIssuedAt(now int64, req bool) bool { if c.IssuedAt == 0 { return !req } return now >= c.IssuedAt } //比较机器ID func (c *License) CompareMachine(machineID string) bool { return strings.Compare(c.MachineID, machineID) == 0 } //编码 func (c *License) ToBytes() ([]byte, error) { var ( jsonValue []byte err error ) if jsonValue, err = json.Marshal(c); err != nil { return nil, err } return jsonValue, nil } func ToLicense(lb []byte) (*License, error) { l := new(License) err := json.Unmarshal(lb, l) if err != nil { return nil, err } return l, nil } func BytesToLicense(license string) (*License, error) { parts := strings.Split(license, ".") if len(parts) != 2 { return nil, fmt.Errorf("%s", "license contains an invalid number of segments") } plainBytes, err := DecodeSegment(parts[0]) if err != nil { return nil, err } l := new(License) err = json.Unmarshal(plainBytes, l) if err != nil { return nil, err } return l, nil } func Struct2Map(obj interface{}) map[string]interface{} { t := reflect.TypeOf(obj) v := reflect.ValueOf(obj) var data = make(map[string]interface{}) for i := 0; i < t.NumField(); i++ { data[t.Field(i).Name] = v.Field(i).Interface() } return data }