package license import ( "bytes" "encoding/json" "fmt" "net/http" "strings" "time" ) // redeemOnline 向你们的核销服务登记/校验延期包 id(删光本地数据后仍能拦截旧包)。 func (m *Manager) redeemOnline(leaseID, action string) error { base := strings.TrimRight(strings.TrimSpace(m.cfg.RedeemURL), "/") if base == "" { return nil } leaseID = strings.TrimSpace(leaseID) if leaseID == "" { return fmt.Errorf("lease id 为空") } body, _ := json.Marshal(map[string]string{ "id": leaseID, "customer": strings.TrimSpace(m.cfg.Customer), "action": action, // check | redeem "secret": strings.TrimSpace(m.cfg.ControlSecret), }) client := &http.Client{Timeout: 15 * time.Second} req, err := http.NewRequest(http.MethodPost, base+"/v1/license/redeem", bytes.NewReader(body)) if err != nil { return err } req.Header.Set("Content-Type", "application/json") req.Header.Set("X-License-Secret", strings.TrimSpace(m.cfg.ControlSecret)) resp, err := client.Do(req) if err != nil { return fmt.Errorf("核销服务不可达(已配置 RedeemURL,导入需联网): %w", err) } defer resp.Body.Close() var out struct { OK bool `json:"ok"` Error string `json:"error"` } _ = json.NewDecoder(resp.Body).Decode(&out) if resp.StatusCode >= 300 || !out.OK { msg := out.Error if msg == "" { msg = fmt.Sprintf("核销失败 HTTP %d", resp.StatusCode) } return fmt.Errorf("%s", msg) } return nil }