# 🚀 CLIENT INTEGRATION GUIDE
## Cara Mengintegrasikan License API ke Website/Aplikasi Client

---

## 📋 **OVERVIEW**

Sistem License API ini menyediakan 2 endpoint utama untuk client:

1. **`POST /api/activate`** - Aktivasi license untuk domain tertentu
2. **`GET /api/verify`** - Verifikasi license sebelum mengakses fitur

**Base URL**: `http://127.0.0.1:8000` (atau domain production Anda)

---

## 🔐 **API ENDPOINTS**

### 1. **ACTIVATE LICENSE** (Sekali saat install)

**Endpoint**: `POST /api/activate`

**Request Body**:
```json
{
    "key": "XXXX-XXXX-XXXX-XXXX",
    "domain": "clientwebsite.com"
}
```

**Success Response** (200):
```json
{
    "status": "activated",
    "msg": "License activated successfully",
    "data": {
        "license_key": "WXYZ-ABCD-1234-5678",
        "domain": "clientwebsite.com",
        "status": "active",
        "activated_at": "2024-11-23 12:00:00"
    }
}
```

**Error Responses**:
- **404**: License key tidak ditemukan
- **400**: License sudah diassign ke domain lain

---

### 2. **VERIFY LICENSE** (Setiap kali akses aplikasi)

**Endpoint**: `GET /api/verify`

**Query Parameters**:
```
key=XXXX-XXXX-XXXX-XXXX&domain=clientwebsite.com
```

**Success Response** (200):
```json
{
    "status": "valid",
    "msg": "License is valid",
    "data": {
        "license_key": "WXXX-XXXX-XXXX-XXXX",
        "domain": "clientwebsite.com",
        "status": "active",
        "expired_at": "2025-12-31"
    }
}
```

**Error Responses**:
- **404**: License key tidak ditemukan
- **403**: License suspended / expired / domain mismatch

---

## 💻 **IMPLEMENTASI CLIENT-SIDE**

### **A. PHP Implementation**

#### 1. **Fungsi Helper License**

Buat file: `license-helper.php`

```php
<?php

class LicenseValidator {
    
    private $apiBaseUrl = 'http://127.0.0.1:8000/api';
    private $licenseFile = 'license.json';
    
    /**
     * Aktivasi license (dijalankan sekali saat instalasi)
     */
    public function activate($licenseKey, $domain) {
        $url = $this->apiBaseUrl . '/activate';
        
        $data = [
            'key' => $licenseKey,
            'domain' => $domain
        ];
        
        $response = $this->sendRequest($url, 'POST', $data);
        
        if ($response && $response['status'] === 'activated') {
            // Simpan license ke file
            file_put_contents($this->licenseFile, json_encode([
                'key' => $licenseKey,
                'domain' => $domain,
                'activated_at' => date('Y-m-d H:i:s')
            ]));
            
            return [
                'success' => true,
                'message' => 'License activated successfully!'
            ];
        }
        
        return [
            'success' => false,
            'message' => $response['msg'] ?? 'Activation failed'
        ];
    }
    
    /**
     * Verifikasi license (dijalankan setiap kali load aplikasi)
     */
    public function verify() {
        // Cek apakah license sudah disimpan
        if (!file_exists($this->licenseFile)) {
            return [
                'valid' => false,
                'message' => 'License not found. Please activate first.'
            ];
        }
        
        $license = json_decode(file_get_contents($this->licenseFile), true);
        
        $url = $this->apiBaseUrl . '/verify?' . http_build_query([
            'key' => $license['key'],
            'domain' => $license['domain']
        ]);
        
        $response = $this->sendRequest($url, 'GET');
        
        if ($response && $response['status'] === 'valid') {
            return [
                'valid' => true,
                'message' => 'License is valid',
                'expires_at' => $response['data']['expired_at'] ?? null
            ];
        }
        
        return [
            'valid' => false,
            'message' => $response['msg'] ?? 'License verification failed'
        ];
    }
    
    /**
     * Helper untuk send HTTP request
     */
    private function sendRequest($url, $method = 'GET', $data = null) {
        $ch = curl_init();
        
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_TIMEOUT, 10);
        
        if ($method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
            curl_setopt($ch, CURLOPT_HTTPHEADER, [
                'Content-Type: application/json'
            ]);
        }
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        if ($httpCode >= 200 && $httpCode < 300) {
            return json_decode($response, true);
        }
        
        return json_decode($response, true) ?? ['status' => 'error', 'msg' => 'Request failed'];
    }
}
```

---

#### 2. **Halaman Aktivasi License**

Buat file: `activate.php`

