# Guida all'integrazione manuale (9 linguaggi, senza necessità di IA)

Questa guida si applica al fornitore Licentivo. I commercianti che dispongono di altri sistemi di autorizzazione possono selezionare un servizio personalizzato in «Selezione e personalizzazione dell'autorizzazione» nel backend, seguire le [API di autorizzazione personalizzata e la procedura di integrazione](/it/launch-documents/external-licensing/) e continuare a usare l'SDK del proprio sistema di autorizzazione.

> Le modifiche attualmente non pubblicate adottano lo scambio dell'identità dell'account. Le responsabilità specifiche e i vincoli di migrazione sono descritti in [Durata degli acquisti e limiti degli SDK account](/it/launch-documents/account-purchase-boundary/). Launch calcola la durata dell'acquisto; gli SDK Licentivo applicano l'autorizzazione.

Installare soltanto il pacchetto di integrazione Launch per il linguaggio corrispondente. Il pacchetto Launch include l'SDK ufficiale, l'adattatore predefinito e la configurazione della connessione; l'indirizzo ufficiale di autorizzazione è fisso: `https://www.licentivo.com`. Il programma accede usando l'account registrato dall'acquirente nel negozio Launch corrente.

## Ottenere il codice di inizializzazione precompilato

1. Completare nel backend Launch l'associazione tra software, piani di vendita e politiche di autorizzazione Licentivo, quindi pubblicarla nell'ambiente corrispondente.
2. Aprire **Integrazione del programma → Verifica dell'integrazione e codice**, quindi selezionare software, linguaggio e ambiente di test/produzione.
3. Fare clic su «Leggi le informazioni del prodotto e genera il codice di integrazione». Launch legge automaticamente l'indirizzo pubblico corrente del sito, le mappature dei prodotti esistenti e la chiave pubblica di firma.
4. Copiare la funzione di connessione mostrata nella pagina nel proprio progetto e scrivere manualmente l'interfaccia e le chiamate applicative come descritto di seguito. È anche possibile esaminare i parametri compilati automaticamente e chiamare direttamente `Connect/connect` nel linguaggio corrispondente.

Non occorre inserire manualmente i due ID interni dei prodotti né generare `launch-config.json` o `product.json`. La pagina consente di salvare la funzione di connessione come codice sorgente. Il file privato del server `config.yaml` serve solo all'avvio del servizio Launch e non può essere distribuito con il software destinato ai clienti.

L'indirizzo del sito proviene dall'indirizzo pubblico valido dell'istanza corrente (`public_url` nella configurazione di avvio oppure l'indirizzo pubblico valido nelle impostazioni del sito nel backend). Può essere un nome di dominio o un indirizzo IP con porta, ma deve includere il protocollo; l'integrazione in produzione usa HTTPS valido. L'indirizzo di ascolto `http_addr` non è l'indirizzo di accesso dei clienti. Dopo aver cambiato l'indirizzo del sito, le mappature dei prodotti o l'ambiente, ottenere nuovamente la funzione di connessione dal sito corrente; le sessioni e le cache del vecchio sito non devono essere usate come autorizzazione per il nuovo sito.

I due identificativi dei prodotti rappresentano una corrispondenza interna già esistente: il prodotto software Launch e il prodotto di autorizzazione Licentivo. La pagina di integrazione li compila automaticamente in base al software selezionato; l'acquirente inserisce soltanto il proprio account del negozio. Il server legge la chiave pubblica di firma tramite la connessione Licentivo configurata; la chiave amministrativa e le credenziali di autorizzazione dei clienti non vengono incluse nel codice sorgente.

## Funzione di `Connect/connect`

`Connect/connect` è il nome usato nei diversi linguaggi per l'operazione «crea un client applicativo Launch». Go, C# e alcune interfacce native usano `Connect` con iniziale maiuscola; Python, JavaScript, Ruby e altri linguaggi usano `connect` secondo le proprie convenzioni. `connectLaunch()`, `connect_launch()` o `LaunchConnection.Open()`, generati dal backend, sono funzioni del progetto con i parametri pubblici precompilati che chiamano internamente il punto di ingresso del linguaggio corrispondente.

La connessione completa soltanto l'inizializzazione: verifica l'indirizzo del negozio, le mappature dei prodotti, l'ambiente e la chiave pubblica di firma, crea il client Launch e configura l'SDK ufficiale Licentivo incluso nel pacchetto. Non verifica l'identità del cliente e non abilita direttamente le funzionalità a pagamento. La sequenza completa è:

