Skip to content

Client Examples

Platform-specific implementations and examples for integrating the License Server API into various programming languages and frameworks.

JavaScript/Node.js

Complete Integration Example

javascript
const fetch = require('node-fetch');
const os = require('os');
const crypto = require('crypto');

class LicenseClient {
  constructor(licenseKey, apiUrl, options = {}) {
    this.licenseKey = licenseKey;
    this.apiUrl = apiUrl;
    this.instanceId = options.instanceId || this.generateInstanceId();
    this.isActivated = false;
    this.licenseInfo = null;
    this.usageTracker = null;
  }

  generateInstanceId() {
    const hostname = os.hostname();
    const platform = os.platform();
    return crypto
      .createHash('sha256')
      .update(`${hostname}-${platform}-${Date.now()}`)
      .digest('hex')
      .substring(0, 16);
  }

  async initialize() {
    try {
      // Verify license
      const verification = await this.verifyLicense();
      if (!verification.valid) {
        throw new Error(`Invalid license: ${verification.error}`);
      }

      // Activate license
      const activation = await this.activateLicense();
      if (!activation.activated) {
        throw new Error(`Activation failed: ${activation.error}`);
      }

      this.isActivated = true;
      this.licenseInfo = verification;

      // Start usage tracking
      this.startUsageTracking();

      console.log('License initialized successfully');
      return true;

    } catch (error) {
      console.error('License initialization failed:', error.message);
      return false;
    }
  }

  async verifyLicense() {
    const response = await fetch(`${this.apiUrl}/verify-license`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ key: this.licenseKey }),
      timeout: 30000
    });

    return response.json();
  }

  async activateLicense() {
    const response = await fetch(`${this.apiUrl}/activate-license`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        key: this.licenseKey,
        instance_id: this.instanceId,
        instance_info: {
          hostname: os.hostname(),
          platform: os.platform(),
          node_version: process.version,
          arch: os.arch()
        }
      }),
      timeout: 30000
    });

    return response.json();
  }

  async validateLicense() {
    const response = await fetch(`${this.apiUrl}/validate-license`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        key: this.licenseKey,
        instance_id: this.instanceId
      }),
      timeout: 30000
    });

    return response.json();
  }

  async trackUsage(usage) {
    const response = await fetch(`${this.apiUrl}/track-usage`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        key: this.licenseKey,
        instance_id: this.instanceId,
        usage
      }),
      timeout: 30000
    });

    return response.json();
  }

  startUsageTracking() {
    this.usageTracker = {
      apiCalls: 0,
      activeUsers: new Set(),
      storageUsed: 0
    };

    // Report usage every 5 minutes
    setInterval(async () => {
      try {
        await this.trackUsage({
          api_calls: this.usageTracker.apiCalls,
          active_users: this.usageTracker.activeUsers.size,
          storage_gb: this.usageTracker.storageUsed / (1024 * 1024 * 1024)
        });

        // Reset counters
        this.usageTracker.apiCalls = 0;
        this.usageTracker.activeUsers.clear();
      } catch (error) {
        console.warn('Usage tracking failed:', error.message);
      }
    }, 300000);
  }

  recordAPICall() {
    if (this.usageTracker) {
      this.usageTracker.apiCalls++;
    }
  }

  recordUserActivity(userId) {
    if (this.usageTracker) {
      this.usageTracker.activeUsers.add(userId);
    }
  }

  updateStorageUsage(bytes) {
    if (this.usageTracker) {
      this.usageTracker.storageUsed = bytes;
    }
  }

  async shutdown() {
    if (this.isActivated) {
      try {
        const response = await fetch(`${this.apiUrl}/revoke-license`, {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            key: this.licenseKey,
            revoked: true
          }),
          timeout: 30000
        });

        const result = await response.json();
        if (result.status === 'revoked') {
          console.log('License revoked successfully');
        }

      } catch (error) {
        console.error('License deactivation failed:', error.message);
      }
    }
  }
}

// Usage
const licenseClient = new LicenseClient(
  process.env.LICENSE_KEY,
  'https://your-license-api.com/v1'
);

licenseClient.initialize().then(success => {
  if (success) {
    console.log('Application ready');
    
    // Your application logic here
    licenseClient.recordAPICall();
    licenseClient.recordUserActivity('user123');
    
    // Graceful shutdown
    process.on('SIGTERM', () => {
      licenseClient.shutdown().then(() => process.exit(0));
    });
  } else {
    process.exit(1);
  }
});

Express.js Middleware

javascript
const express = require('express');

class LicenseMiddleware {
  constructor(licenseClient) {
    this.licenseClient = licenseClient;
    this.activeUsers = new Map();
  }

  // Middleware to track API calls
  trackAPICalls() {
    return (req, res, next) => {
      this.licenseClient.recordAPICall();
      next();
    };
  }

