Guías
Receta: claves de licencia
Vende una app de escritorio, un CLI, un plugin o una plantilla con claves de licencia. La app verifica la clave sin ningún secreto dentro.
Perly Pay emite una clave cuando el pago se entrega, cuenta las activaciones por dispositivo y responde «¿es válida esta clave para este producto aquí?» con endpoints públicos. El programa que distribuyes usa LicenseClient, que no necesita clave secreta.
sell-license-keys del plugin de Perly Pay hace esta receta en tu proyecto. El ejemplo ejecutable es examples/license-keys (MIT) en el repositorio del plugin.Cómo funciona
- 1
Un producto que emite claves
issues_license: trueylicense_activation_limit(dispositivos por clave), con un precio único, vitalicio, por plazo o una suscripción. - 2
Véndelo
Un enlace de pago en tu sitio o una factura por comprador.
- 3
Entrega la clave
Con el webhook
license.created(su objeto es la clave) o conlicenseKeys.list({ customer })trasinvoice.fulfilled. El recibo no lleva la clave. - 4
Activa en la app
activate({ key, product, instance_name })con un nombre que no cambie en ese dispositivo; guarda el id de la activación. - 5
Verifica al arrancar
validate({ key, product, instance }). Unvalid: falseclaro bloquea; sin red, la última respuesta buena vale unos días.
Ejecuta el ejemplo
- 1
Instala
npm installenexamples/license-keys(Node 20.12+). - 2
Clave
Copia
.env.examplea.envy pon una clave de prueba (sk_test_…) enPERLY_PAY_SECRET_KEY. - 3
Prepara
npm run setupcrea el producto y el precio con tu clave e imprime sus ids para.env. - 4
Ejecuta
npm start(onpm run dev), según diga su README. - 5
Paga sin billetera
npm run buy-test -- you@example.comcompra una copia en modo de prueba e imprime la clave; luegonpm run app -- activate <key>ynpm run app -- pro hello.
Errores comunes
- Una clave
sk_…dentro de la app. Cualquiera puede extraerla; el programa que distribuyes usa soloLicenseClient. - Sin
product, la llamada se rechaza (parameter_missing). Pásalo siempre; la clave de cualquier otra cosa respondewrong_product. - Un
instance_nameque cambia en cada arranque: cada arranque gasta una activación.