🔐 License System Documentation
এই ডকুমেন্টেশনে লাইসেন্স সিস্টেমের সম্পূর্ণ বিবরণ, API রেফারেন্স, Deploy গাইড এবং Client Integration কোড রয়েছে।
সিস্টেম ওভারভিউ
পুরো লাইসেন্স সিস্টেমের সারসংক্ষেপ
মূল ফিচারসমূহ
| ফিচার | বিবরণ |
|---|---|
| License Generation | Admin বা User পেমেন্ট করে নতুন লাইসেন্স তৈরি করতে পারে |
| Domain Binding | প্রতিটি লাইসেন্স একটি নির্দিষ্ট ডোমেইনের সাথে যুক্ত |
| Auto Block | Invalid লাইসেন্স ব্যবহার করলে ডোমেইন স্বয়ংক্রিয়ভাবে ব্লক হয় |
| Cache Signal | Admin ইচ্ছামতো ক্লায়েন্ট সাইটের cache মুছতে পারে |
| Kill Switch | Admin যেকোনো সাইটকে রিমোটলি disable করতে পারে |
| HMAC Security | নতুন সাইটে HMAC signature দিয়ে শক্তিশালী নিরাপত্তা |
| License Renewal | মেয়াদ শেষে UddoktaPay দিয়ে পেমেন্ট করে নবায়ন |
ডাটাবেস কাঠামো
সকল টেবিলের বিস্তারিত বিবরণ
📦 licenses টেবিল — মূল লাইসেন্স ডেটা
| Column | Type | বিবরণ |
|---|---|---|
id | bigint PK | Auto increment |
user_id | bigint | লাইসেন্সের মালিক (users টেবিল) |
domain_name | varchar(255) | Normalized ডোমেইন (www/https ছাড়া, lowercase) |
license_key | varchar(255) | Format: LIC-XXXX-XXXX-XXXX |
expiry_date | datetime | মেয়াদ শেষের তারিখ |
status | int | 1 = Active 0 = Inactive |
🛡️ stolen_domains টেবিল — চুরি লগ
| Column | বিবরণ |
|---|---|
domain_name | চেষ্টা করা ডোমেইন |
ip_address | আক্রমণকারীর IP |
cache_signal | Random token — পরিবর্তন হলে ক্লায়েন্ট cache মুছবে |
is_blocked | 1 = Blocked 0 = Unblocked |
status | 0 = Pending 1 = Resolved |
☠️ unauthorized_logs
| Column | বিবরণ |
|---|---|
domain | ডোমেইন নাম |
ip | IP ঠিকানা |
reason | কারণ |
kill_switch | 1 = wipe_out চালু |
🔄 license_renewal_orders
| Column | বিবরণ |
|---|---|
license_id | কোন লাইসেন্সের জন্য |
amount | পেমেন্টের পরিমাণ |
invoice_id | UddoktaPay Invoice |
status | pending / paid / cancelled |
verify-license API
ক্লায়েন্ট সাইট লাইসেন্স যাচাইয়ের Public API
Endpoint
/api/verify-license
Rate Limit: 60/min
Request Parameters
| Parameter | Type | Required | বিবরণ |
|---|---|---|---|
domain | string | হ্যাঁ | ক্লায়েন্ট সাইটের ডোমেইন |
license_key | string | হ্যাঁ | লাইসেন্স কী (LIC-XXXX-XXXX-XXXX) |
signature | string | না | HMAC signature (নতুন ক্লায়েন্টের জন্য) |
url | string | না | সম্পূর্ণ URL (logging এর জন্য) |
✅ Valid Response
{
"status": "valid",
"blocked": false,
"domain_name": "example.com",
"license_key": "LIC-ABCD-EFGH-IJKL",
"expiry_date": "2027-05-15T00:00:00Z",
"secure_token": "a1b2c3d4...",
"cache_signal": "xK9mP2...",
"action": "none"
}
❌ Invalid Response
{
"status": "invalid",
"blocked": true,
"message": "License key or domain is
incorrect or has expired.",
"action": "none"
}
Response Fields ব্যাখ্যা
| Field | মান | বিবরণ |
|---|---|---|
status | valid / invalid | লাইসেন্স বৈধ কিনা |
blocked | true / false | ডোমেইন blocked কিনা |
secure_token | md5 hash | অতিরিক্ত যাচাইয়ের জন্য |
cache_signal | random string | পরিবর্তন হলে ক্লায়েন্ট cache মুছবে |
action | none / wipe_out | wipe_out হলে সাইট disable করতে হবে |
HMAC Security
নতুন ক্লায়েন্টের জন্য উন্নত নিরাপত্তা
⚠️ পুরনো পদ্ধতি (Legacy)
- Signature নেই
- Invalid হলে stolen_domains এ লগ হয়
- সহজ কিন্তু কম secure
✅ নতুন পদ্ধতি (HMAC)
- HMAC-SHA256 signature
- Cleaner — stolen_domains log করে না
- বেশি secure
HMAC Signature তৈরি করার নিয়ম
// PHP
$signature = hash_hmac('sha256', $domain, 'your_secret_salt_key');
// উদাহরণ
$domain = 'example.com';
$signature = hash_hmac('sha256', 'example.com', 'your_secret_salt_key');
// → "a3f9b2c1d4e5f6..."
app/Http/Controllers/Admin/LicenseController.php এ HMAC_SALT ও TOKEN_SALT constants পরিবর্তন করুন। পরিবর্তন করলে সব ক্লায়েন্টে নতুন salt দিতে হবে।Admin প্যানেল
লাইসেন্স ম্যানেজমেন্ট ও নিয়ন্ত্রণ
নতুন লাইসেন্স তৈরি — /admin/licenses
ইউজার সিলেক্ট করুন
ড্রপডাউন থেকে ক্লায়েন্টের অ্যাকাউন্ট বেছে নিন
ডোমেইন দিন
www বা https দিলেও স্বয়ংক্রিয়ভাবে normalize হবে
মেয়াদ সিলেক্ট করুন
১ বছর / ২ বছর / ৩ বছর
Submit করুন
স্বয়ংক্রিয়ভাবে LIC-XXXX-XXXX-XXXX format এ key তৈরি হবে
Stolen Reports — Action বাটনসমূহ
| বাটন | কাজ |
|---|---|
| ⚡ Cache Clear | ক্লায়েন্ট সাইটের cache মুছার signal পাঠানো (৩০ মিনিটের মধ্যে কার্যকর) |
| 🔒 Block | ডোমেইন block করা — ক্লায়েন্ট সাইট বন্ধ হবে |
| 🔓 Unblock | ডোমেইন unblock করা |
| ☠️ Kill Switch | রিমোট wipe-out চালু/বন্ধ করা |
| 🔄 Status | Pending → Resolved toggle |
| 🗑️ Delete | রিপোর্ট মুছা |
রিনিউয়াল অর্ডার ম্যানেজমেন্ট — /admin/license-renewal-orders
User সাইট থেকে renew request করলে এখানে দেখা যাবে।
| Action | ফলাফল |
|---|---|
| Mark as Paid | লাইসেন্স আরো ১ বছর extend হবে, status = paid |
| Mark as Unpaid | পূর্বের অবস্থায় ফেরানো যাবে |
User প্যানেল
ক্লায়েন্টের নিজস্ব লাইসেন্স ম্যানেজমেন্ট
বিনামূল্যে লাইসেন্স
free_license_generation = true করে দেয়ইউজার সরাসরি লাইসেন্স পাবে, কোনো পেমেন্ট লাগবে না।
পেমেন্ট করে লাইসেন্স
মূল্য = license_generation_price × মেয়াদ
User লাইসেন্স Actions
| URL | কাজ |
|---|---|
/my-licenses | সকল লাইসেন্স দেখা |
/license/generate | নতুন লাইসেন্স কেনা |
/license/renew/{id} | মেয়াদ শেষে নবায়ন করা |
/license/update/{id} | ডোমেইন পরিবর্তন |
/license/delete/{id} | লাইসেন্স মুছা |
Stolen Domain সিস্টেম
অবৈধ ব্যবহার স্বয়ংক্রিয়ভাবে ধরা ও ব্লক করা
কীভাবে কাজ করে
ক্লায়েন্ট verify করে
POST /api/verify-license এ domain + license_key পাঠায়
Server চেক করে
ডোমেইন ও কী মিলিয়ে দেখে, মেয়াদ চেক করে
Valid হলে
is_blocked = 0 হয় (auto unblock), status: valid রিটার্ন করে
Invalid হলে
stolen_domains এ লগ হয়, is_blocked = 1, cache_signal নতুন হয়
Admin দেখতে পান
Stolen Reports এ নতুন entry আসে। Block/Unblock করা যায়।
Domain Normalize নিয়ম
| Input | Normalized Output |
|---|---|
https://www.example.com/path | example.com |
http://example.com/ | example.com |
www.EXAMPLE.COM | example.com |
Example.Com | example.com |
Kill Switch
রিমোট wipe-out — ক্লায়েন্ট সাইট disable করা
Kill Switch বন্ধ
{ "action": "none" }
সাইট স্বাভাবিকভাবে কাজ করবে
Kill Switch চালু ☠️
{ "action": "wipe_out" }
ক্লায়েন্ট সাইট নিজেকে disable করবে
কীভাবে চালু/বন্ধ করবেন
Admin প্যানেল খুলুন
Stolen Reports সেকশনে যান
☠️ বাটনে ক্লিক করুন
নির্দিষ্ট ডোমেইনের Kill Switch বাটনে ক্লিক করুন
Confirm করুন
পরের বার ক্লায়েন্ট verify করলে action=wipe_out পাবে
Cache Signal সিস্টেম
ক্লায়েন্ট সাইটের cache রিমোটলি মুছা
উদ্দেশ্য
ক্লায়েন্ট সাইট performance এর জন্য লাইসেন্স ভেরিফিকেশন cache করে রাখতে পারে। Cache Signal ব্যবহার করে Admin যেকোনো সময় ক্লায়েন্ট সাইটের cache মুছতে পারে — সাইটকে সরাসরি access না করেই।
কীভাবে কাজ করে
Admin ⚡ বাটনে ক্লিক করে
Stolen Reports এ নির্দিষ্ট ডোমেইনের Cache Clear বাটন
নতুন cache_signal তৈরি হয়
stolen_domains টেবিলে নতুন random token সেভ হয়
ক্লায়েন্ট verify করে
API response এ নতুন cache_signal পায়
ক্লায়েন্ট পার্থক্য দেখে
পুরনো signal আলাদা → cache মুছে → নতুন signal সেভ করে
Server Deploy নির্দেশিকা
প্রথমবার এবং আপডেট deploy করার নিয়ম
phpMyAdmin এ চালানোর SQL (সব টেবিল)
SSH না থাকলে এই SQL গুলো phpMyAdmin → SQL ট্যাবে paste করে Execute করুন:
-- ১. stolen_domains এ নতুন column
ALTER TABLE `stolen_domains`
ADD COLUMN IF NOT EXISTS `cache_signal` varchar(255) DEFAULT NULL,
ADD COLUMN IF NOT EXISTS `is_blocked` tinyint(1) NOT NULL DEFAULT 0;
-- ২. users টেবিলে free_license_generation
ALTER TABLE `users`
ADD COLUMN IF NOT EXISTS `free_license_generation` tinyint(1) NOT NULL DEFAULT 0;
-- ৩. generalsettings এ license price
ALTER TABLE `generalsettings`
ADD COLUMN IF NOT EXISTS `license_generation_price` decimal(10,2) DEFAULT 1000.00;
-- ৪. unauthorized_logs টেবিল তৈরি
CREATE TABLE IF NOT EXISTS `unauthorized_logs` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`domain` varchar(255) NOT NULL,
`ip` varchar(255) DEFAULT NULL,
`reason` text NOT NULL,
`url` text DEFAULT NULL,
`attempted_at` timestamp NOT NULL,
`kill_switch` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- ৫. license_renewal_orders টেবিল তৈরি
CREATE TABLE IF NOT EXISTS `license_renewal_orders` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) UNSIGNED NOT NULL,
`license_id` bigint(20) UNSIGNED NOT NULL,
`amount` decimal(10,2) NOT NULL DEFAULT 1000.00,
`invoice_id` varchar(255) DEFAULT NULL,
`status` varchar(255) NOT NULL DEFAULT 'pending',
`paid_at` timestamp NULL DEFAULT NULL,
`notes` text DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
SSH থাকলে (Terminal)
php artisan migrate
php artisan config:cache
php artisan route:cache
php artisan cache:clear
Client Site Integration
ক্লায়েন্ট সাইটে লাইসেন্স চেক করার PHP কোড
সহজ পদ্ধতি (Legacy — পুরনো সাইটের জন্য)
<?php
function verifyLicense($domain, $licenseKey, $serverUrl) {
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $serverUrl . '/api/verify-license',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'domain' => $domain,
'license_key' => $licenseKey,
'url' => (isset($_SERVER['HTTPS']) ? 'https' : 'http')
. '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
]),
CURLOPT_TIMEOUT => 10,
]);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
$result = verifyLicense(
'example.com',
'LIC-ABCD-EFGH-IJKL',
'https://yourserver.com'
);
if ($result['status'] === 'valid') {
if ($result['action'] === 'wipe_out') {
die('Site disabled by administrator.');
}
// cache_signal চেক
$saved = @file_get_contents('license_signal.txt');
if ($saved !== $result['cache_signal']) {
clearLocalCache(); // নিজের cache clear function
file_put_contents('license_signal.txt', $result['cache_signal']);
}
// ✅ স্বাভাবিক কাজ চালিয়ে যান
} else {
die('License invalid or domain blocked.');
}
উন্নত পদ্ধতি (HMAC — নতুন সাইটের জন্য)
<?php
define('LICENSE_SERVER', 'https://yourserver.com');
define('LICENSE_DOMAIN', 'example.com');
define('LICENSE_KEY', 'LIC-ABCD-EFGH-IJKL');
define('HMAC_SALT', 'your_secret_salt_key'); // server এর HMAC_SALT
function verifyLicenseHmac() {
$domain = LICENSE_DOMAIN;
$signature = hash_hmac('sha256', $domain, HMAC_SALT);
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => LICENSE_SERVER . '/api/verify-license',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'domain' => $domain,
'license_key' => LICENSE_KEY,
'signature' => $signature,
'url' => (isset($_SERVER['HTTPS']) ? 'https' : 'http')
. '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'],
]),
CURLOPT_TIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => false,
]);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
$result = verifyLicenseHmac();
if (!$result || $result['status'] !== 'valid') {
die('License verification failed.');
}
if ($result['action'] === 'wipe_out') {
die('This installation has been remotely deactivated.');
}
// Cache signal চেক
$cacheFile = __DIR__ . '/.license_signal';
$savedSignal = file_exists($cacheFile) ? trim(file_get_contents($cacheFile)) : '';
if ($result['cache_signal'] && $savedSignal !== $result['cache_signal']) {
if (function_exists('opcache_reset')) opcache_reset();
file_put_contents($cacheFile, $result['cache_signal']);
}
// ✅ লাইসেন্স valid — কাজ চালিয়ে যান
Troubleshooting
সাধারণ সমস্যা ও সমাধান
সমস্যা ১: পুরনো সাইট কাজ করছে না (HTTP 500)
unauthorized_logs টেবিল নেই।সমাধান: phpMyAdmin এ রান করুন:
CREATE TABLE IF NOT EXISTS `unauthorized_logs` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`domain` varchar(255) NOT NULL,
`ip` varchar(255) DEFAULT NULL,
`reason` text NOT NULL,
`url` text DEFAULT NULL,
`attempted_at` timestamp NOT NULL,
`kill_switch` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
সমস্যা ২: সাইট blocked কিন্তু লাইসেন্স valid
stolen_domains.is_blocked = 1 আছে।সমাধান:
UPDATE stolen_domains SET is_blocked = 0 WHERE domain_name = 'example.com';
অথবা Admin → Stolen Reports → 🔓 Unblock বাটন
সমস্যা ৩: Kill Switch বন্ধ করা যাচ্ছে না
UPDATE unauthorized_logs SET kill_switch = 0 WHERE domain = 'example.com';
সমস্যা ৪: kill_switch column নেই
ALTER TABLE `unauthorized_logs` ADD COLUMN `kill_switch` tinyint(1) NOT NULL DEFAULT 0;
সমস্যা ৫: Domain normalize এর কারণে লাইসেন্স পাচ্ছে না
সকল Routes
সম্পূর্ণ route তালিকা
Public (Authentication ছাড়া)
| Method | URL | কাজ |
|---|---|---|
| POST | /api/verify-license | লাইসেন্স ভেরিফিকেশন API |
| GET | /license | লাইসেন্স পেজ (frontend) |
Admin Routes
| Method | URL | কাজ |
|---|---|---|
| GET | /admin/licenses | লাইসেন্স লিস্ট |
| POST | /admin/licenses/store | নতুন লাইসেন্স তৈরি |
| GET | /admin/licenses/edit/{id} | এডিট ডেটা (Ajax) |
| POST | /admin/licenses/update/{id} | লাইসেন্স আপডেট |
| GET | /admin/licenses/delete/{id} | লাইসেন্স মুছা |
| GET | /admin/license-renewal-orders | রিনিউয়াল অর্ডার লিস্ট |
| POST | /admin/license-renewal-orders/{id}/mark-paid | পেইড মার্ক |
| POST | /admin/license-renewal-orders/{id}/mark-unpaid | আনপেইড মার্ক |
| GET | /admin/stolen-reports | চুরির রিপোর্ট |
| POST | /admin/stolen-reports/clear-cache/{id} | Cache Signal আপডেট |
| POST | /admin/stolen-reports/block/{id} | Block/Unblock টগল |
| POST | /admin/stolen-reports/kill-switch/{id} | Kill Switch টগল |
| GET | /admin/stolen-reports/status/{id} | Status পরিবর্তন |
| GET | /admin/stolen-reports/delete/{id} | রিপোর্ট মুছা |
User Routes
| Method | URL | কাজ |
|---|---|---|
| GET | /my-licenses | আমার লাইসেন্সসমূহ |
| GET | /license/generate | নতুন লাইসেন্স ফর্ম |
| POST | /license/generate | লাইসেন্স জেনারেট |
| GET | /license/renew/{id} | রিনিউ পেজ |
| POST | /license/update/{id} | লাইসেন্স আপডেট |
| POST | /license/delete/{id} | লাইসেন্স মুছা |
| GET/POST | /license/renew/success | পেমেন্ট সফল callback |
| POST | /license/renew/webhook | UddoktaPay Webhook |