# Receita: chaves de licença

> Venda um app desktop, um CLI, um plugin ou um template com chaves de licença. O app verifica a chave sem nenhum segredo dentro.

O Perly Pay emite uma chave quando o pagamento é entregue, conta as ativações por dispositivo e responde “esta chave vale para este produto aqui?” com endpoints públicos. O programa que você distribui usa `LicenseClient`, que não precisa de chave secreta.

> **Nota:** Com um assistente: a skill `sell-license-keys` do plugin do Perly Pay faz esta receita no seu projeto. O exemplo executável é `examples/license-keys` (MIT) no repositório do plugin.

## Como funciona

1. **Um produto que emite chaves** — `issues_license: true` e `license_activation_limit` (dispositivos por chave), com um preço único, vitalício, por prazo ou uma assinatura.
2. **Venda** — Um [link de pagamento](https://pay.perly.io/docs/payment-links.md) no seu site ou uma fatura por comprador.
3. **Entregue a chave** — Com o webhook `license.created` (o objeto dele é a chave) ou com `licenseKeys.list({ customer })` depois de `invoice.fulfilled`. O recibo não traz a chave.
4. **Ative no app** — `activate({ key, product, instance_name })` com um nome que não muda naquele dispositivo; guarde o id da ativação.
5. **Verifique ao iniciar** — `validate({ key, product, instance })`. Um `valid: false` claro bloqueia; sem rede, a última resposta boa vale por alguns dias.

**Node**

```js
import { LicenseClient } from "perly-pay";

const licenses = new LicenseClient(); // no secret key, ever
const result = await licenses.activate({ key, product: "prod_…", instance_name: deviceName });
if (!result.valid) showWhy(result.reason); // limit_reached, revoked, expired, …
```

**PHP**

```php
use Perly\Pay\LicenseClient;

$result = (new LicenseClient())->activate(['key' => $key, 'product' => 'prod_…', 'instance_name' => home_url()]);
if (!$result['valid']) echo $result['reason'];
```

## Execute o exemplo

1. **Instale** — `npm install` em `examples/license-keys` (Node 20.12+).
2. **Chave** — Copie `.env.example` para `.env` e coloque uma chave de teste (`sk_test_…`) em `PERLY_PAY_SECRET_KEY`.
3. **Prepare** — `npm run setup` cria o produto e o preço com a sua chave e imprime os ids deles para o `.env`.
4. **Execute** — `npm start` (ou `npm run dev`), como diz o README dele.
5. **Pague sem carteira** — `npm run buy-test -- you@example.com` compra uma cópia no modo de teste e imprime a chave; depois `npm run app -- activate <key>` e `npm run app -- pro hello`.

## Erros comuns

- Uma chave `sk_…` dentro do app. Qualquer um pode extraí-la; o programa que você distribui usa só `LicenseClient`.
- Sem `product`, a chamada é recusada (`parameter_missing`). Passe-o sempre; a chave de qualquer outra coisa responde `wrong_product`.
- Um `instance_name` que muda a cada inicialização: cada inicialização gasta uma ativação.