  // Middleware to track user activity
  trackUserActivity() {
    return (req, res, next) => {
      const userId = req.user?.id || req.headers['x-user-id'];
      if (userId) {
        this.licenseClient.recordUserActivity(userId);
        
        // Track session duration
        this.activeUsers.set(userId, Date.now());
      }
      next();
    };
  }

  // Middleware to enforce license limits
  enforceLimits() {
    return async (req, res, next) => {
      try {
        const validation = await this.licenseClient.validateLicense();
        
        if (!validation.valid) {
          return res.status(403).json({
            error: 'License validation failed',
            message: 'Please check your license status'
          });
        }

        // Check specific limits
        if (validation.limits) {
          const currentUsage = this.getCurrentUsage();
          
          for (const [limit, value] of Object.entries(validation.limits)) {
            if (currentUsage[limit] && currentUsage[limit] >= value) {
              return res.status(429).json({
                error: 'Usage limit exceeded',
                limit: limit,
                current: currentUsage[limit],
                max: value
              });
            }
          }
        }

        next();
      } catch (error) {
        console.error('License validation error:', error.message);
        next(); // Continue on validation errors
      }
    };
  }

  getCurrentUsage() {
    return {
      api_calls: this.licenseClient.usageTracker?.apiCalls || 0,
      active_users: this.licenseClient.usageTracker?.activeUsers?.size || 0
    };
  }
}

// Usage
const app = express();
const licenseMiddleware = new LicenseMiddleware(licenseClient);

// Apply middleware
app.use(licenseMiddleware.trackAPICalls());
app.use(licenseMiddleware.trackUserActivity());
app.use('/api', licenseMiddleware.enforceLimits());

app.get('/api/data', (req, res) => {
  res.json({ data: 'Your protected data' });
});

app.listen(3000, () => {
  console.log('Server running with license protection');
});

Python

Complete Integration Example

python
import requests
import threading
import time
import hashlib
import platform
import psutil
import json
from typing import Dict, Any, Optional
from datetime import datetime, timedelta

