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

# Praxisbeispiele - Verknüpfung mit dem Zahlungsanbieter

> Praxisbeispiele für die Verknüpfung eines Kundenkontos mit dem Konto beim Zahlungsanbieter in WEBSALE: Verwaltung im Kundenkonto mit Setup- und Create-Aktion, Aufheben der Verknüpfung sowie das Opt-in im Bestellablauf.

In diesem Abschnitt finden Sie Praxisbeispiele für die Verknüpfung eines Kundenkontos mit dem Konto beim Zahlungsanbieter. Besteht eine Verknüpfung, muss der Kunde bei Folgebestellungen die Freigabe auf der Seite des Zahlungsanbieters nicht erneut durchlaufen.

Welche Zahlungsarten eine Verknüpfung unterstützen, entscheidet der Zahlungsanbieter. Derzeit unterstützt ausschließlich PayPal Checkout diese Funktion, weshalb die Beispiele die Einbindung des PayPal-SDK zeigen. Die Aktionen selbst sind nicht auf einen bestimmten Zahlungsanbieter festgelegt.

Die Beispiele gehen davon aus, dass die Zahlungsart die ID `paypalCheckout` hat.

***

## Verknüpfung im Kundenkonto verwalten

Die Seite hat zwei Zustände, die über die Funktion [wsAccount.hasPaymentVault() ](/frontend/referenz/module/wsAccount)unterschieden werden: Besteht eine Verknüpfung, wird ein Formular zum Aufheben der Verknüpfung angezeigt. Besteht keine Verknüpfung, wird der PayPal-Button angezeigt. Dieser legt die Verknüpfung in zwei Schritten an: Zunächst holt `PaymentValueSetup` das Setup-Token und anschließend gibt der Kunde die Verknüpfung bei PayPal frei. Zuletzt speichert `PaymentValueCreate` sie.

Weil `PaymentVaultCreate` keinen Antwort-Body liefert, lädt das Beispiel die Seite nach dem Erstellen neu. Erst dadurch liefert `hasPaymentVault()` den neuen Zustand.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{{ extends "layouts/account_layout.htm" }}

{{ block content_account_main }}

{{ var $ppcData = $wsPayPalCheckout.loadConfigData() }}
{{ var $paymentId = "paypalCheckout"}}
{{ var $paymentVault = $wsAccount.hasPaymentVault($paymentId) }}

{{if not $paymentVault }}
    <script type="text/javascript"
            src="https://www.paypal.com/sdk/js?client-id={{= $ppcData.clientId }}&merchant-id={{= $ppcData.merchantId }}"
            data-client-token="{{= $ppcData.getClientToken() }}"></script>
{{ /if }}

<h3>PayPal Checkout Vaulting verwalten</h3>

{{ var $removeVaultAction = $wsActions.create('PaymentVaultRemove') }}
{{ if $removeVaultAction.globalErrors }}
    <div class="alert alert-danger">
        <ul>
            {{ foreach $err in $removeVaultAction.globalErrors }}
                <li>{{= $err.text | ifNull($err.code) }}</li>
            {{ /foreach }}
        </ul>
    </div>
{{ /if }}

{{ var $paymentVaultSetupAction = $wsActions.create('PaymentVaultSetup') }}
{{ if $paymentVaultSetupAction.globalErrors }}
    <div class="alert alert-danger">
        <ul>
            {{ foreach $err in $paymentVaultSetupAction.globalErrors }}
                <li>{{= $err.text | ifNull($err.code) }}</li>
            {{ /foreach }}
        </ul>
    </div>
{{ /if }}

{{ var $paymentVaultCreateAction = $wsActions.create('PaymentVaultCreate') }}
{{ if $paymentVaultCreateAction.globalErrors }}
    <div class="alert alert-danger">
        <ul>
            {{ foreach $err in $paymentVaultCreateAction.globalErrors }}
                <li>{{= $err.text | ifNull($err.code) }}</li>
            {{ /foreach }}
        </ul>
    </div>
{{ /if }}