```text
Connect/connect → Login or Restore → RunFeature → Logout / Close
                                       └──────────→ ReleaseDevice (explicit device unlink only)
```

Durante l'esecuzione dell'applicazione, mantenere lo stesso oggetto client per consentire all'SDK di gestire correttamente gli heartbeat e i posti delle licenze flottanti. La chiusura ordinaria conserva l'associazione del dispositivo; la disconnessione esplicita del cliente e il punto di ingresso compatibile ReleaseDevice chiamano la stessa procedura di disconnessione dell'SDK ufficiale.

## Installazione e punto di ingresso per l'inizializzazione

Tutte le verifiche dell'installazione pubblica nei nove linguaggi della versione 0.1.6 sono state superate (9/9); tutti i metodi di installazione della tabella seguente sono stati verificati. La [release su GitHub](https://github.com/spf86/licentivo-launch-sdk/releases/tag/v0.1.6) fornisce anche pacchetti nativi e file offline; per l'uso, consultare le [istruzioni di installazione dei pacchetti scaricati](/it/launch-documents/integration-packages/#install-a-downloaded-distribution).

| Lingua | Installare solo Launch | Funzione di connessione fornita dalla pagina | API di inizializzazione diretta inclusa nel pacchetto |
| --- | --- | --- | --- |
| Go | `go get github.com/spf86/licentivo-launch-sdk/pkg/launchclient@v0.1.6` | `connectLaunch()` | `launchclient.Connect` |
| Python 3.10+ | `python -m pip install licentivo-launch==0.1.6` | `connect_launch()` | `Application.connect` |
| C# / .NET 8+ | `dotnet add package Licentivo.Launch --version 0.1.6` | `LaunchConnection.Open()` | `Application.Connect` |
| Java 17+ | Maven/Gradle: `com.licentivo.launch:launch-client:0.1.6` | `LaunchConnection.open()` | `Launch.connect` |
| Node.js 20.3+ | `npm install @licentivo/launch@0.1.6` | `connectLaunch()` | `Application.connect` |
| Rust 1.85+ | `cargo add licentivo-launch@=0.1.6` | `connect_launch()` | `Application::connect` |
| Ruby 3.1+ | `gem install licentivo-launch --version 0.1.6` | `connect_launch` | `Application.connect` |
| C11 | Scaricare il pacchetto nativo dalla [release su GitHub](https://github.com/spf86/licentivo-launch-sdk/releases/tag/v0.1.6) e importarlo con CMake | `connect_launch()` | `launch_application_connect` |
| C++17 | Usare lo stesso pacchetto nativo Launch | `connectLaunch()` | `Application::Connect` |

Il codice sorgente pubblico e i README dei singoli linguaggi sono disponibili nel [repository degli SDK Launch](https://github.com/spf86/licentivo-launch-sdk), i pacchetti nativi e i file offline nella [release v0.1.6](https://github.com/spf86/licentivo-launch-sdk/releases/tag/v0.1.6) e i risultati delle installazioni pubbliche nella [verifica dei registri per i nove linguaggi](https://github.com/spf86/licentivo-launch-sdk/blob/main/docs/registry-verification.json). Il README di ogni pacchetto fornisce i comandi di installazione e le API. Il pacchetto JavaScript include le dichiarazioni TypeScript. Le dipendenze ordinarie dei linguaggi vengono risolte dal gestore di pacchetti, ad esempio cryptography per Python, BouncyCastle per C# e base64 per Ruby; non occorre installare il pacchetto dell'SDK ufficiale.

Il modulo pubblico Go si chiama `github.com/spf86/licentivo-launch-sdk` e il percorso di importazione è `github.com/spf86/licentivo-launch-sdk/pkg/launchclient`; l'applicazione non richiede un replace locale. Il pacchetto nativo Windows usa amd64 GNU/MinGW; è disponibile anche un pacchetto nativo Linux amd64. I pacchetti Ruby specifici per piattaforma e la distribuzione Windows Rust/native includono curl; la compilazione dal sorgente su altre piattaforme richiede le normali dipendenze di sviluppo C11 e curl/OpenSSL. Le istruzioni sulle toolchain delle piattaforme si trovano nel README di ciascun pacchetto.

## Accesso e operazioni protette

I frammenti seguenti usano la funzione di connessione copiata nel passaggio precedente. `email` e `password` provengono dalla propria interfaccia di accesso; le password non devono essere scritte nel codice sorgente o nella configurazione. `export` deve essere sostituito con il nome di una funzionalità effettivamente presente nella politica del piano.

### Go

```go
app, err := connectLaunch()
if err != nil { return err }
defer app.Close()
if _, err := app.Login(ctx, email, password); err != nil { return err }
return app.RunFeature("export", func() error {
    return exportReport()
})
```

`ctx` usa il contesto del ciclo di vita dell'applicazione: gli heartbeat non devono essere annullati subito al termine della richiesta di accesso. Eseguire le operazioni di rete in un thread di lavoro in background. Per il ripristino chiamare `Restore(ctx)`; per disconnettere l'account chiamare `Logout(ctx)`; per rilasciare il dispositivo chiamare `ReleaseDevice(ctx)`.

### Python

```python
with connect_launch() as app:
    app.login(email, password)
    result = app.run_feature("export", export_report)
```

`restore()` ripristina una sessione sicura esistente; se non esiste una sessione, mostrare l'interfaccia di accesso. `logout()` elimina i dati dell'account; `release_device()` rilascia esplicitamente il dispositivo. Le operazioni di rete sincrone non devono bloccare il ciclo degli eventi dell'applicazione desktop.

### C# / .NET

```csharp
await using var app = LaunchConnection.Open();
await app.Login(email, password);
await app.RunFeature("export", async () => {
    await ExportReport();
});
```

Usare `await Restore()`, `await Logout()` e `await ReleaseDevice()`. Mantenere attivo il ciclo di vita dell'SDK per tutta la durata dell'applicazione e usare flussi di interfaccia asincroni.

### Java

```java
try (var app = LaunchConnection.open()) {
    app.login(email, passwordChars);
    app.runFeature("export", () -> exportReport());
}
```

La password usa `char[]`. Se non esiste una sessione, `restore()` restituisce un errore `NO_SESSION` e occorre mostrare l'interfaccia di accesso; gli altri errori non devono essere considerati un'autorizzazione. `logout()` e `releaseDevice()` sono operazioni distinte. La chiusura è gestita da try-with-resources.

### JavaScript / Node.js / TypeScript

```javascript
const app = connectLaunch();
try {
  await app.login(email, password);
  const result = await app.runFeature('export', () => exportReport());
} finally {
  await app.close();
}
```

`restore()` restituisce `null` quando non esiste una sessione; le operazioni applicative sono consentite solo dopo un ripristino riuscito. Il valore booleano restituito da `logout()` indica se la disconnessione remota è stata confermata; se il rilascio del dispositivo fallisce, occorre mostrare un errore. Il codice viene eseguito in Node.js, nel processo principale di Electron o in un backend attendibile; il browser e il processo di rendering di Electron non conservano credenziali di autorizzazione.

### Rust

```rust
let mut app = connect_launch()?;
app.login(&email, &password)?;
let result = app.run_feature("export", || {
    export_report()?;
    Ok(())
})?;
app.close();
```

Il callback restituisce `Result<T, Failure>`. `restore()`, `logout()` e `release_device()` restituiscono risultati: gli errori devono essere gestiti. Anche `Drop` si occupa della chiusura del runtime. Per impostazione predefinita, il nucleo nativo viene compilato e collegato da build.rs; non occorre collegare manualmente l'SDK ufficiale.

### Ruby

```ruby
app = connect_launch
begin
  app.login(email, password)
  result = app.run_feature('export') { export_report }
ensure
  app.close
end
```

`restore` ripristina la sessione, `logout` disconnette l'account e `release_device` rilascia il dispositivo. Usare un blocco di codice per le operazioni protette; le eccezioni non devono essere convertite in esiti positivi.

### C

```c
static int export_action(void *context) {
    return export_report(context); /* Return 1 only on success. */
}

launch_application *app = connect_launch();
if (!app) return 0;
int ok = launch_application_login(app, email, password);
if (ok) ok = launch_application_run_feature(app, "export", export_action, context);
/* Check launch_application_error(app) on failure; never log credentials. */
launch_application_close(app);
return ok;
```

`launch_application_restore` prevede tre stati: `1` ripristino riuscito, `0` nessuna sessione, `-1` errore. Solo l'assenza di una sessione deve portare alla normale visualizzazione dell'accesso; un rifiuto o un'eccezione non devono essere considerati un successo. È inoltre necessario verificare i valori restituiti da `logout` e `release_device`.

CMake importa soltanto Launch:

```cmake
find_package(LicentivoLaunch CONFIG REQUIRED)
add_executable(myapp main.c)
licentivo_launch_link(myapp)
```

### C++

```cpp
auto app = connectLaunch();
app.Login(email.c_str(), password.c_str());
app.RunFeature("export", [&] { exportReport(); });
```

`Restore()`, `Logout()` e `ReleaseDevice()` seguono la semantica delle eccezioni C++. Il distruttore RAII gestisce la chiusura. CMake usa `licentivo_launch_link(myapp CXX)`; Launch gestisce automaticamente il collegamento dell'SDK e le librerie runtime incluse nel pacchetto di distribuzione.

## Ciclo di vita, archiviazione sicura ed errori

La creazione di un oggetto di connessione completa soltanto l'inizializzazione. Il programma deve aver effettuato l'accesso o ripristinato la sessione con successo e deve usare un callback di protezione della funzionalità per ogni operazione applicativa. Un ordine pagato, una sessione esistente o un pulsante cliccabile non sostituiscono la verifica dell'SDK.

Per impostazione predefinita, le sessioni vengono conservate soltanto in memoria. Per ricordare l'accesso occorre un'archiviazione sicura: Go, Python, C# e C/C++ nativi forniscono DPAPI per l'utente Windows corrente; Java, Node, Rust e Ruby forniscono un archivio AES-GCM che usa una chiave del chiamante. Le applicazioni multipiattaforma devono integrarsi con l'archivio delle credenziali del sistema. La chiave e il testo cifrato non devono essere collocati nella stessa normale directory.

La chiusura ordinaria conserva le sessioni che l'utente ha scelto esplicitamente di ricordare e arresta il runtime. La disconnessione dell'account chiama prima la procedura unificata di disconnessione dell'SDK ufficiale, quindi elimina i record dell'account propri di Launch. ReleaseDevice è un punto di ingresso compatibile della stessa procedura; se la revoca remota è ancora in sospeso, non si deve indicare che il rilascio è riuscito. Non eliminare la directory della cache dell'SDK ufficiale né i log di ripristino della disconnessione. La protezione delle sessioni di Launch non implica che tutti i file dei dispositivi dell'SDK ufficiale siano cifrati: occorre limitare i permessi della directory della cache.

| Stato | Gestione da parte del programma |
| --- | --- |
| Errore di account o password | Mostrare un errore di accesso generico, senza rivelare se l'account esiste |
| EMAIL_VERIFICATION_REQUIRED | Guidare l'utente nella verifica dell'indirizzo email del negozio |
| ENTITLEMENT_PENDING | Mostrare la sincronizzazione in corso e attendere secondo i tentativi limitati del pacchetto e Retry-After |
| ENTITLEMENT_NOT_PURCHASED | Guidare l'utente all'acquisto o al cambio di account |
| ENTITLEMENT_EXPIRED | Guidare l'utente al rinnovo; non usare vecchie credenziali per aggirare il rifiuto |
| ENTITLEMENT_SUSPENDED | Arrestare le funzionalità protette e contattare il commerciante |
| Limite di dispositivi raggiunto | Guidare l'utente alla gestione o al rilascio esplicito dei dispositivi |
| Rete/HTTP 5xx | È possibile usare soltanto autorizzazioni offline verificate dall'SDK e ancora valide |

Risposte esplicite 401/403/404, account non corrispondenti, annullamenti o limiti di frequenza non devono essere trasformati in autorizzazioni offline riuscite. La prima attivazione e le politiche che vietano l'uso offline richiedono comunque una connessione di rete. Se il dominio/IP del server non è raggiungibile, mostrare un problema di connessione; non connettersi ad altri siti senza avviso.

## Collaudo e riferimenti

Verificare l'accesso reale, l'autorizzazione appartenente all'account, le operazioni protette, il ripristino dopo il riavvio, l'autorizzazione offline valida e la sua scadenza, la manomissione della cache, la disconnessione, il cambio di account e il rilascio del dispositivo. Questo documento non richiede l'uso dell'IA. Per gli strumenti di test e i limiti del collaudo esterno, consultare [acceptance.md](/it/launch-documents/acceptance/); per i pacchetti locali e le istruzioni di compilazione, consultare [integration-packages.md](/it/launch-documents/integration-packages/).

La verifica della configurazione, la generazione del codice e i test locali non dimostrano automaticamente che un pagamento reale, il rilascio di un'autorizzazione o l'attivazione sul sito ufficiale siano riusciti. I negozi esterni e le sandbox di pagamento devono essere configurati e collaudati separatamente.