class LicenseClient:
    def __init__(self, license_key: str, api_url: str, instance_id: Optional[str] = None):
        self.license_key = license_key
        self.api_url = api_url.rstrip('/')
        self.instance_id = instance_id or self.generate_instance_id()
        self.is_activated = False
        self.license_info = None
        self.usage_tracker = None
        self.validation_thread = None
        self.tracking_thread = None
        self.is_running = False
        
    def generate_instance_id(self) -> str:
        """Generate a unique instance identifier."""
        hostname = platform.node()
        system = platform.system()
        timestamp = str(int(time.time()))
        
        unique_string = f"{hostname}-{system}-{timestamp}"
        return hashlib.sha256(unique_string.encode()).hexdigest()[:16]
    
    def initialize(self) -> bool:
        """Initialize license verification and activation."""
        try:
            # Verify license
            verification = self.verify_license()
            if not verification.get('valid'):
                raise Exception(f"Invalid license: {verification.get('error', 'Unknown error')}")
            
            # Activate license
            activation = self.activate_license()
            if not activation.get('activated'):
                raise Exception(f"Activation failed: {activation.get('error', 'Unknown error')}")
            
            self.is_activated = True
            self.license_info = verification
            
            # Start background tasks
            self.start_background_tasks()
            
            print("License initialized successfully")
            return True
            
        except Exception as e:
            print(f"License initialization failed: {e}")
            return False
    
    def verify_license(self) -> Dict[str, Any]:
        """Verify license key validity."""
        response = requests.post(
            f'{self.api_url}/verify-license',
            json={'key': self.license_key},
            timeout=30
        )
        return response.json()
    
    def activate_license(self) -> Dict[str, Any]:
        """Activate license for this instance."""
        instance_info = self.get_instance_info()
        
        response = requests.post(
            f'{self.api_url}/activate-license',
            json={
                'key': self.license_key,
                'instance_id': self.instance_id,
                'instance_info': instance_info
            },
            timeout=30
        )
        return response.json()
    
    def validate_license(self) -> Dict[str, Any]:
        """Validate current license status."""
        response = requests.post(
            f'{self.api_url}/validate-license',
            json={
                'key': self.license_key,
                'instance_id': self.instance_id
            },
            timeout=30
        )
        return response.json()
    
    def track_usage(self, usage: Dict[str, Any]) -> Dict[str, Any]:
        """Report usage metrics."""
        response = requests.post(
            f'{self.api_url}/track-usage',
            json={
                'key': self.license_key,
                'instance_id': self.instance_id,
                'usage': usage
            },
            timeout=30
        )
        return response.json()
    
    def get_instance_info(self) -> Dict[str, Any]:
        """Gather instance information."""
        return {
            'hostname': platform.node(),
            'platform': platform.system(),
            'architecture': platform.machine(),
            'python_version': platform.python_version(),
            'processor': platform.processor(),
            'cpu_count': psutil.cpu_count(),
            'memory_gb': psutil.virtual_memory().total / (1024**3),
            'boot_time': datetime.fromtimestamp(psutil.boot_time()).isoformat()
        }
    
    def start_background_tasks(self):
        """Start background validation and usage tracking."""
        self.is_running = True
        self.usage_tracker = {
            'api_calls': 0,
            'active_users': set(),
            'storage_used': 0,
            'start_time': time.time()
        }
        
        # Start validation thread
        self.validation_thread = threading.Thread(target=self._validation_loop)
        self.validation_thread.daemon = True
        self.validation_thread.start()
        
        # Start tracking thread
        self.tracking_thread = threading.Thread(target=self._tracking_loop)
        self.tracking_thread.daemon = True
        self.tracking_thread.start()
    
    def _validation_loop(self):
        """Background license validation."""
        while self.is_running:
            try:
                validation = self.validate_license()
                if not validation.get('valid'):
                    print(f"License validation failed: {validation.get('error')}")
                    self._handle_invalid_license()
                    break
                    
                time.sleep(3600)  # Check every hour
                
            except Exception as e:
                print(f"Validation error: {e}")
                time.sleep(300)  # Retry in 5 minutes on error
    
    def _tracking_loop(self):
        """Background usage tracking."""
        while self.is_running:
            try:
                if self.usage_tracker:
                    usage = {
                        'api_calls': self.usage_tracker['api_calls'],
                        'active_users': len(self.usage_tracker['active_users']),
                        'storage_gb': self.usage_tracker['storage_used'] / (1024**3),
                        'uptime_hours': (time.time() - self.usage_tracker['start_time']) / 3600,
                        'cpu_percent': psutil.cpu_percent(),
                        'memory_percent': psutil.virtual_memory().percent
                    }
                    
                    self.track_usage(usage)
                    
                    # Reset counters
                    self.usage_tracker['api_calls'] = 0
                    self.usage_tracker['active_users'].clear()
                
                time.sleep(300)  # Report every 5 minutes
                
            except Exception as e:
                print(f"Usage tracking error: {e}")
                time.sleep(300)
    
    def _handle_invalid_license(self):
        """Handle invalid license scenario."""
        print("License is invalid - shutting down application")
        self.shutdown()
        # In a real application, you might want to exit or disable features
    
    def record_api_call(self):
        """Record an API call."""
        if self.usage_tracker:
            self.usage_tracker['api_calls'] += 1
    
    def record_user_activity(self, user_id: str):
        """Record user activity."""
        if self.usage_tracker:
            self.usage_tracker['active_users'].add(user_id)
    
    def update_storage_usage(self, bytes_used: int):
        """Update storage usage."""
        if self.usage_tracker:
            self.usage_tracker['storage_used'] = bytes_used
    
    def shutdown(self):
        """Shutdown license client and deactivate."""
        print("Shutting down license client...")
        self.is_running = False
        
        if self.is_activated:
            try:
                response = requests.post(
                    f'{self.api_url}/revoke-license',
                    json={
                        'key': self.license_key,
                        'revoked': True
                    },
                    timeout=30
                )
                
                result = response.json()
                if result.get('status') == 'revoked':
                    print("License revoked successfully")
                    
            except Exception as e:
                print(f"License deactivation failed: {e}")

# Usage example
def main():
    import os
    
    license_client = LicenseClient(
        os.getenv('LICENSE_KEY'),
        'https://your-license-api.com/v1'
    )
    
    if license_client.initialize():
        print("Application starting with valid license")
        
        try:
            # Simulate application work
            while True:
                license_client.record_api_call()
                license_client.record_user_activity('user123')
                time.sleep(1)
                
        except KeyboardInterrupt:
            print("\nShutdown requested...")
            license_client.shutdown()
    else:
        print("Failed to initialize license - exiting")
        exit(1)

if __name__ == "__main__":
    main()

Flask Integration

python
from flask import Flask, request, jsonify, g
from functools import wraps

app = Flask(__name__)
license_client = None  # Initialize with your license client

class LicenseFlaskIntegration:
    def __init__(self, license_client):
        self.license_client = license_client
        
    def require_valid_license(self, f):
        """Decorator to require valid license for routes."""
        @wraps(f)
        def decorated_function(*args, **kwargs):
            try:
                validation = self.license_client.validate_license()
                if not validation.get('valid'):
                    return jsonify({
                        'error': 'Invalid license',
                        'message': 'License validation failed'
                    }), 403
                    
                g.license_info = validation
                return f(*args, **kwargs)
                
            except Exception as e:
                return jsonify({
                    'error': 'License validation error',
                    'message': str(e)
                }), 500
        return decorated_function
    
    def track_request(self):
        """Track incoming requests."""
        self.license_client.record_api_call()
        
        user_id = request.headers.get('X-User-ID')
        if user_id:
            self.license_client.record_user_activity(user_id)