{{ if $paymentVault }}
    <div class="panel panel-default">
        <div class="panel-heading">PayPal-Verbindung löschen</div>
        <div class="panel-body">
            <form method="POST" action="{{= $wsViews.current.url() }}" class="form-horizontal">
                <input type="hidden" name="wscsrf" value="{{= $removeVaultAction.csrf }}">
                <input type="hidden" name="wsact" value="{{= $removeVaultAction.id }}">
                <input type="hidden" name="paymentId" value="{{= $paymentId}}">
                <div class="form-group">
                    <div class="col-sm-offset-4 col-sm-8">
                        <button type="submit" class="btn btn-primary">Jetzt Verbindung entfernen</button>
                    </div>
                </div>
            </form>
        </div>
    </div>
{{ else }}
    <div class="panel panel-default">
        <div class="panel-heading">PayPal-Verbindung erstellen</div>
        <div id="ppcbtn-div"></div>
    </div>
    <script>
        window.paypal.Buttons({
            createVaultSetupToken: async () => {
                const data = {
                    wscsrf: "{{= $paymentVaultSetupAction.csrf }}",
                    wsact:  "{{= $paymentVaultSetupAction.id }}",
                    paymentId: "{{= $paymentId }}"
                };
                try {
                    const rawResponse = await fetch("{{! $wsViews.current.url() }}", {
                        method: "POST",
                        body: new URLSearchParams(data)
                    });
                    const text = await rawResponse.text();
                    if (!text) {
                        return false;
                    }
                    return JSON.parse(text).token;
                } catch(excp) {
                    console.log(excp)
                }
                return false;
            },
            onApprove: async (data) => {
                const payload = {
                    "wscsrf" : "{{= $paymentVaultCreateAction.csrf }}",
                    "wsact": "{{= $paymentVaultCreateAction.id }}",
                    "paymentId": "{{= $paymentId }}",
                    "token": data.vaultSetupToken
                };
                const rawResponse = fetch("{{! $wsViews.current.url() }}", {
                    method: "POST",
                    body: new URLSearchParams(payload)
                });
                rawResponse.then(() => {
                    window.location.reload()
                });
            },
            onError: (error) => {
                console.log(error);
            }
        }).render("#ppcbtn-div");
    </script>
{{ /if }}

{{ /block }}
```

<Info>
  Das Beispiel ist auf Testbarkeit ausgelegt, nicht auf Produktionsreife. Der JavaScript-Teil sollte vor dem Livebetrieb ausgebaut werden: `onError` gibt Fehler nur auf der Konsole aus, und ein Fehlschlag von `PaymentVaultCreate` bleibt dem Kunden verborgen, weil die Seite unmittelbar danach neu geladen wird und die Aktionsfehler des vorangegangenen POST damit verloren gehen.
</Info>

***

## Verknüpfung im Bestellablauf anbieten

Wenn für die gewählte Zahlungsart bereits eine Verknüpfung besteht, wird die Bestellung direkt darüber bezahlt und der PayPal-Button entfällt. Besteht noch keine Verknüpfung, können Sie dem Kunden anbieten, diese mit der aktuellen Bestellung anzulegen. Dafür genügt das Formularfeld `initPaymentValue` - die Verknüpfung wird dann beim Bestellabschluss automatisch erstellt.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
...
{{ var $showPPButton = ($wsCheckout.selectedPayment == "paypalCheckout" or $wsCheckout.selectedPayment == "paypalCheckoutSepa" or $wsCheckout.selectedPayment == "paypalCheckoutPayLater") and $wsCheckout.isValid }}
...
{{ var $ppcVault = $wsCheckout.selectedPayment == "paypalCheckout" and $wsCheckout.hasPaymentVault() }}
{{ $showPPButton = $showPPButton and not $ppcVault}}
...
{{ if  $showPPButton }}
    ...
    {{ if not $ppcData }}
        Konnte nicht richtig konfigurieren
    {{ else }}
      <div>
        <input type="checkbox" name="initPaymentVault" value="y"> PayPal Account für zukünftige Zahlungen speichern
      </div>
      <div id="paypal-button-container"></div>
    {{ /if }}
    ...
{{ /if }}
```

Das Feld wird beim Bestellabschluss ausgewertet. Die Verknüpfung entsteht nur, wenn zusätzlich alle folgenden Bedingungen erfüllt sind:

* Der Kunde ist angemeldet.
* Es handelt sich nicht um einen Express-Checkout.
* Die gewählte Zahlungsart ist die reine PayPal-Zahlung, nicht PayPal SEPA oder PayPal PayLater.
* Es besteht noch keine Verknüpfung.

<Info>
  Ist eine dieser Bedingungen nicht erfüllt, wird die Bestellung normal abgeschlossen und die Verknüpfung schlicht nicht angelegt, dafür gibt es keinen Fehlercode. Soll dem Kunden das Anlegen zuverlässig angeboten werden, verwenden Sie den Weg über eine eigene Seite im Kundenkonto, siehe [Verknüpfung im Kundenkonto verwalten](#verknupfung-im-kundenkonto-verwalten).
</Info>


## Related topics

- [actions - Benutzerkonto](/konfiguration/actions-fehlertexte-e-mails/actions-benutzerkonto.md)
- [$wsAccount - Account & Adressdaten](/frontend/referenz/module/wsAccount.md)
- [$wsCheckout - Checkout](/frontend/referenz/module/wscheckout.md)
- [Praxisbeispiele - Gutscheine](/gutscheine.md)
- [API Basics](/schnittstellen/admin-interface-api/api-basics.md)
