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

# PPC- (PayPal Checkout)

> Build the PayPal Checkout integration in the template: embed the PayPal SDK, set the return addresses, evaluate errors, and save and manage the buyer's PayPal account.

With PayPal Checkout, a large part of the payment process takes place in the buyer's browser. The shop embeds the PayPal SDK, PayPal displays its buttons, and after the buyer confirms, the SDK sends them back to an address specified by the shop.

The `PPC-` tags provide the building blocks for this exchange: the credentials for the SDK address, the three return addresses, error evaluation, and everything related to the saved PayPal account.

Guide: PayPal Checkout

## Does this payment method run via PayPal Checkout

Not only PayPal itself is connected via PayPal Checkout, but also credit card, direct debit, purchase on invoice, and other methods. Which of these a shop processes through it is determined by its configuration. `PPC-UsePayPalCheckout` answers the question for the currently selected payment method.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{PPC-UsePayPalCheckout}
   <div id="paypal-button-container"></div>
{/PPC-UsePayPalCheckout}
```

> [!NOTE]
>
> In Express Checkout, the positive range tag does not apply. There, no payment method has been selected yet, and the integration runs via its own states.

> [!NOTE]
>
> The range tag also does not apply if a saved PayPal account already exists for the buyer and they want to use it. In this case, the page no longer needs the PayPal buttons, because the payment runs without logging in again.

## Embedding the PayPal SDK

You compose the address of the SDK script from several pieces of information. Each of them has its own tag.

| Tag | Returns |
| - | - |
| `PPC-ClientID` | the shop's ClientID at PayPal |
| `PPC-MerchantID` | the shop's MerchantID |
| `PPC-Intent` | the intent, i.e. whether the amount is captured immediately or only authorized |
| `PPC-IntegrationDate` | the integration date |
| `PPC-ClientToken` | the client token, only for credit card payment |

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{PPC-UsePayPalCheckout}
   <script src="https://www.paypal.com/sdk/js?client-id=~PPC-ClientID~&merchant-id=~PPC-MerchantID~&intent=~PPC-Intent~&integration-date=~PPC-IntegrationDate~"></script>
{/PPC-UsePayPalCheckout}
```

> [!NOTE]
>
> `PPC-ClientID` and `PPC-MerchantID` accept the payment method code as an argument. Without an argument, they use the currently selected payment method. If it does not belong to PayPal Checkout, the output remains empty.

> [!WARNING]
>
> No payment method has been selected yet on the basket page. For Express Checkout, you must therefore pass the payment method code explicitly, i.e. `~PPC-ClientID(37)~` and `~PPC-MerchantID(37)~`. Without an argument, you get nothing there.

Materials: Payment method codes

`PPC-Sandbox` applies if the payment method is currently running against PayPal's test environment. This lets you display test notices that disappear automatically in live operation.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{PPC-Sandbox}
   <p class="hinweis">Testumgebung. Es findet keine echte Zahlung statt.</p>
{/PPC-Sandbox}
```

## The return addresses

Depending on the outcome of the process, the SDK calls a different address. The shop system provides all four ready-made.

| Tag | Is called |
| - | - |
| `PPC-OnApproveLink` | after the buyer has confirmed the payment |
| `PPC-OnCancelLink` | if the buyer cancels |
| `PPC-OnErrorLink` | if an error occurs |
| `PPC-PendingLink` | for the waiting page while PayPal is still checking the process |

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<script>
   paypal.Buttons({
      onApprove: () => { window.location.href = "~PPC-OnApproveLink~" },
      onCancel:  () => { window.location.href = "~PPC-OnCancelLink~" },
      onError:   () => { window.location.href = "~PPC-OnErrorLink~" }
   }).render("#paypal-button-container");
</script>
```

> [!NOTE]
>
> The waiting page needs `PPC-PendingLink` for itself. It reloads itself at intervals until PayPal has completed the process.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<head>
   <meta http-equiv="Refresh" content="5;url=~PPC-PendingLink~">