# Initialize integration
license_integration = LicenseFlaskIntegration(license_client)

@app.before_request
def before_request():
    if license_client and license_client.is_activated:
        license_integration.track_request()

@app.route('/api/protected-data')
@license_integration.require_valid_license
def get_protected_data():
    return jsonify({
        'data': 'This is protected data',
        'license_tier': g.license_info.get('tier')
    })

@app.route('/api/license-status')
def license_status():
    if not license_client or not license_client.is_activated:
        return jsonify({'status': 'not_activated'})
    
    try:
        validation = license_client.validate_license()
        return jsonify({
            'status': 'active' if validation.get('valid') else 'invalid',
            'tier': license_client.license_info.get('tier'),
            'expires_at': license_client.license_info.get('expires_at')
        })
    except Exception as e:
        return jsonify({
            'status': 'error',
            'error': str(e)
        }), 500

if __name__ == '__main__':
    import os
    
    # Initialize license client
    license_client = LicenseClient(
        os.getenv('LICENSE_KEY'),
        'https://your-license-api.com/v1'
    )
    
    if license_client.initialize():
        print("Starting Flask app with license protection")
        app.run(debug=False, host='0.0.0.0', port=5000)
    else:
        print("Failed to initialize license - exiting")
        exit(1)

Java

Complete Integration Example

java
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;

public class LicenseClient {
    private final String licenseKey;
    private final String apiUrl;
    private final String instanceId;
    private final HttpClient httpClient;
    private final ObjectMapper objectMapper;
    private final ScheduledExecutorService scheduler;
    
    private boolean isActivated = false;
    private JsonNode licenseInfo;
    private UsageTracker usageTracker;
    
    public LicenseClient(String licenseKey, String apiUrl) {
        this.licenseKey = licenseKey;
        this.apiUrl = apiUrl.replaceAll("/$", "");
        this.instanceId = generateInstanceId();
        this.httpClient = HttpClient.newBuilder()
            .connectTimeout(Duration.ofSeconds(30))
            .build();
        this.objectMapper = new ObjectMapper();
        this.scheduler = Executors.newScheduledThreadPool(2);
        this.usageTracker = new UsageTracker();
    }
    
    private String generateInstanceId() {
        try {
            String hostname = java.net.InetAddress.getLocalHost().getHostName();
            String os = System.getProperty("os.name");
            String timestamp = String.valueOf(System.currentTimeMillis());
            String combined = hostname + "-" + os + "-" + timestamp;
            
            java.security.MessageDigest digest = java.security.MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(combined.getBytes());
            StringBuilder hexString = new StringBuilder();
            
            for (int i = 0; i < Math.min(8, hash.length); i++) {
                String hex = Integer.toHexString(0xff & hash[i]);
                if (hex.length() == 1) {
                    hexString.append('0');
                }
                hexString.append(hex);
            }
            
            return hexString.toString();
        } catch (Exception e) {
            return "java-instance-" + System.currentTimeMillis();
        }
    }
    
    public boolean initialize() {
        try {
            // Verify license
            JsonNode verification = verifyLicense();
            if (!verification.get("valid").asBoolean()) {
                throw new RuntimeException("Invalid license: " + 
                    verification.path("error").asText("Unknown error"));
            }
            
            // Activate license
            JsonNode activation = activateLicense();
            if (!activation.get("activated").asBoolean()) {
                throw new RuntimeException("Activation failed: " + 
                    activation.path("error").asText("Unknown error"));
            }
            
            this.isActivated = true;
            this.licenseInfo = verification;
            
            // Start background tasks
            startBackgroundTasks();
            
            System.out.println("License initialized successfully");
            return true;
            
        } catch (Exception e) {
            System.err.println("License initialization failed: " + e.getMessage());
            return false;
        }
    }
    
    public JsonNode verifyLicense() throws IOException, InterruptedException {
        String requestBody = objectMapper.writeValueAsString(
            java.util.Map.of("key", licenseKey)
        );
        
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(apiUrl + "/verify-license"))
            .header("Content-Type", "application/json")
            .timeout(Duration.ofSeconds(30))
            .POST(HttpRequest.BodyPublishers.ofString(requestBody))
            .build();
        
        HttpResponse<String> response = httpClient.send(request, 
            HttpResponse.BodyHandlers.ofString());
        
