Technical Support
🟢 Online now
Hello 👋

How can we help you today?
Contact on WhatsApp
B4X Store
jdashboardUI / Licenciamiento / JLicenseManager + Licensr Pro
Licenciamiento

JLicenseManager + Licensr Pro

Motor de licencias offline + Licensr Pro incluido con código fuente, ambos usando el mismo JLicenseManager

Buscar en toda jdashboardUI
Fuente
jdashboardUI.b4xlib · Solo API pública
Idioma de la tienda: es
Capturas reales — JLicenseManager + Licensr Pro
Licensr Pro está construido con jdashboardUI, se entrega con su código fuente y usa el mismo módulo JLicenseManager que la aplicación cliente. No es un generador independiente con otra lógica: ambos lados comparten el mismo motor de licenciamiento.
REAL UI
Diálogo real de activación de JLicenseManager dentro de una aplicación B4J
Diálogo real del lado cliente: HWID, código de activación, Activate Now, Trial, Cancel y tema Cyber Orange.
Licensr Pro Generator
Licensr Pro — Generator: programa, HWID, nivel, licencia perpetua o con expiración y generación del código.
Licensr Pro Programs
Licensr Pro — Programs: programas registrados y Base Secret Key de cada producto.
Licensr Pro Languages
Licensr Pro — Languages: interfaz multilenguaje del generador incluido.
Licensr Pro Settings
Licensr Pro — Settings: idioma, información del sistema, base de datos y acciones de mantenimiento.
Licensr Pro About
Licensr Pro — About: pantalla real del generador incluido con la librería.

Visión general

JLicenseManager es el módulo de licenciamiento offline de jdashboardUI para aplicaciones B4J/Windows. No es solamente un validador: reúne identificación de hardware, generación y validación de códigos, persistencia local, Trial, expiración, protección básica frente a retroceso del reloj, diálogo de activación, temas y callbacks de activación.

Una característica especialmente importante de la distribución es que Licensr Pro, el generador/administrador de licencias incluido con la librería, usa el mismo módulo JLicenseManager que usa la aplicación cliente. Además, Licensr Pro está construido con la propia jdashboardUI y se entrega con su código fuente, por lo que sirve como implementación de referencia real y como demostración completa de la librería.

Esto significa que la documentación debe entenderse en dos lados:

  • Aplicación cliente: carga, valida y guarda la licencia, obtiene el HWID, muestra el diálogo de activación y puede bloquear la aplicación.
  • Licensr Pro: administra programas y claves base y genera los códigos que recibirá el cliente utilizando el mismo sistema de licenciamiento.

Las capturas mostradas en esta página son capturas reales del diálogo cliente y de Licensr Pro.

Arquitectura: el mismo módulo en ambos lados

El punto central es que no existen dos motores de licencia incompatibles. JLicenseManager es el módulo común.

Licensr Pro se incluye para evitar que el desarrollador tenga que construir desde cero una herramienta administrativa o reproducir manualmente la lógica criptográfica. El código fuente incluido también permite personalizar la herramienta para el flujo de trabajo propio.

En las capturas reales de Licensr Pro se pueden ver:

  • selección del programa;
  • ingreso del HWID del cliente;
  • selección del nivel de licencia;
  • licencia perpetua o con fecha de expiración;
  • generación del código;
  • historial de licencias;
  • registro de programas;
  • Base Secret Key por programa;
  • idiomas;
  • ajustes y mantenimiento;
  • información del sistema.

Recomendación: para emisión remota de licencias, toma el código fuente de Licensr Pro incluido como implementación de referencia. No dupliques el formato ni la lógica criptográfica en otro generador si no es necesario.

Plataforma y dependencias

La implementación actual de JLicenseManager está orientada a B4J sobre Windows porque GetHWID obtiene el número de serie de la placa base mediante PowerShell y usa WMIC como fallback.

El módulo utiliza internamente, entre otros:

  • B4XSerializator;
  • B4XCipher / jB4XEncryption;
  • StringUtils;
  • jShell;
  • custom_form;
  • JEditText;
  • jButton;
  • JTextFlow;
  • JIconFont;
  • CustomMessageBox;
  • CSSUtils.

El proyecto de jdashboardUI incluye bcprov-jdk18on-1.85, necesario para la infraestructura criptográfica usada por jB4XEncryption.

Inicialización

La firma pública real es:

Dim LM As JLicenseManager
LM.Initialize("MY_BASE_SECRET", "MyApplication", Me, "LM")

Parámetros:

