QuantumLock™ Guia de Integração
Como Integrar Licenciamento Quântico no Seu Software
Este guia completo mostra como proteger seu software com licenças QuantumLock™.
📋 Índice
- Visão Geral
- Fluxo de Licenciamento
- Modelos de Integração
- Integração Backend (SaaS)
- Integração Desktop
- Integração API/Microservices
- Feature Gating
- Distribuição de Licenças
- Renovação e Expiração
- Segurança
Visão Geral
O QuantumLock™ oferece três modelos de integração:
| Modelo | Caso de Uso | Componente |
|---|---|---|
| Online | SaaS, APIs | SDK + API |
| Offline | Desktop, Embarcados | SDK + Validator |
| Híbrido | Apps conectados | SDK + Validator + API |
Fluxo de Licenciamento
┌─────────────────────────────────────────────────────────────────────────────┐
│ FLUXO DE LICENCIAMENTO │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────────┐ ┌─────────────────┐ │
│ │ SUA APP │────▶│ GERAR LICENÇA│────▶│ ENTREGAR AO │ │
│ │ BACKEND │ │ (via API) │ │ SEU CLIENTE │ │
│ └──────────┘ └──────────────┘ └─────────────────┘ │
│ │ │ │
│ │ ▼ │
│ │ ┌──────────────────────────────────────┐ │
│ │ │ SEU CLIENTE USA │ │
│ │ │ (Desktop/Mobile/Web/API) │ │
│ │ └──────────────────┬───────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌──────────────┐ ┌─────────────────────┐ │
│ │ VALIDAÇÃO │◀─ ─ ─ ─ ─▶│ VALIDAÇÃO OFFLINE │ │
│ │ ONLINE (API) │ │ (arquivo .lic) │ │
│ └──────────────┘ └─────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
Modelos de Integração
1. Modelo Online (SaaS)
Ideal para aplicações web e APIs onde há conectividade constante.
# Seu backend gera licenças via API
from quantumlock.sdk import QuantumLockClient
client = QuantumLockClient(api_key=os.environ["QUANTUMLOCK_API_KEY"])
# Quando cliente compra seu produto
def on_purchase(customer_email, plan):
features = get_features_for_plan(plan)
license = client.generate_license(
end_customer_id=customer_email,
features=features,
valid_days=365
)
# Salvar no seu banco
save_license(customer_email, license)
# Enviar para o cliente
send_license_email(customer_email, license)
2. Modelo Offline (Desktop)
Para softwares que rodam sem internet.
# No software do seu cliente
from quantumlock.sdk import HybridLicenseValidator
# Configurar modo offline
validator = HybridLicenseValidator() # Usa QUANTUMLOCK_LICENSE_PATH
def main():
# Verificar licença no startup (< 5ms)
result = validator.validate()
if not result.is_valid:
show_license_dialog(result.message)
sys.exit(1)
# Software liberado!
print(f"Bem-vindo, {result.customer_name}!")
run_application()
3. Modelo Híbrido (Recomendado)
Validação offline instantânea com verificação online em background.
from quantumlock.sdk import HybridLicenseValidator
# Cria validador híbrido
validator = HybridLicenseValidator()
# Callback quando licença for revogada
@validator.on_revoked
def handle_revocation(result):
show_revoked_dialog()
disable_features()
# Callback quando entrar em grace period
@validator.on_grace_period
def handle_grace(result):
show_reconnect_warning(result.grace_period_ends)
def startup():
# Validação instantânea (< 5ms)
result = validator.validate()
if result.is_valid:
print(f"✅ Licença válida: {result.status.value}")
print(f" Mode: {result.validation_mode}")
return True
else:
print(f"❌ {result.message}")
return False
Integração Backend (SaaS)
Arquitetura Recomendada
┌─────────────────────────────────────────────────────────────────┐
│ SEU BACKEND SAAS │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────┐ ┌────────────────┐ │
│ │ User Service │ │ License Service│ │
│ │ │────▶│ (QuantumLock) │ │
│ └────────────────┘ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────┐ │
│ │ QuantumLock SDK Client │ │
│ └───────────┬────────────┘ │
│ │ │
└────────────────────────────────┼───────────────────────────────┘
│
▼
┌────────────────────────┐
│ QuantumLock™ API │
│ (api.quantumlock. │
│ softquantus.com) │
└────────────────────────┘
Exemplo: FastAPI License Service
# license_service.py
from fastapi import FastAPI, Depends, HTTPException
from pydantic import BaseModel
from quantumlock.sdk import QuantumLockClient
import os
app = FastAPI()
# Singleton client
_client = None
def get_client() -> QuantumLockClient:
global _client
if _client is None:
_client = QuantumLockClient(
api_key=os.environ["QUANTUMLOCK_API_KEY"]
)
return _client
class CreateLicenseRequest(BaseModel):
customer_email: str
plan: str # "basic", "premium", "enterprise"
class LicenseResponse(BaseModel):
license_key: str
features: list
valid_until: str
# Mapeamento de planos para features
PLAN_FEATURES = {
"basic": ["basic"],
"premium": ["basic", "premium", "api_access"],
"enterprise": ["basic", "premium", "api_access", "enterprise", "unlimited"]
}
@app.post("/api/licenses/create", response_model=LicenseResponse)
async def create_license(
request: CreateLicenseRequest,
client: QuantumLockClient = Depends(get_client)
):
"""Cria licença quando cliente compra produto"""
features = PLAN_FEATURES.get(request.plan, ["basic"])
try:
license = client.generate_license(
end_customer_id=request.customer_email,
features=features,
valid_days=365
)
return LicenseResponse(
license_key=license["license_key"],
features=license["features"],
valid_until=license["valid_until"]
)
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.post("/api/licenses/validate")
async def validate_license(
license_key: str,
customer_email: str,
client: QuantumLockClient = Depends(get_client)
):
"""Valida licença do cliente"""
result = client.validate_license(
license_key=license_key,
end_customer_id=customer_email
)
return result
Integração Desktop
Estrutura de Projeto
myapp/
├── main.py
├── licensing/
│ ├── __init__.py
│ ├── checker.py # Verificação de licença
│ └── features.py # Feature gating
├── features/
│ ├── basic.py
│ ├── premium.py
│ └── enterprise.py
└── config/
└── license.lic # Arquivo de licença
Implementação
# licensing/checker.py
import os
import sys
from pathlib import Path
from quantumlock.sdk import LicenseValidator, LicenseError
class LicenseChecker:
"""Gerenciador de licença da aplicação"""
# Locais onde procurar licença
LICENSE_PATHS = [
Path.home() / ".myapp" / "license.lic",
Path("/etc/myapp/license.lic"),
Path(os.environ.get("MYAPP_LICENSE", "")),
]
def __init__(self):
self.validator = None
self.license_path = None
def find_license(self) -> Path:
"""Procura arquivo de licença"""
for path in self.LICENSE_PATHS:
if path and path.exists():
return path
return None
def check(self) -> bool:
"""Verifica licença"""
self.license_path = self.find_license()
if not self.license_path:
return False
self.validator = LicenseValidator(
license_path=str(self.license_path)
)
try:
return self.validator.validate()
except LicenseError:
return False
def get_features(self) -> list:
"""Retorna features licenciadas"""
if self.validator and self.validator._is_valid:
info = self.validator.get_license_info()
return info.get("features", [])
return []
def has_feature(self, feature: str) -> bool:
"""Verifica se feature está licenciada"""
return feature in self.get_features()
# Singleton global
license_checker = LicenseChecker()
# licensing/features.py
from functools import wraps
from licensing.checker import license_checker
class FeatureNotLicensed(Exception):
pass
def require_feature(feature: str):
"""Decorador para proteger funções"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
if not license_checker.has_feature(feature):
raise FeatureNotLicensed(
f"Feature '{feature}' não está licenciada"
)
return func(*args, **kwargs)
return wrapper
return decorator
def require_any_feature(*features):
"""Requer pelo menos uma das features"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for feature in features:
if license_checker.has_feature(feature):
return func(*args, **kwargs)
raise FeatureNotLicensed(
f"Nenhuma feature licenciada: {features}"
)
return wrapper
return decorator
# main.py
import sys
from licensing.checker import license_checker
from licensing.features import require_feature, FeatureNotLicensed
from features import basic, premium
def show_license_required():
print("=" * 50)
print(" LICENÇA NECESSÁRIA")
print("=" * 50)
print()
print("Esta aplicação requer uma licença válida.")
print()
print("Para adquirir: https://portal.softquantus.com")
print()
print("Após obter a licença, coloque o arquivo em:")
print(f" ~/.myapp/license.lic")
print()
def main():
# Verificar licença
if not license_checker.check():
show_license_required()
sys.exit(1)
# Mostrar features disponíveis
features = license_checker.get_features()
print(f"Licença válida! Features: {', '.join(features)}")
# Executar aplicação
basic.run() # Sempre disponível
try:
premium.run() # Só se tiver "premium"
except FeatureNotLicensed:
print("Premium features não disponíveis")
if __name__ == "__main__":
main()
Integração API/Microservices
Arquitetura com Gateway
┌─────────────────────────────────────────────────────────────────┐
│ API GATEWAY │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────┐ ┌────────────────┐ │
│ │ Auth Middleware│────▶│License Checker │ │
│ └──────── ────────┘ └───────┬────────┘ │
│ │ │
│ ┌───────────────────────┼───────────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌────────────┐ ┌────────────┐ ┌────────────┐ │
│ │ Service A │ │ Service B │ │ Service C │ │
│ │ (basic) │ │ (premium) │ │(enterprise)│ │
│ └────────────┘ └────────────┘ └────────────┘ │
│ │
└────────────────────────────────────────────────────────────────┘
Middleware de Licença
# middleware/license_middleware.py
from fastapi import Request, HTTPException
from starlette.middleware.base import BaseHTTPMiddleware
from quantumlock.sdk import LicenseValidator
class LicenseMiddleware(BaseHTTPMiddleware):
"""Middleware para verificar licença em cada request"""
# Rotas que não precisam de licença
EXEMPT_PATHS = ["/health", "/docs", "/openapi.json"]
# Mapeamento de rotas para features requeridas
ROUTE_FEATURES = {
"/api/premium/": ["premium", "enterprise"],
"/api/enterprise/": ["enterprise"],
"/api/analytics/": ["analytics"],
}
def __init__(self, app, license_path: str):
super().__init__(app)
self.validator = LicenseValidator(license_path=license_path)
self.validator.validate()
async def dispatch(self, request: Request, call_next):
path = request.url.path
# Rotas isentas
if path in self.EXEMPT_PATHS:
return await call_next(request)
# Verificar se licença está válida
if not self.validator._is_valid:
raise HTTPException(
status_code=503,
detail="Licença inválida ou expirada"
)
# Verificar feature para a rota
for route_prefix, required_features in self.ROUTE_FEATURES.items():
if path.startswith(route_prefix):
has_feature = any(
self.validator.has_feature(f)
for f in required_features
)
if not has_feature:
raise HTTPException(
status_code=403,
detail=f"Features requeridas: {required_features}"
)
break
return await call_next(request)
# app.py
from fastapi import FastAPI
from middleware.license_middleware import LicenseMiddleware
app = FastAPI()
# Adicionar middleware
app.add_middleware(
LicenseMiddleware,
license_path="/etc/myapi/license.lic"
)
@app.get("/api/basic/data")
def basic_data():
return {"tier": "basic"}
@app.get("/api/premium/data")
def premium_data():
return {"tier": "premium", "exclusive": True}
@app.get("/api/enterprise/data")
def enterprise_data():
return {"tier": "enterprise", "unlimited": True}
Feature Gating
Padrões Recomendados
1. Decorador Simples
from quantumlock.sdk import LicenseValidator
validator = LicenseValidator(license_path="/etc/app/license.lic")
validator.validate()
@validator.require_feature("premium")
def premium_function():
"""Só executa com feature premium"""
return expensive_computation()
2. Context Manager
from contextlib import contextmanager
@contextmanager
def licensed_feature(feature: str):
if not validator.has_feature(feature):
raise FeatureNotLicensed(feature)
yield
# Uso
with licensed_feature("analytics"):
run_analytics()
3. Feature Flags
class FeatureFlags:
"""Flags baseadas em licença"""
def __init__(self, validator: LicenseValidator):
self.validator = validator
self._cache = {}
def __getattr__(self, name: str) -> bool:
if name.startswith("_"):
return super().__getattr__(name)
if name not in self._cache:
self._cache[name] = self.validator.has_feature(name)
return self._cache[name]
# Uso
flags = FeatureFlags(validator)
if flags.premium:
show_premium_ui()
if flags.analytics:
enable_analytics()
4. UI Conditional
# Para aplicações com GUI
def build_menu(validator: LicenseValidator):
menu = ["File", "Edit", "View"]
if validator.has_feature("premium"):
menu.append("Premium Tools")
if validator.has_feature("enterprise"):
menu.append("Enterprise Admin")
return menu
Distribuição de Licenças
Fluxo Recomendado
1. Cliente compra seu produto
│
▼
2. Seu sistema gera licença via API
│
▼
3. Licença armazenada no seu banco
│
▼
4. Cliente recebe licença (email/portal/API)
│
▼
5. Cliente instala licença no software
│
▼
6. Software valida e libera features
Métodos de Entrega
Via Email
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
def send_license_email(customer_email: str, license: dict):
msg = MIMEMultipart()
msg["Subject"] = "Sua licença MyApp"
msg["From"] = "licenses@mycompany.com"
msg["To"] = customer_email
body = f"""
Obrigado por adquirir MyApp!
Sua licença: {license['license_key']}
Válida até: {license['valid_until']}
Features: {', '.join(license['features'])}
Instruções:
1. Baixe o arquivo de licença em anexo
2. Salve em ~/.myapp/license.lic
3. Inicie o MyApp
Suporte: support@mycompany.com
"""
msg.attach(MIMEText(body, "plain"))
# Anexar arquivo de licença
license_content = json.dumps(license, indent=2)
attachment = MIMEApplication(license_content.encode())
attachment["Content-Disposition"] = 'attachment; filename="license.lic"'
msg.attach(attachment)
# Enviar
with smtplib.SMTP("smtp.mycompany.com") as server:
server.send_message(msg)
Via Portal (Download)
# endpoint para download
@app.get("/api/licenses/{license_id}/download")
async def download_license(
license_id: str,
current_user = Depends(get_current_user)
):
license = get_license_from_db(license_id, current_user.id)
if not license:
raise HTTPException(404, "Licença não encontrada")
content = json.dumps(license.data, indent=2)
return Response(
content=content,
media_type="application/json",
headers={
"Content-Disposition": f"attachment; filename=license.lic"
}
)
Via API (Provisioning Automático)
# Seu cliente busca licença via API
@app.get("/api/licenses/current")
async def get_current_license(
api_key: str = Header(..., alias="X-API-Key")
):
"""Cliente pode buscar sua licença atual"""
customer = get_customer_by_api_key(api_key)
license = get_active_license(customer.id)
return license.data
Renovação e Expiração
Verificação de Expiração
from datetime import datetime, timedelta
def check_license_expiry(validator: LicenseValidator):
"""Verifica e alerta sobre expiração"""
if not validator._is_valid:
return {"status": "expired", "action_required": True}
info = validator.get_license_info()
valid_until = datetime.fromisoformat(
info["valid_until"].replace("Z", "+00:00")
)
days_left = (valid_until - datetime.now(valid_until.tzinfo)).days
if days_left <= 0:
return {"status": "expired", "action_required": True}
elif days_left <= 30:
return {"status": "expiring_soon", "days_left": days_left}
else:
return {"status": "active", "days_left": days_left}
Notificação Automática
# job_scheduler.py
from apscheduler.schedulers.background import BackgroundScheduler
def check_expiring_licenses():
"""Job diário para verificar licenças expirando"""
expiring = get_licenses_expiring_soon(days=30)
for license in expiring:
# Notificar cliente
send_renewal_reminder(
customer_email=license.customer_email,
days_left=license.days_until_expiry,
renewal_link=f"https://mycompany.com/renew/{license.id}"
)
scheduler = BackgroundScheduler()
scheduler.add_job(check_expiring_licenses, "cron", hour=9)
scheduler.start()
Segurança
Boas Práticas
-
Nunca exponha sua API Key
# ❌ Errado
api_key = "ql_abc123..."
# ✅ Correto
api_key = os.environ["QUANTUMLOCK_API_KEY"] -
Proteja o arquivo de licença
chmod 600 /etc/myapp/license.lic
chown myapp:myapp /etc/myapp/license.lic -
Validação em múltiplos pontos
# Validar no startup
def startup():
if not check_license():
sys.exit(1)
# Validar em operações críticas
@require_feature("enterprise")
def critical_operation():
... -
Cache com TTL
from functools import lru_cache
from datetime import datetime, timedelta
_last_check = None
_cached_result = None
def validate_with_cache():
global _last_check, _cached_result
# Re-validar a cada hora
if _last_check and datetime.now() - _last_check < timedelta(hours=1):
return _cached_result
_cached_result = validator.validate()
_last_check = datetime.now()
return _cached_result -
Logs de auditoria
import logging
audit_logger = logging.getLogger("license.audit")
def on_license_check(result: bool, feature: str = None):
audit_logger.info(
f"License check: valid={result}, feature={feature}, "
f"user={current_user}, ip={client_ip}"
)
📞 Suporte
- Email: support@softquantus.com
- Portal: https://portal.softquantus.com
- Docs: https://docs.softquantus.com
© 2025 SoftQuantus. Todos os direitos reservados.