Meses sin Intereses en Stripe con Python y React parte 2
Tags: python, react, flask, stripe
Published: 2020-11-14 19:12:38

En el post pasado iniciamos creando nuestra estructura de archivos y directorios para nuestro formulario de pago con stripe usando React y Flask.

Ya con todo eso listo podemos iniciar a crear los componentes de React que necesitaremos para procesar los pagos.

# Instalando la librería de react para stripe

Esto es muy simple lo único que debemos hacer es:

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

y listo, ya se actualizo nuestro package.json y se instalo la librería.

# Agregando Bootstrap (para que no se vea tan feo)

Bootstrap es un framework de frontend con el propósito de estilizar nuestras aplicaciones o sitios web.

Existen muchas maneras de agregarlo a un proyecto en React pero la más simple y la que vamos a utilizar es agregando el CDN a el index de nuestra aplicación.

Pero no lo vamos a agregar al index.js si no que dentro de la carpeta public encontraremos un archivo de nombre index.html y es en este dónde agregaremos el CDN de (bootstrap)[https://getbootstrap.com/docs/4.5/getting-started/introduction/]

Al igual que cualquier archivo css este va dentro de un tag `<link>` y dentro del `<head>` de la pagina quedando algo como esto.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/a99s31vgx9ihvgn7166w.png)

# Modificando la estructura de archivos

Cuando creamos un nuevo proyecto de react usando `create-react-app` este nos da una estructura de archivos inicial, para este caso vamos a modificar un poco esta estructura.

- Ir a la carpeta src
- Dejar únicamente el archivo index.js

Cuando eliminemos estos archivos y tratemos de iniciar el proyecto con `npm start` seguramente tendremos varios errores y estos serán causados por las importaciones de archivos que ya no existen por lo que vamos a modificar ese archivo index.js de la siguiente manera.

```
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App'

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

# Creando los componentes

Ahora aun tendremos un error de importación por que para este punto aún no existe el componente `App` por lo que vamos a crearlo al mismo nivel que index.js

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/k6oznurhwoo4cl40aazw.png)

Para toda esta serie de tutoriales vamos a utilizar `functional componets` que es la forma en la que React nos dice que deberíamos trabajar, si alguno de ustedes esta acostumbrado a utilizar `ClassComponents` es muy fácil migrar de uno a otro.

Ahora si el componente `App` 

```
// App.js

import React from 'react'
import { Elements } from '@stripe/react-stripe-js'
import { loadStripe } from '@stripe/stripe-js'

const App = () => {
    const stripePromice = loadStripe('stripe_public_key')
    
    return (
        <div className="container">
            <div className="row">
                <Elements stripe={stripePromice}>
                    
                </Elements>
            </div>
        </div>
    )
}

export default App
```

Ok.. todo se ve muy cool pero que estamos haciendo, bueno partiendo de la estructura fuente de un `functional component` lo que estamos haciendo es importar `Elements` de la librería de stripe la cual nos va a permitir utilizar los objetos `Element` de stripe en cualquier componente heredado.

Y la otra cosa que estamos haciendo es autenticandonos con nuestra clave publica de stripe esto con la función `loadStripe` la cual cargara de forma asíncrona al script de `Stripe.js`.

Esa autenticación se la pasamos como prop el componente `Element` y listo ya podemos utilizar stripe.

# Creando el CardElement

Dentro de la carpeta src vamos a crear una nueva carpeta llamada `components` y dentro de esta crearemos un archivo llamado `CheckoutForm.js` y escribiremos lo siguiente:

```
// CheckoutForm.js
import React from 'react'
import CardSection from './CardSection'

const CheckoutForm = () => {
    return (
        <div className="col-lg-12">
            <form>
                <h1>Formulario de Pago</h1>
                <div className="form-group">
                    <CardSection/>
                </div>
                <button className="btn btn-primary">Pay</button>
            </form>
        </div>
    )
}

export default CheckoutForm
```

Este componente nos va a servir para agregar todos los datos del formulario de pago que vallamos a necesitar, es decir nombre del cliente, email, etc... Todo lo que queremos saber del cliente y por supuesto los datos de su tarjeta para realizar el cobro.

En este caso únicamente estaré pidiendo los datos de la tarjeta, pero desde este componente es donde se pedirá toda la información del cliente.

Ahora en este punto no tenemos creado aun el componente `CardSection` por lo que vamos a hacerlo.

Dentro de la carpeta components vamos a crear un archivo llamado `CardSection.js`, dentro de este archivo escribimos lo sigueinte.

```
import React, { useState } from 'react'
import { CardElement } from '@stripe/react-stripe-js'
import '../css/stripe_form.css'

const  CardSection = () => {

    const [state, setState] = useState({
        'errorMessage': ''
    })

    const card_element_options = {
        style: {
            base: {
                color: "#32325d",
                fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
                fontSmoothing: "antialiased",
                fontSize: "16px",
                "::placeholder": {
                    color: "#aab7c4",
                },
            },
            invalid: {
                color: "#fa755a",
                iconColor: "#fa755a",
            },
        }
    }

    const handleOnChanage = (event) => {
        setState({errorMessage: ''})
        if (event.error) {
            setState({error: true, errorMessage:event.error.message})
        }
    }

    return (
        <>
            <CardElement options={card_element_options} onChange={handleOnChanage}/>
            <div className="card-errors">
            <p>{state.errorMessage}</p>
            </div>
        </>
    )
}

export default CardSection
```

Muy bien vamos a la explicación.

En este componente estamos importando de stripe el componente `CardElement`.

Stripe nos proporciona muchos `Elements` para crear nuestro formulario de pago, pero el `CardElement` es uno de los mas utilices desde mi punto de vista por que engloba todos los datos de la tarjeta que necesitamos en un solo input evitando tener que hacer muchos clics o lo que sea, de todos modos aquí les dejo el resto de los elemento que nos provee stripe. https://stripe.com/docs/stripe-js

Ahora tambien estamos agregando algunas opciones de estilos por default al `CardElement`.

También estamos validando si existe algún error en los datos de la tarjeta haciendo uso del prop `onChange` del componente `CardElement`, para esta validación hacemos uso del hook de React `useState` de tal forma que cuando hay un error en el objeto event del componente `CardElement` actualizamos el `state` y lo renderizamos en el tag <p>

Aquí les dejo la documentación de stripe en donde podremos ver todas las props que le podemos pasar a los elementos de stripe

https://stripe.com/docs/js/elements_object/create_element?type=card#elements_create-options

En este componente también agregamos algunos estilos por CSS, mismos que les dejare en el Repo del proyecto para no escribir todo el código aquí.

Ya con todos los componentes listos solo nos queda importar el componente `CardForm` dentro de `App`.

```
        <div className="container">
            <div className="row">
                <Elements stripe={stripePromice}>
                    {/* Load the checkout form */}
                    <CheckoutForm/>
                </Elements>
            </div>
        </div>
```

y listo ya tenemos nuestro formulario.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/lwghfqjiuoja8gutg4rj.png)

Aun no acepta pagos, pero esto lo iremos haciendo en los siguientes post.

Les dejo el Repo del proyecto de React en donde podrán ver todo el código o clonarlo para verlo en uso en sus computadoras.

https://github.com/leonardoAlonso/StripeForm