package main import ( "bytes" "crypto/rand" "encoding/hex" "encoding/json" "fmt" "io" "net/http" "os" "strings" "time" ) func required(name string) string { value := os.Getenv(name) if strings.TrimSpace(value) == "" { panic(fmt.Sprintf("Set %s before running this example.", name)) } return value } func optional(name, fallback string) string { value := os.Getenv(name) if value == "" { return fallback } return value } func envOrDefault(name string, fallback string) string { value := os.Getenv(name) if strings.TrimSpace(value) == "" { return fallback } return strings.TrimRight(value, "/") } func correlationID() string { buffer := make([]byte, 8) if _, err := rand.Read(buffer); err != nil { panic(err) } return "auto-auct-006-go-" + hex.EncodeToString(buffer) } func jsonRequest(client *http.Client, method string, url string, token string, payload any, correlationID string, target any) error { var body io.Reader if payload != nil { encoded, err := json.Marshal(payload) if err != nil { return err } body = bytes.NewReader(encoded) } req, err := http.NewRequest(method, url, body) if err != nil { return err } req.Header.Set("Content-Type", "application/json") if token != "" { req.Header.Set("Authorization", "Bearer "+token) } if correlationID != "" { req.Header.Set("X-Correlation-Id", correlationID) } resp, err := client.Do(req) if err != nil { return err } defer resp.Body.Close() responseBody, err := io.ReadAll(resp.Body) if err != nil { return err } if resp.StatusCode < 200 || resp.StatusCode >= 300 { return fmt.Errorf("%s %s failed with HTTP %d: %s", method, url, resp.StatusCode, string(responseBody)) } if target != nil && len(responseBody) > 0 { return json.Unmarshal(responseBody, target) } return nil } func main() { identityURL := envOrDefault("DECISIOQ_IDENTITY_URL", "https://identity.vinquery.com/connect/token") catalogURL := envOrDefault("DECISIOQ_DKS_URL", "https://dks.vinquery.com") decisionServiceURL := envOrDefault("DECISIOQ_DDE_URL", "https://dde.vinquery.com") correlationID := correlationID() client := &http.Client{Timeout: 30 * time.Second} tokenRequest := map[string]string{ "clientId": required("DECISIOQ_CLIENT_ID"), "clientSecret": required("DECISIOQ_CLIENT_SECRET"), "audience": optional("DECISIOQ_AUDIENCE", "vinquery:api:decisioq"), } var tokenResponse struct { JwtToken string `json:"jwtToken"` } if err := jsonRequest(client, http.MethodPost, identityURL, "", tokenRequest, "", &tokenResponse); err != nil { panic(err) } if strings.TrimSpace(tokenResponse.JwtToken) == "" { panic("Token response did not contain jwtToken.") } if err := jsonRequest(client, http.MethodGet, catalogURL+"/decisioncatalog/decisions/AUTO-AUCT-006", tokenResponse.JwtToken, nil, correlationID, nil); err != nil { panic(err) } executionRequest := map[string]any{ "decisionId": "AUTO-AUCT-006", "profileId": "balanced", "scenarioId": "standard", "algorithm": "TOPSIS", "weightStrategy": "Expert", "runSensitivity": false, "requestContext": map[string]string{"correlationId": correlationID}, "options": []map[string]any{ { "optionId": "MANHEIM-TORONTO", "name": "Manheim Toronto", "values": map[string]float64{ "vehicle_availability_score": 88, "buyer_fee_level": 1250, "average_vehicle_quality": 88, "distance_to_facility": 54, "auction_reputation_score": 88, "title_processing_speed": 88, }, }, { "optionId": "ADESA-TORONTO", "name": "ADESA Toronto", "values": map[string]float64{ "vehicle_availability_score": 81, "buyer_fee_level": 1750, "average_vehicle_quality": 81, "distance_to_facility": 71, "auction_reputation_score": 81, "title_processing_speed": 81, }, }, }, } var result any if err := jsonRequest(client, http.MethodPost, decisionServiceURL+"/api/v1/decide", tokenResponse.JwtToken, executionRequest, correlationID, &result); err != nil { panic(err) } encoded, _ := json.MarshalIndent(result, "", " ") fmt.Println(string(encoded)) }