# YoPlanning Payment Manager — API-Dokumentation

### `POST /api/create-payment`

Erstellt einen Zahlungslink (Stripe) und gibt eine URL zurück, zu der der Kunde weitergeleitet werden soll.

**Basis-URL**: `https://payment.yoplanning.pro`

***

### Authentifizierung

Der Payment Manager verwendet eine **tokenbasierte Authentifizierung**, die vom Haupt-API-Token von YoPlanning getrennt ist.

```
Authorization: Token <PAYMENT_MANAGER_TOKEN>
Content-Type: application/json
```

> **Wichtig:** Das Token des Payment Managers ist **nicht** identisch mit dem Token der YoPlanning API v3.1. Es handelt sich um zwei unterschiedliche Token. Die Verwendung des falschen Tokens führt zu dem Fehlercode `401 "Ungültiges Token."`.

| Token                     | Wird verwendet für                                             | Wo man es finden kann                          |
| ------------------------- | -------------------------------------------------------------- | ---------------------------------------------- |
| YoPlanning API-Token      | `yoplanning.pro/api/v3.1/*` (Verfügbarkeit, Bestellungen usw.) | Backoffice > API > Tokens                      |
| **Zahlungsmanager-Token** | `payment.yoplanning.pro/api/*`                                 | Backoffice > Zahlungseinstellungen > API-Token |

***

### Anfrage

```
POST https://payment.yoplanning.pro/api/create-payment
Authorization: Token <PAYMENT_MANAGER_TOKEN>
Content-Type: application/json
```

#### Körperparameter

| Feld                            | Erforderlich | Art                 | Beschreibung                                                                                                                |
| ------------------------------- | ------------ | ------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `order_id`                      | Ja           | Zeichenkette        | Ihre Bestellnummer (also die UUID, die von `/order-typicalvalidation` zurückgegeben wird)                                   |
| `vendor_id`                     | Ja           | Zeichenkette (UUID) | Ihre Händlerkennung (zu finden in Ihren YoPlanning-Zahlungseinstellungen)                                                   |
| `Preis`                         | Ja           | Nummer              | Gesamtbetrag in der Haupteinheit der Währung (z. B. 196,00 für 196 Euro). **Nicht in Cent.**                                |
| `Währung`                       | Ja           | Zeichenkette        | ISO 4217 Währungscode (z. B. `"EUR"`, `"USD"`)                                                                              |
| `callback_url`                  | Ja           | Zeichenkette (URL)  | Die IPN-Benachrichtigungs-URL muss öffentlich zugänglich sein. Sie wird nach Zahlungsabschluss per POST-Anfrage aufgerufen. |
| `redirection_url`               | NEIN         | Zeichenkette (URL)  | Wohin soll der Kunde nach einer erfolgreichen Zahlung weitergeleitet werden?                                                |
| `cancel_url`                    | NEIN         | Zeichenkette (URL)  | Wohin soll der Kunde weitergeleitet werden, wenn er storniert?                                                              |
| `payer_email`                   | NEIN         | Zeichenkette        | Füllt das E-Mail-Feld auf der Zahlungsseite automatisch aus.                                                                |
| `cardholder_first_name`         | NEIN         | Zeichenkette        | Füllt den Vornamen des Karteninhabers automatisch aus                                                                       |
| `cardholder_last_name`          | NEIN         | Zeichenkette        | Füllt den Nachnamen des Karteninhabers automatisch aus                                                                      |
| `billing_address_line1`         | NEIN         | Zeichenkette        | Rechnungsadresse Zeile 1                                                                                                    |
| `billing_address_line2`         | NEIN         | Zeichenkette        | Rechnungsadresse Zeile 2                                                                                                    |
| `billing_address_city`          | NEIN         | Zeichenkette        | Stadt                                                                                                                       |
| `Rechnungsadresse_Postleitzahl` | NEIN         | Zeichenkette        | Postleitzahl                                                                                                                |
| `billing_address_country`       | NEIN         | Zeichenkette        | Land                                                                                                                        |
| `billing_address_state`         | NEIN         | Zeichenkette        | Bundesland/Region                                                                                                           |

#### Wichtige Hinweise

* **Das Feld heißt `price`, nicht `amount`.** Wenn Sie `amount` anstelle von `price` senden, erhalten Sie einen `500 Internal Server Error`, da der Server `price=None` empfängt.
* **Der Preis ist in Euro (oder Ihrer Währung) angegeben, nicht in Cent.** Senden Sie 196,00, nicht 19600.
* Die Angabe von `callback_url` ist erforderlich, auch wenn Sie keine IPN-Benachrichtigungen aktiv verarbeiten. Wird sie weggelassen, führt dies zu einem Validierungsfehler.
* Der Payment Manager ist ein **Zahlungslink-Service für Pauschalzahlungen** – er benötigt einen Gesamtpreis, keine Einzelpostenaufschlüsselung. Bestellpositionen gehören zur YoPlanning-Buchungs-API (`/order-validation`), nicht hierher.

