311 lines
7.2 KiB
Markdown
311 lines
7.2 KiB
Markdown
# 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.
|