Parámetro Tipo Uso
SecretBase String Base secreta usada por el motor de licencias
AppName String Nombre usado para File.DirData(AppName)
Callback Object Objeto que recibirá eventos
EventName String Prefijo de eventos

La implementación crea automáticamente el directorio de datos si todavía no existe.

En un comentario antiguo del fuente aparece Initialize2, pero el método público actual se llama Initialize.

Integración mínima recomendada

Una forma sencilla de proteger el inicio de una aplicación es utilizar CheckLicenseAndBlock:

Private LM As JLicenseManager

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1

    LM.Initialize("MY_BASE_SECRET", "MyApplication", Me, "LM")
    LM.Theme = LM.THEME_DARKPRO
    LM.ShowTrialButton = True
    LM.DefaultTrialDays = 7

    Wait For (LM.CheckLicenseAndBlock(MainForm)) Complete (Allowed As Boolean)

    If Allowed = False Then
        ExitApplication
        Return
    End If

    MainForm.Show
End Sub

Si la licencia local es válida, devuelve True. Si está próxima a vencer puede mostrar una advertencia. Si no existe o no es válida, abre el diálogo de activación. Si el usuario no consigue activar, devuelve False.

LicenseResult

El módulo define:

Type LicenseResult ( _
    IsValid As Boolean, _
    Message As String, _
    Level As String, _
    ExpirationTicks As Long, _
    ExpirationDate As String)

Campos:

Campo Descripción
IsValid Resultado de validación
Message Mensaje de estado
Level Nivel de licencia
ExpirationTicks Expiración en ticks; 0 representa sin expiración
ExpirationDate Fecha formateada

Obtener el HWID

Dim HardwareId As String = LM.GetHWID
Log(HardwareId)

La implementación intenta:

  1. PowerShell con Get-CimInstance -ClassName Win32_BaseBoard.
  2. Si falla, CMD + wmic baseboard get serialnumber.
  3. El valor queda cacheado durante la sesión.

Si ninguno de los dos métodos obtiene un valor, devuelve HWID_ERROR_O_NO_SOPORTADO.

Esto hace que la implementación actual de HWID sea específica de Windows.

Generación del código

El módulo expone:

Dim Code As String = LM.GenerateLicenseCode( _
    ClientHWID, _
    ExpirationTicks, _
    "Pro")

La estructura interna serializada contiene:

  • hwid;
  • exp;
  • level;
  • issued.

Luego se cifra y se convierte a Base64.

Licencia perpetua

La validación interpreta ExpirationTicks = 0 como licencia sin expiración.

Licencia temporal

Para una licencia con fecha:

Dim Exp As Long = DateTime.Add(DateTime.Now, 0, 1, 0)

Licensr Pro ofrece esta selección desde su interfaz y es el flujo recomendado cuando el código se genera en una máquina administrativa para un cliente remoto.

Validar manualmente un código

Dim Result As LicenseResult = LM.ValidateLicense(LicenseCode)

If Result.IsValid Then
    Log("Level: " & Result.Level)
    Log("Expires: " & Result.ExpirationDate)
Else
    Log(Result.Message)
End If

La validación comprueba:

  • que el código pueda descifrarse;
  • que corresponda al HWID esperado;
  • que no haya expirado.

Cuando es válida, actualiza también el estado público del módulo.

Guardar y cargar licencia local

SaveLocalLicense

LM.SaveLocalLicense(LicenseCode)

Guarda:

  • license.lic: código de licencia;
  • sys_time.dat: control de tiempo cifrado.

Ambos se gestionan dentro de File.DirData(AppName).

LoadLocalLicense

Dim Result As LicenseResult = LM.LoadLocalLicense

Carga el archivo, comprueba manipulación del reloj y ejecuta ValidateLicense.

Protección frente a retroceso del reloj

El módulo mantiene sys_time.dat con la última hora conocida cifrada.

Si la hora actual retrocede más de una hora respecto de la almacenada, LoadLocalLicense considera que existe manipulación y bloquea la licencia.

Si el archivo de tiempo no se puede descifrar, la implementación actual lo regenera con la hora actual en lugar de bloquear automáticamente.

Esta protección es una medida local adicional; no sustituye una validación en servidor si tu modelo de seguridad requiere control online.

Trial

StartTrialMode

LM.StartTrialMode(7)

Solo crea el Trial si todavía no existe license.lic.

Internamente:

  • calcula la fecha de expiración;
  • genera una licencia con nivel Trial;
  • la guarda con SaveLocalLicense.
