> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dodopayments.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Prezzi basati sui posti con add-on e link di pagamento

> Scopri come creare add-on per prezzi basati sui posti e generare link di pagamento con quantità di add-on personalizzate utilizzando Dodo Payments

In questo tutorial, imparerai come implementare prezzi basati sui posti utilizzando gli add-on di Dodo Payments. Creeremo un prodotto in abbonamento con add-on per posti aggiuntivi e ti mostreremo come generare link di pagamento con quantità di add-on personalizzate.

<Note>
  Questo tutorial fornisce codice di implementazione di esempio per un'applicazione Node.js/Express. Puoi modificare questo codice per il tuo framework specifico (Next.js, React, Vue, ecc.) e personalizzare l'interfaccia utente in base alle esigenze della tua applicazione.
</Note>

Alla fine di questo tutorial, saprai come:

* Creare prodotti in abbonamento con prezzi basati sui posti
* Configurare add-on per posti aggiuntivi
* Generare link di pagamento con quantità di add-on personalizzate
* Gestire sessioni di checkout con conteggi di posti dinamici

## Cosa stiamo costruendo

Creiamo un modello di prezzo basato sui posti:

* **Piano Base**: \$49/mese per un massimo di 5 membri del team
* **Add-on per Posto**: \$2/mese per ogni posto aggiuntivo
* **Link di Pagamento**: Checkout dinamico con quantità di posti personalizzate

<Info>
  Prima di iniziare, assicurati di avere:

  * Un account Dodo Payments
  * Una conoscenza di base di TypeScript/Node.js
</Info>

## Passo 1: Crea il tuo Add-On per Posti

Ora dobbiamo creare un add-on che rappresenti posti aggiuntivi. Questo add-on sarà collegato al nostro abbonamento base e permetterà ai clienti di acquistare posti aggiuntivi.

<Frame>
  <img src="https://mintcdn.com/dodopayments/ajOhO6Du1yNsg0hy/images/cookbooks/seat-based/seat-based-addons-creation.png?fit=max&auto=format&n=ajOhO6Du1yNsg0hy&q=85&s=d2c17b4a9f2f9a1b19f537f0507656a4" alt="Creazione del prodotto di abbonamento base" style={{ maxHeight: '500px', width: 'auto' }} width="2348" height="1606" data-path="images/cookbooks/seat-based/seat-based-addons-creation.png" />
</Frame>

<Tip>
  **Cosa stiamo creando**: un componente aggiuntivo che costa \$2/mese per postazione e può essere aggiunto a qualsiasi abbonamento base.
</Tip>

<Steps>
  <Step title="Navigate to Add-Ons">
    1. Nella dashboard di Dodo Payments, resta nella sezione **Products**
    2. Clicca sulla scheda **Add-Ons**
    3. Clicca su **Create Add-On**

    Questo aprirà il modulo di creazione del componente aggiuntivo.
  </Step>

  <Step title="Enter add-on details">
    Compila questi valori per il nostro componente aggiuntivo per postazioni:

    **Add-On Name**: `Additional Team Seat`

    **Description**: `Add extra team members to your workspace with full access to all features`

    **Price**: Inserisci → `2.00`

    **Valuta**: Deve corrispondere alla valuta del tuo abbonamento base

    **Categoria Fiscale**: Seleziona la categoria appropriata per il tuo prodotto.
  </Step>

  <Step title="Save your add-on">
    1. Controlla tutte le impostazioni:
       * Nome: Additional Team Seat
       * Prezzo: \$2.00/mese
    2. Clicca su **Create Add-On**

    <Check>
      **Componenti aggiuntivo creato!** Il tuo componente per le postazioni è ora disponibile per essere collegato agli abbonamenti.
    </Check>
  </Step>
</Steps>

## Passo 2: Crea il tuo Prodotto in Abbonamento Base

Iniziamo creando un prodotto in abbonamento base che include 5 membri del team. Questa sarà la base del nostro modello di prezzo basato sui posti.

<Frame>
  <img src="https://mintcdn.com/dodopayments/ajOhO6Du1yNsg0hy/images/cookbooks/seat-based/seat-based-subscription.png?fit=max&auto=format&n=ajOhO6Du1yNsg0hy&q=85&s=f17e96f3d106b88b6dc32a00be535620" alt="Creazione del prodotto di abbonamento base" style={{ maxHeight: '500px', width: 'auto' }} width="2118" height="1580" data-path="images/cookbooks/seat-based/seat-based-subscription.png" />
</Frame>

