# IronLicensing Go SDK Software licensing and activation SDK for Go applications. Validate licenses, manage activations, check features, and handle trials. ## Installation ```bash go get github.com/IronServices/ironlicensing-go ``` ## Quick Start ### Using Global Client ```go package main import ( "fmt" "log" licensing "github.com/IronServices/ironlicensing-go" ) func main() { // Initialize the global client err := licensing.Init("pk_live_your_public_key", "your-product-slug") if err != nil { log.Fatal(err) } // Validate a license result := licensing.Validate("IRON-XXXX-XXXX-XXXX-XXXX") if result.Valid { fmt.Println("License is valid!") fmt.Printf("Status: %s\n", result.License.Status) } else { fmt.Printf("Validation failed: %s\n", result.Error) } // Check for features if licensing.HasFeature("premium") { fmt.Println("Premium features enabled!") } } ``` ### Using Client Instance ```go package main import ( "context" "fmt" "log" licensing "github.com/IronServices/ironlicensing-go" ) func main() { client, err := licensing.NewClient(licensing.Options{ PublicKey: "pk_live_your_public_key", ProductSlug: "your-product-slug", Debug: true, }) if err != nil { log.Fatal(err) } // Activate with context ctx := context.Background() result := client.ActivateContext(ctx, "IRON-XXXX-XXXX-XXXX-XXXX", "My Machine") if result.Valid { fmt.Printf("Activated! License type: %s\n", result.License.Type) } } ``` ## Configuration ```go options := licensing.Options{ PublicKey: "pk_live_xxx", // Required ProductSlug: "your-product", // Required APIBaseURL: "https://api.ironlicensing.com", // Default Debug: false, // Enable debug logging EnableOfflineCache: true, // Cache for offline use CacheValidationMinutes: 60, // Cache duration OfflineGraceDays: 7, // Offline grace period HTTPTimeout: 30 * time.Second, // Request timeout } ``` ### Functional Options ```go err := licensing.Init("pk_live_xxx", "product-slug", licensing.WithDebug(true), ) ``` ## License Validation ```go // Simple validation result := client.Validate("IRON-XXXX-XXXX-XXXX-XXXX") // With context for timeout/cancellation ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() result := client.ValidateContext(ctx, "IRON-XXXX-XXXX-XXXX-XXXX") if result.Valid { license := result.License fmt.Printf("License: %s\n", license.Key) fmt.Printf("Status: %s\n", license.Status) fmt.Printf("Type: %s\n", license.Type) fmt.Printf("Activations: %d/%d\n", license.CurrentActivations, license.MaxActivations) } ``` ## License Activation ```go // Simple activation (uses hostname as machine name) result := client.Activate("IRON-XXXX-XXXX-XXXX-XXXX") // With custom machine name result := client.ActivateContext(ctx, "IRON-XXXX-XXXX-XXXX-XXXX", "Production Server") if result.Valid { fmt.Println("License activated successfully!") // View activations for _, activation := range result.Activations { fmt.Printf("- %s (%s)\n", activation.MachineName, activation.Platform) } } ``` ## License Deactivation ```go if client.Deactivate() { fmt.Println("License deactivated from this machine") } ``` ## Feature Checking ```go // Check if feature is available if client.HasFeature("advanced-analytics") { // Enable advanced analytics } // Require feature (returns error if not available) if err := client.RequireFeature("export-pdf"); err != nil { fmt.Printf("Feature not available: %v\n", err) return } // Get feature details feature := client.GetFeature("max-users") if feature != nil { fmt.Printf("Feature: %s - %s\n", feature.Name, feature.Description) } ``` ## Trial Management ```go result := client.StartTrial("user@example.com") if result.Valid { fmt.Println("Trial started!") fmt.Printf("Trial key: %s\n", result.License.Key) if result.License.ExpiresAt != nil { fmt.Printf("Expires: %s\n", result.License.ExpiresAt.Format(time.RFC3339)) } } ``` ## In-App Purchase ```go // Get available tiers tiers := client.GetTiers() for _, tier := range tiers { fmt.Printf("%s - $%.2f %s\n", tier.Name, tier.Price, tier.Currency) } // Start checkout checkout := client.StartPurchase("tier-id", "user@example.com") if checkout.Success { fmt.Printf("Checkout URL: %s\n", checkout.CheckoutURL) // Open URL in browser for user to complete purchase } ``` ## License Status ```go // Get current license license := client.License() if license != nil { fmt.Printf("Licensed to: %s\n", license.Email) } // Check status status := client.Status() switch status { case licensing.StatusValid: fmt.Println("License is valid") case licensing.StatusExpired: fmt.Println("License has expired") case licensing.StatusTrial: fmt.Println("Running in trial mode") case licensing.StatusNotActivated: fmt.Println("No license activated") default: fmt.Printf("Status: %s\n", status) } // Quick checks if client.IsLicensed() { fmt.Println("Application is licensed") } if client.IsTrial() { fmt.Println("Running in trial mode") } ``` ## License Types | Type | Description | |------|-------------| | `TypePerpetual` | One-time purchase, never expires | | `TypeSubscription` | Recurring payment, expires if not renewed | | `TypeTrial` | Time-limited trial license | ## License Statuses | Status | Description | |--------|-------------| | `StatusValid` | License is valid and active | | `StatusExpired` | License has expired | | `StatusSuspended` | License temporarily suspended | | `StatusRevoked` | License permanently revoked | | `StatusTrial` | Active trial license | | `StatusTrialExpired` | Trial period ended | | `StatusNotActivated` | No license activated | ## Thread Safety The client is thread-safe and can be used concurrently from multiple goroutines: ```go var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() if client.HasFeature("concurrent-feature") { // Safe to call from multiple goroutines } }() } wg.Wait() ``` ## Error Handling ```go // Validation errors result := client.Validate(licenseKey) if !result.Valid { switch result.Error { case "license_not_found": fmt.Println("Invalid license key") case "license_expired": fmt.Println("Your license has expired") case "max_activations_reached": fmt.Println("No more activations available") default: fmt.Printf("Error: %s\n", result.Error) } } // Feature requirement errors err := client.RequireFeature("premium") if err != nil { if lre, ok := err.(*licensing.LicenseRequiredError); ok { fmt.Printf("Feature '%s' requires a valid license\n", lre.Feature) } } ``` ## Machine ID The SDK automatically generates and persists a unique machine ID at `~/.ironlicensing/machine_id`. This ID is used for: - Tracking activations per machine - Preventing license sharing - Offline validation ## License MIT License - see LICENSE file for details.