</head>
```

## Evaluating errors from PayPal

If PayPal rejects the process, the response contains an error code. `PPC-PayPalErrorCode` applies as a range tag if any code exists at all, and with a code in the argument only for exactly that code.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{PPC-PayPalErrorCode(PAYMENT_SOURCE_INFO_CANNOT_BE_VERIFIED)}
   <p class="fehler">
      Die Kombination aus Ihrem Namen und Ihrer Anschrift konnte nicht validiert werden.
      Bitte korrigieren Sie Ihre Daten und versuchen Sie es erneut.
   </p>
{/PPC-PayPalErrorCode(PAYMENT_SOURCE_INFO_CANNOT_BE_VERIFIED)}

{PPC-PayPalErrorCode}
   {!PPC-PayPalErrorCode(PAYMENT_SOURCE_INFO_CANNOT_BE_VERIFIED)}
      <p class="fehler">
         Die gewählte Zahlungsart kann derzeit nicht genutzt werden.
         Bitte wählen Sie eine andere.
      </p>
   {/!PPC-PayPalErrorCode(PAYMENT_SOURCE_INFO_CANNOT_BE_VERIFIED)}
{/PPC-PayPalErrorCode}
```

> [!NOTE]
>
> The outer range tag without an argument catches all other codes. Without it, the general notice would also appear if there is no error at all.

> [!WARNING]
>
> For purchase on invoice via PayPal, the service provider Ratepay specifies the wording of the rejection texts, including the references to its privacy policy and its contact form. Use these texts unchanged and do not rephrase them.

> [!NOTE]
>
> The code is found in PayPal's response under `details.issue`. Which codes can occur depends on the payment method and is described in PayPal's documentation.

## Saving the PayPal account

A logged-in buyer can store their PayPal account in the shop and pay next time without logging in again.

| Tag | Returns |
| - | - |
| `PPC-Vaulted` | applies if a PayPal account is saved for the buyer |
| `PPC-VaultedEmailAddress` | the email address of the saved account |
| `PPC-VaultedPayment` | applies if payment is currently being made with the saved account |
| `PPC-UserIDToken` | the token that identifies the saved account to PayPal |

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{PPC-Vaulted}
   <p>Sie zahlen mit ~PPC-VaultedEmailAddress~.</p>
{/PPC-Vaulted}

{!PPC-Vaulted}
   <label>
      <input type="checkbox" name="~WS-PPCSaveInVault_input~" ~WS-PPCSaveInVault_checked~>
      PayPal-Konto für zukünftige Zahlungen speichern
   </label>
{/!PPC-Vaulted}
```

> [!NOTE]
>
> `PPC-Vaulted` and `PPC-VaultedEmailAddress` only apply as long as saving is enabled in the shop at all. If it is disabled, both remain silent, and the negative range tag shows the offer to save. Therefore, additionally hide this offer via the configuration if it should not apply in the shop.

> [!NOTE]
>
> `PPC-UserIDToken` is not a passive value. The shop system retrieves the token from PayPal as soon as the tag is evaluated. Therefore, only place it where it is needed.

> [!NOTE]
>
> On the order overview, `PPC-UserIDToken` only returns a value if the buyer has checked the option to save. On the management page, it returns a value as long as no account has been saved yet.

## The management page for the saved account

The `PPCVaultManage` template shows the buyer their saved account and lets them create or delete it. It has two states.

| Tag | Shows |
| - | - |
| `PPC-VaultOverview` | the overview of the saved account |
| `PPC-VaultConfirmDelete` | the confirmation prompt before deletion |

| Tag | Returns the link |
| - | - |
| `PPC-DeleteVaultConfirm` | to the confirmation prompt before deletion |
| `PPC-DeleteVaultNoConfirm` | that deletes immediately |
| `PPC-CreateSetupTokenLink` | via which the SDK retrieves a setup token |
| `PPC-CreatePaymentTokenLink` | via which the setup token becomes a saved account |

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{PPC-VaultOverview}
   {PPC-Vaulted}
      <p>Gespeichertes Konto: ~PPC-VaultedEmailAddress~</p>
      <a href="~PPC-DeleteVaultConfirm~">Verbindung mit PayPal löschen</a>
   {/PPC-Vaulted}

   {!PPC-Vaulted}
      <div id="ppcbtn-div"></div>
   {/!PPC-Vaulted}
{/PPC-VaultOverview}

{PPC-VaultConfirmDelete}
   <p>Möchten Sie die Verbindung mit PayPal wirklich löschen?</p>
   <a href="~PPC-DeleteVaultNoConfirm~">ja, löschen</a>
{/PPC-VaultConfirmDelete}
```