<Steps>
  <Step title="Navigate to Products">
    1. Accedi alla dashboard di Dodo Payments
    2. Clicca su **Products** nella barra laterale sinistra
    3. Clicca sul pulsante **Create Product**
    4. Seleziona **Subscription** come tipo di prodotto

    Dovresti vedere un modulo in cui configureremo il nostro abbonamento base.
  </Step>

  <Step title="Fill in the subscription details">
    Ora inseriremo i dettagli specifici per il nostro piano base:

    **Product Name**: `Motion`

    **Description**: `Where your team's documentation lives.`

    **Recurring Price**: Inserisci → `49.00`

    **Billing Cycle**: Seleziona → `Monthly`

    **Currency**: Seleziona la valuta preferita (es. `USD`)
  </Step>
</Steps>

## Passo 3: Collega l'Add-On all'Abbonamento

Ora dobbiamo associare il nostro add-on per posti con l'abbonamento base in modo che i clienti possano acquistare posti aggiuntivi durante il checkout.

<Steps>
  <Step title="Attach the seat add-on">
    <Frame>
      <img src="https://mintcdn.com/dodopayments/ajOhO6Du1yNsg0hy/images/cookbooks/seat-based/seat-based-addons.png?fit=max&auto=format&n=ajOhO6Du1yNsg0hy&q=85&s=ea4ce0d437201c92590eea6c31a14e80" alt="Collegamento del componente aggiuntivo all'abbonamento" style={{ maxHeight: '500px', width: 'auto' }} width="2338" height="1196" data-path="images/cookbooks/seat-based/seat-based-addons.png" />
    </Frame>

    1. Scorri verso il basso fino alla sezione **Add-Ons**
    2. Clicca su **Aggiungi Add-Ons**
    3. Dal menu a discesa, seleziona il tuo add-on per posti
    4. Conferma che appare nella configurazione del tuo abbonamento
  </Step>

  <Step title="Save subscription changes">
    1. Controlla l'intera configurazione dell'abbonamento:
       * Piano base: \$49/mese per 5 postazioni
       * Componente aggiuntivo: \$2/mese per postazione aggiuntiva
       * Prova gratuita: 14 giorni
    2. Clicca su **Save Changes**

    <Check>
      **Prezzi basati sui posti configurati!** I clienti ora possono acquistare il piano base e aggiungere postazioni extra secondo necessità.
    </Check>
  </Step>
</Steps>

## Passo 4: Genera Link di Pagamento con Quantità di Add-On Personalizzate

Ora creiamo un'applicazione Express.js che genera link di pagamento con quantità di add-on personalizzate. Qui entra in gioco il vero potere dei prezzi basati sui posti: puoi creare dinamicamente sessioni di checkout con qualsiasi numero di posti aggiuntivi.

