# Stripe Elements

Stripe Elements is a set of prebuilt UI components for securely collecting and handling payment information in web applications. It allows developers to easily integrate a customizable payment form while ensuring compliance with security standards like PCI DSS.

Violet integrates with Stripe Elements to let you easily use all their features while processing payment during Checkout through Violet. This guide will walk you through the steps to integrate Stripe Elements with Violet, depending on which Checkout flow you are using.

## Pre-requisites

**Install up Stripe.js**

Install the Stripe.js React libraries and the Stripe JS loader from the [npm public registry](https://www.npmjs.com/package/@stripe/react-stripe-js):

```json
npm install --save @stripe/react-stripe-js @stripe/stripe-js
```

## Checkout Flows

Depending on the Checkout flow you use, add support for Stripe Elements by following the guides below.

<details>

<summary>Standard Checkout</summary>

To integrate with Stripe Elements you will need to do the following:

**1. Creating a Cart**

The general process to [Create a Cart](https://docs.violet.io/prism/overview/place-an-order/create-cart) remains the same, however, you will need to add the following flag to the request body:

```json
{
    "wallet_based_checkout": true
}
```

This ensures that the Cart that is creates includes a payment intent in the response that can be used with Stripe Elements.

**2. Accessing the Payment Intent Client Secret**

In order to configure Stripe Elements in your UI, you will need to use the Payment Intent Client Secret on the Order. This can be accessed from the Cart response, within `payment_transactions`.

```json
"payment_transactions": [
    {
    "id": 84808,
    "order_id": 123981,
    "payment_provider": "STRIPE",
    "amount": 900,
    "currency": "USD",
    "capture_status": "REQUIRES_PAYMENT_METHOD",
    "capture_method": "AUTOMATIC",
    "transfer_status": "PENDING",
    "transfer_method": "AUTOMATIC",
    "metadata": {
        "payment_intent_client_secret": "pi_3QpCRx2eXDTnoxH51SOBjwot_secret_0VYreFpdISo01L0K26HPSXUWt",
        "payment_intent_id": "pi_3QpCRx2eXDTnoxH51SOBjwot"
    },
    "errors": [],
    "date_created": "2025-02-05T17:31:45+0000",
    "date_last_modified": "2025-02-05T17:31:45+0000",
    "status": "REQUIRES_PAYMENT_METHOD"
    }
]
```

**3. Add and configure the Payment Element**

To use the Stripe Payment element, wrap your checkout page in a Stripe Elements provider. This is where you will also use the `Stripe Key` and `Payment Intent Client Secret` provided in the Order response.

```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('{{STRIPE_KEY_FROM_ORDER_RESPONSE}}', {});

function App() {
    const options = {
        clientSecret: '{{PAYMENT_INTENT_CLIENT_SECRET_FROM_ORDER_RESPONSE}}',

        // Fully customizable with appearance API.
        appearance: {
            /*...*/
        },
    };

    return (
        <Elements stripe={stripePromise} options={options}>
            <CheckoutForm />
        </Elements>
    );
}

ReactDOM.render(<App />, document.getElementById('root'));
```

**4. Add the Payment Element to your Checkout Form**

In your checkout form, render the Stripe `PaymentElement` component:

```jsx
import React from 'react';
import { PaymentElement } from '@stripe/react-stripe-js';

const CheckoutForm = () => {
    return (
        <form>
            <PaymentElement />
            <button>Submit</button>
        </form>
    );
};

export default CheckoutForm;

```

The Payment Element renders a dynamic form that allows your customer to pick a payment method. Depending on their payment method, the form automatically requests that the customer fills in all necessary payment details.

You can customize the Payment Element to match the design of your site by passing the [appearance object](https://stripe.com/docs/elements/appearance-api) into `options` when creating the `Elements` provider.

By default, the Payment Element only collects necessary billing address details. In cases where you need to collect full billing address, like for calculating tax for digital goods and services, you can use the [Address Element](https://stripe.com/docs/elements/address-element) in Billing mode.

**5. Confirm Payment**

When your shopper is ready to complete their cart and submit their order, you will need to confirm the payment. Note that you should only confirm a payment as [the final step before calling `/submit`](https://docs.violet.io/checkout-guides/guides/violet-checkout-with-stripejs-v3#submit-cart) on a cart to Violet since no other action can be taken on the cart that alters the cart total (like setting shipping methods or adding skus) after confirming the payment.

Add a listener to your Checkout form and then call `Stripe.confirmPayment` to attach the payment method your shopper provided to the payment intent sent by Violet and authorize the payment. Stripe will automatically request all the information that is needed for that payment method.

{% hint style="info" %}
The `Stripe.confirmPayment` call does not charge the credit card. Instead, it only authorizes the amount that needs to be paid and ensures there are sufficient funds. Charges are only captured once an order has successfully been placed in the external merchant store.

If there are issues during submission, the shopper’s card is never charged. The authorization will fall off their card within a few business days.
{% endhint %}

```jsx
import React from 'react';
import {
    useStripe,
    useElements,
    PaymentElement,
} from '@stripe/react-stripe-js';

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 has not yet loaded.
            // Make sure to disable form submission until Stripe.js has loaded.
            return;
        }

        const result = await stripe.confirmPayment({
            elements,
            confirmParams: {
                // Make sure to change this to your payment completion page
                return_url: '<http://localhost:3000>',
            },
        });

        stripePaymentMethodHandler(result);
    };

    return (
        <form onSubmit={handleSubmit}>
            <PaymentElement />
            <button type="submit" disabled={!stripe}>
                Submit Payment
            </button>
        </form>
    );
}

```

If a successful `result` is returned from the call to Stripe, a payment method has successfully been attached to the payment intent that Violet provided.

**6. Submit the Cart to Violet**

You can submit the order in the `stripePaymentMethodHandler` method called above. This is where you will call Violet Checkout submit:

```jsx
const stripePaymentMethodHandler = async (result) => {
    if (result.error) {
        // Show error in payment form
    } else {
        // Otherwise submit order to Violet
        const res = await fetch('{{baseUrl}}/checkout/cart/:cart_id/submit', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({
                app_order_id: //orderId for this order in your system,
            })
        });

        const orderResponse = await res.json();

        handleServerResponse(orderResponse);
    }
}
```

**Optional: Further Payment Requirements**

If there are further actions required for your customer during the payment process, such as 3D secure authentication, Violet will respond with the following status on the order:

```jsx
{
    "payment_status": "REQUIRES_ACTION",
}

```

If this is the case, you can use the same `payment_intent_client_secret` and the `Stripe.handleNextAction` method to request the additional information from the shopper.

```jsx
const handleServerResponse = async (orderResponse) => {
    if (response.error) {
        // Show error from server on payment form
    } else if (orderResponse.payment_status.requires_action) {
        // Use Stripe.js to handle the required next action
        const { error: errorAction, paymentIntent } = await stripe.handleNextAction(
            {
                clientSecret: orderResponse.payment_intent_client_secret,
            }
        );

        if (errorAction) {
            // Show error from Stripe.js in payment form
        } else {
            // Actions handled, submit order to Violet once again
            const res = await fetch('{{baseUrl}}/checkout/cart/:cart_id/submit', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                    app_order_id: //orderId for this order in your system,
                })
            });
        }
    } else {
        // No actions needed, show success message
    }
};

```

</details>

<details>

<summary>Quick Checkout</summary>

Stripe Elements in Quick Checkout operates as it does for Standard Checkout. Refer to the section above to learn how to integrate Stripe Elements with Quick Checkout.

</details>

<details>

<summary>Direct Order Submission</summary>

Unlike Standard and Quick Checkout, Carts are not created during Direct Order Submission. As a result, to use Stripe Elements with Direct Order Submission, Violet only requires you to send in a payment method. There are two payment methods Violet currently accepts:

1. Payment Intent

When using Direct Order Submission with Payment Intents, you can directly interact with the Stripe API and Stripe Elements to create a Payment Intent and attach a Payment Method to it. Once you have the Payment Intent ID and its in a state where it can be captured, you can include it in the Create Order API request body.

```json
{
    "payment_method": {
        "type": "PAYMENT_INTENT",
        "payment_provider": "STRIPE",
        "token": "pi_3QpCRx2eXDTnoxH51SOBjwot"
    }
}
```

2. Payment Method Token

To use Direct Order Submission with a Stripe Card Token, you can generate a token using Stripe Elements as described [here](https://docs.stripe.com/js/tokens/create_token?type=cardElement). Once you have a token, you can include it in the Create Order API request body.

```json
{
    "payment_method": {
        "type": "SINGLE_USE_CARD_TOKEN",
        "payment_provider": "STRIPE",
        "token": "tok_i1s2h8a9nyg1ukrju12h31kj212kh"
    }
}
```

To learn more about Direct Order Submission, review our complete [DOS guide](https://docs.violet.io/prism/checkout-guides/guides/direct-order-submission)

</details>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.violet.io/prism/payments/payment-integrations/supported-providers/stripe/stripe-elements.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
