# Accept an EPS payment Learn how to accept EPS, a common payment method in Austria. # Elements > The content of this section refers to a *Legacy* (Technology that's no longer recommended) product. You should use the [Accept a payment](https://docs.stripe.com/payments/accept-a-payment.md) guide for the most recent integration path instead. While Stripe still supports this product, this support might end if the product is deprecated. EPS is a [single use](https://docs.stripe.com/payments/payment-methods.md#usage) payment method where customers are required to [authenticate](https://docs.stripe.com/payments/payment-methods.md#customer-actions) their payment. Customers pay with EPS by redirecting from your website, authorizing the payment, then returning to your website, where you get [immediate notification](https://docs.stripe.com/payments/payment-methods.md#payment-notification) about whether the payment succeeded or failed. > Your use of EPS must be in accordance with the [EPS Terms of Service](https://stripe.com/eps/legal). ## Set up Stripe [Server-side] First, you need a Stripe account. [Register now](https://dashboard.stripe.com/register). Use our official libraries for access to the Stripe API from your application: #### Ruby ```bash # Available as a gem sudo gem install stripe ``` ```ruby # If you use bundler, you can add this line to your Gemfile gem 'stripe' ``` ## Create a PaymentIntent [Server-side] A [PaymentIntent](https://docs.stripe.com/api/payment_intents/object.md) represents your intent to collect payment from a customer and tracks the lifecycle of the payment process. Create a `PaymentIntent` on your server and specify the `amount` to collect, and the `eur` currency (EPS doesn’t support other currencies). [Enable the payment method](https://dashboard.stripe.com/settings/payment_methods) in your Dashboard. Stripe displays eligible payment methods to customers automatically. ```curl curl https://api.stripe.com/v1/payment_intents \ -u "<>:" \ -d amount=1099 \ -d currency=eur \ -d "automatic_payment_methods[enabled]=true" ``` ### Retrieve the client secret The PaymentIntent includes a *client secret* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)) that the client side uses to securely complete the payment process. You can use different approaches to pass the client secret to the client side. #### Single-page application Retrieve the client secret from an endpoint on your server, using the browser’s `fetch` function. This approach is best if your client side is a single-page application, particularly one built with a modern frontend framework like React. Create the server endpoint that serves the client secret: #### Ruby ```ruby get '/secret' do intent = # ... Create or retrieve the PaymentIntent {client_secret: intent.client_secret}.to_json end ``` And then fetch the client secret with JavaScript on the client side: ```javascript (async () => { const response = await fetch('/secret'); const {client_secret: clientSecret} = await response.json(); // Render the form using the clientSecret })(); ``` #### Server-side rendering Pass the client secret to the client from your server. This approach works best if your application generates static content on the server before sending it to the browser. Add the [client_secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) in your checkout form. In your server-side code, retrieve the client secret from the PaymentIntent: #### Ruby ```erb
``` ```ruby get '/checkout' do @intent = # ... Fetch or create the PaymentIntent erb :checkout end ``` ## Collect payment method details [Client-side] You’re ready to collect payment information on the client with [Stripe Elements](https://docs.stripe.com/payments/elements.md). Elements is a set of prebuilt UI components for collecting payment details. A Stripe Element contains an iframe that securely sends the payment information to Stripe over an HTTPS connection. The checkout page address must also start with https:// rather than http:// for your integration to work. You can test your integration without using HTTPS. [Enable it](https://docs.stripe.com/security/guide.md#tls) when you’re ready to accept live payments. ### Set up Stripe Elements #### HTML + JS Stripe Elements is automatically available as a feature of Stripe.js. Include the Stripe.js script on your payment page by adding it to the `head` of your HTML file. Always load Stripe.js directly from js.stripe.com to remain PCI compliant. Don’t include the script in a bundle or host a copy of it yourself. ```html Checkout ``` Create an instance of Elements with the following JavaScript on your checkout page: ```javascript const stripe = Stripe('<>'); const elements = stripe.elements(); ``` ### Add and configure an epsBank Element > This doc refers to a *Legacy* (Technology that's no longer recommended) feature that’s no longer available in the latest version of Stripe.js. We recommend you use the [Payment Element](https://docs.stripe.com/payments/payment-element.md), a UI component for the web that accepts 40+ payment methods, validates input, and handles errors. Elements needs a place to live in your payment form. Create empty DOM nodes (containers) with unique IDs in your payment form and then pass those IDs to Elements. #### HTML ```html
``` When the form above has loaded, [create an instance](https://docs.stripe.com/js/elements_object/create_element?type=epsBank) of an `epsBank` Element and mount it to the Element container created above: ```javascript const options = { // Custom styling can be passed to options when creating an Element style: { base: { padding: '10px 12px', color: '#32325d', fontSize: '16px', '::placeholder': { color: '#aab7c4' }, }, }, }; // Create an instance of the epsBank Element const epsBank = elements.create('epsBank', options); // Add an instance of the epsBank Element into // the `eps-bank-element`
epsBank.mount('#eps-bank-element'); ``` Elements are completely customizable. You can [style Elements](https://docs.stripe.com/js/elements_object/create_element?type=epsBank#elements_create-options) to match the look and feel of your site, providing a seamless checkout experience for your customers. It’s also possible to style various input states, for example when the Element has focus. #### React #### npm Install [React Stripe.js](https://www.npmjs.com/package/@stripe/react-stripe-js) and the [Stripe.js loader](https://www.npmjs.com/package/@stripe/stripe-js) from the npm public registry. ```bash npm install --save @stripe/react-stripe-js @stripe/stripe-js ``` #### umd We also provide a UMD build for sites that don’t use npm or modules. Include the Stripe.js script, which exports a global `Stripe` function, and the UMD build of React Stripe.js, which exports a global `ReactStripe` object. Always load the Stripe.js script directly from **js.stripe.com** to remain PCI compliant. Don’t include the script in a bundle or host a copy of it yourself. ```html ``` > The [demo in CodeSandbox](https://codesandbox.io/s/react-stripe-official-q1loc?fontsize=14&hidenavigation=1&theme=dark) lets you try out React Stripe.js without having to create a new project. ### Add Stripe.js and Elements to your page To use Element components, wrap your checkout page component in an [Elements provider](https://docs.stripe.com/sdks/stripejs-react.md#elements-provider). Call `loadStripe` with your publishable key and pass the returned `Promise` to the `Elements` provider. ```jsx import React from 'react'; import ReactDOM from 'react-dom'; import {Elements} from '@stripe/react-stripe-js'; import {loadStripe} from '@stripe/stripe-js'; import CheckoutForm from './CheckoutForm'; // Make sure to call `loadStripe` outside of a component's render to avoid // recreating the `Stripe` object on every render. const stripePromise = loadStripe('<>'); function App() { return ( ); }; ReactDOM.render(, document.getElementById('root')); ``` ### Add and configure an EpsBankElement component Use the `EpsBankElement` to allow your customer to select their preferred bank. #### JSX ```jsx /** * Use the CSS tab above to style your Element's container. */ import React from 'react'; import {EpsBankElement} from '@stripe/react-stripe-js'; import './EpsBankSectionStyles.css' const EPS_ELEMENT_OPTIONS = { // Custom styling can be passed to options when creating an Element style: { base: { padding: '10px 12px', color: '#32325d', fontSize: '16px', '::placeholder': { color: '#aab7c4' }, }, }, }; function EpsBankSection() { return ( ); }; export default EpsBankSection; ``` Elements are completely customizable. You can [style Elements](https://docs.stripe.com/js/elements_object/create_element?type=epsBank#elements_create-options) to match the look and feel of your site, providing a seamless checkout experience for your customers. It’s also possible to style various input states, for example when the Element has focus. ## Submit the payment to Stripe [Client-side] Rather than sending the entire PaymentIntent object to the client, use its [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret). This is different from your API keys that authenticate Stripe API requests. The client secret should be handled carefully as it can complete the charge. Don’t log it, embed it in URLs, or expose it to anyone but the customer. #### HTML + JS Use [stripe.confirmEpsPayment](https://docs.stripe.com/js/payment_intents/confirm_eps_payment) to handle the redirect away from your page and to complete the payment. Add a [return_url](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-return_url) to this function to indicate where Stripe should redirect the user after they complete the payment on their bank’s website or mobile application. ```javascript const form = document.getElementById('payment-form'); const accountholderName = document.getElementById('accountholder-name'); form.addEventListener('submit', (event) => { event.preventDefault(); // Redirects away from the client const {error} = await stripe.confirmEpsPayment( '{{PAYMENT_INTENT_CLIENT_SECRET}}', { payment_method: { eps: epsBank, billing_details: { name: accountholderName.value, }, }, return_url: 'https://example.com/checkout/complete', } ); }); ``` #### React Use [stripe.confirmEpsPayment](https://docs.stripe.com/js/payment_intents/confirm_eps_payment) to handle the redirect away from your page and to complete the payment. Add a [return_url](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-return_url) to this function to indicate where Stripe should redirect the user after they complete the payment on their bank’s website or mobile application. To call `stripe.confirmEpsPayment` from your payment form component, use the [useStripe](https://docs.stripe.com/sdks/stripejs-react.md#usestripe-hook) and [useElements](https://docs.stripe.com/sdks/stripejs-react.md#useelements-hook) hooks. If you prefer traditional class components over hooks, you can instead use an [ElementsConsumer](https://docs.stripe.com/sdks/stripejs-react.md#elements-consumer). #### Hooks ```jsx import React from 'react'; import {useStripe, useElements, EpsBankElement} from '@stripe/react-stripe-js'; import EpsBankSection from './EpsBankSection'; export default function CheckoutForm() { const stripe = useStripe(); const elements = useElements(); const handleSubmit = async (event) => { // We don't want to let default form submission happen here, // which would refresh the page. event.preventDefault(); if (!stripe || !elements) { // Stripe.js hasn't yet loaded. // Make sure to disable form submission until Stripe.js has loaded. return; } const epsBank = elements.getElement(EpsBankElement); // For brevity, this example is using uncontrolled components for // the accountholder's name. In a real world app you will // probably want to use controlled components. // https://reactjs.org/docs/uncontrolled-components.html // https://reactjs.org/docs/forms.html#controlled-components const accountholderName = event.target['accountholder-name']; const {error} = await stripe.confirmEpsPayment('{CLIENT_SECRET}', { payment_method: { eps: epsBank, billing_details: { name: accountholderName.value, }, }, return_url: 'https://example.com/checkout/complete', }); if (error) { // Show error to your customer. console.log(error.message); } // Otherwise the customer will be redirected away from your // page to complete the payment with their bank. }; return (
); } ``` #### Class Components ```jsx import React from 'react'; import {ElementsConsumer, EpsBankElement} from '@stripe/react-stripe-js'; import EpsBankSection from './EpsBankSection'; class CheckoutForm extends React.Component { handleSubmit = async (event) => { // We don't want to let default form submission happen here, // which would refresh the page. event.preventDefault(); const {stripe, elements} = this.props if (!stripe || !elements) { // Stripe.js hasn't yet loaded. // Make sure to disable form submission until Stripe.js has loaded. return; } const epsBank = elements.getElement(EpsBankElement); // For brevity, this example is using uncontrolled components for // the accountholder's name. In a real world app you will // probably want to use controlled components. // https://reactjs.org/docs/uncontrolled-components.html // https://reactjs.org/docs/forms.html#controlled-components const accountholderName = event.target['accountholder-name']; const {error} = await stripe.confirmEpsPayment('{CLIENT_SECRET}', { payment_method: { eps: epsBank, billing_details: { name: accountholderName.value, }, }, return_url: 'https://example.com/checkout/complete', }); if (error) { // Show error to your customer. console.log(error.message); } // Otherwise the customer will be redirected away from your // page to complete the payment with their bank. }; render() { const {stripe} = this.props; return (
); } } export default function InjectedCheckoutForm() { return ( {({stripe, elements}) => ( )} ); } ``` When your customer submits a payment, Stripe redirects them to the `return_url` and includes the following URL query parameters. The return page can use them to get the status of the PaymentIntent so it can display the payment status to the customer. When you specify the `return_url`, you can also append your own query parameters for use on the return page. | Parameter | Description | | ------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `payment_intent` | The unique identifier for the `PaymentIntent`. | | `payment_intent_client_secret` | The [client secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) of the `PaymentIntent` object. For subscription integrations, this client_secret is also exposed on the `Invoice` object through [`confirmation_secret`](https://docs.stripe.com/api/invoices/object.md#invoice_object-confirmation_secret) | When the customer is redirected back to your site, you can use the `payment_intent_client_secret` to query for the PaymentIntent and display the transaction status to your customer. You can find details about the bank account the customer used to complete the payment on the resulting Charge under the [payment_method_details](https://docs.stripe.com/api/charges/object.md#charge_object-payment_method_details-eps) property. #### Json ```json { "charges": { "data": [ {"payment_method_details": { "eps": { "bank": "bank_austria", "verified_name": "JENNY ROSEN" }, "type": "eps" }, "id": "src_16xhynE8WzK49JbAs9M21jaR", "object": "source", "amount": 1099, "client_secret": "src_client_secret_UfwvW2WHpZ0s3QEn9g5x7waU", "created": 1445277809, "currency": "eur", "flow": "redirect", "livemode": true, "statement_descriptor": null, "status": "pending", "type": "eps", "usage": "single_use" } ], "object": "list", "has_more": false, "url": "/v1/charges?payment_intent=pi_1G1sgdKi6xqXeNtkldRRE6HT" }, "payment_method_options": { "eps": {} }, "payment_method_types": [ "eps" ], "id": "pi_1G1sgdKi6xqXeNtkldRRE6HT", "object": "payment_intent", "amount": 1099, "client_secret": "pi_1G1sgdKi6xqXeNtkldRRE6HT_secret_h9B56ObhTN72fQiBAuzcVPb2E", "confirmation_method": "automatic", "created": 1579259303, "currency": "eur", "livemode": true, "next_action": null } ``` ## Test your integration Select any bank in the EPS bank list with your test API keys. After confirming the payment, you’re redirected to a test page with options to succeed or fail the payment. You can test a successful payment by authenticating the payment on the redirect page. The PaymentIntent will transition from `requires_action` to `succeeded`. To test authentication failure, select any bank with your test API keys. On the redirect page, click **Fail test payment**. Your PaymentIntent will transition from `requires_action` to `requires_payment_method`. ## Optional: Handle post-payment events [Server-side] Stripe sends a [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.succeeded) event when the payment completes. Use the Dashboard, a custom *webhook* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests), or a partner solution to receive these events and run actions, like sending an order confirmation email to your customer, logging the sale in a database, or starting a shipping workflow. Listen for these events rather than waiting on a callback from the client. On the client, the customer could close the browser window or quit the app before the callback executes, and malicious clients could manipulate the response. Setting up your integration to listen for asynchronous events also helps you accept more payment methods in the future. Learn about the [differences between all supported payment methods](https://stripe.com/payments/payment-methods-guide). ### Receive events and run business actions There are a few options for receiving and running business actions. #### Manually Use the Stripe Dashboard to view all your Stripe payments, send email receipts, handle payouts, or retry failed payments. - [View your test payments in the Dashboard](https://dashboard.stripe.com/test/payments) #### Custom code Build a webhook handler to listen for events and build custom asynchronous payment flows. Test and debug your webhook integration locally with the Stripe CLI. - [Build a custom webhook](https://docs.stripe.com/webhooks/handling-payment-events.md#build-your-own-webhook) #### Prebuilt apps Handle common business events, like [automation](https://stripe.partners/?f_category=automation) or [marketing and sales](https://stripe.partners/?f_category=marketing-and-sales), by integrating a partner application. ## Optional: Handle EPS Bank Element changes [Client-side] The EPS Bank Element outputs the customer’s selected bank as it changes. To perform additional logic with the bank value (for example, requiring the field for form validation), you can listen to the change event: #### HTML + JS ```javascript epsBank.on('change', (event) => { const bank = event.value; // Perform any additional logic here... }); ``` #### React ```jsx { const bank = event.value; // Perform any additional logic here... }}> ``` The change event contains other parameters that can help to build a richer user experience. Refer to the [Stripe.js reference](https://docs.stripe.com/js/element/events/on_change?type=epsBankElement#element_on_change-handler) for more detail. ## Optional: Handle EPS redirect manually [Server-side] We recommend relying on Stripe.js to handle EPS redirects and payments with `confirmEpsPayment`. However, you can also manually redirect your customers by: 1. Providing the URL where your customers is redirected after they complete their payment. 2. Optionally providing the customer’s bank, where they’re be redirected to authorize the payment. You can find the list of available banks under the [Bank values](https://docs.stripe.com/payments/eps/accept-a-payment.md#bank-values) section. #### curl ```bash curl https://api.stripe.com/v1/payment_intents/{{PAYMENT_INTENT_ID}}/confirm \ -u <>: \ -d "return_url"="https://example.com/checkout/complete" \ -d "payment_method_data[type]"="eps" \ -d "payment_method_data[eps][bank]"="bank_austria" ``` 1. Confirming the `PaymentIntent` has a status of `requires_action`. The type for the `next_action` will be `redirect_to_url`. #### Json ```json {"next_action": { "type": "redirect_to_url", "redirect_to_url": { "url": "https://hooks.stripe.com/...", "return_url": "https://example.com/checkout/complete" } }, "charges": { "data": [ { "payment_method_details": { "eps": { "bank": "bank_austria", "verified_name": "JENNY ROSEN" }, "type": "eps" }, "id": "src_16xhynE8WzK49JbAs9M21jaR", "object": "source", "amount": 1099, "client_secret": "src_client_secret_UfwvW2WHpZ0s3QEn9g5x7waU", "created": 1445277809, "currency": "eur", "flow": "redirect", "livemode": true, "statement_descriptor": null, "status": "pending", "type": "eps", "usage": "single_use" } ], "object": "list", "has_more": false, "url": "/v1/charges?payment_intent=pi_1G1sgdKi6xqXeNtkldRRE6HT" }, "payment_method_options": { "eps": {} }, "payment_method_types": [ "eps" ], "id": "pi_1G1sgdKi6xqXeNtkldRRE6HT", "object": "payment_intent", "amount": 1099, "client_secret": "pi_1G1sgdKi6xqXeNtkldRRE6HT_secret_h9B56ObhTN72fQiBAuzcVPb2E", "confirmation_method": "automatic", "created": 1579259303, "currency": "eur", "livemode": true } ``` 1. Redirecting the customer to the URL provided in the `next_action` property. ```javascript const action = intent.next_action; if (action && action.type === 'redirect_to_url') { window.location = action.redirect_to_url.url; } ``` When the customer finishes the payment process, they’re sent to the `return_url` destination. The `payment_intent` and `payment_intent_client_secret` URL query parameters are included and you can pass through your own query parameters, as described above. ## Optional: Store the customer's bank preference [Client-side] You can’t reuse EPS *PaymentMethods* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) or save them to customers. You must use the EPS Bank Element to create a new EPS `PaymentMethod` each time your customer selects this method of payment in your checkout. To track your customer’s bank preference, store their preference in your own database or use the `metadata` property on the object you use to represent your customer (either a customer-configured [Account](https://docs.stripe.com/api/v2/core/accounts/object.md#v2_account_object-metadata) or a [Customer](https://docs.stripe.com/api/customers/object.md#customer_object-metadata)). > #### Use the Accounts v2 API to represent customers > > The Accounts v2 API is generally available for Connect users, and in public preview for other Stripe users. If you’re part of the Accounts v2 preview, you need to specify a [preview version](https://docs.stripe.com/api-v2-overview.md#sdk-and-api-versioning) in your code. > > To request access to the Accounts v2 preview, > > For most use cases, we recommend [modeling your customers as customer-configured Account objects](https://docs.stripe.com/accounts-v2/use-accounts-as-customers.md) instead of using [Customer](https://docs.stripe.com/api/customers.md) objects. You can prefill the EPS Bank Element with the customer’s bank preference when creating the Element: #### HTML + JS ```javascript const options = { // Include the bank name along with any custom stylingvalue: "bank_austria", style: { base: { padding: '10px 12px', color: '#32325d', fontSize: '16px', '::placeholder': { color: '#aab7c4' }, }, }, } // Create an instance of the Element const epsBank = elements.create('epsBank', options); // Mount the Element epsBank.mount('#eps-bank-element');TODO: highlight: [3] ``` #### React ```jsx const EPS_ELEMENT_OPTIONS = { // Include the bank name along with any custom stylingvalue: "bank_austria", style: { base: { padding: '10px 12px', color: '#32325d', fontSize: '16px', '::placeholder': { color: '#aab7c4' }, }, }, } ``` ## Bank values | Bank name | Value | | ----------------------------------------- | --------------------------------------- | | Ärzte- und Apothekerbank | arzte_und_apotheker_bank | | Austrian Anadi Bank AG | austrian_anadi_bank_ag | | Bank Austria | bank_austria | | Bankhaus Carl Spängler & Co.AG | bankhaus_carl_spangler | | Bankhaus Schelhammer & Schattera AG | bankhaus_schelhammer_und_schattera_ag | | BAWAG P.S.K. AG | bawag_psk_ag | | BKS Bank AG | bks_bank_ag | | Brüll Kallmus Bank AG | brull_kallmus_bank_ag | | BTV VIER LÄNDER BANK | btv_vier_lander_bank | | Capital Bank Grawe Gruppe AG | capital_bank_grawe_gruppe_ag | | Dolomitenbank | dolomitenbank | | Easybank AG | easybank_ag | | Erste Bank und Sparkassen | erste_bank_und_sparkassen | | Hypo Alpe-Adria-Bank International AG | hypo_alpeadriabank_international_ag | | HYPO NOE LB für Niederösterreich u. Wien | hypo_noe_lb_fur_niederosterreich_u_wien | | HYPO Oberösterreich, Salzburg, Steiermark | hypo_oberosterreich_salzburg_steiermark | | Hypo Tirol Bank AG | hypo_tirol_bank_ag | | Hypo Vorarlberg Bank AG | hypo_vorarlberg_bank_ag | | HYPO-BANK BURGENLAND Aktiengesellschaft | hypo_bank_burgenland_aktiengesellschaft | | Marchfelder Bank | marchfelder_bank | | Oberbank AG | oberbank_ag | | Raiffeisen Bankengruppe Österreich | raiffeisen_bankengruppe_osterreich | | Schoellerbank AG | schoellerbank_ag | | Sparda-Bank Wien | sparda_bank_wien | | Volksbank Gruppe | volksbank_gruppe | | Volkskreditbank AG | volkskreditbank_ag | | VR-Bank Braunau | vr_bank_braunau |