<Steps>
  <Step title="Set up your project">
    Crea un nuovo progetto Node.js e installa le dipendenze richieste:

    ```bash theme={null}
    mkdir seat-based-pricing
    cd seat-based-pricing
    npm init -y
    npm install dodopayments express dotenv
    npm install -D @types/node @types/express typescript ts-node
    ```

    Crea un file `tsconfig.json`:

    ```json theme={null}
    {
      "compilerOptions": {
        "target": "ES2020",
        "module": "commonjs",
        "outDir": "./dist",
        "rootDir": "./src",
        "strict": true,
        "esModuleInterop": true,
        "skipLibCheck": true,
        "forceConsistentCasingInFileNames": true
      }
    }
    ```
  </Step>

  <Step title="Create your environment file">
    Crea un file `.env` con la tua chiave API di Dodo Payments:

    ```bash theme={null}
    DODO_PAYMENTS_API_KEY=your_actual_dodo_api_key_here
    ```

    <Warning>
      Non inserire mai la tua chiave API nel controllo di versione. Aggiungi `.env` al tuo file `.gitignore`.
    </Warning>
  </Step>

  <Step title="Implement the checkout session creation">
    Crea un file `src/server.ts` con il seguente codice:

    <CodeGroup>
      ```typescript server.ts expandable theme={null}
      // Add this new endpoint for dynamic seat quantities
      import 'dotenv/config';
      import DodoPayments from 'dodopayments';
      import express, { Request, Response } from 'express';

      const app = express();

      // Initialize the Dodo Payments client
      const client = new DodoPayments({
        bearerToken: process.env.DODO_PAYMENTS_API_KEY,
        environment: 'test_mode'
      });

      async function createCheckoutSession(seatCount: number) {
        try {
          const session = await client.checkoutSessions.create({
            // Products to sell - use IDs from your Dodo Payments dashboard
            product_cart: [
              {
                product_id: 'pdt_7Rl9OWT2Mz4wwUTKz74iZ', // Replace with your actual product ID
                quantity: 1,
                addons: [
                  {
                    addon_id: 'adn_eKQbNakKrivDpaxmI8wKI', // Replace with your actual addon ID
                    quantity: seatCount
                  }
                ]
              }
            ],
            
            // Pre-fill customer information to reduce friction
            customer: {
              email: 'steve@example.com',
              name: 'Steve Irwin',
            },
            // Where to redirect after successful payment
            return_url: 'https://example.com/checkout/success',
          });

          // Redirect your customer to this URL to complete payment
          console.log('Checkout URL:', session.checkout_url);
          console.log('Session ID:', session.session_id);
          
          return session;
          
        } catch (error) {
          console.error('Failed to create checkout session:', error);
          throw error;
        }
      }

      // Example usage in an Express.js route
      app.post('/create-checkout/:seatCount', async (req: Request, res: Response) => {
        try {
          const seatCount = parseInt(req.params.seatCount);
          const session = await createCheckoutSession(seatCount);
          res.json({ checkout_url: session.checkout_url });
        } catch (error) {
          res.status(500).json({ error: 'Failed to create checkout session' });
        }
      });

      // Add this line after your other middleware
      app.use(express.static('public'));

      // Add this route to serve the demo page
      app.get('/', (req, res) => {
        res.sendFile(__dirname + '/../public/index.html');
      });

      app.listen(3000, () => {
        console.log('Server is running on port 3000');
      });
      ```
    </CodeGroup>
  </Step>

  <Step title="Add a simple web interface">
    Crea un file `public/index.html` per testare facilmente:

    <CodeGroup>
      ```html index.html expandable theme={null}
      <!DOCTYPE html>
      <html>
      <head>
          <title>Seat-Based Pricing Demo</title>
          <style>
              body { font-family: Arial, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; }
              .form-group { margin: 20px 0; }
              label { display: block; margin-bottom: 5px; font-weight: bold; }
              input { width: 100%; padding: 10px; border: 1px solid #ddd; border-radius: 4px; }
              button { background: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; cursor: pointer; }
              button:hover { background: #0056b3; }
              .result { margin-top: 20px; padding: 15px; background: #f8f9fa; border-radius: 4px; }
          </style>
      </head>
      <body>
          <h1>Seat-Based Pricing Demo</h1>
          <p>Generate checkout links with custom seat quantities:</p>
          
          <div class="form-group">
              <label for="seatCount">Number of Additional Seats:</label>
              <input type="number" id="seatCount" value="3" min="0" max="50">
          </div>
          
          <button onclick="createCheckout()">Generate Checkout Link</button>
          
          <div id="result" class="result" style="display: none;">
              <h3>Checkout Link Generated!</h3>
              <p><strong>Seat Count:</strong> <span id="seatCountDisplay"></span></p>
              <p><strong>Total Cost:</strong> $<span id="totalCost"></span>/month</p>
              <p><strong>Checkout URL:</strong></p>
              <a id="checkoutUrl" href="#" target="_blank">Click here to checkout</a>
          </div>

          <script>
              async function createCheckout() {
                  const seatCount = document.getElementById('seatCount').value;
                  
                  try {
                      const response = await fetch(`/create-checkout/${seatCount}`, {
                          method: 'POST'
                      });
                      
                      const data = await response.json();
                      
                      if (response.ok) {
                          document.getElementById('seatCountDisplay').textContent = seatCount;
                          document.getElementById('totalCost').textContent = data.total_cost;
                          document.getElementById('checkoutUrl').href = data.checkout_url;
                          document.getElementById('result').style.display = 'block';
                      } else {
                          alert('Error: ' + data.error);
                      }
                  } catch (error) {
                      alert('Error creating checkout session');
                  }
              }
          </script>
      </body>
      </html>
      ```
    </CodeGroup>

    <Check>
      **Interfaccia Web creata!** Ora hai una semplice interfaccia per provare diverse quantità di postazioni.
    </Check>
  </Step>

  <Step title="Serve static files">
    Aggiungi questo al tuo `src/server.ts` per servire il file HTML:

    ```typescript theme={null}
    // Add this line after your other middleware
    app.use(express.static('public'));

    // Add this route to serve the demo page
    app.get('/', (req, res) => {
      res.sendFile(__dirname + '/../public/index.html');
    });
    ```

    <Check>
      **File statici configurati!** Visita `http://localhost:3000` per vedere la tua interfaccia demo.
    </Check>
  </Step>
</Steps>

## Passo 5: Testa la tua Implementazione

Testiamo la nostra implementazione dei prezzi basati sui posti per assicurarci che tutto funzioni correttamente.

