# Przepis: klucze licencyjne

> Sprzedawaj aplikację desktopową, CLI, wtyczkę lub szablon z kluczami licencyjnymi. Aplikacja sprawdza klucz bez żadnego sekretu w środku.

Perly Pay wydaje klucz, gdy płatność zostanie zrealizowana, liczy aktywacje na urządzeniach i odpowiada na pytanie „czy ten klucz jest ważny dla tego produktu tutaj?” przez publiczne endpointy. Program, który dystrybuujesz, używa `LicenseClient` — nie potrzebuje klucza tajnego.

> **Uwaga:** Z asystentem: ten przepis realizuje w Twoim projekcie skill `sell-license-keys` wtyczki Perly Pay. Działający przykład to `examples/license-keys` (MIT) w repozytorium wtyczki.

## Jak to działa

1. **Produkt wydający klucze** — `issues_license: true` i `license_activation_limit` (urządzeń na klucz), z ceną jednorazową, dożywotnią, okresową albo subskrypcją.
2. **Sprzedaż** — [Link do płatności](https://pay.perly.io/docs/payment-links.md) na stronie albo faktura dla każdego kupującego.
3. **Wyślij klucz** — Po webhooku `license.created` (jego obiekt to klucz) albo przez `licenseKeys.list({ customer })` po `invoice.fulfilled`. Paragon nie zawiera klucza.
4. **Aktywacja w aplikacji** — `activate({ key, product, instance_name })` z nazwą, która nie zmienia się na tym urządzeniu; zapisz identyfikator aktywacji.
5. **Sprawdzenie przy starcie** — `validate({ key, product, instance })`. Wyraźne `valid: false` blokuje; bez sieci przez kilka dni obowiązuje ostatnia dobra odpowiedź.

**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'];
```

## Uruchom przykład

1. **Zainstaluj** — `npm install` w `examples/license-keys` (Node 20.12+).
2. **Klucz** — Skopiuj `.env.example` do `.env` i wpisz klucz testowy (`sk_test_…`) w `PERLY_PAY_SECRET_KEY`.
3. **Przygotuj** — `npm run setup` tworzy produkt i cenę Twoim kluczem i drukuje ich identyfikatory do `.env`.
4. **Uruchom** — `npm start` (lub `npm run dev`), jak mówi jego README.
5. **Zapłać bez portfela** — `npm run buy-test -- you@example.com` kupuje kopię w trybie testowym i drukuje klucz; potem `npm run app -- activate <key>` i `npm run app -- pro hello`.

## Pułapki

- Klucz `sk_…` w aplikacji. Wyciągnie go każdy; program, który dystrybuujesz, używa tylko `LicenseClient`.
- Bez `product` wywołanie jest odrzucane (`parameter_missing`). Podawaj go zawsze; klucz do czegokolwiek innego daje `wrong_product`.
- `instance_name`, który zmienia się przy każdym uruchomieniu: każde uruchomienie zjada aktywację.