        return objectMapper.readTree(response.body());
    }
    
    public JsonNode activateLicense() throws IOException, InterruptedException {
        java.util.Map<String, Object> instanceInfo = getInstanceInfo();
        
        java.util.Map<String, Object> requestBody = java.util.Map.of(
            "key", licenseKey,
            "instance_id", instanceId,
            "instance_info", instanceInfo
        );
        
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(apiUrl + "/activate-license"))
            .header("Content-Type", "application/json")
            .timeout(Duration.ofSeconds(30))
            .POST(HttpRequest.BodyPublishers.ofString(
                objectMapper.writeValueAsString(requestBody)))
            .build();
        
        HttpResponse<String> response = httpClient.send(request, 
            HttpResponse.BodyHandlers.ofString());
        
        return objectMapper.readTree(response.body());
    }
    
    public JsonNode validateLicense() throws IOException, InterruptedException {
        String requestBody = objectMapper.writeValueAsString(java.util.Map.of(
            "key", licenseKey,
            "instance_id", instanceId
        ));
        
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(apiUrl + "/validate-license"))
            .header("Content-Type", "application/json")
            .timeout(Duration.ofSeconds(30))
            .POST(HttpRequest.BodyPublishers.ofString(requestBody))
            .build();
        
        HttpResponse<String> response = httpClient.send(request, 
            HttpResponse.BodyHandlers.ofString());
        
        return objectMapper.readTree(response.body());
    }
    
    public JsonNode trackUsage(java.util.Map<String, Object> usage) 
            throws IOException, InterruptedException {
        java.util.Map<String, Object> requestBody = java.util.Map.of(
            "key", licenseKey,
            "instance_id", instanceId,
            "usage", usage
        );
        
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(apiUrl + "/track-usage"))
            .header("Content-Type", "application/json")
            .timeout(Duration.ofSeconds(30))
            .POST(HttpRequest.BodyPublishers.ofString(
                objectMapper.writeValueAsString(requestBody)))
            .build();
        
        HttpResponse<String> response = httpClient.send(request, 
            HttpResponse.BodyHandlers.ofString());
        
        return objectMapper.readTree(response.body());
    }
    
    private java.util.Map<String, Object> getInstanceInfo() {
        Runtime runtime = Runtime.getRuntime();
        
        return java.util.Map.of(
            "hostname", getHostname(),
            "os_name", System.getProperty("os.name"),
            "os_version", System.getProperty("os.version"),
            "java_version", System.getProperty("java.version"),
            "processors", runtime.availableProcessors(),
            "max_memory_mb", runtime.maxMemory() / (1024 * 1024),
            "start_time", Instant.now().toString()
        );
    }
    
    private String getHostname() {
        try {
            return java.net.InetAddress.getLocalHost().getHostName();
        } catch (Exception e) {
            return "unknown";
        }
    }
    
    private void startBackgroundTasks() {
        // Start validation task (every hour)
        scheduler.scheduleAtFixedRate(this::validateLicenseBackground, 
            1, 1, TimeUnit.HOURS);
        
        // Start usage tracking task (every 5 minutes)
        scheduler.scheduleAtFixedRate(this::reportUsage, 
            5, 5, TimeUnit.MINUTES);
    }
    
    private void validateLicenseBackground() {
        try {
            JsonNode validation = validateLicense();
            if (!validation.get("valid").asBoolean()) {
                System.err.println("License validation failed: " + 
                    validation.path("error").asText());
                handleInvalidLicense();
            }
        } catch (Exception e) {
            System.err.println("License validation error: " + e.getMessage());
        }
    }
    
    private void reportUsage() {
        try {
            java.util.Map<String, Object> usage = usageTracker.getCurrentUsage();
            if (!usage.isEmpty()) {
                trackUsage(usage);
                usageTracker.reset();
            }
        } catch (Exception e) {
            System.err.println("Usage reporting error: " + e.getMessage());
        }
    }
    
    private void handleInvalidLicense() {
        System.err.println("License is invalid - application should shut down");
        shutdown();
    }
    
    public void recordApiCall() {
        usageTracker.recordApiCall();
    }
    
    public void recordUserActivity(String userId) {
        usageTracker.recordUserActivity(userId);
    }
    
    public void updateStorageUsage(long bytes) {
        usageTracker.updateStorageUsage(bytes);
    }
    
    public void shutdown() {
        System.out.println("Shutting down license client...");
        
        if (isActivated) {
            try {
                deactivateLicense();
            } catch (Exception e) {
                System.err.println("License deactivation failed: " + e.getMessage());
            }
        }
        
        scheduler.shutdown();
        try {
            if (!scheduler.awaitTermination(10, TimeUnit.SECONDS)) {
                scheduler.shutdownNow();
            }
        } catch (InterruptedException e) {
            scheduler.shutdownNow();
        }
    }
    
    private void deactivateLicense() throws IOException, InterruptedException {
        String requestBody = objectMapper.writeValueAsString(java.util.Map.of(
            "key", licenseKey,
            "revoked", true
        ));
        
        HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(apiUrl + "/revoke-license"))
            .header("Content-Type", "application/json")
            .timeout(Duration.ofSeconds(30))
            .POST(HttpRequest.BodyPublishers.ofString(requestBody))
            .build();
        
        HttpResponse<String> response = httpClient.send(request, 
            HttpResponse.BodyHandlers.ofString());
        
        JsonNode result = objectMapper.readTree(response.body());
        if ("revoked".equals(result.get("status").asText())) {
            System.out.println("License revoked successfully");
        }
    }
    
    // Inner class for usage tracking
    private static class UsageTracker {
        private final AtomicInteger apiCalls = new AtomicInteger(0);
        private final Set<String> activeUsers = ConcurrentHashMap.newKeySet();
        private final AtomicLong storageUsed = new AtomicLong(0);
        private final long startTime = System.currentTimeMillis();
        
        public void recordApiCall() {
            apiCalls.incrementAndGet();
        }
        
        public void recordUserActivity(String userId) {
            activeUsers.add(userId);
        }
        
        public void updateStorageUsage(long bytes) {
            storageUsed.set(bytes);
        }
        
        public java.util.Map<String, Object> getCurrentUsage() {
            java.util.Map<String, Object> usage = new java.util.HashMap<>();
            
            usage.put("api_calls", apiCalls.get());
            usage.put("active_users", activeUsers.size());
            usage.put("storage_gb", storageUsed.get() / (1024.0 * 1024.0 * 1024.0));
            usage.put("uptime_hours", (System.currentTimeMillis() - startTime) / (1000.0 * 60.0 * 60.0));
            
            return usage;
        }
        
        public void reset() {
            apiCalls.set(0);
            activeUsers.clear();
            // Note: don't reset storageUsed as it's a current value, not a counter
        }
    }
    
    // Getters
    public boolean isActivated() { return isActivated; }
    public JsonNode getLicenseInfo() { return licenseInfo; }
    public String getInstanceId() { return instanceId; }
}