<Steps>
  <Step title="Start your server">
    1. Assicurati di avere il file `.env` con la chiave API corretta
    2. Aggiorna gli ID di prodotto e componente aggiuntivo nel tuo codice con i valori effettivi della dashboard Dodo Payments
    3. Avvia il server:

    ```bash theme={null}
    npm run dev
    ```

    <Check>
      Il server dovrebbe avviarsi correttamente e mostrare "Server running on `http://localhost:3000`"
    </Check>
  </Step>

  <Step title="Test the web interface">
    <Frame>
      <img src="https://mintcdn.com/dodopayments/ajOhO6Du1yNsg0hy/images/cookbooks/seat-based/seat-based-billing-ui.png?fit=max&auto=format&n=ajOhO6Du1yNsg0hy&q=85&s=37d166d8e76b0bfbb4959bc9a3eff1f8" alt="Creazione del prodotto di abbonamento base" style={{ maxHeight: '500px', width: 'auto' }} width="1806" height="1416" data-path="images/cookbooks/seat-based/seat-based-billing-ui.png" />
    </Frame>

    1. Apri il browser e vai su `http://localhost:3000`
    2. Dovresti vedere l'interfaccia demo basata sui posti
    3. Prova diverse quantità di postazioni (0, 3, 10, ecc.)
    4. Clicca su “Generate Checkout Link” per ogni quantità
    5. Verifica che gli URL di checkout vengano generati correttamente
  </Step>

  <Step title="Test a checkout session">
    1. Genera un link di checkout con 3 postazioni aggiuntive
    2. Clicca sull'URL di checkout per aprire il checkout di Dodo Payments
    3. Verifica che il checkout mostri:
       * Piano base: \$49/mese
       * Postazioni aggiuntive: 3 × 2 dollari = \$6/mese
    4. Completa l'acquisto di prova

    <Check>
      Il checkout dovrebbe mostrare la suddivisione corretta dei prezzi e permetterti di completare l'acquisto.
    </Check>
  </Step>

  <Step title="Listen for webhooks and update your DB">
    Per mantenere il database sincronizzato con i cambiamenti dell'abbonamento e delle postazioni, devi ascoltare gli eventi webhook di Dodo Payments. I webhook notificano il backend quando un cliente completa il checkout, aggiorna l'abbonamento o modifica il numero di postazioni.

    Segui la guida ufficiale ai webhook di Dodo Payments per istruzioni passo-passo su come impostare gli endpoint webhook e gestire gli eventi:

    <Card title="Dodo Payments Webhooks Documentation" icon="bell" href="/developer-resources/webhooks">
      Scopri come ricevere e elaborare in modo sicuro gli eventi webhook per la gestione degli abbonamenti e delle postazioni.
    </Card>
  </Step>
</Steps>

## Risoluzione dei Problemi

Problemi comuni e le loro soluzioni:

<AccordionGroup>
  <Accordion title="Checkout creation failing">
    **Possibili cause:**

    * ID del prodotto o del componente aggiuntivo non valido
    * La chiave API non ha autorizzazioni sufficienti
    * Il componente aggiuntivo non è correttamente associato all'abbonamento
    * Problemi di connettività di rete

    **Soluzioni:**

    1. Verifica che gli ID di prodotto e componente aggiuntivo esistano nella dashboard Dodo Payments
    2. Controlla che il componente aggiuntivo sia correttamente attaccato all'abbonamento
    3. Assicurati che la chiave API abbia i permessi per creare sessioni di checkout
    4. Testa la connettività API con una semplice richiesta GET
  </Accordion>
</AccordionGroup>

## Congratulazioni! Hai Implementato Prezzi Basati sui Posti

Hai creato con successo un sistema di prezzi basati sui posti con Dodo Payments! Ecco cosa hai realizzato:

<CardGroup cols={2}>
  <Card title="Base Subscription">
    Creato un prodotto di abbonamento con 5 postazioni incluse a \$49/mese
  </Card>

  <Card title="Seat Add-ons">
    Configurati i componenti aggiuntivi per postazioni aggiuntive a \$2/mese ciascuna
  </Card>

  <Card title="Checkout">
    Costruita un'API che genera sessioni di checkout con quantità di postazioni personalizzate
  </Card>

  <Card title="Web Interface">
    Creata una semplice interfaccia web per testare diverse quantità di postazioni
  </Card>
</CardGroup>

<Info>
  Questo esempio dimostra solo un'implementazione minima dei prezzi basati sulle postazioni. Per l'uso in produzione, dovresti aggiungere un solido handling degli errori, autenticazione, validazione dei dati, misure di sicurezza e adattare la logica alle esigenze della tua applicazione.
</Info>
