# Accept Sofort payments (/limited-release/apm/sofort)



> **Warning:** **\*** &#x2A;*Important:** Sofort will be sunset on April 18, 2024. PayPal will not support Sofort payments starting April 19, 2024. Offer your users PayPal wallet and other alternative payment methods. [Learn more](https://www.paypal.com/us/cshelp/article/sofort-deprecation-help1145).

Sofort is a payment method in Europe.

| Countries                                                                                            | Payment type  | Payment flow | Currencies | Minimum amount | Maximum amount | Refunds         |
| ---------------------------------------------------------------------------------------------------- | ------------- | ------------ | ---------- | -------------- | -------------- | --------------- |
| Austria (`AT`) <br />Belgium (`BE`) <br />Germany (`DE`) <br />Spain (`ES`) <br />Netherlands (`NL`) | bank redirect | redirect     | `EUR`      | 1 `EUR`        | 5000 `EUR`     | Within 180 days |
| United Kingdom (`GB` only)                                                                           |               |              | `GBP`      |                | 5000 `GB`      |                 |

## How it works [#how-it-works]

<img src="https://www.paypalobjects.com/ppdevdocs/img/docs/apm/unbranded-flow.svg" alt="Alternative,payment,methods,diagram" />

1. Your checkout page offers alternative payment methods.
2. The buyer enters their personal details and selects an alternative payment method from your checkout page.
3. The buyer is redirected to their selected issuing bank to confirm the purchase.
4. The buyer authorizes and completes the payment.
5. The buyer returns to your website to see the confirmation of the purchase.
6. The merchant completes the payment process. PayPal transfers the funds to the merchant, and the transaction shows up in your PayPal account with the buyer's chosen payment method.

## Eligibility [#eligibility]

* Available to merchants globally, except in Russia, Japan, and Brazil.
* Billing agreements, multiple seller payments, and shipping callback aren't supported.
* Support for order capture only (order authorize is not supported). See [authorized and captured payments](/api/nvp-soap/paypal-payments-pro/integration-guide/authorizations).
* Chargebacks aren't supported.
* Transaction must be an online purchase (buy online, pay in store is not supported).

## Integrate [#integrate]

There are 2 integration paths you can take:

* **JavaScript SDK:** Merchants can use PayPal-hosted UI components, called payment fields, to collect payment information for alternative payment methods.
* **Orders REST API:** Integrate directly with the Orders API to fully customize the checkout experience.

#### JS SDK

Use the JavaScript SDK to render payment fields and buttons and process payments with Orders API.

### Buyer experience [#buyer-experience]

<iframe sandbox="allow-scripts allow-same-origin allow-forms" src="https://www.sandbox.paypal.com/altpayfields/examples/sofort" title="Sofort Buyer Experience" frameBorder="0" scrolling="no" />

> **Note:** **Note:** The payment button is disabled in the buyer experience demo. On button click, the user is redirected to their bank to authorize the transaction.

### Know before you code [#know-before-you-code]

* Complete the steps in [Get started](/api/rest/) to get your sandbox account information from the Developer Dashboard:
  * Client ID: Authenticates your account with PayPal and identifies an app in your sandbox.
  * Client Secret: Authorizes an app inyour sandbox. Keep this secret safeand don't share it.
  * Business account credentials
* Make sure the preference for receiving payments in your PayPal business account is set to accept and convert them to the default currency. In your profile, select **Account Settings** > **Payment preferences** > **Block payments** and click **Update** to mark this preference.
* This client-side and server-side integrations uses the following:
  * [PayPal JavaScript SDK](/sdk/js/)
  * [Webhooks Management REST API](/api/webhooks/v1/)
  * [Orders REST API](/api/orders/v2/)
* Make sure you're [subscribed to the following webhook events](/payment-methods/webhooks):
  * `CHECKOUT.ORDER.APPROVED` - Listen for this webhook and then capture the payment.
  * `CHECKOUT.PAYMENT-APPROVAL.REVERSED` - This webhook tells you when an approved order is cancelled and refunded because it wasn't captured within the capture window. Let the payer know about the problem and the reversed order.