> [!WARNING]
>
> `PPC-DeleteVaultConfirm` does not delete anything. It leads to the confirmation prompt, i.e. to the `PPC-VaultConfirmDelete` area. Deletion only happens via `PPC-DeleteVaultNoConfirm`. Therefore, only place this second tag within the confirmation prompt and not in the overview.

> [!WARNING]
>
> Both links output nothing as long as no account is saved. The markup then contains an empty `href`. Therefore, wrap them with `{PPC-Vaulted}`, as in the example.

The two token links serve the PayPal button on the management page. The SDK retrieves a setup token via the first one, and the second turns it into permanent storage.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
<script>
   window.paypal.Buttons({
      createVaultSetupToken: async () => {
         const result = await fetch("~PPC-CreateSetupTokenLink~")
         const data = await result.json()
         return data.ppc_setuptoken
      },
      onApprove: (data) => {
         const url = new URL("~PPC-CreatePaymentTokenLink~")
         url.searchParams.append("ppc_setuptoken", data.vaultSetupToken)
         window.location.replace(url)
      }
   }).render("#ppcbtn-div")
</script>
```

## The raw responses from PayPal

Three tags output PayPal's responses unchanged as JSON.

| Tag | Returns the response to |
| - | - |
| `PPC-CreateOrderRawResponse` | the creation of the process |
| `PPC-OrderDetailsRawResponse` | the query of the process data |
| `PPC-CaptureAuthorizeRawResponse` | the capture or authorization |

> [!NOTE]
>
> `PPC-OrderDetailsRawResponse` is not only intended for troubleshooting. Via the JSON interface, you can retrieve individual values from it, for example the address provided by PayPal.

```html theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
~EJD-SetRawDataHexCodedInput($PPC-OrderDetailsRawResponse$)~
```

Reference: EJD- (JSON interface)

> [!WARNING]
>
> The other two raw responses contain complete process data. Do not output them on a page that a buyer can reach in live operation.

## Present in the shop system, not previously described

Ten more `PPC-` tags exist in the shop system but are not listed in the previous documentation. Nine of them belong to Google Pay and Apple Pay via PayPal Checkout.

| Tag | Returns |
| - | - |
| `PPC-OrderID` | the process identifier at PayPal |
| `PPC-PaymentDataName` | the field name for the payment data |
| `PPC-PaymentDataRawResponse` | the payment data as a raw response |
| `PPC-GPayTransactionInfo` | the transaction information for Google Pay |
| `PPC-GPayExpressOnPaymentDataChangedLink` | the callback address for changed payment data with Google Pay |
| `PPC-APayBrandName` | the brand name stored for Apple Pay |
| `PPC-APayBillingContact` | the billing address for Apple Pay |
| `PPC-APayLineItems` | the order items for Apple Pay |
| `PPC-APayExpressCompleteShippingContactSelectionLink` | the callback address after address selection with Apple Pay |
| `PPC-APayExpressCompleteShippingMethodSelectionLink` | the callback address after shipping method selection with Apple Pay |

> [!NOTE]
>
> These tags are only listed here so that they do not remain puzzling when reading other people's templates. Before they count as a committed interface, they must be confirmed.

## Tags with other prefixes on this topic

The feature spans several prefixes. The other tags are described under their respective prefix.

* **Express Checkout, buttons**: `BT-PPCExpress`, `BT-PPCExpress_cancel`, and `BT-PPCExpress_reload` are described under BT- (Buttons)
* **Express Checkout, states**: `ST-PPCExpress` and the five variants `_allowed`, `_cancel`, `_error`, `_locked`, and `_selected` are described under ST- (Page states)
* **Input fields and links**: `WS-PPCSaveInVault_input`, `WS-PPCSaveInVault_checked`, `WS-PPCVaultManageLink`, as well as `WS-PPCExpressUseDeliveryAddressForBilling_input` and `_checked` are described under WS- (General tags)
* **Message**: `MSG-PPCVault_Notify` is described under MSG- (Messages)

## The tags at a glance

| Tag | Single tag | Range tag | Negative range tag | Loop tag |
| - | - | - | - | - |
| `PPC-UsePayPalCheckout` | – | yes | yes | – |
| `PPC-ClientID(<Zahlungsarten-Code>)` | yes | – | – | – |
| `PPC-MerchantID(<Zahlungsarten-Code>)` | yes | – | – | – |
| `PPC-ClientToken` | yes | – | – | – |
| `PPC-Intent` | yes | – | – | – |
| `PPC-IntegrationDate` | yes | – | – | – |
| `PPC-Sandbox` | – | yes | yes | – |
| `PPC-OnApproveLink` | yes | – | – | – |
| `PPC-OnCancelLink` | yes | – | – | – |
| `PPC-OnErrorLink` | yes | – | – | – |
| `PPC-PendingLink` | yes | – | – | – |
| `PPC-PayPalErrorCode(<Code>)` | yes | yes | yes | – |
| `PPC-Vaulted` | – | yes | yes | – |
| `PPC-VaultedPayment` | – | yes | yes | – |
| `PPC-VaultedEmailAddress` | yes | yes | yes | – |
| `PPC-UserIDToken` | yes | yes | yes | – |
| `PPC-VaultOverview` | – | yes | yes | – |
| `PPC-VaultConfirmDelete` | – | yes | yes | – |
| `PPC-DeleteVaultConfirm` | yes | – | – | – |
| `PPC-DeleteVaultNoConfirm` | yes | – | – | – |
| `PPC-CreateSetupTokenLink` | yes | – | – | – |
| `PPC-CreatePaymentTokenLink` | yes | – | – | – |
| `PPC-CreateOrderRawResponse` | yes | yes | yes | – |
| `PPC-OrderDetailsRawResponse` | yes | yes | yes | – |
| `PPC-CaptureAuthorizeRawResponse` | yes | yes | yes | – |

All tags are permitted on all templates. The tags related to managing the saved account only return meaningful values on the `PPCVaultManage` template.

## Related topics

* Guide: PayPal Checkout
* Reference: PAY- (Displaying and selecting payment methods)
* Reference: EJD- (JSON interface)
* Materials: Payment method codes


## Related topics

- [PPP- (PayPal PLUS)](https://dokumentation.websale.de/en/v8s/referenz/tags/ppp-paypal-plus.md)
- [$wsPayPalCheckout - PayPal](https://dokumentation.websale.de/en/frontend/referenz/module/wspaypalcheckout.md)
- [PAYPALEXPRESS- (PayPal Express Checkout)](https://dokumentation.websale.de/en/v8s/referenz/tags/paypalexpress.md)
- [Buttons for payment methods](https://dokumentation.websale.de/en/v8s/referenz/tags/bt/zahlungsarten.md)
- [checkout - Order flow](https://dokumentation.websale.de/en/konfiguration/checkout-bestellablauf.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.