El proceso de pago es uno de los punto mas críticos de una aplicación, pues un mal diseño puede causar que el cliente desista de realizar la compra, y no por el mero diseño, si no que le puede generar una cierta inseguridad sobre si el sitio es seguro.

En este artículo analizaremos como crear un formulario de pago atractivo y dinámico que le de cierta seguridad a nuestros clientes, utilizando para ello es componte react-credit-cards, con un resultado como el siguiente:

Antes de comenzar de dejaré el repositorio en GitHub donde podrás descargar este ejemplo: https://github.com/Centripio/youtube-react-creditcard

También puedes ver este mismo ecuatorial en Youtube:

Básicamente lo que tenemos que hace es importar el componente Cards y los sus estilos correspondientes, tal y como podemos ver en las líneas 2 y 3, el siguiente paso es Renderizar el componente Cards con al menos 5 propiedad, number donde ponemos el número de la tarjeta, name donde ponemos el nombre del dueño de la tarjeta y los campo expiry y cvc para representar la fecha de vigencia y el código de seguridad respectivamente. Finalmente el campo focused indica el nombre del campo de la tarjeta que tiene el foco.

import React, { useState } from 'react'
import Cards from 'react-credit-cards'
import 'react-credit-cards/es/styles-compiled.css'
<Cards
	number={state.number}
	name={state.name}
	expiry={state.expiry}
	cvc={state.cvc}
	focused={state.focus}
/>

Ya con esto definido, solo queda crear el formulario para actualizar el estado y con ellos los datos de la tarjeta, para esto, vamos a crear un formulario como el siguiente:

<form>
	<div className="form-group">
		<label htmlFor="number">Número de la tarjeta</label>
		<input
			type="text"
			name="number"
			id="number"
			maxLength="16"
			className="form-control"
			onChange={handleInputChange}
			onFocus={handleFocusChange}
		/>
	</div>
	<div className="form-group">
		<label htmlFor="name">Nombre</label>
		<input
			type="text"
			name="name"
			id="name"
			maxLength="30"
			className="form-control"
			onChange={handleInputChange}
			onFocus={handleFocusChange}
		/>
	</div>
	<div className="form-row">
		<div className="form-group col-md-6">
			<label htmlFor="expiry">Fecha de expiración</label>
			<input
				type="text"
				name="expiry"
				id="expiry"
				maxLength="4"
				className="form-control"
				onChange={handleInputChange}
				onFocus={handleFocusChange}
			/>
		</div>
		<div className="form-group col-md-6">
			<label htmlFor="cvc">CVC</label>
			<input
				type="text"
				name="cvc"
				id="cvc"
				maxLength="4"
				className="form-control"
				onChange={handleInputChange}
				onFocus={handleFocusChange}
			/>
		</div>
	</div>
	<button onClick={processPayment} type="button" className="btn btn-success btn-block btn-lg">Pagar</button>
</form>

Observa como cada input tiene como name el nombre de la propiedad que requiere el componente Cards, además tiene los eventos handleInputChange que actualiza el estado cada vez que capturamos actualizamos cada campo:

const handleInputChange = (e) => {
	setState({
		...state,
		[e.target.name] : e.target.value
	})
}

Observa que esta función utiliza la propiedad name para determinar que input fue el actualizado y cambiar esa misma propiedad en el estado.

Finalmente, tenemos la función handleFocusChange que nos permite identificar que input tiene el foco, y con eso animar la tarjeta de crédito para seleccionar el campo que estamos capturando:

const handleFocusChange = (e) => {
	setState({
		...state,
		focus : e.target.name
	})
}

Podrás ver nuevamente la importancia de la propiedad  name para actualizar la propiedad focus del estado.

Finalmente, aquí puedes ver como se ve el componente terminado:

import React, { useState } from 'react'
import Cards from 'react-credit-cards'
import 'react-credit-cards/es/styles-compiled.css'

const PaymentForms = () => {

    const [state, setState] = useState({
        number: "",
        name: "",
        expiry: "",
        cvc: "",
        focus: ""
    })

    const handleInputChange = (e) => {
        setState({
            ...state,
            [e.target.name] : e.target.value
        })
    }

    const handleFocusChange = (e) => {
        setState({
            ...state,
            focus : e.target.name
        })
    }

    const processPayment = () => {
        console.log("number => ", state.number)
        console.log("name => ", state.name)
        console.log("expiry => ", state.expiry)
        console.log("cvc => ", state.cvc)
        console.log(JSON.stringify(state))
    }

    return (
        <div className="card">
            <div className="card-body">

                <Cards
                    number={state.number}
                    name={state.name}
                    expiry={state.expiry}
                    cvc={state.cvc}
                    focused={state.focus}
                />
                <form>
                    <div className="form-group">
                        <label htmlFor="number">Número de la tarjeta</label>
                        <input
                            type="text"
                            name="number"
                            id="number"
                            maxLength="16"
                            className="form-control"
                            onChange={handleInputChange}
                            onFocus={handleFocusChange}
                        />
                    </div>
                    <div className="form-group">
                        <label htmlFor="name">Nombre</label>
                        <input
                            type="text"
                            name="name"
                            id="name"
                            maxLength="30"
                            className="form-control"
                            onChange={handleInputChange}
                            onFocus={handleFocusChange}
                        />
                    </div>
                    <div className="form-row">
                        <div className="form-group col-md-6">
                            <label htmlFor="expiry">Fecha de expiración</label>
                            <input
                                type="text"
                                name="expiry"
                                id="expiry"
                                maxLength="4"
                                className="form-control"
                                onChange={handleInputChange}
                                onFocus={handleFocusChange}
                            />
                        </div>
                        <div className="form-group col-md-6">
                            <label htmlFor="cvc">CVC</label>
                            <input
                                type="text"
                                name="cvc"
                                id="cvc"
                                maxLength="4"
                                className="form-control"
                                onChange={handleInputChange}
                                onFocus={handleFocusChange}
                            />
                        </div>
                    </div>

                    <button onClick={processPayment} type="button" className="btn btn-success btn-block btn-lg">Pagar</button>
                </form>
            </div>
        </div>
    )
}

export default PaymentForms
Si quieres aprender más de React, te invitamos a que te des una vuelta por nuestro curso Mastering React, donde aprenderás todo lo necesario para crear tus propias aplicaciones, incluyendo la conexión con un API REST.