# Pagos con tarjeta sin autenticación bancaria

Crea una integración más simple con limitaciones regionales.

Esta integración es compatible con empresas que solo aceptan tarjetas de EE. UU. y Canadá. Es más fácil de construir, pero no escala para soportar una base de clientes internacional.

### Cómo funciona esta integración

Los bancos de regiones como Europa y la India suelen requerir la autenticación en dos pasos para confirmar una compra. Si operas principalmente en EE. UU. y Canadá, puedes ignorar la *autenticación de tarjetas* (A bank might require the customer to authenticate a card payment before processing. Implementation varies by bank but commonly consists of a customer entering in a security code sent to their phone) para simplificar la integración, ya que los bancos no suelen solicitarla en esas regiones.

Cuando un banco requiere autenticación, esta integración básica rechaza de inmediato el pago (como sucede al rechazar una tarjeta) en lugar de gestionar la autenticación para completar el pago de manera asincrónica. La ventaja es que el pago se realiza correctamente o se rechaza de inmediato, y la confirmación del pago se produce en el servidor, de manera que puedes tomar medidas inmediatas posteriores al pago sin un *webhook* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests).

### Comparación con la integración global

| Característica                                                                      | Esta integración | Integración global |
| ----------------------------------------------------------------------------------- | ---------------- | ------------------ |
| Formulario de pago personalizado                                                    | ✔                | ✔                  |
| Los datos confidenciales no tienen contacto con tu servidor                         | ✔                | ✔                  |
| Funciona con clientes de EE. UU. y Canadá                                           | ✔                | ✔                  |
| Rechaza pagos si los datos de la tarjeta no son correctos o no hay fondos           | ✔                | ✔                  |
| Rechaza pagos con solicitudes de autenticación bancaria                             | ✔                |                    |
| Funciona con clientes de todo el mundo                                              |                  | ✔                  |
| Gestiona automáticamente los pagos con tarjeta que requieren autenticación bancaria |                  | ✔                  |
| Webhooks recomendados para tareas posteriores al pago                               |                  | ✔                  |
| Es fácil de escalar a otros métodos de pagos (por ejemplo, adeudos bancarios)       |                  | ✔                  |