LM.ShowTrialButton = True
LM.DefaultTrialDays = 7

El botón Trial del diálogo usa DefaultTrialDays.

Diálogo de activación

Dim Result As LicenseResult = LM.ShowActivationDialog(MainForm)

La captura real incluida en esta página corresponde a este diálogo.

El diálogo incorpora:

  • estado de licencia;
  • HWID de solo lectura;
  • botón para copiar HWID;
  • campo para código de activación;
  • Activate / Update License;
  • Trial opcional;
  • Cancel;
  • tema configurable;
  • alertas visuales.

Una característica interesante es que el propio diálogo usa componentes de jdashboardUI, entre ellos JEditText, jButton, JTextFlow, CustomMessageBox y custom_form.

Eventos

El módulo declara cuatro eventos:

Private Sub LM_ActivationSuccess(Result As LicenseResult)
    Log("Activated: " & Result.Level)
End Sub

Private Sub LM_ActivationFailed(Message As String)
    Log("Failed: " & Message)
End Sub

Private Sub LM_TrialActivated(Result As LicenseResult)
    Log("Trial expires: " & Result.ExpirationDate)
End Sub

Private Sub LM_ActivationCancelled
    Log("Cancelled")
End Sub

Comportamiento confirmado del código actual:

  • ActivationSuccess: se dispara después de validar y guardar correctamente.
  • ActivationFailed: se dispara si el código introducido no es válido.
  • TrialActivated: se dispara cuando se activa correctamente el Trial.
  • ActivationCancelled: está declarado, pero los handlers actuales de Cancel y cierre simplemente cierran el formulario y no realizan CallSub. No conviene depender de este callback hasta que esa implementación se ajuste.

SetCallback

Puedes cambiar posteriormente el receptor:

LM.SetCallback(Me, "License")

Estado público de la licencia

Después de cargar o validar puedes consultar:

Log(LM.LicenseIsValid)
Log(LM.LicenseLevel)
Log(LM.LicenseExpirationTicks)
Log(LM.LicenseExpirationDate)
Log(LM.LicenseMessage)

Campos disponibles:

  • LicenseIsValid As Boolean;
  • LicenseLevel As String;
  • LicenseExpirationTicks As Long;
  • LicenseExpirationDate As String;
  • LicenseMessage As String.

Aviso antes de expirar

LM.WarningDaysBeforeExpiration = 5

CheckLicenseAndBlock muestra una advertencia si una licencia válida vence dentro del número de días configurado, pero permite continuar.

Temas

Theme usa DarkPro por defecto.

LM.Theme = LM.THEME_OCEAN
LM.ApplyTheme(LM.Theme)

Constantes disponibles:

Constante Valor
THEME_DARKPRO DarkPro
THEME_NORDICFROST NordicFrost
THEME_FORESTGREEN ForestGreen
THEME_MIDNIGHTBLUE MidnightBlue
THEME_MATERIALINDIGO MaterialIndigo
THEME_VAMPIRERED VampireRed
THEME_CYBERPUNK Cyberpunk
THEME_SLATEGRAY SlateGray
THEME_DEEPPURPLE DeepPurple
THEME_COFFEEBEANS CoffeeBeans
THEME_OCEAN Ocean
THEME_SUNSET Sunset
THEME_ICE Ice
THEME_DARKELEGANT DarkElegant
THEME_LIGHTPRO LightPro
THEME_ROSEGOLD RoseGold
THEME_SAGEGREEN SageGreen
THEME_TEALMINIMALIST TealMinimalist
THEME_WARMCOPPER WarmCopper
THEME_CYBERORANGE CyberOrange
THEME_LAVENDER Lavender
THEME_SOFTBLUE SoftBlue

Prácticamente todos los textos importantes son públicos:

  • DialogTitle;
  • DialogStatusExpired;
  • DialogStatusInvalid;
  • DialogStatusActive;
  • DialogHWIDLabel;
  • DialogLicenseLabel;
  • DialogCopyButton;
  • DialogActivateButton;
  • DialogUpdateButton;
  • DialogCancelButton;
  • DialogTrialButton;
  • DialogSuccessTitle;
  • DialogSuccessMsg;
  • DialogErrorTitle;
  • DialogErrorMsg;
  • DialogWarningTitle;
  • DialogWarningMsg;
  • DialogTrialSuccessMsg;
  • DialogStatusTrial;
  • DialogStatusAboutToExpire;
  • DialogBlockMessage;
  • DialogBlockTitle;
  • DialogExpirationWarningTitle.

