> ## 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.

# Platsbaserad prissättning med tillägg och betalningslänkar

> Lär dig hur du skapar tillägg för platsbaserad prissättning och genererar betalningslänkar med anpassade tilläggsmängder med Dodo Payments

I den här handledningen kommer du att lära dig hur du implementerar platsbaserad prissättning med Dodo Payments-tillägg. Vi kommer att skapa en prenumerationsprodukt med tillägg för ytterligare platser och visa hur du genererar betalningslänkar med anpassade tilläggsmängder.

<Note>
  Den här handledningen innehåller exempel på implementationskod för en Node.js/Express-applikation. Du kan anpassa koden till din specifika ram (Next.js, React, Vue osv.) och skräddarsy användargränssnittet efter din applikations behov.
</Note>

I slutet av denna handledning kommer du att veta hur man:

* Skapar prenumerationsprodukter med platsbaserad prissättning
* Ställer in tillägg för ytterligare platser
* Genererar betalningslänkar med anpassade tilläggsmängder
* Hanterar kassa-sessioner med dynamiska platsantal

## Vad vi bygger

Låt oss skapa en platsbaserad prissättningsmodell:

* **Basplan**: 49 USD/månad för upp till 5 teammedlemmar
* **Plats-tillägg**: 2 USD/månad per ytterligare plats
* **Betalningslänkar**: Dynamisk kassa med anpassade platsmängder

<Info>
  Innan vi börjar, se till att du har:

  * Ett Dodo Payments-konto
  * Grundläggande kunskaper om TypeScript/Node.js
</Info>

## Steg 1: Skapa ditt plats-tillägg

Nu behöver vi skapa ett tillägg som representerar ytterligare platser. Detta tillägg kommer att kopplas till vår basprenumeration och tillåta kunder att köpa ytterligare platser.

<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="Skapa grundläggande prenumerationsprodukt" style={{ maxHeight: '500px', width: 'auto' }} width="2348" height="1606" data-path="images/cookbooks/seat-based/seat-based-addons-creation.png" />
</Frame>

<Tip>
  **Vad vi bygger**: Ett tillägg som kostar \$2/månad per plats och kan läggas till vilken basprenumeration som helst.
</Tip>

<Steps>
  <Step title="Navigate to Add-Ons">
    1. I din Dodo Payments-instrumentpanel, håll dig kvar i avsnittet **Products**
    2. Klicka på fliken **Add-Ons**
    3. Klicka på **Create Add-On**

    Detta öppnar formuläret för att skapa tillägg.
  </Step>

  <Step title="Enter add-on details">
    Fyll i de här värdena för vårt plats-tillägg:

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

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

    **Price**: Enter → `2.00`

    **Valuta**: Måste matcha din basprenumerationsvaluta

    **Skattekategori**: Välj lämplig kategori för din produkt.
  </Step>

  <Step title="Save your add-on">
    1. Gå igenom alla inställningar:
       * Namn: Additional Team Seat
       * Pris: \$2,00/månad
    2. Klicka på **Create Add-On**

    <Check>
      **Tillägg skapat!** Ditt plats-tillägg finns nu tillgängligt för att kopplas till prenumerationer.
    </Check>
  </Step>
</Steps>

## Steg 2: Skapa din basprenumerationsprodukt

Vi börjar med att skapa en basprenumerationsprodukt som inkluderar 5 teammedlemmar. Detta kommer att vara grunden för vår platsbaserade prissättningsmodell.

<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="Skapa grundläggande prenumerationsprodukt" 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. Logga in på din Dodo Payments-instrumentpanel
    2. Klicka på **Products** i vänstra sidomenyn
    3. Klicka på knappen **Create Product**
    4. Välj **Subscription** som produkttyp

    Du bör nu se ett formulär där vi konfigurerar vår basprenumeration.
  </Step>

  <Step title="Fill in the subscription details">
    Nu anger vi de specifika detaljerna för vår basplan:

    **Product Name**: `Motion`

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

    **Recurring Price**: Enter → `49.00`

    **Billing Cycle**: Select → `Monthly`

    **Currency**: Select your preferred currency (e.g., `USD`)
  </Step>
</Steps>

## Steg 3: Koppla tillägg till prenumeration

Nu behöver vi koppla vårt plats-tillägg till basprenumerationen så att kunder kan köpa ytterligare platser under kassan.

<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="Fästa tillägg till prenumeration" style={{ maxHeight: '500px', width: 'auto' }} width="2338" height="1196" data-path="images/cookbooks/seat-based/seat-based-addons.png" />
    </Frame>

    1. Scrolla ner till sektionen **Tillägg**
    2. Klicka på **Lägg till Tillägg**
    3. Välj ditt plats-tillägg från rullgardinsmenyn
    4. Bekräfta att det visas i din prenumerationskonfiguration
  </Step>

  <Step title="Save subscription changes">
    1. Granska hela prenumerationsinställningen:
       * Basplan: \$49/månad för 5 platser
       * Tillägg: \$2/månad per extra plats
       * Gratis testperiod: 14 dagar
    2. Klicka på **Save Changes**

    <Check>
      **Sätebaserad prissättning konfigurerad!** Kunder kan nu köpa din basplan och lägga till extra platser vid behov.
    </Check>
  </Step>
</Steps>

## Steg 4: Generera betalningslänkar med anpassade tilläggsmängder