```php
<?php
require_once 'license-helper.php';

$licenseValidator = new LicenseValidator();
$message = '';
$success = false;

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $licenseKey = $_POST['license_key'] ?? '';
    $domain = $_POST['domain'] ?? $_SERVER['HTTP_HOST'];
    
    $result = $licenseValidator->activate($licenseKey, $domain);
    $message = $result['message'];
    $success = $result['success'];
    
    if ($success) {
        header('Location: index.php');
        exit;
    }
}
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Activate License</title>
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 min-h-screen flex items-center justify-center">
    <div class="bg-white p-8 rounded-lg shadow-lg max-w-md w-full">
        <h1 class="text-2xl font-bold text-gray-900 mb-6">Activate Your License</h1>
        
        <?php if ($message): ?>
        <div class="mb-4 p-4 rounded-lg <?= $success ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800' ?>">
            <?= htmlspecialchars($message) ?>
        </div>
        <?php endif; ?>
        
        <form method="POST" action="">
            <div class="mb-4">
                <label class="block text-sm font-medium text-gray-700 mb-2">License Key</label>
                <input type="text" name="license_key" required 
                    placeholder="XXXX-XXXX-XXXX-XXXX"
                    class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
            </div>
            
            <div class="mb-6">
                <label class="block text-sm font-medium text-gray-700 mb-2">Domain</label>
                <input type="text" name="domain" value="<?= $_SERVER['HTTP_HOST'] ?>" required
                    class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500">
            </div>
            
            <button type="submit" class="w-full bg-indigo-600 text-white py-2 px-4 rounded-lg hover:bg-indigo-700 font-semibold">
                Activate License
            </button>
        </form>
    </div>
</body>
</html>
```

---

#### 3. **Proteksi Halaman (License Guard)**

Buat file: `license-guard.php`

```php
<?php
require_once 'license-helper.php';

function checkLicense() {
    $licenseValidator = new LicenseValidator();
    $result = $licenseValidator->verify();
    
    if (!$result['valid']) {
        // Redirect ke halaman aktivasi
        header('Location: activate.php');
        exit;
    }
    
    return $result;
}

// Call this function di setiap halaman yang perlu proteksi
$licenseInfo = checkLicense();
```

---

#### 4. **Halaman Utama dengan Proteksi**

Buat file: `index.php`

```php
<?php
require_once 'license-guard.php';
// License sudah diverifikasi, user bisa akses halaman ini
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Protected Page</title>
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100">
    <div class="container mx-auto p-8">
        <div class="bg-white rounded-lg shadow-lg p-6">
            <div class="flex items-center justify-between mb-6">
                <h1 class="text-3xl font-bold text-gray-900">Welcome to Protected Area</h1>
                <span class="px-4 py-2 bg-green-100 text-green-800 rounded-full text-sm font-semibold">
                    ✓ License Valid
                </span>
            </div>
            
            <div class="bg-blue-50 border border-blue-200 rounded-lg p-4 mb-6">
                <p class="text-sm text-blue-800">
                    <strong>License Info:</strong><br>
                    Expires: <?= htmlspecialchars($licenseInfo['expires_at'] ?? 'N/A') ?>
                </p>
            </div>
            
            <div class="prose max-w-none">
                <h2>Your Premium Content Here</h2>
                <p>Konten ini hanya bisa diakses oleh user dengan license valid.</p>
            </div>
        </div>
    </div>
</body>
</html>
```

---

### **B. JavaScript/Node.js Implementation**

```javascript
// license-validator.js

const axios = require('axios');
const fs = require('fs');

class LicenseValidator {
    constructor() {
        this.apiBaseUrl = 'http://127.0.0.1:8000/api';
        this.licenseFile = 'license.json';
    }
    
    async activate(licenseKey, domain) {
        try {
            const response = await axios.post(`${this.apiBaseUrl}/activate`, {
                key: licenseKey,
                domain: domain
            });
            
            if (response.data.status === 'activated') {
                // Save license
                fs.writeFileSync(this.licenseFile, JSON.stringify({
                    key: licenseKey,
                    domain: domain,
                    activated_at: new Date().toISOString()
                }));
                
                return { success: true, message: 'License activated!' };
            }
        } catch (error) {
            return { 
                success: false, 
                message: error.response?.data?.msg || 'Activation failed' 
            };
        }
    }
    
    async verify() {
        try {
            if (!fs.existsSync(this.licenseFile)) {
                return { valid: false, message: 'License not found' };
            }
            
            const license = JSON.parse(fs.readFileSync(this.licenseFile, 'utf8'));
            
            const response = await axios.get(`${this.apiBaseUrl}/verify`, {
                params: {
                    key: license.key,
                    domain: license.domain
                }
            });
            
            if (response.data.status === 'valid') {
                return { 
                    valid: true, 
                    message: 'License is valid',
                    data: response.data.data
                };
            }
        } catch (error) {
            return { 
                valid: false, 
                message: error.response?.data?.msg || 'Verification failed' 
            };
        }
    }
}

module.exports = LicenseValidator;
```

---

### **C. Python Implementation**