Ejemplo:

LM.DialogTitle = "Activación del producto"
LM.DialogHWIDLabel = "Código de hardware"
LM.DialogActivateButton = "Activar"
LM.DialogTrialButton = "Probar gratis"
LM.DialogCancelButton = "Cancelar"

Los placeholders también son configurables:

  • PlaceholderExpiration = "{EXP}";
  • PlaceholderLevel = "{LEVEL}";
  • PlaceholderDays = "{DAYS}".

Formato de fecha

LM.ExpirationDateFormat = "dd/MM/yyyy"
Log(LM.FormatDate(DateTime.Now))

Si ticks <= 0, FormatDate devuelve Never.

AlwaysOnTop

LM.AlwaysOnTop = True

Se aplica a los formularios y alertas creados por el módulo.

CheckLicenseAndBlock en detalle

CheckLicenseAndBlock(Parent) es la API de alto nivel más cómoda:

  1. Aplica el tema.
  2. Ejecuta LoadLocalLicense.
  3. Si es válida, comprueba proximidad de expiración.
  4. Si no es válida y existía archivo, informa del error.
  5. Abre ShowActivationDialog.
  6. Si se activa correctamente devuelve True.
  7. Si no, muestra Access Denied y devuelve False.

Licensr Pro incluido con código fuente

La distribución de la librería incluye Licensr Pro y su código fuente.

Esto es relevante por tres motivos:

  1. Usa el mismo JLicenseManager. El generador no representa un formato de licencia distinto al que usa la aplicación cliente.
  2. Está creado con jdashboardUI. Sirve como ejemplo real de una aplicación de escritorio completa hecha con los controles de la librería.
  3. Es modificable. El desarrollador puede adaptar idiomas, flujo, niveles de licencia, interfaz y administración de programas.

Licensr Pro incluye cinco áreas principales visibles en las capturas y en el código fuente incluido:

Generator

Permite seleccionar programa, introducir HWID, seleccionar tipo/nivel, elegir licencia perpetua o con expiración, generar el código y copiarlo.

Programs

Administra programas registrados y su Base Secret Key.

Languages

Incluye una interfaz de selección multilenguaje.

Settings

Muestra información del sistema, ubicación de base de datos, estadísticas y acciones de mantenimiento.

About

Identifica la aplicación Licensr Pro y presenta la información del generador.

Flujo completo recomendado

En la aplicación cliente

LM.Initialize("MY_BASE_SECRET", "MyApplication", Me, "LM")
LM.Theme = LM.THEME_DARKPRO

Wait For (LM.CheckLicenseAndBlock(MainForm)) Complete (Allowed As Boolean)
If Allowed = False Then ExitApplication

Para emitir la licencia

  1. Registrar el programa en Licensr Pro.
  2. Configurar la misma Base Secret Key correspondiente a ese producto.
  3. Obtener el HWID mostrado por el cliente.
  4. Seleccionar nivel y expiración.
  5. Generar el código.
  6. Entregar el código al usuario.
  7. El usuario lo introduce en el diálogo de JLicenseManager.
  8. El módulo valida y guarda la licencia local.

API pública completa

Método Retorno Función
Initialize(SecretBase, AppName, Callback, EventName) - Inicializa módulo
SetCallback(Callback, EventName) - Cambia receptor de eventos
GetHWID String Obtiene HWID
StartTrialMode(Days) - Inicia Trial si no existe licencia
SaveLocalLicense(LicenseCode) - Guarda licencia y control horario
LoadLocalLicense LicenseResult Carga y valida
GenerateLicenseCode(HWID, ExpirationTicks, MyLicenseLevel) String Genera código
ValidateLicense(LicenseCode) LicenseResult Valida código
ApplyTheme(ThemeName) - Aplica tema
ShowActivationDialog(Parent) LicenseResult Muestra activación modal
FormatDate(ticks) String Formatea expiración
CheckLicenseAndBlock(Parent) ResumableSub Flujo completo de protección

Límites y consideraciones

  • El HWID actual está diseñado para Windows.
  • Un cambio de placa base puede cambiar el identificador y afectar una licencia ligada al hardware.
  • La seguridad offline depende de proteger adecuadamente la Base Secret Key.
  • Una licencia offline no puede ofrecer por sí sola revocación instantánea desde servidor.
  • La protección de reloj es local y usa una tolerancia de una hora.
  • Si necesitas emisión remota, usa Licensr Pro y su fuente incluida como referencia del lado administrativo.