***

### Antwort

#### Erfolg (`200`)

```
{
  "success": true,
  "payment_id": "179384e3-4e32-4f03-b6ea-2fdc998e2c6c",
  "customer_id": null,
  "vakario_fee": "0.00",
  "payment_solution": "Stripe",
  "payment_url": "https://payment.yoplanning.pro/pay/8edf6170-5495-432d-8b04-6717ccb8ad68"
}
```

| Feld               | Art                    | Beschreibung                                                           |
| ------------------ | ---------------------- | ---------------------------------------------------------------------- |
| `Erfolg`           | boolescher Wert        | `true`, wenn der Zahlungslink erstellt wurde                           |
| `payment_id`       | Zeichenkette (UUID)    | Eindeutige Zahlungskennung                                             |
| `customer_id`      | Zeichenkette oder Null | Kunden-ID, falls erkannt                                               |
| `vakario_fee`      | Zeichenkette           | Plattformgebühr (Dezimalzahl)                                          |
| `payment_solution` | Zeichenkette           | Verwendeter Zahlungsanbieter („Stripe“)                                |
| `payment_url`      | Zeichenkette (URL)     | **Leiten Sie den Kunden zur Zahlungsabwicklung auf diese URL weiter.** |

#### Validierungsfehler (`400`)

```
{
  "success": false,
  "errors": {
    "callback_url": ["This field is required."]
  }
}
```

#### Authentifizierungsfehler (`401`)

Kein `Authorization`-Header:

```
{"detail": "Authentication credentials were not provided."}
```

Falsches Token (z. B. Verwendung des YoPlanning-API-Tokens anstelle des Payment-Manager-Tokens):

```
{"detail": "Invalid token."}
```

#### Serverfehler (`500`)

Gibt eine HTML-Fehlerseite (nicht JSON) mit der Meldung „Die Zahlungsplattform ist vorübergehend nicht verfügbar.“ zurück.

Es handelt sich **nicht** um einen tatsächlichen Plattformausfall. In der Praxis werden 500-Fehler durch Folgendes verursacht:

| Grundursache                            | Serverseitiger Fehler                                                                                         | Fix                                                                                                  |
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| Das Feld `price` fehlt oder ist `null`. | `TypeError: '>' wird zwischen Instanzen von 'NoneType' und 'int' nicht unterstützt` in `checkPaymentSolution` | Stellen Sie sicher, dass `price` im JSON-Body eine Zahl ist. Das Feld heißt `price`, nicht `amount`. |
| `vendor_id` fehlt oder ist ungültig     | Verschiedene Django-Formularfehler                                                                            | Stellen Sie sicher, dass `vendor_id` eine gültige UUID-Zeichenkette ist.                             |

> Die 500-Antwort liefert HTML, nicht JSON. Parsen Sie die Daten vorsorglich, wenn Sie JSON erwarten.

***

### IPN-Rückruf

Wenn die Zahlung abgeschlossen ist (oder fehlschlägt), sendet der Zahlungsmanager eine `POST`-Anfrage an Ihre `callback_url`:

```
{
  "success": true,
  "payed": true,
  "order_id": "your-order-id",
  "payment_solution": "Stripe",
  "payer_lang": "fr"
}
```

| Feld               | Art             | Beschreibung                                                        |
| ------------------ | --------------- | ------------------------------------------------------------------- |
| `Erfolg`           | boolescher Wert | Ob die Zahlung erfolgreich war                                      |
| `bezahlt`          | boolescher Wert | Ob die Zahlung eingezogen wurde                                     |
| `order_id`         | Zeichenkette    | Die `order_id`, die Sie beim Erstellen der Zahlung angegeben haben. |
| `payment_solution` | Zeichenkette    | Anbieter verwendet                                                  |
| `payer_lang`       | Zeichenkette    | Sprache des Browsers des Zahlers                                    |

Anforderungen an `callback_url`:

* Muss öffentlich zugänglich sein (keine Authentifizierung erforderlich)
* POST-Anfragen müssen akzeptiert werden.
* Es muss ein 2xx-Statuscode zurückgegeben werden.

***

### Vollständiges Beispiel

#### cURL

