# How to add Braintree as a payment provider

Source: https://dev.arcxp.com/subscriptions/sales/build/payment-provider-braintree/

[Braintree](https://www.braintreepayments.com/) is a payment processing platform owned by PayPal, providing online and mobile payment solutions for businesses of all sizes.

## Prerequisites

1. [Add Braintree as a payment provider](https://dev.arcxp.com/subscriptions/sales/configure/payment-gateway-providers/#setting-up-a-payment-provider) through the Admin tool.

## Checkout flow

> **Note:**
> 
> We will walk through this document using our SDK methods, but if you need to call the APIs directly, please check [How to Connect with Arc XP Sales SDK and APIs on the web](https://dev.arcxp.com/subscriptions/sales/build/how-to-connect-with-sdks-and-apis/#arc-xp-sales-sdks-and-apis) to see the API that our SDK methods are wrapping.

The checkout workflow using Braintree follows the steps defined on [Checkout to purchase a subscription](https://dev.arcxp.com/subscriptions/sales/learn/checkout-to-purchase-a-subscription/). The code provided below is explained according to the **regular checkout** flow.

Regardless of the payment provider, Steps `1` to `5` (Authenticate, Get products and prices, Add item(s) to cart, Create order and Get payment options) are exactly the same as described on [Checkout to purchase a subscription](https://dev.arcxp.com/subscriptions/sales/learn/checkout-to-purchase-a-subscription/#regular-checkout/). See [How to add Stripe Intents as a payment provider](https://dev.arcxp.com/subscriptions/sales/build/payment-provider-stripe-intents/#checkout-flow) for implementation details.

1. `Authenticate`.
2. `Get products and prices`.
3. `Add item(s) to cart`.
4. `Create order`.
5. `Get payment options`.
6. `Initialize payment`: On the previous step, you can identify [payment methods](https://dev.arcxp.com/subscriptions/sales/configure/payment-gateway-providers/) set up for Braintree by checking if they have **paymentMethodType: 15**. For each element returned, you will see a **paymentMethodID**, this value, together with the orden number are required when calling `Sales.initializePayment()`.  
```js
    const orderNumber = Sales.currentOrder.orderNumber;
    const paymentProvider = chosenPaymentOption; // chosen by the user with paymentMethodType: 15
    ...
    const payment = await Sales.initializePayment(orderNumber, paymentProvider.paymentMethodID);
```
`Sales.initializePayment()` will return a token in parameter1\. This token is used to initialize and render the Braintree’s Drop-in UI. The [Braintree's Drop-in](https://developer.paypal.com/braintree/docs/start/drop-in) is a customizable payment UI solution from Braintree. It allows you to easily integrate multiple payment methods, such as credit cards and PayPal, without building a UI from scratch.  
```js
    ...
    import Sales from '@arc-publishing/sdk-sales';
    import DropIn from 'braintree-web-drop-in';
    ...
    export const BraintreeCheckout = props => {
        const [error, setError] = useState(null);
        const [isSubmitting, setIsSubmitting] = useState(false);
        useEffect(() => {
            const initPayment = async () => {
                try {
                    const payment = await Sales.initializePayment(orderNumber, paymentMethodID);
                    var button = document.querySelector('#submit-button');
                    DropIn.create(
                        {
                            authorization: payment.parameter1,
                            container: '#dropin-container',
                            card: {
                                cardholderName: {
                                required: true
                                }
                            },
                            paypal: {
                                flow: 'vault'
                            }
                        },
                        (_createErr, instance) => {
                            button.addEventListener('click', () => {
                                instance.requestPaymentMethod((err, payload) => {
                                    setIsSubmitting(true);
                                    if (payload && payload.nonce) {
                                        // If you need to pass reCAPTCHA
                                        // Sales.finalizePayment(orderNumber, paymentMethodID, payload.nonce, null, captcha)
                                        Sales.finalizePayment(orderNumber, paymentMethodID, payload.nonce)
                                            .then(() => {
                                                setIsSubmitting(false);
                                                // Then, direct the user to a success page
                                            })
                                            .catch(err => {
                                                setIsSubmitting(false);
                                                if (err && err.message) {
                                                    setError(err.message);
                                                }
                                            });
                                    } else {
                                        setIsSubmitting(false);
                                        if (err && err.message) {
                                            setError(err.message);
                                        }
                                    }
                                });
                            });
                        }
                    );
                } catch (err) {
                    if (err && err.message) {
                        setError(err.message);
                    }
                }
            };
            initPayment();
        }, [orderNumber, paymentMethodID]);
        return (
            <>
                {error && <p> error: {error}</p>}
                <div id="dropin-container"></div>
                <button id="submit-button" className="button is-primary is-fullwidth" disabled={isSubmitting}>
                    Purchase {isSubmitting && <i className="fas fa-spinner fa-pulse fa-lg"></i>}
                </button>
            </>
        );
    }
```
 </> ); }">
7. `Finalize payment`: In the previous code, you can see that once `payload.nonce` is detected, we call `Sales.finalizePayment()` along with the order number and the reCAPTCHA token (if this feature is enabled for checkout).

> **Note:**
> 
> Please refer to [Braintree documentation](https://developer.paypal.com/braintree/docs/) for more details. [Here](https://developer.paypal.com/braintree/docs/guides/credit-cards/testing-go-live/php) you can find a list of accepted cards for testing purpose.