* By adding funding sources to your checkout integration, you agree to the [PayPal alternative payment methods agreement](https://www.paypal.com/us/webapps/mpp/ua/apm-tnc). This is in addition to the user agreement applicable to the country in which your business is physically located.
* Request approval to enable iDEAL by visiting these Sandbox and Live links. Replace `MERCHANT-COUNTRY` in the URL with the 2-character [country code](/api/codes/country-region) for the merchant's country of operation:
  * **Sandbox:** `https://www.sandbox.paypal.com/bizsignup/entry?product=ideal&capabilities=IDEAL&country.x=MERCHANT-COUNTRY`
  * **Live:** `https://www.paypal.com/bizsignup/entry?product=ideal&capabilities=IDEAL&country.x=MERCHANT-COUNTRY`

> **Note:** **Note:** The integration steps for implementing alternative payment methods are similar. If you've integrated another alternative payment method before, you can likely reuse that code with adjustments for this payment method.

* Use Postman to explore and test PayPal APIs.

   

Get up and running in GitHub Codespaces

GitHub Codespaces are cloud-based development environments where you can code and test your PayPal integrations. [Learn more](/sandbox-testing/overview)

[Open in Codespaces](https://codespaces.new/paypal-examples/googlepay)

### 1. Add PayPal JavaScript SDK [#1-add-paypal-javascript-sdk]

Add or update the JavaScript SDK script on your web page.

```text lineNumbers
<script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID&components=buttons,payment-fields,marks,funding-eligibility&enable-funding=sofort¤cy=EUR"></script>
```

See the [JS SDK reference](/platforms/checkout/apm/reference/js-sdk-params-payment-fields/) for a list of parameters you pass to the JavaScript SDK.

### 2. Render payment mark [#2-render-payment-mark]

You can use a [mark integration](/v5/checkout/show-payment-method) for payment fields components to present the payment method options to the buyer as radio buttons.

<img src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTM4cHgiIGhlaWdodD0iMzJweCIgdmlld0JveD0iMCAwIDEzOCA0NCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDomI3gyRjsmI3gyRjt3d3cudzMub3JnJiN4MkY7MjAwMCYjeDJGO3N2ZyI+PGcgc3Ryb2tlPSJub25lIiBzdHJva2Utd2lkdGg9IjEiIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0iZXZlbm9kZCI+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTI0LjAwMDAwMCwgLTQzNi4wMDAwMDApIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNC4wMDAwMDAsIDQzNi4wMDAwMDApIj48ZyBzdHJva2Utd2lkdGg9IjEiPjxnIG1hc2s9InVybCgjbWFzay0yKSIgZmlsbC1ydWxlPSJldmVub2RkIiBmaWxsPSIjRUI2RjkzIj48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMTM4IiBoZWlnaHQ9IjQ0Ij48L3JlY3Q+PC9nPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE2LjAwMDAwMCwgNS4wMDAwMDApIiBmaWxsLXJ1bGU9Im5vbnplcm8iIGZpbGw9IiNGRkZGRkYiPjxwYXRoIGQ9Ik04LjU1MTA3MTMzLDI0LjAzODYyNDcgQzkuMjI4Nzk0MTEsMjQuNjg2MTY3MSA5LjI0MzI3NzQ1LDI1Ljc0MjU3NjMgOC41ODM1NDcxMywyNi40MDczOTU3IEw4LjQ1MTEwOTA0LDI2LjU0MjM2MjcgQzcuNzkwODYzNTUsMjcuMTk4MzE3NSA2LjY5ODk3Njk2LDI3LjIxNDQwNjYgNi4wMTIyNDAzMiwyNi41NzIyNTY2IEwyLjE3Mjg5MTA3LDIyLjg3NjgwNTQgQzEuMTE1OTA5MjIsMjEuODQ1ODYxOCAwLjk2NDEwMzMzLDIwLjU3NTQ2MzIgMS42MzY3ODkxNCwxOS45MDQyMzY1IEwxLjc3MTU5MzY2LDE5Ljc2Njg5NjYgQzIuMzI1OTg5NzUsMTkuMjEyNjA2MiAzLjIyOTcwMzA5LDE5LjE1NDEyNTIgMy44NjAxNjQ2NCwxOS42MzYwNjczIEM0LjE1OTkwMTI5LDE5Ljg2NTE5NDMgNC41OTQyNDA2NiwxOS44MTUwNzg0IDQuODMwMjg4NzgsMTkuNTI0MTMwMyBDNS4wNjYzMzY5LDE5LjIzMzE4MjIgNS4wMTQ3MDcxNCwxOC44MTE1NzgxIDQuNzE0OTcwNSwxOC41ODI0NTEyIEMzLjUyODQ0OTcsMTcuNjc1NDQyIDEuODI3NjcyNDEsMTcuNzg1NTAyNiAwLjc3NTY4ODExMSwxOC44MzczNjk4IEwwLjY0MTM3OTMxLDE4Ljk3NDIxNDYgQy0wLjYwNDY5MjMyOCwyMC4yMTc1Mjk0IC0wLjM1NDI4Mjk2NCwyMi4zMTMwOTgzIDEuMTk2ODM5NDgsMjMuODI1OTc4OSBMNS4wNDY1NjgzOSwyNy41MzEzNDI3IEM2LjI4NzI2NDM1LDI4LjY5MTU4MzEgOC4yNDg1NzgzOCwyOC42NjI2ODI4IDkuNDQ1NDk5MjQsMjcuNDczMzk5OSBMOS41ODEzMjMzOSwyNy4zMzUwNDQ3IEMxMC43NjM2NjMzLDI2LjE0MzU5OTkgMTAuNzM3NjQ3NSwyNC4yNDYwMTI1IDkuNTIwMjgwMDIsMjMuMDgyODU2OCBDOS4yNDgzNzk2MiwyMi44MjMwNjQ3IDguODEwOTk2MDUsMjIuODI2NDE3NSA4LjU0MzM1NjQ2LDIzLjA5MDM0NTUgQzguMjc1NzE2ODcsMjMuMzU0MjczNSA4LjI3OTE3MDk0LDIzLjc3ODgzMjUgOC41NTEwNzEzMywyNC4wMzg2MjQ3IFoiPjwvcGF0aD48cGF0aCBkPSJNNi4yNTMxNjEzNyw0LjAwNDYzOTAxIEw3LjgyNDUwMjY1LDE2LjU1ODI4NTEgQzcuODcwNTE5NDQsMTYuOTI1OTE5MSA4LjIxNDg1MjA0LDE3LjE4NzczNTIgOC41OTM1OTEwNCwxNy4xNDMwNjc2IEM4Ljk3MjMzMDAzLDE3LjA5ODQwMDEgOS4yNDIwNTQ2OCwxNi43NjQxNjM3IDkuMTk2MDM3ODksMTYuMzk2NTI5NyBMNy42MTk4MjE2NywzLjgwMzkzNzEgTDcuNjA0MjM4OTgsMy43MjIxODEyIEM3LjMzNTM1NDU3LDIuNjc4MTc5MzcgOC4wMDM3NzE4MywxLjUwNzUxODU4IDguODk0MzEyNTEsMS4zMjMyMjQwNSBDOS4zOTM1MDk0NCwxLjIxOTc3MTA1IDkuOTE0MzkyNywxLjMxNTEyMzIgMTAuMzQwMzE2NywxLjU4Nzg1MTYzIEMxMC43NjYyNDA2LDEuODYwNTgwMDcgMTEuMDYxNTUyMiwyLjI4Nzg1NTMzIDExLjE2MDAwOTcsMi43NzM4MzQ3IEwxMy44OTU5OTE0LDE0LjEzMDQ5MTggQzEzLjk4Mjg4MDcsMTQuNDkxMDk3NSAxNC4zNTQ0Nzc0LDE0LjcxNTA1MzcgMTQuNzI1OTc1NywxNC42MzA3MTIxIEMxNS4wOTc0NzQsMTQuNTQ2MzcwNCAxNS4zMjgxOTUyLDE0LjE4NTY2OTMgMTUuMjQxMzA1OSwxMy44MjUwNjM3IEwxMi41MTA0OTUxLDIuNDkxNzMwMzcgQzEyLjM0NTc1NTcsMS42NzYzODc5MiAxMS44MzYxMjk0LDAuOTM5MDI4NzI3IDExLjEwMTEwMjEsMC40NjgzNzQ3MTYgQzEwLjM2NjA3NDksLTAuMDAyMjc5Mjk0MjEgOS40NjcxNzQxNCwtMC4xNjY4MzA3OCA4LjYwNjAzMzU4LDAuMDExNjMxMDM5NiBDNi45MzEyMDQ3MSwwLjM1ODIzMTQ3NyA1LjgzMDc2OTA4LDIuMjY0NDcwMTUgNi4yNTMxNjEzNyw0LjAwNDYzOTAxIFoiPjwvcGF0aD48cGF0aCBkPSJNMjAuNjk0NjM4NSwxOC43NTYyMTU3IEwyMy44MDE2NjU1LDMuNzA4MDY3NTcgQzI0LjE2Mjc1MjcsMi4wODgyMzU5MSAyMy4xNzEwOTgsMC40NjE5MzAyMzcgMjEuNTI0MzczMywtMC4wMTMxMzgwNTY1IEMxOS42ODA2NjM5LC0wLjQ2NTkyNzM5OCAxNy44MzMxNDUyLDAuNTg4OTgyOTY3IDE3LjM1MTg0MTEsMi4zNDYyMjU2MiBMMTMuOTExOTQ0NSwxMy43OTYzNTkyIEMxMy44MDUxNDA5LDE0LjE1MTg4OTkgMTQuMDE1NDgsMTQuNTI0MTQ3MiAxNC4zODE3NTAxLDE0LjYyNzgxOTMgQzE0Ljc0ODAyMDEsMTQuNzMxNDkxMyAxNS4xMzE1MjIxLDE0LjUyNzMxOTYgMTUuMjM4MzI1NywxNC4xNzE3ODg5IEwxOC42ODI2NTAxLDIuNzA2MjMzMzUgQzE4Ljk3NDAzNTQsMS42NDMxMjgzNSAyMC4wNzU1NDE4LDEuMDE0MTgxNzkgMjEuMTU4MzM2NywxLjI3OTc1MzA5IEMyMi4wODQ5ODQzLDEuNTQ3NjgzNjggMjIuNjU5NjE1NCwyLjQ5MDA3NDA0IDIyLjQ0OTEzMjEsMy40MzQ1MTM5OCBMMTkuMzM5OTU2MSwxOC40OTI2NzMyIEMxOS4yNjQ5ODI2LDE4Ljg1NTc4OTggMTkuNTA3NDYwNSwxOS4yMDkxNSAxOS44ODE1NDU3LDE5LjI4MTkyNTMgQzIwLjI1NTYzMDksMTkuMzU0NzAwNiAyMC42MTk2NjQ5LDE5LjExOTMzMjQgMjAuNjk0NjM4NSwxOC43NTYyMTU3IFoiPjwvcGF0aD48cGF0aCBkPSJNMTIuODY5MTg5MiwzMy4yNTM4ODg5IEM3Ljk0Mzk0NjE1LDMzLjI1Mzg4ODkgMy44MzAyNzAyNywyOS43NDQzMDI1IDMuODMwMjcwMjcsMjQuNzU3MDM3IEMzLjgzMDI3MDI3LDI0LjM4NjY5OTQgMy41MjA5ODM3NCwyNC4wODY0ODE1IDMuMTM5NDU5NDYsMjQuMDg2NDgxNSBDMi43NTc5MzUxOCwyNC4wODY0ODE1IDIuNDQ4NjQ4NjUsMjQuMzg2Njk5NCAyLjQ0ODY0ODY1LDI0Ljc1NzAzNyBDMi40NDg2NDg2NSwzMC41MjYyNTUxIDcuMjE3NzI4NDcsMzQuNTk1IDEyLjg2OTE4OTIsMzQuNTk1IEMxMy4yNTA3MTM1LDM0LjU5NSAxMy41NiwzNC4yOTQ3ODIxIDEzLjU2LDMzLjkyNDQ0NDQgQzEzLjU2LDMzLjU1NDEwNjggMTMuMjUwNzEzNSwzMy4yNTM4ODg5IDEyLjg2OTE4OTIsMzMuMjUzODg4OSBaIj48L3BhdGg+PHBhdGggZD0iTTEwLjQzMjczNSwyMS41MjM5ODUgQzEwLjMyNTI3LDIxLjg5OTc4OTggMTAuMDg0ODQ1NiwyMi4yMjY4MzIyIDkuNzUzNjc4NzMsMjIuNDQ3Njg1NyBMOS42MDU5OTYzLDIyLjU0MzE3NTIgQzguODExMzUxNjIsMjMuMDYyMDIyNiA3LjczNzM3ODI0LDIyLjg2MDc3MSA3LjIwMDQxMTkzLDIyLjA5NDM4MjggTDQuMTgwMDAxMjksMTcuNzI4MDQ1NSBDMy4zNTU5NjQ1OSwxNi41MTMzNzEyIDMuNDYzNzEyMjgsMTUuMjM1Mzg2NiA0LjI1Njg4MDk4LDE0LjcwNjkyNjIgTDQuNDA0ODE0NTEsMTQuNjExMjY5MyBDNS40MjIyMjk0OSwxNC4wMzg4MjI2IDYuMjg2NjY1NTcsMTQuNDczMTM2NCA3LjE3NTMxMjk2LDE1LjcyOTg0MjggTDkuNzAxMDIzMTgsMTkuMzgyMjQzMSBDOS45MTM2NjAyNywxOS42ODk3Mjk3IDEwLjM0MjgzMzQsMTkuNzcxNjc0NiAxMC42NTk2MDgxLDE5LjU2NTI3MjMgQzEwLjk3NjM4MjksMTkuMzU4ODY5OSAxMS4wNjA4MDMxLDE4Ljk0MjI4MDYgMTAuODQ4MTY2LDE4LjYzNDc5NCBMOC4zMTg0MzYyOCwxNC45NzY2NDU4IEM3LjA2OTA2OTk1LDEzLjIwOTc1NDcgNS41MjEwMTU0NiwxMi40MzE5NzQzIDMuNjc0NTIzNTEsMTMuNDczNTY2OSBMMy40ODI3NTMwNSwxMy41OTYxMzgxIEMxLjk5Nzk5OTY1LDE0LjU4NTMwMjcgMS44MjA2NTU3NiwxNi42ODg3NjA4IDMuMDI5NTQxNDIsMTguNDcwNjUxMSBMNi4wNTU2NzQzOCwyMi44NDUyODc5IEM3LjAyMjQ5ODQ0LDI0LjIyNTIxMzggOC45NTE2MzU2OCwyNC41ODY3MTQ0IDEwLjM3NDc1NzksMjMuNjU3NTAyNyBMMTAuNTI4MDU3OCwyMy41NTgzMDYzIEMxMS4xMzQ5MTY0LDIzLjE1MzY3NDkgMTEuNTY5Njg3NiwyMi41NjIyNjgxIDExLjc2NDAyMTgsMjEuODgyNjgxNyBDMTEuODY2MDY1MiwyMS41MjU4MzYxIDExLjY1MDc2OSwyMS4xNTYyNTg2IDExLjI4MzE0NDMsMjEuMDU3MjA3MiBDMTAuOTE1NTE5NiwyMC45NTgxNTU5IDEwLjUzNDc3ODQsMjEuMTY3MTM5NCAxMC40MzI3MzUsMjEuNTIzOTg1IFoiPjwvcGF0aD48cGF0aCBkPSJNMTUuMDA3MTEzMiwyMy43NDUxNDgyIEMxMy41NzE2OTM3LDI0LjUyMzU1OTcgMTIuNjc5MjA2MSwyNS45ODkyNTEyIDEyLjU2ODM3OTMsMjguMjA2MzkxMyBDMTIuNTQ5ODg5MiwyOC41NzYyOTM3IDEyLjg0MzgyMzIsMjguODkwNzA4NiAxMy4yMjQ4OTkxLDI4LjkwODY1NjUgQzEzLjYwNTk3NTEsMjguOTI2NjA0NCAxMy45Mjk4ODc0LDI4LjY0MTI4ODkgMTMuOTQ4Mzc3NCwyOC4yNzEzODY1IEMxNC4wNDg3NDQsMjYuMjYzNTA4MyAxNC44NTI1MDc2LDI1LjE3OTU2MSAxNi4xNTI1MTUsMjQuNzA0NTU1IEMxNi44NDgyMjY4LDI0LjQ1MDM1MDkgMTcuNjA0Njk3OSwyNC4zOTk2Mjc2IDE4LjI3MTEwMzgsMjQuNDY4NDcwNyBDMTguMzYwNjc1OCwyNC40Nzc3MjQgMTguNDIwMTgyMSwyNC40ODYzMzM0IDE4LjQ0NDI0MDIsMjQuNDkwNjg1OCBDMTkuMzMzNzY2MSwyNC42NTE2MTA1IDE5LjYwNDUyMDMsMjMuMzY4NTkzNCAxOC43MjE0NTMxLDIzLjE3NzA2MzUgTDEzLjQwOTAyMDYsMjIuMDI0ODQxMyBDMTAuOTIyNTAzNiwyMS4zNjM4NjIxIDEwLjU0NzIzNjEsMjAuNDcwNDU2MSAxMS4wMDc2MjI3LDE4Ljk4MDgzMDkgQzExLjIwNjQxODcsMTguMzMxNzY2OSAxMS42MTQ3NzE4LDE3Ljk5ODYxNDcgMTIuMjMwNjc3NiwxNy44NjU2ODcgQzEyLjYzNzMxODksMTcuNzc3OTIzOCAxMy4wOTQxMjI2LDE3Ljc4ODgzNjYgMTMuNTI4Mjg0MSwxNy44NjI2ODgyIEMxMy42NTM4MDAzLDE3Ljg4NDAzODcgMTMuNzQyMDczMSwxNy45MDQzMzA4IDEzLjc4MTEzNTIsMTcuOTE1MjI0NCBMMjEuODQ1MTIwOCwxOS43NDMzNjk0IEMyMS44OTg1MjM3LDE5Ljc1MzM0OTYgMjEuOTM2MTUyNSwxOS43NjM0NzkgMjIuMDAyMDE1NCwxOS43OTI0NDk0IEMyMi4xMzU0MDAyLDE5Ljg1MTEyMDEgMjIuMjc0MjY3OCwxOS45NDUzODI5IDIyLjQwOTcyNDcsMjAuMDg1ODc4OSBDMjIuOTUwMjkwNSwyMC42NDY1NTQzIDIzLjI0ODU1MDksMjEuNzA0MTk1OSAyMy4wOTc1OCwyMy40NDE0MTI3IEMyMi41NzE2MTQsMjkuNTMxNDczNSAxOS42NDgzMDA1LDMzLjMxMzA0MDYgMTIuNzE5NTg2MywzMy4yNTM5MTQ4IEMxMi4zMzgwNzY4LDMzLjI1MDY1OTIgMTIuMDI2MDgzMywzMy41NDgyMjY0IDEyLjAyMjcyOTQsMzMuOTE4NTQ5NyBDMTIuMDE5Mzc1NSwzNC4yODg4NzMgMTIuMzI1OTMxMiwzNC41OTE3MTg1IDEyLjcwNzQ0MDcsMzQuNTk0OTc0MSBDMjAuNDk0NDAyOSwzNC42NjE0MjM3IDIzLjg5NDk0NTcsMzAuMjYyNTE4IDI0LjQ3NDM0MiwyMy41NTM3OTU1IEMyNC42NTU4MjE0LDIxLjQ2NTUyMTQgMjQuMjUyMTc4OCwyMC4wMzQxOTE1IDIzLjQxODQ5MjIsMTkuMTY5NDkwOSBDMjIuOTU4ODExOSwxOC42OTI3MSAyMi40NzM3MjA0LDE4LjQ3OTMzNzYgMjIuMTAxNTk3NCwxOC40MjY3OTc3IEwxNC4xMjg5MzMzLDE2LjYxNzc0MTcgQzE0LjA3ODgyMDgsMTYuNjAyODc5MSAxMy45NDM0NjUxLDE2LjU3MTc2MzcgMTMuNzY2NzY1MiwxNi41NDE3MDY3IEMxMy4xNjkxMzIsMTYuNDQwMDQ4MyAxMi41NDAxOTgzLDE2LjQyNTAyMzQgMTEuOTMwODA1MSwxNi41NTY1NDU1IEMxMC44NDkzNjI1LDE2Ljc4OTk0NzUgMTAuMDMzMzU3OSwxNy40NTU2Nzk2IDkuNjgzNzc4NjcsMTguNTk3MDU5OCBDOS4wMTkxMzQzLDIwLjc0NzU3MzcgOS43Mjg4OTc4NSwyMi40MzczMjA2IDEzLjA3NjExMzQsMjMuMzI2MDU0MyBMMTUuMDA3MTEzMiwyMy43NDUxNDgyIFoiPjwvcGF0aD48L2c+PC9nPjxwYXRoIGQ9Ik02MC43MiwzMC4yODYgQzYzLjcxMiwzMC4yODYgNjYsMjguMjg0IDY2LDI1LjMzNiBDNjYsMjIuNjA4IDY0LjA2NCwyMS40MiA2MS42ODgsMjAuNzE2IEM2MC4xNywyMC4yNzYgNTkuMjI0LDE5Ljk0NiA1OS4yMjQsMTguODY4IEM1OS4yMjQsMTcuOTY2IDU5Ljg4NCwxNy4yNjIgNjAuOTE4LDE3LjI2MiBDNjEuNzk4LDE3LjI2MiA2Mi40NTgsMTcuNzY4IDYyLjkyLDE4LjUzOCBMNjUuNDA2LDE2Ljk3NiBDNjQuNjM2LDE1LjI2IDYyLjg5OCwxNC4zOCA2MS4wMDYsMTQuMzggQzU4LjAxNCwxNC4zOCA1Ni4xMjIsMTYuNTM2IDU2LjEyMiwxOS4wMjIgQzU2LjEyMiwyMS4wMDIgNTcuMzEsMjIuNTQyIDYwLjI1OCwyMy40IEM2MS44NjQsMjMuODYyIDYyLjg3NiwyNC4xNyA2Mi44NzYsMjUuNDQ2IEM2Mi44NzYsMjYuNjM0IDYyLjAxOCwyNy4zODIgNjAuNzY0LDI3LjM4MiBDNTkuNDIyLDI3LjM4MiA1OC40MSwyNi41MjQgNTcuNzk0LDI1LjczMiBMNTUuNzI2LDI3LjgyMiBDNTYuODI2LDI5LjMxOCA1OC42MywzMC4yODYgNjAuNzIsMzAuMjg2IFogTTczLjU0NiwzMC4yODYgQzcwLjM3OCwzMC4yODYgNjcuODA0LDI3Ljc1NiA2Ny44MDQsMjQuNjc2IEM2Ny44MDQsMjEuNTk2IDcwLjM3OCwxOS4wNjYgNzMuNTQ2LDE5LjA2NiBDNzYuNzE0LDE5LjA2NiA3OS4yODgsMjEuNTk2IDc5LjI4OCwyNC42NzYgQzc5LjI4OCwyNy43NTYgNzYuNzE0LDMwLjI4NiA3My41NDYsMzAuMjg2IFogTTczLjU0NiwyNy40NyBDNzUuMDg2LDI3LjQ3IDc2LjI5NiwyNi4yNiA3Ni4yOTYsMjQuNjc2IEM3Ni4yOTYsMjMuMDkyIDc1LjA4NiwyMS44ODIgNzMuNTQ2LDIxLjg4MiBDNzIuMDA2LDIxLjg4MiA3MC43OTYsMjMuMDkyIDcwLjc5NiwyNC42NzYgQzcwLjc5NiwyNi4yNiA3Mi4wMDYsMjcuNDcgNzMuNTQ2LDI3LjQ3IFogTTg3LjQyOCwxNy40MTYgTDg3LjQyOCwxNC42IEw4Ni45ODgsMTQuNiBDODMuMzM2LDE0LjYgODEuNTU0LDE3LjAyIDgxLjU1NCwxOS44OCBMODEuNTU0LDMwIEw4NC41NDYsMzAgTDg0LjU0NiwyNS41NTYgQzg0LjU0NiwyNC4wODIgODUuNjksMjMuMDI2IDg3LjM0LDIyLjk4MiBMODcuMzQsMjAuMTIyIEM4Ni4xNTIsMjAuMTIyIDg1LjIwNiwyMC40NzQgODQuNTQ2LDIxLjE3OCBMODQuNTQ2LDIwLjAzNCBDODQuNTQ2LDE4LjE4NiA4NS43NTYsMTcuMzUgODcuNDI4LDE3LjQxNiBaIE05NS4wMTgsMzAuMjg2IEM5MS44NSwzMC4yODYgODkuMjc2LDI3Ljc1NiA4OS4yNzYsMjQuNjc2IEM4OS4yNzYsMjEuNTk2IDkxLjg1LDE5LjA2NiA5NS4wMTgsMTkuMDY2IEM5OC4xODYsMTkuMDY2IDEwMC43NiwyMS41OTYgMTAwLjc2LDI0LjY3NiBDMTAwLjc2LDI3Ljc1NiA5OC4xODYsMzAuMjg2IDk1LjAxOCwzMC4yODYgWiBNOTUuMDE4LDI3LjQ3IEM5Ni41NTgsMjcuNDcgOTcuNzY4LDI2LjI2IDk3Ljc2OCwyNC42NzYgQzk3Ljc2OCwyMy4wOTIgOTYuNTU4LDIxLjg4MiA5NS4wMTgsMjEuODgyIEM5My40NzgsMjEuODgyIDkyLjI2OCwyMy4wOTIgOTIuMjY4LDI0LjY3NiBDOTIuMjY4LDI2LjI2IDkzLjQ3OCwyNy40NyA5NS4wMTgsMjcuNDcgWiBNMTA2LjAxOCwyMC41NjIgTDEwNi4wMTgsMTkuMzUyIEwxMDMuMTE0LDE5LjM1MiBMMTAzLjExNCwzMCBMMTA2LjEwNiwzMCBMMTA2LjEwNiwyNS4xMzggQzEwNi4xMDYsMjMuMzc4IDEwNy4xNCwyMi4zODggMTA4Ljk0NCwyMi4zODggTDEwOC45NDQsMTkuMTc2IEMxMDcuNTgsMTkuMTMyIDEwNi42MTIsMTkuNTk0IDEwNi4wMTgsMjAuNTYyIFogTTExNC4zNzgsMjQuNTY2IEwxMTQuMzc4LDIxLjk3IEMxMTUuMDM4LDIyLjY3NCAxMTUuOTg0LDIzLjAyNiAxMTcuMTcyLDIzLjAyNiBMMTE3LjE3MiwyMC4xNjYgQzExNS41NDQsMjAuMTIyIDExNC4zNzgsMTkuMDQ0IDExNC4zNzgsMTcuNTkyIEwxMTQuMzc4LDE1LjkyIEwxMTEuMzg2LDE1LjkyIEwxMTEuMzg2LDI0LjcyIEMxMTEuMzg2LDI3LjU4IDExMy4xNjgsMzAgMTE2LjgyLDMwIEwxMTcuMjYsMzAgTDExNy4yNiwyNy4xODQgQzExNS41ODgsMjcuMjUgMTE0LjM3OCwyNi40MTQgMTE0LjM3OCwyNC41NjYgWiBNMTIxLjU3MiwzMC4xNzYgQzEyMi42NzIsMzAuMTc2IDEyMy41NzQsMjkuMjc0IDEyMy41NzQsMjguMTc0IEMxMjMuNTc0LDI3LjA3NCAxMjIuNjcyLDI2LjE3MiAxMjEuNTcyLDI2LjE3MiBDMTIwLjQ3MiwyNi4xNzIgMTE5LjU3LDI3LjA3NCAxMTkuNTcsMjguMTc0IEMxMTkuNTcsMjkuMjc0IDEyMC40NzIsMzAuMTc2IDEyMS41NzIsMzAuMTc2IFoiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD48L2c+PC9nPjwvZz48L3N2Zz4" alt="Sofort,Mark" />

```text lineNumbers
const sofortButton = paypal.Buttons({
  fundingSource: paypal.FUNDING.SOFORT
});
```

You can also [render a set of eligible payment methods](/platforms/checkout/standard/customize/standalone-buttons/).

### 3. Render payment fields [#3-render-payment-fields]

Use payment fields to collect payment information from buyers. Fields dynamically render based on the selected funding source and you can customize the fields to align with your brand.

Choose from a single page checkout flow or a multi-page checkout flow.

### Single page [#single-page]

For Sofort, payment fields country, first name, and last name.

<iframe sandbox="allow-scripts allow-same-origin allow-forms" src="https://www.sandbox.paypal.com/altpayfields/?fundingSource=sofort" width="600" height="150" title="Sofort Buyer Experience" frameBorder="0" scrolling="no" />

If there are validation errors in the input fields, they'll show on the click of the button.

```text lineNumbers
paypal.PaymentFields({
  fundingSource: paypal.FUNDING.SOFORT,
  /* style object (optional) */
  style: {
    /* customize field attributes (optional) */
    variables: {},
    /* set custom rules to apply to fields classes (optional) */
    rules: {},
  },
  fields: {
    /* fields prefill info (optional) */
    name: {
      value: "John Doe",
    },
  }
})
.render("#sofort-container");
```

### Multi-page [#multi-page]

A multi-page checkout flow spreads the checkout steps into two or more pages. This experience is applicable when an order details page needs to be shown to the buyer before an order is placed.

> **Note:** **Tip:** German merchants can leverage the multi-page flow to comply with local regulations.

### First page of the checkout flow [#first-page-of-the-checkout-flow]

This example renders the mark and payment fields, but not the payment button, on your checkout page.

<img src="https://www.paypalobjects.com/images/checkout/altpayfields/Multipage_1_temp.png" alt="Multipage,Flow,Page,1" />

```text lineNumbers
paypal.Marks({
    fundingSource: paypal.FUNDING.SOFORT
}).render('#sofort-mark')
```

```text lineNumbers
paypal.PaymentFields({
  fundingSource: paypal.FUNDING.SOFORT,
  /* style object (optional) */
  style: {
    /* customize field attributes (optional) */
    variables: {},
    /* set custom rules to apply to fields classes (optional) */
    rules: {},
  },
  onInit: (data, actions) => {
    const form = document.querySelector("form.paypal-payment-form");

    form.addEventListener("submit", (e) => {
      const formData = new FormData(form);
      const paymentSource = formData.get("payment-option");

      if (paymentSource === paypal.FUNDING.SOFORT) {
        e.preventDefault();

        actions.validate().then((valid) => {
          if (valid) {
            window.location.href = `/second-page.html?payment-option=${paypal.FUNDING.SOFORT}`;
          }
        });
      }
    });
  },
  fields: {
     /* fields prefill info (optional) */
    name: {
      value: "John Doe",
    },
  },
})
.render("#sofort-container");
```

### Second page of the checkout flow [#second-page-of-the-checkout-flow]

Based on the payment method selected on the first page, this example renders only the payment button along with the order details on the page. To complete checkout, the buyer clicks the payment button, authorizes, and confirms payment. You get the code to render the payment button in step 4.

<img src="https://www.paypalobjects.com/images/checkout/altpayfields/Multipage_2_temp.png" alt="Multipage,Flow,Page,2" />

For `style` parameters, please reference this style page: [Custom style for payment fields](/payment-methods/style)

### 4. Render payment button [#4-render-payment-button]

<iframe sandbox="allow-scripts allow-same-origin allow-forms" src="https://www.sandbox.paypal.com/smart/buttons?fundingSource=sofort&style.label=pay&style.layout=horizontal&style.color=silver&style.shape=rect&style.tagline=false&components.0=buttons&components.1=fields&components.2=marks&components.3=funding-eligibility&locale.country=GB&locale.lang=en&sdkMeta=eyJ1cmwiOiJodHRwczovL3d3dy5wYXlwYWwuY29tL3Nkay9qcz9jbGllbnQtaWQ9QWZQYmRVYlY0TEpkSzAtMEIwUVBlVXlIbnpHZ1ZoSXdaZkJPM3dZUm9hemFTWVJKQUlLd3dIbmZJMEViZWtKQjQyRkp1VmktMy12Z3NRdmkmY29tcG9uZW50cz1idXR0b25zLGZpZWxkcyxtYXJrcyxmdW5kaW5nLWVsaWdpYmlsaXR5JmVuYWJsZS1mdW5kaW5nPXNvZm9ydCZjdXJyZW5jeT1FVVIiLCJhdHRycyI6eyJkYXRhLXVpZCI6InVpZF91Y3B6Y2lwcmZ2cmpsem1pc29icnBwbHRheXBsbnoifX0&clientID=AfPbdUbV4LJdK0-0B0QPeUyHnzGgVhIwZfBO3wYRoazaSYRJAIKwwHnfI0EbekJB42FJuVi-3-vgsQvi&sdkCorrelationID=f507013ce04df&storageID=1a5b3406eb_mja6mjm6mtq&sessionID=uid_127fb80639_mji6mte6mzq&buttonSessionID=uid_5e193c344a_mji6mte6mzq&env=sandbox&fundingEligibility=eyJwYXlwYWwiOnsiZWxpZ2libGUiOnRydWUsInZhdWx0YWJsZSI6dHJ1ZX0sInBheWxhdGVyIjp7ImVsaWdpYmxlIjpmYWxzZSwicHJvZHVjdHMiOnsicGF5SW40Ijp7ImVsaWdpYmxlIjpmYWxzZSwidmFyaWFudCI6bnVsbH0sInBheWxhdGVyIjp7ImVsaWdpYmxlIjpmYWxzZSwidmFyaWFudCI6bnVsbH19fSwiY2FyZCI6eyJlbGlnaWJsZSI6dHJ1ZSwiYnJhbmRlZCI6dHJ1ZSwiaW5zdGFsbG1lbnRzIjpmYWxzZSwidmVuZG9ycyI6eyJ2aXNhIjp7ImVsaWdpYmxlIjp0cnVlLCJ2YXVsdGFibGUiOnRydWV9LCJtYXN0ZXJjYXJkIjp7ImVsaWdpYmxlIjp0cnVlLCJ2YXVsdGFibGUiOnRydWV9LCJhbWV4Ijp7ImVsaWdpYmxlIjp0cnVlLCJ2YXVsdGFibGUiOnRydWV9LCJkaXNjb3ZlciI6eyJlbGlnaWJsZSI6dHJ1ZSwidmF1bHRhYmxlIjp0cnVlfSwiaGlwZXIiOnsiZWxpZ2libGUiOmZhbHNlLCJ2YXVsdGFibGUiOmZhbHNlfSwiZWxvIjp7ImVsaWdpYmxlIjpmYWxzZSwidmF1bHRhYmxlIjp0cnVlfSwiamNiIjp7ImVsaWdpYmxlIjpmYWxzZSwidmF1bHRhYmxlIjp0cnVlfX19LCJ2ZW5tbyI6eyJlbGlnaWJsZSI6ZmFsc2V9LCJpdGF1Ijp7ImVsaWdpYmxlIjpmYWxzZX0sImNyZWRpdCI6eyJlbGlnaWJsZSI6ZmFsc2V9LCJhcHBsZXBheSI6eyJlbGlnaWJsZSI6ZmFsc2V9LCJzZXBhIjp7ImVsaWdpYmxlIjpmYWxzZX0sImlkZWFsIjp7ImVsaWdpYmxlIjpmYWxzZX0sImJhbmNvbnRhY3QiOnsiZWxpZ2libGUiOmZhbHNlfSwiZ2lyb3BheSI6eyJlbGlnaWJsZSI6ZmFsc2V9LCJlcHMiOnsiZWxpZ2libGUiOmZhbHNlfSwic29mb3J0Ijp7ImVsaWdpYmxlIjp0cnVlfSwibXliYW5rIjp7ImVsaWdpYmxlIjpmYWxzZX0sInAyNCI6eyJlbGlnaWJsZSI6ZmFsc2V9LCJ6aW1wbGVyIjp7ImVsaWdpYmxlIjpmYWxzZX0sIndlY2hhdHBheSI6eyJlbGlnaWJsZSI6ZmFsc2V9LCJwYXl1Ijp7ImVsaWdpYmxlIjpmYWxzZX0sImJsaWsiOnsiZWxpZ2libGUiOmZhbHNlfSwidHJ1c3RseSI6eyJlbGlnaWJsZSI6ZmFsc2V9LCJveHhvIjp7ImVsaWdpYmxlIjpmYWxzZX0sIm1heGltYSI6eyJlbGlnaWJsZSI6ZmFsc2V9LCJib2xldG8iOnsiZWxpZ2libGUiOmZhbHNlfSwibWVyY2Fkb3BhZ28iOnsiZWxpZ2libGUiOmZhbHNlfX0&platform=desktop&experiment.enableVenmo=false&experiment.disablePaylater=false&flow=purchase&currency=EUR&intent=capture&commit=true&vault=false&enableFunding.0=sofort&renderedButtons.0=sofort&debug=false&applePaySupport=false&supportsPopups=true&supportedNativeBrowser=false" width="500" height="55" title="Sofort Button" frameBorder="0" scrolling="no" />

```text lineNumbers
paypal.Buttons({
fundingSource: paypal.FUNDING.SOFORT,
  style: {
    label: "pay",
  },
  createOrder() {
    return fetch("/my-server/create-paypal-order", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      // use the "body" param to optionally pass additional order information
      // like product skus and quantities
      body: JSON.stringify({
        cart: [
          {
            sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT",
            quantity: "YOUR_PRODUCT_QUANTITY",
          },
        ],
      }),
    })
    .then((response) => response.json())
    .then((order) => order.id);
  },
   onApprove(data) {
    return fetch("/my-server/capture-paypal-order", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        orderID: data.orderID
      })
    })
    .then((response) => response.json())
    .then((orderData) => {
      // Successful capture! For dev/demo purposes:
      console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
      const transaction = orderData.purchase_units[0].payments.captures[0];
      console.log('Transaction Status:',  transaction.status);
      console.log('Transaction ID:', transaction.id);
      // When ready to go live, remove the alert and show a success message within this page. For example:
      // const element = document.getElementById('paypal-button-container');
      // element.innerHTML = '<h3>Thank you for your payment!</h3>';
      // Or go to another URL:  window.location.href = 'thank_you.html';
    });
  },
  onCancel(data, actions) {
    console.log(`Order Canceled - ID: ${data.orderID}`);
  },
  onError(err) {
    console.error(err);
  }
})
.render("#sofort-btn");
```

* `createOrder`

  Implement the `createOrder` function to allow the JavaScript SDK to submit buyer information and set up the transaction on the click of the button.

  > **Note:** **Note:** Create Sofort orders in EUR/GBP currency.

  Use your server-side [Create order](/api/orders/v2/orders-create) call to set up the details of a one-time transaction including the amount, line item detail, and more.

  If order creation fails, the Orders API can [return an error](/api/orders/v2/error-messages) in the console.

  After order creation, orders are confirmed with buyer selected payment source. If the order cannot be processed with the selected payment source, the relevant errors are returned in the console.
* `onCancel`

  Implement the optional `onCancel()` function to show a cancellation page or return to the shopping cart.
* `onError`

  Implement the optional `onError()` function to handle errors and display generic error message or page to the buyers. This error handler is a catch-all. Errors at this point are not expected to be handled beyond showing a generic error message or page.

### 5. Capture the transaction [#5-capture-the-transaction]

Implement the `onApprove` function, which is called after the buyer approves the transaction.

Captures the funds from the transaction and shows a message to the buyer to let them know the transaction is successful. The method is called after the buyer approves the transaction on paypal.com.

Because this is a client-side call, PayPal calls the [Orders API](/api/orders/v2/orders-capture) on your behalf, so you don't need to provide the headers and body.

capture() - Promise returning the [order details](/api/orders/v2#orders-capture-response).

```text lineNumbers
paypal.Buttons({
  fundingSource: paypal.FUNDING.SOFORT,
 createOrder() {
    return fetch("/my-server/create-paypal-order", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      // use the "body" param to optionally pass additional order information
      // like product skus and quantities
      body: JSON.stringify({
        cart: [
          {
            sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT",
            quantity: "YOUR_PRODUCT_QUANTITY",
          },
        ],
      }),
    })
    .then((response) => response.json())
    .then((order) => order.id);
  },
  onApprove(data) {
    return fetch("/my-server/capture-paypal-order", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        orderID: data.orderID
      })
    })
    .then((response) => response.json())
    .then((orderData) => {
      // Successful capture! For dev/demo purposes:
      console.log('Capture result', orderData, JSON.stringify(orderData, null, 2));
      const transaction = orderData.purchase_units[0].payments.captures[0];
      console.log('Transaction Status:',  transaction.status);
      console.log('Transaction ID:', transaction.id);
      // When ready to go live, remove the alert and show a success message within this page. For example:
      // const element = document.getElementById('paypal-button-container');
      // element.innerHTML = '<h3>Thank you for your payment!</h3>';
      // Or go to another URL:  window.location.href = 'thank_you.html';
    });
  },
  onCancel(data, actions) {
    console.log(`Order Canceled - ID: ${data.orderID}`);
  },
  onError(err) {
    console.error(err);
  }
})
.render('#sofort-button-container');
//This function displays payment buttons on your web page.
```

For the capture call details and example responses, see [Capture payment for order](/api/orders/v2/orders-capture) in the Orders API reference.

If order capture fails, the Orders API can [return an error](/api/orders/v2/error-messages) in the console.

### 6. Handle webhook events [#6-handle-webhook-events]

A webhook handler is a script you create on your server that completes specific actions on webhooks that hit your listener URL.

* We recommend subscribing to `CHECKOUT.ORDER.APPROVED` webhook event in case a customer accidentally closes the browser and exits the checkout process after approving the transaction through their APM but before finalizing the transaction on your site.
* Listen for the `CHECKOUT.PAYMENT-APPROVAL.REVERSED` webhook as an indication that an approved order wasn't captured within the capture window resulting in a cancellation of the order and a refund the buyer's account. Then notify your buyer of the problem and the reversed order.
* `PAYMENT.CAPTURE.PENDING`, `PAYMENT.CAPTURE.COMPLETED`, and `PAYMENT.CAPTURE.DENIED` webhooks indicate capture status.

See [Subscribe to checkout webhooks](/api/webhooks) for more information.

Here are some additional resources as you create webhook handler code:

* [Webhook Management API](/api/webhooks/v1/) - Manage webhooks, list event notifications, and more.
* Webhook events
  * [Checkout webhook events](/api/rest/webhooks/event-names/#checkout-buyer-approval) - Checkout buyer approval-related webhooks.
  * [Order webhook events](/api/rest/webhooks/event-names/) - Other order-related webhooks.
* [Show order details endpoint](/api/orders/v2/orders-get) - Determine the status of an order.

### Sample integration [#sample-integration]

See a sample Sofort integration in the [PayPal GitHub repository](https://github.com/paypal-examples/sofort-paypal-payment-js-sdk).

#### Orders API

Render payment buttons and process payments with Orders API.

### Know before you code [#know-before-you-code-1]

* Make sure you're [subscribed to the following webhook events](/payment-methods/webhooks):
  * `PAYMENT.CAPTURE.COMPLETED` - Listen for this webhook to get notified about a successful order capture.
  * `PAYMENT.CAPTURE.DENIED` - This webhook tells you when an order capture fails.
* Make sure your preference for receiving payments in your PayPal business or merchant account is set to accept and convert to the currency in your account. In your profile, select **Account Settings** > **Payment preferences** > **Block payments** and click **Update** to mark this preference.
* Request approval to enable iDEAL by visiting these Sandbox and Live links. Replace `MERCHANT-COUNTRY` in the URL with the 2-character [country code](/api/codes/country-region) for the merchant's country of operation:
  * **Sandbox:** `https://www.sandbox.paypal.com/bizsignup/entry?product=ideal&capabilities=IDEAL&country.x=MERCHANT-COUNTRY`
  * **Live:** `https://www.paypal.com/bizsignup/entry?product=ideal&capabilities=IDEAL&country.x=MERCHANT-COUNTRY`

> **Note:** **Note:** The integration steps for implementing alternative payment methods using the Orders v2 REST API are similar. If you've integrated another alternative payment method before, you can likely reuse that code with adjustments for this payment method.

* When processing Sofort payments, capture payment for order is not required.

### 1. Offer Sofort on your checkout page [#1-offer-sofort-on-your-checkout-page]

You'll need to create the user interface to offer Sofort and collect the buyer's information, then you'll use the API calls described in the remainder of this topic to:

* Create the order with Sofort as the payment source and buyer's `full_name` and `country_code`.
* Redirect the buyer to Sofort.

Refer to [Payment method icons](/platforms/checkout/apm/reference/method-icons/) for icons you can use and download locations.

### 2. Create an order with Sofort as the payment source [#2-create-an-order-with-sofort-as-the-payment-source]

Use the buyer information you captured from your user interface to create an order with Sofort as the payment source.

#### Sample request [#sample-request]

API endpoint used: [Create order](/api/orders/v2/orders-create)

```text lineNumbers
curl -v -k -X POST 'https://api-m.sandbox.paypal.com/v2/checkout/orders' \
 -H 'PayPal-Request-Id: <PayPal-Request-Id>' \
 -H 'Authorization: Bearer <Access-Token>' \
 -H 'Content-Type: application/json' \
 -d '{
    "intent": "CAPTURE",
    "purchase_units": [
        {
            "reference_id": "d9f80740-38f0-11e8-b467-0ed5f89f718b",
            "amount": {
                "currency_code": "EUR",
                "value": "1.00"
            }
        }
    ],
    "payment_source": {
        "sofort": {
            "country_code": "DE",
            "name": "John Doe",
            "email": "john.doe@example.com"
        }
    },
    "processing_instruction": "ORDER_COMPLETE_ON_PAYMENT_APPROVAL",
    "application_context": {
        "locale": "en-DE",
        "return_url": "https://example.com/returnUrl",
        "cancel_url": "https://example.com/cancelUrl"
    }
}'
```

#### Modify the code [#modify-the-code]

After you copy the code in the sample request, modify the following:

* `Access-Token` - Your [access token](/api/rest/authentication).
* `PayPal-Request-Id` - Replace the sample ID with a unique ID you generate. This ID helps prevent duplicate authorizations in the event that the API call is disrupted. See also: [API idempotency](/reference/guidelines/idempotency/)
* `intent` - To use an alternative payment method, this parameter must be set to `CAPTURE` as it is in this sample code.
* `payment_source` - Specify `sofort` as the payment method and include the country code and account holder's full name.
* `purchase_units: amount` - Pass the amount of the order and the currency code.
* `processing_instruction` - Set this value to `ORDER_COMPLETE_ON_PAYMENT_APPROVAL` as it is in this sample code.
* `application_context` - Specify the preferred language for returned errors, the URL the buyer is returned to after approving the purchase with their selected payment method, and the URL the buyer is returned to after canceling an approval with their selected payment method. While `return_url` and `cancel_url` are optional fields, this integration requires you specify them to handle the handoff from the payment method back to your site. You can use the `cancel_url` to redirect buyers when an error occurs while they're on the payment method's site, so make sure your cancel URL works for that situation as well as an actual cancellation by the buyer.

> **Note:** **Note:** Change or add other parameters in the [Create order request body](/api/orders/v2/orders-create) to create an order that reflects the actual order details.

#### Step result [#step-result]

A successful request results in the following:

* A return status code of HTTP `200 OK`.
* A JSON response body that contains the order ID. You'll use the order ID and `payer-action` HATEOAS URL in the next step. See also: [HATEOAS links](/api/rest/responses/#hateoas-links).

##### Sample response [#sample-response]

```text lineNumbers
{
  "id": "5KP92830L1747245S",
  "intent": "CAPTURE",
  "status": "PAYER_ACTION_REQUIRED",
  "payment_source": {
    "sofort": {
      "name": "John Doe",
      "country_code": "DE"
    }
  },
  "links": [
    {
      "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5KP92830L1747245S",
      "rel": "self",
      "method": "GET"
    },
    {
      "href": "https://www.sandbox.paypal.com/payment/sofort?token=5KP92830L1747245S",
      "rel": "payer-action",
      "method": "GET"
    }
  ]
}
```

### 3. Redirect buyer to issuing bank's website or app to approve the purchase [#3-redirect-buyer-to-issuing-banks-website-or-app-to-approve-the-purchase]

In your user interface, attach the `payer-action` redirect URL returned in the `Create Order` response to the Sofort payment button. This sends the buyer to their bank to approve the purchase. Once the buyer approves the purchase, the payment is automatically captured.

In the sample, the redirect URL is: `"https://sandbox.paypal.com/payment/sofort?token=5KP92830L1747245S"`.

#### Step result [#step-result-1]

After successfully completing the bank approval:

* The buyer is redirected to the `return_url` mentioned in the Create Order request.
* The `PAYMENT.CAPTURE.COMPLETED` webhook event is triggered, which indicates that payment capture was successful.

After unsuccessful bank approval:

* The buyer is redirected to the `cancel_url` mentioned in the Create Order request.

### 4. Listen to webhooks to get the result of payment status [#4-listen-to-webhooks-to-get-the-result-of-payment-status]

Listen to the following webhooks to get the result of order capture:

* The `PAYMENT.CAPTURE.COMPLETED` webhook event indicates a successful order capture.
* The `PAYMENT.CAPTURE.DENIED` webhook events indicate a failed order capture.
* Optional: Use [Show order details](/api/orders/v2/orders-get) endpoint to determine the status of an order.
  * The `up` HATEOAS link indicates the order associated with this capture.

See [Subscribe to checkout webhooks](/payment-methods/webhooks) for more information.

Here are some additional resources as you create webhook handler code:

* [Webhook Management API](/api/webhooks/v1) - Manage webhooks, list event notifications, and more.
* Webhook events
  * [Checkout webhook events](/api/rest/webhooks/event-names/#checkout-buyer-approval) - Checkout buyer approval-related webhooks.
  * [Order webhook events](/api/rest/webhooks/event-names/) - Other order-related webhooks.
* [Show order details endpoint](/api/orders/v2/orders-get) - Determine the status of an order.

### Sample PAYMENT.CAPTURE.COMPLETED webhook [#sample-paymentcapturecompleted-webhook]

```text lineNumbers
{
  "id": "WH-2B342482FC0449155-12X09416XP387753C",
  "event_version": "1.0",
  "zts": 1481046241,
  "create_time": "2022-04-08T10:37:05Z",
  "resource_type": "capture",
  "resource_version": "2.0",
  "event_type": "PAYMENT.CAPTURE.COMPLETED",
  "summary": "Payment completed for EUR 1.00 EUR",
  "resource": {
    "amount": {
      "value": "1.00",
      "currency_code": "EUR"
    },
    "create_time": "2022-04-08T10:37:05Z",
    "update_time": "2022-04-08T10:37:05Z",
    "final_capture": true,
    "seller_receivable_breakdown": {
      "paypal_fee": {
        "value": "0.20",
        "currency_code": "EUR"
      },
      "gross_amount": {
        "value": "1.00",
        "currency_code": "EUR"
      },
      "net_amount": {
        "value": "0.80",
        "currency_code": "EUR"
      }
    },
    "links": [
      {
        "method": "GET",
        "rel": "self",
        "href": "https://api-m.sandbox.paypal.com/v2/payments/captures/8SS60826HT082593F"
      },
      {
        "method": "POST",
        "rel": "refund",
        "href": "https://api-m.sandbox.paypal.com/v2/payments/captures/8SS60826HT082593F/refund"
      },
      {
        "method": "GET",
        "rel": "up",
        "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5KP92830L1747245S"
      }
    ],
    "id": "8SS60826HT082593F",
    "status": "COMPLETED"
  },
  "links": [
    {
      "href": "https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-2B342482FC0449155-12X09416XP387753C",
      "rel": "self",
      "method": "GET"
    },
    {
      "href": "https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-2B342482FC0449155-12X09416XP387753C/resend",
      "rel": "resend",
      "method": "POST"
    }
  ]
}
```

> **Note:** **Note:** order ID from **Step 2** should match `resource.supplementary_data.related_ids.order_id` parameter in the webhook payload.

### Sample PAYMENT.CAPTURE.DENIED webhook [#sample-paymentcapturedenied-webhook]

```text lineNumbers
{
  "id": "WH-2B342482FC0449155-12X09416XP387753C",
  "event_version": "1.0",
  "create_time": "2022-04-08T10:37:05Z",
  "resource_type": "capture",
  "resource_version": "2.0",
  "event_type": "PAYMENT.CAPTURE.DENIED",
  "summary": "Payment denied for EUR 1.00 EUR",
  "resource": {
    "amount": {
      "value": "1.00",
      "currency_code": "EUR"
    },
    "supplementary_data": {
      "related_ids": {
        "order_id": "5KP92830L1747245S"
      }
    },
    "create_time": "2022-04-08T10:37:05Z",
    "update_time": "2022-04-08T10:37:05Z",
    "final_capture": true,
    "seller_receivable_breakdown": {
      "paypal_fee": {
        "value": "0.20",
        "currency_code": "EUR"
      },
      "gross_amount": {
        "value": "1.00",
        "currency_code": "EUR"
      },
      "net_amount": {
        "value": "0.80",
        "currency_code": "EUR"
      }
    },
    "links": [
      {
        "method": "GET",
        "rel": "self",
        "href": "https://api-m.sandbox.paypal.com/v2/payments/captures/8SS60826HT082593F"
      },
      {
        "method": "POST",
        "rel": "refund",
        "href": "https://api-m.sandbox.paypal.com/v2/payments/captures/8SS60826HT082593F/refund"
      },
      {
        "method": "GET",
        "rel": "up",
        "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5KP92830L1747245S"
      }
    ],
    "id": "8SS60826HT082593F",
    "status": "DECLINED"
  },
  "links": [
    {
      "href": "https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-2B342482FC0449155-12X09416XP387753C",
      "rel": "self",
      "method": "GET"
    },
    {
      "href": "https://api-m.sandbox.paypal.com/v1/notifications/webhooks-events/WH-2B342482FC0449155-12X09416XP387753C/resend",
      "rel": "resend",
      "method": "POST"
    }
  ]
}
```

> **Note:** **Note:** order ID from **Step 2** should match `resource.supplementary_data.related_ids.order_id` parameter in the webhook payload.

Alternatively, you can get the order capture result from the [Show order details](/api/orders/v2/orders-get) endpoint.

> **Note:** **Important:** Exercise caution when polling for order capture result using the [Show order details](/api/orders/v2/orders-get) endpoint. PayPal enforces rate limits on API requests.

### Sample request [#sample-request-1]

```text lineNumbers
curl -v -X GET https://api-m.sandbox.paypal.com/v2/checkout/orders/5KP92830L1747245S \
 -H "Content-Type: application/json" \
 -H "Authorization: Bearer <Access-Token>"
```

### Sample response [#sample-response-1]

```text lineNumbers
{
  "id": "5KP92830L1747245S",
  "intent": "CAPTURE",
  "status": "COMPLETED",
  "payment_source": {
    "sofort": {
      "name": "John Doe",
      "country_code": "DE"
    }
  },
  "processing_instruction": "ORDER_COMPLETE_ON_PAYMENT_APPROVAL",
  "purchase_units": [
    {
      "reference_id": "default",
      "amount": {
        "currency_code": "EUR",
        "value": "1.00"
      },
      "payments": {
        "captures": [
          {
            "id": "8SS60826HT082593F",
            "status": "COMPLETED",
            "amount": {
              "currency_code": "EUR",
              "value": "1.00"
            },
            "final_capture": true,
            "seller_receivable_breakdown": {
              "gross_amount": {
                "currency_code": "EUR",
                "value": "1.00"
              },
              "paypal_fee": {
                "currency_code": "EUR",
                "value": "0.20"
              },
              "net_amount": {
                "currency_code": "EUR",
                "value": "0.80"
              }
            },
            "links": [
              {
                "href": "https://api-m.sandbox.paypal.com/v2/payments/captures/8SS60826HT082593F",
                "rel": "self",
                "method": "GET"
              },
              {
                "href": "https://api-m.sandbox.paypal.com/v2/payments/captures/8SS60826HT082593F/refund",
                "rel": "refund",
                "method": "POST"
              },
              {
                "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5KP92830L1747245S",
                "rel": "up",
                "method": "GET"
              }
            ],
            "create_time": "2022-04-08T10:37:05Z",
            "update_time": "2022-04-04T10:37:05Z"
          }
        ]
      }
    }
  ],
  "create_time": "2022-04-08T10:37:05Z",
  "update_time": "2022-04-08T10:37:05Z",
  "links": [
    {
      "href": "https://api-m.sandbox.paypal.com/v2/checkout/orders/5KP92830L1747245S",
      "rel": "self",
      "method": "GET"
    }
  ]
}
```

### Step result [#step-result-2]

A successful request returns the HTTP `200 OK` status code with a JSON response body that returns a `COMPLETED` status.

A successfully captured order has the following:

* The order status as `COMPLETED`, which means the order was captured successfully.
* A capture with `COMPLETED` status is present in the response parameter `purchase_units[0].payments.captures[0]`.
* The `up` HATEOAS link indicates the order associated with this capture.

### 5. Notify buyer of success [#5-notify-buyer-of-success]

After a successful payment, notify the buyer of a successful transaction. You can do this by sending a confirmation email.

## Next steps [#next-steps]

* [Test in PayPal sandbox](/sandbox-testing/overview), then [go live in PayPal's production environment](/api/rest/production/).