// Usage example
public class Main {
    public static void main(String[] args) {
        String licenseKey = System.getenv("LICENSE_KEY");
        if (licenseKey == null) {
            System.err.println("LICENSE_KEY environment variable not set");
            System.exit(1);
        }
        
        LicenseClient licenseClient = new LicenseClient(
            licenseKey, 
            "https://your-license-api.com/v1"
        );
        
        if (licenseClient.initialize()) {
            System.out.println("Application starting with valid license");
            
            // Add shutdown hook
            Runtime.getRuntime().addShutdownHook(new Thread(licenseClient::shutdown));
            
            // Simulate application work
            try {
                while (true) {
                    licenseClient.recordApiCall();
                    licenseClient.recordUserActivity("user123");
                    Thread.sleep(1000);
                }
            } catch (InterruptedException e) {
                System.out.println("Application interrupted");
            }
        } else {
            System.err.println("Failed to initialize license - exiting");
            System.exit(1);
        }
    }
}

Go

Complete Integration Example

go
package main

import (
    "bytes"
    "crypto/sha256"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "os"
    "runtime"
    "sync"
    "sync/atomic"
    "time"
)

type LicenseClient struct {
    licenseKey   string
    apiURL       string
    instanceID   string
    httpClient   *http.Client
    isActivated  bool
    licenseInfo  map[string]interface{}
    usageTracker *UsageTracker
    stopChan     chan struct{}
    wg           sync.WaitGroup
    mu           sync.RWMutex
}

type UsageTracker struct {
    apiCalls     int64
    activeUsers  sync.Map
    storageUsed  int64
    startTime    time.Time
    mu           sync.Mutex
}

func NewLicenseClient(licenseKey, apiURL string) *LicenseClient {
    return &LicenseClient{
        licenseKey:   licenseKey,
        apiURL:       apiURL,
        instanceID:   generateInstanceID(),
        httpClient:   &http.Client{Timeout: 30 * time.Second},
        usageTracker: &UsageTracker{startTime: time.Now()},
        stopChan:     make(chan struct{}),
    }
}

func generateInstanceID() string {
    hostname, _ := os.Hostname()
    goos := runtime.GOOS
    timestamp := fmt.Sprintf("%d", time.Now().UnixNano())
    
    combined := fmt.Sprintf("%s-%s-%s", hostname, goos, timestamp)
    hash := sha256.Sum256([]byte(combined))
    return fmt.Sprintf("%x", hash[:8])
}