```
curl -X POST "https://payment.yoplanning.pro/api/create-payment" \
  -H "Authorization: Token YOUR_PAYMENT_MANAGER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "order_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "vendor_id": "your-vendor-uuid",
    "price": 196.00,
    "currency": "EUR",
    "payer_email": "customer@example.com",
    "cardholder_first_name": "Jean",
    "cardholder_last_name": "Dupont",
    "callback_url": "https://yoursite.com/api/payment-callback",
    "redirection_url": "https://yoursite.com/confirmation?status=success",
    "cancel_url": "https://yoursite.com/confirmation?status=cancelled"
  }'
```

#### JavaScript (fetch)

```
const response = await fetch('https://payment.yoplanning.pro/api/create-payment', {
  method: 'POST',
  headers: {
    'Authorization': 'Token YOUR_PAYMENT_MANAGER_TOKEN',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    order_id: orderId,
    vendor_id: 'your-vendor-uuid',
    price: 196.00,       // euros, NOT cents
    currency: 'EUR',
    payer_email: 'customer@example.com',
    callback_url: 'https://yoursite.com/api/payment-callback',
    redirection_url: 'https://yoursite.com/confirmation?status=success',
    cancel_url: 'https://yoursite.com/confirmation?status=cancelled',
  }),
});
​
const data = await response.json();
​
if (data.success && data.payment_url) {
  // Redirect customer to payment page
  window.open(data.payment_url, '_blank');
}
```

#### Python (requests)

```
import requests
​
response = requests.post(
    "https://payment.yoplanning.pro/api/create-payment",
    headers={
        "Authorization": "Token YOUR_PAYMENT_MANAGER_TOKEN",
        "Content-Type": "application/json",
    },
    json={
        "order_id": order_id,
        "vendor_id": "your-vendor-uuid",
        "price": 196.00,
        "currency": "EUR",
        "payer_email": "customer@example.com",
        "callback_url": "https://yoursite.com/api/payment-callback",
        "redirection_url": "https://yoursite.com/confirmation?status=success",
        "cancel_url": "https://yoursite.com/confirmation?status=cancelled",
    },
)
​
data = response.json()
payment_url = data.get("payment_url")
```

***

### Typischer Integrationsablauf

```
1. Customer selects dates and products
         │
         ▼
2. Check availability
   GET yoplanning.pro/api/v3.1/teams/{team}/online-products/{product}/availabilities/
         │
         ▼
3. Validate the order
   POST yoplanning.pro/api/v3.1/teams/{team}/order-validation
   → Returns order ID
         │
         ▼
4. Create payment link
   POST payment.yoplanning.pro/api/create-payment
   → Returns payment_url
         │
         ▼
5. Redirect customer to payment_url (Stripe checkout)
         │
         ▼
6. Customer pays → redirected to redirection_url
   Payment Manager POSTs to callback_url (IPN)
```

***

### CORS

Die Payment Manager API gibt **keine** CORS-Header zurück. Direkte Aufrufe von einem Browser werden durch die Same-Origin-Policy des Browsers blockiert.

**Lösungen**:

* Verwenden Sie einen serverseitigen Proxy (z. B. Cloudflare Worker, Node.js-Backend, Serverless-Funktion), um Anfragen weiterzuleiten.
* Rufen Sie die API von Ihrem Backend aus auf, nicht von clientseitigem JavaScript.

***

### Häufig gestellte Fragen

**F: Ich erhalte die Fehlermeldung „401 Ungültiges Token“, obwohl mein Token in der YoPlanning API funktioniert.** A: Der Payment Manager verwendet ein eigenes Token, das vom Token der YoPlanning API v3.1 getrennt ist. Überprüfen Sie Ihre Zahlungseinstellungen im Backend, um das korrekte Token zu finden.

**F: Ich erhalte eine HTML-Fehlerseite (500) anstelle von JSON.** A: Dies bedeutet fast immer, dass ein Pflichtfeld fehlt oder den Wert `null` hat. Prüfen Sie, ob `price` (nicht `amount`) im Anfragetext eine Zahl ist. Stellen Sie außerdem sicher, dass `vendor_id` vorhanden und gültig ist.

**F: Meine `callback_url` ist noch nicht erreichbar. Kann ich sie weglassen?** A: Nein, die `callback_url` ist erforderlich. Sie können eine Platzhalter-URL verwenden, die den Statuscode 200 zurückgibt, aber das Feld muss vorhanden sein.

**F: Muss ich die Bestellpositionen an den Zahlungsmanager übergeben?** A: Nein. Der Zahlungsmanager wickelt nur die Zahlung ab – er benötigt einen Festpreis. Die Bestellpositionen gehören zur YoPlanning-Bestell-API (`/order-validation`).

**F: Ist der Preis in Cent oder in der Haupteinheit der Währung angegeben?** A: Haupteinheit. Für EUR senden Sie bitte 196,00, nicht 19600.
