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

# Practical examples - Linking with the payment provider

> Practical examples for linking a customer account with the account at the payment provider in WEBSALE: management in the customer account with setup and create actions, removing the link, and the opt-in during checkout.

This section contains practical examples for linking a customer account with the account at the payment provider. If a link exists, the customer does not have to go through the approval on the payment provider's site again for follow-up orders.

Which payment methods support a link is decided by the payment provider. Currently only PayPal Checkout supports this feature, which is why the examples show the integration of the PayPal SDK. The actions themselves are not tied to a specific payment provider.

The examples assume that the payment method has the ID `paypalCheckout`.

***

## Manage the link in the customer account

The page has two states, which are distinguished via the function [wsAccount.hasPaymentVault()](/frontend/referenz/module/wsAccount): if a link exists, a form for removing the link is displayed. If no link exists, the PayPal button is displayed. This creates the link in two steps: first, `PaymentValueSetup` fetches the setup token, and then the customer approves the link at PayPal. Finally, `PaymentValueCreate` saves it.

Because `PaymentVaultCreate` does not return a response body, the example reloads the page after creation. Only then does `hasPaymentVault()` return the new state.

```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>Manage PayPal Checkout vaulting</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">Delete PayPal connection</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">Remove connection now</button>
                    </div>
                </div>
            </form>
        </div>
    </div>
{{ else }}
    <div class="panel panel-default">
        <div class="panel-heading">Create PayPal connection</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>
  The example is designed for testability, not for production readiness. The JavaScript part should be extended before going live: `onError` only logs errors to the console, and a failure of `PaymentVaultCreate` stays hidden from the customer because the page is reloaded immediately afterwards, causing the action errors of the preceding POST to be lost.
</Info>

***

## Offer the link during checkout

If a link already exists for the selected payment method, the order is paid directly through it and the PayPal button is omitted. If no link exists yet, you can offer the customer the option to create one with the current order. All that is needed for this is the form field `initPaymentValue` — the link is then created automatically at order completion.

```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 }}
        Could not configure correctly
    {{ else }}
      <div>
        <input type="checkbox" name="initPaymentVault" value="y"> Save PayPal account for future payments
      </div>
      <div id="paypal-button-container"></div>
    {{ /if }}
    ...
{{ /if }}
```

The field is evaluated at order completion. The link is only created if, in addition, all of the following conditions are met:

* The customer is logged in.
* It is not an express checkout.
* The selected payment method is pure PayPal payment, not PayPal SEPA or PayPal PayLater.
* No link exists yet.

<Info>
  If one of these conditions is not met, the order is completed normally and the link is simply not created; there is no error code for this. If you want to offer link creation to the customer reliably, use the approach via a dedicated page in the customer account, see [Manage the link in the customer account](#manage-the-link-in-the-customer-account).
</Info>


## Related topics

- [Practical examples - Vouchers](/en/gutscheine.md)
- [payment - Payment methods](/en/konfiguration/payment-zahlungsmethoden.md)
- [Overview - Payment methods](/en/frontend/funktionsubersicht/zahlungsarten.md)
- [$wsCheckout - Checkout](/en/frontend/referenz/module/wscheckout.md)
- [Checkout process](/en/frontend/funktionsubersicht/bestellablauf.md)