Nu låt oss skapa en Express.js-applikation som genererar betalningslänkar med anpassade tilläggsmängder. Det är här den verkliga kraften i platsbaserad prissättning kommer in - du kan dynamiskt skapa kassa-sessioner med vilket antal ytterligare platser som helst.

<Steps>
  <Step title="Set up your project">
    Skapa ett nytt Node.js-projekt och installera nödvändiga beroenden:

    ```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
    ```

    Skapa en `tsconfig.json`-fil:

    ```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">
    Skapa en `.env`-fil med din Dodo Payments API-nyckel:

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

    <Warning>
      Committra aldrig din API-nyckel till versionshantering. Lägg till `.env` i din `.gitignore`-fil.
    </Warning>
  </Step>

  <Step title="Implement the checkout session creation">
    Skapa en `src/server.ts`-fil med följande kod:

    <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">
    Skapa en `public/index.html`-fil för enkel testning:

    <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>
      **Webbgränssnitt skapat!** Du har nu ett enkelt UI för att testa olika antal platser.
    </Check>
  </Step>

  <Step title="Serve static files">
    Lägg till detta i din `src/server.ts` för att leverera HTML-filen:

    ```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>
      **Statisk filkonfiguration klar!** Besök `http://localhost:3000` för att se din demo.
    </Check>
  </Step>
</Steps>

## Steg 5: Testa din implementation

Låt oss testa vår platsbaserade prissättningsimplementation för att säkerställa att allt fungerar korrekt.

<Steps>
  <Step title="Start your server">
    1. Se till att du har din `.env`-fil med korrekt API-nyckel
    2. Uppdatera produkt- och tilläggs-ID:n i din kod med de faktiska värdena från din Dodo Payments-instrumentpanel
    3. Starta din server:

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

    <Check>
      Din server bör starta utan problem och visa "Server running on [http://localhost:3000](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="Skapa grundläggande prenumerationsprodukt" style={{ maxHeight: '500px', width: 'auto' }} width="1806" height="1416" data-path="images/cookbooks/seat-based/seat-based-billing-ui.png" />
    </Frame>

    1. Öppna din webbläsare och gå till `http://localhost:3000`
    2. Du bör se demonstrationen för platspreiser
    3. Testa olika antal platser (0, 3, 10 osv.)
    4. Klicka på "Generate Checkout Link" för varje antal
    5. Bekräfta att checkout-URL:erna genereras korrekt
  </Step>

  <Step title="Test a checkout session">
    1. Generera en checkout-länk med 3 extra platser
    2. Klicka på checkout-URL:en för att öppna Dodo Payments-checkouten
    3. Bekräfta att checkouten visar:
       * Basplan: \$49/månad
       * Extra platser: 3 × 2 dollar = \$6/månad
    4. Slutför testköpet

    <Check>
      Checkouten bör visa rätt prissammanställning och tillåta dig att slutföra köpet.
    </Check>
  </Step>

  <Step title="Listen for webhooks and update your DB">
    För att hålla din databas synkroniserad med prenumerations- och platsändringar behöver du lyssna på webhook-händelser från Dodo Payments. Webhooks meddelar din backend när en kund slutför checkout, uppdaterar sin prenumeration eller ändrar platsantal.

    Följ den officiella Dodo Payments-webhookguiden för steg-för-steg-instruktioner om hur du ställer in webhook-slutpunkter och hanterar händelser:

    <Card title="Dodo Payments Webhooks Documentation" icon="bell" href="/developer-resources/webhooks">
      Lär dig hur du säkert tar emot och behandlar webhook-händelser för prenumerations- och plats-hantering.
    </Card>
  </Step>
</Steps>

## Felsökning

Vanliga problem och deras lösningar:

<AccordionGroup>
  <Accordion title="Checkout creation failing">
    **Möjliga orsaker:**

    * Ogiltigt produkt-ID eller tilläggs-ID
    * API-nyckeln har inte tillräckliga behörigheter
    * Tillägget är inte korrekt kopplat till prenumerationen
    * Problem med nätverksanslutningen

    **Lösningar:**

    1. Verifiera att produkt- och tilläggs-ID:n finns i din Dodo Payments-instrumentpanel
    2. Kontrollera att tillägget är korrekt kopplat till prenumerationen
    3. Säkerställ att API-nyckeln har behörighet att skapa checkout-sessioner
    4. Testa API-anslutningen med en enkel GET-förfrågan
  </Accordion>
</AccordionGroup>

## Grattis! Du har implementerat platsbaserad prissättning

Du har framgångsrikt skapat ett system för platsbaserad prissättning med Dodo Payments! Här är vad du har åstadkommit:

<CardGroup cols={2}>
  <Card title="Base Subscription">
    Skapade en prenumerationsprodukt med 5 inkluderade platser för \$49/månad
  </Card>

  <Card title="Seat Add-ons">
    Konfigurerade tillägg för extra platser för \$2/månad per plats
  </Card>

  <Card title="Checkout">
    Byggde ett API som genererar checkout-sessioner med anpassade platsantal
  </Card>

  <Card title="Web Interface">
    Skapade ett enkelt webbgränssnitt för att testa olika platsantal
  </Card>
</CardGroup>

<Info>
  Detta exempel visar endast en minimal implementation av platsbaserad prissättning. För produktion bör du lägga till robust felhantering, autentisering, datavalidering, säkerhetsåtgärder och anpassa logiken efter din applikations behov.
</Info>