func (lc *LicenseClient) Initialize() error {
    // Verify license
    verification, err := lc.verifyLicense()
    if err != nil {
        return fmt.Errorf("license verification failed: %w", err)
    }
    
    valid, ok := verification["valid"].(bool)
    if !ok || !valid {
        errorMsg := "unknown error"
        if errStr, ok := verification["error"].(string); ok {
            errorMsg = errStr
        }
        return fmt.Errorf("invalid license: %s", errorMsg)
    }
    
    // Activate license
    activation, err := lc.activateLicense()
    if err != nil {
        return fmt.Errorf("license activation failed: %w", err)
    }
    
    activated, ok := activation["activated"].(bool)
    if !ok || !activated {
        errorMsg := "unknown error"
        if errStr, ok := activation["error"].(string); ok {
            errorMsg = errStr
        }
        return fmt.Errorf("activation failed: %s", errorMsg)
    }
    
    lc.mu.Lock()
    lc.isActivated = true
    lc.licenseInfo = verification
    lc.mu.Unlock()
    
    // Start background tasks
    lc.startBackgroundTasks()
    
    fmt.Println("License initialized successfully")
    return nil
}

func (lc *LicenseClient) verifyLicense() (map[string]interface{}, error) {
    payload := map[string]interface{}{
        "key": lc.licenseKey,
    }
    
    return lc.makeRequest("POST", "/verify-license", payload)
}

func (lc *LicenseClient) activateLicense() (map[string]interface{}, error) {
    instanceInfo := lc.getInstanceInfo()
    
    payload := map[string]interface{}{
        "key":           lc.licenseKey,
        "instance_id":   lc.instanceID,
        "instance_info": instanceInfo,
    }
    
    return lc.makeRequest("POST", "/activate-license", payload)
}

func (lc *LicenseClient) validateLicense() (map[string]interface{}, error) {
    payload := map[string]interface{}{
        "key":         lc.licenseKey,
        "instance_id": lc.instanceID,
    }
    
    return lc.makeRequest("POST", "/validate-license", payload)
}

func (lc *LicenseClient) trackUsage(usage map[string]interface{}) (map[string]interface{}, error) {
    payload := map[string]interface{}{
        "key":         lc.licenseKey,
        "instance_id": lc.instanceID,
        "usage":       usage,
    }
    
    return lc.makeRequest("POST", "/track-usage", payload)
}

func (lc *LicenseClient) makeRequest(method, endpoint string, payload map[string]interface{}) (map[string]interface{}, error) {
    jsonData, err := json.Marshal(payload)
    if err != nil {
        return nil, err
    }
    
    url := lc.apiURL + endpoint
    req, err := http.NewRequest(method, url, bytes.NewBuffer(jsonData))
    if err != nil {
        return nil, err
    }
    
    req.Header.Set("Content-Type", "application/json")
    
    resp, err := lc.httpClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    
    body, err := io.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }
    
    var result map[string]interface{}
    if err := json.Unmarshal(body, &result); err != nil {
        return nil, err
    }
    
    return result, nil
}

func (lc *LicenseClient) getInstanceInfo() map[string]interface{} {
    hostname, _ := os.Hostname()
    
    var memStats runtime.MemStats
    runtime.ReadMemStats(&memStats)
    
    return map[string]interface{}{
        "hostname":      hostname,
        "os":           runtime.GOOS,
        "arch":         runtime.GOARCH,
        "go_version":   runtime.Version(),
        "num_cpu":      runtime.NumCPU(),
        "memory_mb":    memStats.Sys / 1024 / 1024,
        "num_goroutine": runtime.NumGoroutine(),
        "start_time":   time.Now().Format(time.RFC3339),
    }
}

func (lc *LicenseClient) startBackgroundTasks() {
    // Start validation goroutine
    lc.wg.Add(1)
    go lc.validationLoop()
    
    // Start usage tracking goroutine
    lc.wg.Add(1)
    go lc.usageTrackingLoop()
}

func (lc *LicenseClient) validationLoop() {
    defer lc.wg.Done()
    
    ticker := time.NewTicker(1 * time.Hour)
    defer ticker.Stop()
    
    for {
        select {
        case <-ticker.C:
            validation, err := lc.validateLicense()
            if err != nil {
                fmt.Printf("License validation error: %v\n", err)
                continue
            }
            
            valid, ok := validation["valid"].(bool)
            if !ok || !valid {
                errorMsg := "unknown error"
                if errStr, ok := validation["error"].(string); ok {
                    errorMsg = errStr
                }
                fmt.Printf("License validation failed: %s\n", errorMsg)
                lc.handleInvalidLicense()
                return
            }
            
        case <-lc.stopChan:
            return
        }
    }
}

func (lc *LicenseClient) usageTrackingLoop() {
    defer lc.wg.Done()
    
    ticker := time.NewTicker(5 * time.Minute)
    defer ticker.Stop()
    
    for {
        select {
        case <-ticker.C:
            usage := lc.usageTracker.getCurrentUsage()
            if len(usage) > 0 {
                _, err := lc.trackUsage(usage)
                if err != nil {
                    fmt.Printf("Usage tracking error: %v\n", err)
                } else {
                    lc.usageTracker.reset()
                }
            }
            
        case <-lc.stopChan:
            return
        }
    }
}