```python
# license_validator.py

import requests
import json
import os

class LicenseValidator:
    def __init__(self):
        self.api_base_url = 'http://127.0.0.1:8000/api'
        self.license_file = 'license.json'
    
    def activate(self, license_key, domain):
        try:
            response = requests.post(
                f'{self.api_base_url}/activate',
                json={'key': license_key, 'domain': domain}
            )
            
            if response.status_code == 200 and response.json()['status'] == 'activated':
                # Save license
                with open(self.license_file, 'w') as f:
                    json.dump({
                        'key': license_key,
                        'domain': domain
                    }, f)
                
                return {'success': True, 'message': 'License activated!'}
            
            return {'success': False, 'message': response.json().get('msg', 'Activation failed')}
        except Exception as e:
            return {'success': False, 'message': str(e)}
    
    def verify(self):
        try:
            if not os.path.exists(self.license_file):
                return {'valid': False, 'message': 'License not found'}
            
            with open(self.license_file, 'r') as f:
                license = json.load(f)
            
            response = requests.get(
                f'{self.api_base_url}/verify',
                params={'key': license['key'], 'domain': license['domain']}
            )
            
            if response.status_code == 200 and response.json()['status'] == 'valid':
                return {'valid': True, 'message': 'License is valid', 'data': response.json()['data']}
            
            return {'valid': False, 'message': response.json().get('msg', 'Verification failed')}
        except Exception as e:
            return {'valid': False, 'message': str(e)}
```

---

## 🎯 **FLOW IMPLEMENTASI DI CLIENT**

### **Step 1: First Time Installation**

```
User Install Website/App
    ↓
Tampilkan Form Aktivasi License
    ↓
User Input License Key
    ↓
POST /api/activate
    ↓
Server Validates & Assign Domain
    ↓
Save License Info ke Local (file/database)
    ↓
Redirect ke Dashboard
```

### **Step 2: Every Page Load**

```
User Access Protected Page
    ↓
Check Local License File
    ↓
GET /api/verify dengan license key & domain
    ↓
Server Validates License
    ↓
Valid? → Allow Access
Invalid? → Redirect to Activation Page
```

---

## 🔒 **SECURITY BEST PRACTICES**

1. **HTTPS Only** - Gunakan SSL di production
2. **Store License Securely** - Encrypt jika memungkinkan
3. **Rate Limiting** - Batasi request verify per menit
4. **Cache Verification** - Cache hasil verify 5-15 menit
5. **Domain Validation** - Strict check domain

---

## 📝 **EXAMPLE: WordPress Plugin Integration**

```php
<?php
/**
 * Plugin Name: License Checker
 */

add_action('admin_menu', function() {
    add_menu_page('License', 'License', 'manage_options', 'license', 'license_page');
});

function license_page() {
    require_once plugin_dir_path(__FILE__) . 'license-helper.php';
    $validator = new LicenseValidator();
    
    if ($_POST['activate']) {
        $result = $validator->activate($_POST['key'], $_SERVER['HTTP_HOST']);
        echo '<div class="notice">' . $result['message'] . '</div>';
    }
    
    ?>
    <div class="wrap">
        <h1>Activate License</h1>
        <form method="post">
            <input type="text" name="key" placeholder="License Key" required>
            <button type="submit" name="activate" class="button button-primary">Activate</button>
        </form>
    </div>
    <?php
}

// Protect features
add_action('init', function() {
    require_once plugin_dir_path(__FILE__) . 'license-helper.php';
    $validator = new LicenseValidator();
    $result = $validator->verify();
    
    if (!$result['valid']) {
        // Disable premium features
        remove_action('premium_feature');
    }
});
```

---

## 🧪 **TESTING**

### Test dengan cURL:

```bash
# 1. Activate License
curl -X POST http://127.0.0.1:8000/api/activate \
  -H "Content-Type: application/json" \
  -d '{"key":"XXXX-XXXX-XXXX-XXXX","domain":"testsite.com"}'

# 2. Verify License
curl "http://127.0.0.1:8000/api/verify?key=XXXX-XXXX-XXXX-XXXX&domain=testsite.com"
```

---

## 📊 **RESPONSE CODES**

| Code | Meaning |
|------|---------|
| 200 | Success |
| 400 | Bad Request / Already Assigned |
| 403 | Forbidden / Suspended / Expired / Domain Mismatch |
| 404 | License Not Found |
| 500 | Server Error |

---

## ✅ **CHECKLIST IMPLEMENTASI CLIENT:**

- [ ] Install dependencies (curl/axios/requests)
- [ ] Buat file license-helper sesuai bahasa pemrograman
- [ ] Buat halaman aktivasi license
- [ ] Implement license guard di setiap protected page
- [ ] Test aktivasi dengan license key valid
- [ ] Test verifikasi license
- [ ] Handle error responses
- [ ] Add license info di dashboard admin
- [ ] Implement cache untuk reduce API calls
- [ ] Setup HTTPS di production

---

## 🚀 **READY TO USE!**

Sistem License API sudah **100% berfungsi** dan siap diintegrasikan ke website client manapun! 

Gunakan contoh code di atas sesuai dengan teknologi yang digunakan di client website Anda.