Las empresas internacionales o en crecimiento deben usar la [integración global](https://docs.stripe.com/payments/accept-a-payment.md) de Stripe para poder aceptar solicitudes bancarias de autenticación en dos pasos y permitir que los clientes paguen con otros métodos de pago.
El flujo de pago que estás integrando (See full diagram at https://docs.stripe.com/payments/without-card-authentication)
## Crea un formulario de compra [Lado del cliente]

[Elements](https://docs.stripe.com/payments/elements.md), que forma parte de Stripe.js, proporciona componentes de interfaz de usuario insertables para recopilar los datos de las tarjetas de los clientes. Stripe los aloja y los coloca en tu formulario de pago como un iframe para que los datos de tarjeta del cliente no entren en contacto con tu código.

#### HTML + JS

Primero, incluye el script [Stripe.js](https://docs.stripe.com/js.md) en el encabezado de cada página de tu sitio web.

```html
<script src="https://js.stripe.com/dahlia/stripe.js"></script>
```

Incluir el script en cada página de tu sitio web te permite aprovechar la [funcionalidad avanzada contra el fraude](https://docs.stripe.com/radar.md) de Stripe y la capacidad de detectar comportamientos de navegación anómalos.

### Requisitos de seguridad

Este script siempre debe cargarse directamente desde **js.stripe.com** para seguir siendo [compatible con PCI](https://docs.stripe.com/security/guide.md). No puedes incluir el script en un paquete ni alojar una copia por ti mismo.

Cuando usas Elements, toda la información de pago se envía a una conexión HTTPS segura.

La dirección de la página que contiene Elements también debe comenzar por **https://** en lugar por **http://**. Para obtener más información sobre cómo obtener certificados SSL e integrarlos con tu servidor con el fin de habilitar una conexión HTTPS segura, consulta la documentación de [seguridad](https://docs.stripe.com/security.md).

### Añadir Elements a tu página

A continuación, necesitas una cuenta de Stripe. [Inscríbete ahora](https://dashboard.stripe.com/register).

Crea elementos DOM (contenedores) vacíos con ID únicos en tu formulario de pago.

```html
<form id="payment-form">
  <div id="card-element"><!-- placeholder for Elements --></div>
  <button id="card-button">Submit Payment</button>
  <p id="payment-result"><!-- we'll pass the response from the server here --></p>
</form>
```

Crea una instancia del [objeto Stripe](https://docs.stripe.com/js.md#stripe-function), proporcionando tu [clave API](https://docs.stripe.com/keys.md) publicable como primer parámetro. Después, crea una instancia del [objeto Elements](https://docs.stripe.com/js.md#stripe-elements) y úsalo para [montar](https://docs.stripe.com/js.md#element-mount) un elemento de tarjeta en el contenedor de elementos DOM vacío de la página.

```javascript
const stripe = Stripe('<<YOUR_PUBLISHABLE_KEY>>');

const elements = stripe.elements();
const cardElement = elements.create('card');
cardElement.mount('#card-element');
```

Usa [stripe.createPaymentMethod](https://docs.stripe.com/js/payment_methods/create_payment_method) en tu cliente para recopilar los datos de la tarjeta y crear un [PaymentMethod](https://docs.stripe.com/api/payment_methods.md) cuando el cliente envíe el formulario de pago. Envía el ID del PaymentMethod a tu servidor.

```javascript
const form = document.getElementById("payment-form");

var resultContainer = document.getElementById('payment-result');

// cardElement is defined in the previous step
cardElement.on('change', function(event) {
  if (event.error) {
    resultContainer.textContent = event.error.message;
  } else {
    resultContainer.textContent = '';
  }
});

form.addEventListener('submit', async event => {
  event.preventDefault();
  resultContainer.textContent = '';
  const result = await stripe.createPaymentMethod({
    type: 'card',
    card: cardElement,
  });
  handlePaymentMethodResult(result);
});

const handlePaymentMethodResult = async ({ paymentMethod, error }) => {
  if (error) {
    // An error happened when collecting card details, show error in payment form
    resultContainer.textContent = error.message;
  } else {
    // Send paymentMethod.id to your server (see Step 3)
    const response = await fetch("/pay", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ payment_method_id: paymentMethod.id })
    });

    const responseJson = await response.json();

    handleServerResponse(responseJson);
  }
};

const handleServerResponse = async responseJson => {
  if (responseJson.error) {
    // An error happened when charging the card, show it in the payment form
    resultContainer.textContent = responseJson.error;
  } else {
    // Show a success message
    resultContainer.textContent = 'Success!';
  }
};
```

#### React

Primero, instala [Stripe.js](https://github.com/stripe/stripe-js) y [React Stripe.js](https://docs.stripe.com/sdks/stripejs-react.md).

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

> Esta guía asume que ya tienes conocimientos básicos de React y que ya has configurado un proyecto con esta biblioteca. Si no la conoces, te recomendamos que leas la [guía de inicio](https://reactjs.org/docs/getting-started.html) de React antes de continuar.
> 
> Si buscas una forma rápida de probar React Stripe.js sin necesidad de crear un nuevo proyecto, empieza con esta [demostración en CodeSandbox](https://codesandbox.io/s/react-stripe-official-q1loc?fontsize=14&hidenavigation=1&theme=dark).

### Requisitos de seguridad

Cuando usas Elements, toda la información de pago se envía a una conexión HTTPS segura.

La dirección de la página que contiene Elements también debe comenzar por **https://** en lugar por **http://**. Para obtener más información sobre cómo obtener certificados SSL e integrarlos con tu servidor con el fin de habilitar una conexión HTTPS segura, consulta la documentación de [seguridad](https://docs.stripe.com/security.md).

### Carga Stripe.js y añade Elements a tu página

Para usar Elements, envuelve la raíz de tu aplicación React en un proveedor de [Elements](https://docs.stripe.com/sdks/stripejs-react.md#elements-provider). Llama a [loadStripe](https://github.com/stripe/stripe-js#loadstripe) con tu clave publicable y pasa la `Promise` devuelta al proveedor de `Elements`.

Importa y llama a `loadStripe` en la raíz de tu aplicación React para aprovechar la [funcionalidad avanzada de fraude](https://docs.stripe.com/radar.md) de Stripe y la capacidad de detectar comportamientos de navegación anómalos.

```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("<<YOUR_PUBLISHABLE_KEY>>");

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

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

### Crea un PaymentMethod

Utiliza el `CardElement` y el [stripe.createPaymentMethod](https://docs.stripe.com/js/payment_methods/create_payment_method) en tu cliente para recopilar los datos de la tarjeta y crear un [PaymentMethod](https://docs.stripe.com/api/payment_methods.md) cuando el cliente envíe el formulario de pago. Envía el ID del PaymentMethod a tu servidor.

Para llamar a `stripe.createPaymentMethod` desde el componente de tu formulario de pago, usa los hooks [useStripe](https://docs.stripe.com/sdks/stripejs-react.md#usestripe-hook) y [useElements](https://docs.stripe.com/sdks/stripejs-react.md#useelements-hook). Si prefieres utilizar los componentes de clase tradicionales en lugar de los hooks, puedes usar un [ElementsConsumer](https://docs.stripe.com/sdks/stripejs-react.md#elements-consumer).

#### Hooks

```jsx
import React from 'react';
import {useStripe, useElements, CardElement} 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();
const result = await stripe.createPaymentMethod({
      type: 'card',
      card: elements.getElement(CardElement),
      billing_details: {
        // Include any additional collected billing details.
        name: 'Jenny Rosen',
      },
    });

    handlePaymentMethodResult(result);
  };

  const handlePaymentMethodResult = async (result) => {
    if (result.error) {
      // An error happened when collecting card details,
      // show `result.error.message` in the payment form.
    } else {
      // Otherwise send paymentMethod.id to your server (see Step 3)
      const response = await fetch('/pay', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          payment_method_id: result.paymentMethod.id,
        }),
      });

      const serverResponse = await response.json();

      handleServerResponse(serverResponse);
    }
  };

  const handleServerResponse = (serverResponse) => {
    if (serverResponse.error) {
      // An error happened when charging the card,
      // show the error in the payment form.
    } else {
      // Show a success message
    }
  };

  const handleCardChange = (event) => {
    if (event.error) {
      // Show `event.error.message` in the payment form.
    }
  };

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

## Configura Stripe [Lado del servidor]

Usa una biblioteca oficial para hacer solicitudes a la API de Stripe desde tu aplicación:

#### 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'
```

## Efectúa un pago [Lado del servidor]

Configura un punto de conexión en tu servidor para recibir la solicitud del cliente.

Stripe utiliza un objeto [PaymentIntent](https://docs.stripe.com/api/payment_intents.md) para representar tu intención de cobrarle un pago a un cliente y hace un seguimiento de los intentos de cobro y de los cambios en el estado del pago a lo largo del proceso.

Decide siempre cuánto cobrar del lado del servidor, un entorno de confianza, y no del lado del cliente. Esto impide que clientes malintencionados puedan elegir sus propios precios.

Crea un punto de conexión HTTP para responder a la solicitud AJAX del paso 1. En ese punto de conexión, debes decidir cuánto le cobrarás al cliente. Para crear un pago, crea un PaymentIntent usando el ID *PaymentMethod* (PaymentMethods represent your customer's payment instruments, used with the Payment Intents or Setup Intents APIs) del paso 1 con el siguiente código:

#### curl

```curl
# Check the status of the PaymentIntent to make sure it succeeded

curl https://api.stripe.com/v1/payment_intents \
  -u <<YOUR_SECRET_KEY>>: \
  -d amount=1099 \
  -d currency=usd \

# A PaymentIntent can be confirmed some time after creation,
# but here we want to confirm (collect payment) immediately.
  -d confirm=true \
  -d payment_method="{{PAYMENT_METHOD_ID}}" \

# If the payment requires any follow-up actions from the
# customer, like two-factor authentication, Stripe will error
# and you will need to prompt them for a new payment method.
  -d error_on_requires_action=true
```

> Si estableces [error_on_requires_action](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-error_on_requires_action) en `true` al confirmar el pago, Stripe produce automáticamente un error en el pago si se exige al usuario la autenticación de dos factores.

#### Respuesta de la API Payment Intents

Cuando efectúas un pago con la API, la respuesta incluye el estado del PaymentIntent. Si el pago se ha realizado correctamente, el estado será `succeeded`.

```json
{
  "id": "pi_0FdpcX589O8KAxCGR6tGNyWj",
  "object": "payment_intent",
  "amount": 1099,
  "charges": {
    "object": "list",
    "data": [
      {
        "id": "ch_GA9w4aF29fYajT",
        "object": "charge",
        "amount": 1099,
        "refunded": false,
        "status": "succeeded",
      }
    ]
  },
  "client_secret": "pi_0FdpcX589O8KAxCGR6tGNyWj_secret_e00tjcVrSv2tjjufYqPNZBKZc",
  "currency": "usd",
  "last_payment_error": null,"status": "succeeded",
}
```

Si el pago se ha rechazado, la respuesta incluye el código de error y el mensaje de error. A continuación, encontrás un ejemplo de un pago fallido porque para la tarjeta se exigía la autenticación de dos factores.

```json
{
  "error": {"code": "authentication_required",
    "decline_code": "authentication_not_handled",
    "doc_url": "https://docs.stripe.com/error-codes#authentication-required",
    "message": "This payment required an authentication action to complete, but `error_on_requires_action` was set. When you're ready, you can upgrade your integration to handle actions at https://stripe.com/docs/payments/payment-intents/upgrade-to-handle-actions.",
    "payment_intent": {
      "id": "pi_1G8JtxDpqHItWkFAnB32FhtI",
      "object": "payment_intent",
      "amount": 1099,
      "status": "requires_payment_method",
      "last_payment_error": {
        "code": "authentication_required",
        "decline_code": "authentication_not_handled",
        "doc_url": "https://docs.stripe.com/error-codes#authentication-required",
        "message": "This payment required an authentication action to complete, but `error_on_requires_action` was set. When you're ready, you can upgrade your integration to handle actions at https://stripe.com/docs/payments/payment-intents/upgrade-to-handle-actions.",
        "type": "card_error"
      },
    },
    "type": "card_error"
  }
}
```

## Prueba la integración

Stripe proporciona varias tarjetas de prueba que puedes usar en un *entorno de prueba* (A sandbox is an isolated test environment that allows you to test Stripe functionality in your account without affecting your live integration. Use sandboxes to safely experiment with new features and changes) para asegurarte de que la integración está lista. Úsalos con cualquier CVC, código postal y fecha de vencimiento futura.

| Número           | Descripción                                                                                                    |
| ---------------- | -------------------------------------------------------------------------------------------------------------- |
| 4242424242424242 | La transacción se realiza correctamente y el pago se procesa de inmediato.                                     |
| 4000000000009995 | Siempre da error con un código de rechazo `insufficient_funds`.                                                |
| 4000002500003155 | Requiere autenticación, que en esta integración fallará con el código de rechazo `authentication_not_handled`. |

Ver la lista completa de [tarjetas de prueba](https://docs.stripe.com/testing.md).

## Actualiza tu integración para gestionar la autenticación de tarjetas

Se ha completado tu integración para pagos básicos con tarjeta. Ten en cuenta que esta integración **rechaza las tarjetas que exigen autenticación durante el pago**.

Si empiezas a ver en el Dashboard pagos que aparecen como `Failed`, tienes que [actualizar tu integración](https://docs.stripe.com/payments/payment-intents/upgrade-to-handle-actions.md). La integración global de Stripe gestiona estos pagos en lugar de rechazarlos automáticamente.