func (lc *LicenseClient) handleInvalidLicense() {
    fmt.Println("License is invalid - application should shut down")
    lc.Shutdown()
}

func (lc *LicenseClient) RecordAPICall() {
    atomic.AddInt64(&lc.usageTracker.apiCalls, 1)
}

func (lc *LicenseClient) RecordUserActivity(userID string) {
    lc.usageTracker.activeUsers.Store(userID, time.Now())
}

func (lc *LicenseClient) UpdateStorageUsage(bytes int64) {
    atomic.StoreInt64(&lc.usageTracker.storageUsed, bytes)
}

func (lc *LicenseClient) Shutdown() {
    fmt.Println("Shutting down license client...")
    
    lc.mu.RLock()
    isActivated := lc.isActivated
    lc.mu.RUnlock()
    
    if isActivated {
        if err := lc.deactivateLicense(); err != nil {
            fmt.Printf("License deactivation failed: %v\n", err)
        }
    }
    
    close(lc.stopChan)
    lc.wg.Wait()
}

func (lc *LicenseClient) deactivateLicense() error {
    payload := map[string]interface{}{
        "key":     lc.licenseKey,
        "revoked": true,
    }
    
    result, err := lc.makeRequest("POST", "/revoke-license", payload)
    if err != nil {
        return err
    }
    
    status, ok := result["status"].(string)
    if ok && status == "revoked" {
        fmt.Println("License revoked successfully")
    }
    
    return nil
}

// UsageTracker methods
func (ut *UsageTracker) getCurrentUsage() map[string]interface{} {
    ut.mu.Lock()
    defer ut.mu.Unlock()
    
    // Count active users
    activeUserCount := 0
    ut.activeUsers.Range(func(key, value interface{}) bool {
        activeUserCount++
        return true
    })
    
    usage := map[string]interface{}{
        "api_calls":     atomic.LoadInt64(&ut.apiCalls),
        "active_users":  activeUserCount,
        "storage_gb":    float64(atomic.LoadInt64(&ut.storageUsed)) / (1024 * 1024 * 1024),
        "uptime_hours":  time.Since(ut.startTime).Hours(),
    }
    
    return usage
}

func (ut *UsageTracker) reset() {
    atomic.StoreInt64(&ut.apiCalls, 0)
    ut.activeUsers = sync.Map{} // Create new map to clear old users
}

// Getters
func (lc *LicenseClient) IsActivated() bool {
    lc.mu.RLock()
    defer lc.mu.RUnlock()
    return lc.isActivated
}

func (lc *LicenseClient) GetLicenseInfo() map[string]interface{} {
    lc.mu.RLock()
    defer lc.mu.RUnlock()
    return lc.licenseInfo
}

func (lc *LicenseClient) GetInstanceID() string {
    return lc.instanceID
}

// Main usage example
func main() {
    licenseKey := os.Getenv("LICENSE_KEY")
    if licenseKey == "" {
        fmt.Println("LICENSE_KEY environment variable not set")
        os.Exit(1)
    }
    
    licenseClient := NewLicenseClient(licenseKey, "https://your-license-api.com/v1")
    
    if err := licenseClient.Initialize(); err != nil {
        fmt.Printf("Failed to initialize license: %v\n", err)
        os.Exit(1)
    }
    
    fmt.Println("Application starting with valid license")
    
    // Simulate application work
    go func() {
        for {
            licenseClient.RecordAPICall()
            licenseClient.RecordUserActivity("user123")
            time.Sleep(1 * time.Second)
        }
    }()
    
    // Wait for interrupt signal
    c := make(chan os.Signal, 1)
    signal.Notify(c, os.Interrupt)
    <-c
    
    fmt.Println("\nShutdown requested...")
    licenseClient.Shutdown()
}

Best Practices

1. Error Handling

  • Implement comprehensive error handling for network failures
  • Use exponential backoff for retries
  • Distinguish between retriable and non-retriable errors
  • Log errors appropriately without exposing sensitive information

2. Performance

  • Use connection pooling for HTTP clients
  • Implement request timeouts
  • Cache license verification results
  • Use background threads/goroutines for non-blocking operations

3. Security

  • Never log full license keys
  • Use secure HTTP (TLS) for all requests
  • Validate certificates and hostnames
  • Store credentials securely

4. Monitoring

  • Track license verification success/failure rates
  • Monitor usage reporting health
  • Set up alerts for license-related issues
  • Implement health checks

5. Configuration

  • Make API endpoints configurable
  • Allow timeout configuration
  • Support different environments (dev/staging/prod)
  • Implement feature flags for license enforcement

Next Steps