# Aceptar pagos con OXXO Cómo aceptar pagos con OXXO, un método de pago muy usado en México. # Directo en las API > El contenido de esta sección se refiere a un producto *heredado* (Technology that's no longer recommended). En cambio, debes usar la guía [Aceptar un pago](https://docs.stripe.com/payments/accept-a-payment.md) para la ruta de integración más reciente. Si bien Stripe aún admite este producto, el soporte podría finalizar si el producto queda obsoleto. En México, los usuarios de Stripe pueden aceptar pagos OXXO de clientes en México usando las API Payment Intents y Payment Methods. Los *clientes* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments) abonan presentando un vale OXXO con un número y el pago en efectivo efectuado en una tienda OXXO de 24 horas. Stripe te notifica cuando se completa el pago. ## Configurar Stripe [Lado del servidor] Primero, necesitas una cuenta de Stripe. [Inscríbete ahora](https://dashboard.stripe.com/test/register). Usa nuestras bibliotecas oficiales para acceder 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' ``` ## Crear un PaymentIntent [Lado del servidor] Stripe usa un objeto [PaymentIntent](https://docs.stripe.com/api/payment_intents.md) para representar tu intención de cobrar a un cliente y hace el seguimiento de los cambios de estado desde la creación del vale OXXO hasta que se completa el pago. Crea un PaymentIntent en tu servidor con un importe y la moneda `mxn` (OXXO no admite otras monedas). Si ya tienes una integración con la [API Payment Intents](https://docs.stripe.com/payments/payment-intents.md), agrega `oxxo` a la lista de [tipos de métodos](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method_types) de pago para tu `PaymentIntent`. #### curl ```bash curl https://api.stripe.com/v1/payment_intents \ -u <>: \ -d "amount"=1099 \ -d "currency"="mxn" \ -d "payment_method_types[]"="oxxo" ``` ### Recuperar el secreto de cliente El PaymentIntent incluye un *secreto de cliente* (The client secret is a unique key returned from Stripe as part of a PaymentIntent. This key lets the client access important fields from the PaymentIntent (status, amount, currency) while hiding sensitive ones (metadata, customer)) que el lado del cliente usa para completar el proceso de pago de forma segura. Puedes usar diferentes métodos para pasar el secreto del cliente al lado del cliente. #### Aplicación de una sola página Recupera el secreto de cliente de un punto de conexión de tu servidor con la funcionalidad `fetch` del navegador. Este método es más conveniente si tu lado del cliente es una aplicación de una sola página, especialmente, si fue diseñada con un marco de front-end moderno como React. Crea el punto de conexión del servidor que se usa para el secreto de cliente: #### Ruby ```ruby get '/secret' do intent = # ... Create or retrieve the PaymentIntent {client_secret: intent.client_secret}.to_json end ``` Luego recupera el secreto de cliente con JavaScript del lado del cliente: ```javascript (async () => { const response = await fetch('/secret'); const {client_secret: clientSecret} = await response.json(); // Render the form using the clientSecret })(); ``` #### Renderización del lado del servidor Especifica el secreto de cliente desde tu servidor al cliente. Este enfoque funciona mejor si tu aplicación genera contenido estático en el servidor antes de enviarlo al navegador. Agrega [client_secret](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) en tu formulario de finalización de compra. En el código del lado de tu servidor, recupera el secreto de cliente de PaymentIntent: #### Ruby ```erb
``` ```ruby get '/checkout' do @intent = # ... Fetch or create the PaymentIntent erb :checkout end ``` ### Opciones de métodos de pago adicionales Puedes especificar un parámetro opcional `expires_after_days` en las [opciones de métodos de pago](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method_options-oxxo-expires_after_days) de tu `PaymentIntent` que define la cantidad de días calendario que deben pasar para que venza el vale de OXXO. Por ejemplo, si creas un vale de OXXO un lunes y defines `expires_after_days` en 2, el vale vencerá el miércoles a las 23:59, hora de América/Sao_Paulo (UTC-3). El parámetro `expires_after_days` puede ser de 1 a 7 días. El valor predeterminado es de 3 días. ## Recopilar datos del método de pago [Lado del cliente] Crea un formulario de pago del lado de tu cliente para recopilar los datos de facturación necesarios: | Campo | Valor | | ------- | ---------------------------------------------------------------------------------------------------------------------------------- | | `name` | El nombre completo (nombre y apellido) del cliente. Tanto el nombre como el apellido deben tener al menos dos caracteres cada uno. | | `email` | La dirección de correo electrónico completa del cliente. | ```html
``` ## Enviar el pago a Stripe [Lado del cliente] Cuando el cliente hace clic para pagar con OXXO, usa Stripe.js para enviar el pago a Stripe. [Stripe.js](https://docs.stripe.com/payments/elements.md) es nuestra biblioteca principal de JavaScript para crear flujos de pago. Incluye el script de Stripe.js en tu página de finalización de compra agregándolo al `head` de tu archivo HTML. ```html Checkout ``` Crea una instancia de Stripe.js con el siguiente JavaScript en tu página de pago. ```javascript // Set your publishable key. Remember to switch to your live publishable key in production! // See your keys here: https://dashboard.stripe.com/apikeys const stripe = Stripe('<>'); ``` Usa [stripe.confirmOxxoPayment](https://docs.stripe.com/js/payment_intents/confirm_oxxo_payment) y el [secreto de cliente](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-client_secret) del objeto `PaymentIntent` que creaste en el Paso 2 para enviar los datos de pagos del cliente. Una vez recibida la confirmación, Stripe abrirá automáticamente un cuadro de diálogo para mostrar el vale OXXO al cliente. ```javascript const form = document.getElementById('payment-form'); form.addEventListener('submit', async (event) => { event.preventDefault(); const result = await stripe.confirmOxxoPayment( '{{PAYMENT_INTENT_CLIENT_SECRET}}', { payment_method: { billing_details: { name: document.getElementById('name').value, email: document.getElementById('email').value, }, }, }); // Stripe.js will open a modal to display the OXXO voucher to your customer // This async function finishes when the customer closes the modal if (result.error) { // Display error to your customer const errorMsg = document.getElementById('error-message'); errorMsg.innerText = result.error.message; } }); ``` > `stripe.confirmOxxoPayment` puede tardar varios segundos en completarse. Durante ese tiempo, deshabilita tu formulario para no reenviarlo y muestra un indicador de espera, por ejemplo, un indicador giratorio. Si recibes un mensaje de error, muéstraselo al cliente, vuelve a habilitar el formulario y oculta el indicador de espera. Cuando se crea un vale OXXO correctamente, el valor de la propiedad `status` del PaymentIntent devuelto es `requires_action`. Comprueba el estado del PaymentIntent en el [Dashboard](https://dashboard.stripe.com/test/payments) o examina la propiedad de estado en el objeto. Si el vale OXXO no se creó correctamente, examina el mensaje de `error` que da el sistema para determinar la causa (p. ej., formato del correo electrónico no válido). ### Opcional: enviar al cliente el enlace del vale por correo electrónico Stripe envía un evento [payment_intent.requires_action](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.requires_action) cuando el vale de OXXO se crea correctamente. Si necesitas enviar a tus clientes el enlace del vale por correo electrónico, puedes [recuperar el PaymentIntent](https://docs.stripe.com/api/payment_intents/retrieve.md) para obtener el enlace al recibir el evento. El campo `hosted_voucher_url` en [payment_intent.next_action.oxxo_display_details](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-oxxo_display_details-hosted_voucher_url) contiene el enlace para acceder al vale. ### Opcional: personalizar tu vale Stripe permite la personalización de las interfaces de usuario del cliente en la página de [configuración de imagen de marca](https://dashboard.stripe.com/account/branding). La siguiente configuración de marca puede aplicarse al vale: - **Ícono**: tu imagen de marca y el nombre público de la empresa - **Color de énfasis**: se utiliza como color del botón Copiar número - **Color de la marca**: se utiliza como color de fondo ## Gestionar eventos posteriores al pago [Lado del servidor] OXXO es un método de pago con [notificación diferida](https://docs.stripe.com/payments/payment-methods.md#payment-notification), de manera que los fondos no están disponibles de inmediato. Puede que el *Cliente* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments) no pague el vale OXXO en una tienda de 24 horas inmediatamente después de realizar la compra. Stripe envía un evento [payment_intent.succeeded](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.succeeded) el siguiente día hábil (de lunes a viernes, excepto que sea día feriado en México) por cada vale de OXXO pagado. Utiliza el Dashboard o crea un controlador de *webhooks* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) para recibir estos eventos y ejecutar acciones (por ejemplo, enviar un correo electrónico de confirmación del pedido a tu cliente, registrar la venta en una base de datos o iniciar el flujo de envío). Después de la fecha de vencimiento, el estado del PaymentIntent pasa a ser `processing`, y el cliente ya no puede pagar el vale OXXO vencido. Si el vale no se paga antes de las 23:59, hora de America/Mexico_City (UTC-6) del día del vencimiento, Stripe envía un evento [payment_intent.payment_failed](https://docs.stripe.com/api/events/types.md#event_types-payment_intent.payment_failed) dentro de los 10 días calendario posteriores a la fecha de vencimiento (en la mayoría de los casos, el evento se envía en el término de 7 días calendario). Por ejemplo, si el vale OXXO vence el 1 de septiembre, el evento se envía el 10 de septiembre a más tardar. | Evento | Descripción | Próximos pasos | | -------------------------------- | ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- | | `payment_intent.requires_action` | El vale OXXO se creó correctamente. | Espera a que el cliente pague el vale OXXO. | | `payment_intent.processing` | El cliente ya no puede pagar el vale OXXO. | Espera hasta saber si el pago se concreta o no. | | `payment_intent.succeeded` | El cliente pagó el vale OXXO antes del vencimiento. | Entrega los bienes o servicios que el cliente compró. | | `payment_intent.payment_failed` | El cliente no pagó el vale OXXO antes del vencimiento. | Comunícate con el cliente por correo electrónico o envía una notificación push y solicítale otro método de pago. | ### Recibir eventos y realizar operaciones comerciales #### Manualmente Utiliza el Dashboard de Stripe para ver todos tus pagos en Stripe, enviar recibos por correo electrónico, gestionar transferencias o reintentar pagos fallidos. - [Visualiza tus pagos de prueba en el Dashboard](https://dashboard.stripe.com/test/payments) #### Código personalizado Crea un controlador de webhooks para escuchar eventos y crear flujos de pago asincrónicos personalizados. Prueba y depura tu integración de webhooks en forma local con la CLI de Stripe. - [Crear un webhook personalizado](https://docs.stripe.com/webhooks/handling-payment-events.md#build-your-own-webhook) ## Probar la integración En el entorno de prueba, establece `payment_method.billing_details.email` en los siguientes valores cuando llames a [stripe.confirmOxxoPayment](https://docs.stripe.com/js/payment_intents/confirm_oxxo_payment) para probar diferentes escenarios. | Correo electrónico | Descripción | | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `{any_prefix}@{any_domain}` | Simula un vale OXXO abonado por el cliente al cabo de 3 minutos con el webhook `payment_intent.succeeded` recibido después de 3 minutos. En modo activo, este webhook llega después de 1 día hábil. Ejemplo: fulano@test.com | | `{any_prefix}succeed_immediately@{any_domain}` | Simula un vale OXXO abonado por el cliente de inmediato con el webhook `payment_intent.succeeded` recibido después de unos segundos. En modo activo, este webhook llega después de 1 día hábil. Ejemplo: succeed_immediately@test.com | | `{any_prefix}expire_immediately@{any_domain}` | Simula un vale OXXO que venza antes de que pague el cliente con el webhook `payment_intent.payment_failed` recibido después de unos segundos. El campo `expires_after` en [next_action.oxxo_display_details](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-oxxo_display_details-expires_after) está establecido en la hora actual, independientemente de cómo esté definido el parámetro `expires_after_days` en [opciones de métodos de pago](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method_options-oxxo-expires_after_days). Ejemplo: expire_immediately@test.com | | `{any_prefix}expire_with_delay@{any_domain}` | Simula un vale OXXO que venza antes de que pague el cliente con el webhook `payment_intent.payment_failed` recibido después de 3 minutos. El campo `expires_after` en [next_action.oxxo_display_details](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-oxxo_display_details-expires_after) se establece en 3 minutos, independientemente de cómo esté definido el parámetro `expires_after_days` en [opciones de métodos de pago](https://docs.stripe.com/api/payment_intents/create.md#create_payment_intent-payment_method_options-oxxo-expires_after_days). Ejemplo: expire_with_delay@test.com | | `{any_prefix}fill_never@{any_domain}` | Simula un vale OXXO que venza antes de que pague el cliente con el webhook `payment_intent.payment_failed` recibido después de 1 día hábil y 2 días calendario. En modo activo, este webhook llega a la misma hora que en modo de prueba. Ejemplo: fill_never@test.com | ## Optional: Muestra los datos de OXXO a tu cliente [Lado del cliente] Te recomendamos que uses Stripe.js para mostrar en pantalla el vale OXXO con `confirmOxxoPayment`. No obstante, también puedes presentar manualmente el vale a tus clientes. Puedes especificar `handleActions: false` al llamar a `stripe.confirmOxxoPayment` en el paso 4 para indicar que te encargarás de la siguiente acción de mostrar los datos de OXXO a tu cliente. ```javascript const form = document.getElementById('payment-form'); form.addEventListener('submit', async (event) => { event.preventDefault(); const result = await stripe.confirmOxxoPayment( '{{PAYMENT_INTENT_CLIENT_SECRET}}', { payment_method: { billing_details: { name: document.getElementById('name').value, email: document.getElementById('email').value, }, }, }, {handleActions: false}, ); if (result.error) { // Display error to your customer const errorMsg = document.getElementById('error-message'); errorMsg.innerText = result.error.message; } else { // An OXXO voucher was successfully created const amount = result.paymentIntent.amount; const currency = result.paymentIntent.currency; const details = result.paymentIntent.next_action.oxxo_display_details; const number = details.number; const expires_after = details.expires_after; // Handle the next action by displaying the OXXO details to your customer // You can also use the generated hosted voucher const hosted_voucher_url = result.paymentIntent.next_action.oxxo_display_details.hosted_voucher_url; } }); ``` Incluye, como mínimo, lo siguiente: | Detalle | Descripción | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Logotipo de OXXO | [Descargar](https://stripe.com/img/docs/payments/oxxo.png) y mostrar el logotipo de OXXO en el vale. oxxo | | Número | Busca el número en el objeto `PaymentIntent` en [next_action.oxxo_display_details.number](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-oxxo_display_details-number). | | Fecha de vencimiento | Busca la marca de tiempo UNIX después de la cual vence el vale OXXO en el `PaymentIntent` en [next_action.oxxo_display_details.expires_after](https://docs.stripe.com/api/payment_intents/object.md#payment_intent_object-next_action-oxxo_display_details-expires_after). | | Importe | El importe que se cobrará. | | Moneda | Los vales OXXO siempre se expresan en pesos mexicanos. | | Código de barras | Genera el código de barras a partir del número con el [Código 128](https://en.wikipedia.org/wiki/Code_128). El código de barras debe tener aproximadamente 7.5 cm de ancho una vez impreso. Para las pantallas de dispositivos móviles, asegúrate de que el código de barras pueda ampliarse. De esta forma, el cajero de la tienda OXXO de 24 horas podrá escanearlo mejor. Puedes usar una biblioteca externa como [JSBarcode](https://lindell.me/JsBarcode/). | | Instrucciones de pago | Las instrucciones de pago para el cliente. A continuación, encontrarás las traducciones al inglés y al español. | ### Instrucciones de pago en tiendas OXXO #### Inglés OXXO payment instructions: 1. Give the voucher to the cashier to scan the barcode. 1. Provide cash payment to the cashier. 1. After the payment is complete, keep the receipt of your payment for your records. 1. Para cualquier duda o aclaración, ponte en contacto con la empresa. #### HTML ```html
MX
Expires
Instructions to pay your OXXO:
  1. Give the voucher to the cashier to scan the barcode.

  2. Provide cash payment to the cashier.

  3. After the payment is complete, keep the receipt of your payment for your records.

  4. For any questions or clarification, please contact the merchant.

``` #### Español Instrucciones de pago en OXXO: 1. Entregue el código al cajero en cualquier OXXO para que lo escanee. 1. Proporcione el pago en efectivo al cajero. 1. Una vez completado el pago, guarde el recibo de su pago para sus archivos. 1. Para cualquier duda o aclaración, por favor contacte al comerciante. #### HTML ```html
MX
Expira el
Instrucciones de pago en OXXO:
  1. Entregue el código al cajero en cualquier OXXO para que lo escanee.

  2. Proporcione el pago en efectivo al cajero.

  3. Una vez completado el pago, guarde el recibo de su pago para sus archivos.

  4. Para cualquier duda o aclaración, por favor contacte al comerciante.

``` Los *clientes* (Customer objects represent customers of your business. They let you reuse payment methods and give you the ability to track multiple payments) suelen imprimir el vale OXXO para llevarlo a la tienda OXXO. Puedes ofrecerles un botón para que lo impriman o enviarles el vale por correo electrónico. Haz la prueba de imprimir un vale OXXO para verificar el tamaño del código de barras (que debe tener aproximadamente 7.5 cm de ancho). ## Optional: Enviar correos electrónicos con instrucciones de pago Puedes habilitar los correos electrónicos con instrucciones de pago con OXXO en la página de [configuración de correo electrónico](https://dashboard.stripe.com/settings/emails) en el Dashboard. Una vez habilitados, Stripe envía estos correos cuando se confirma el PaymentIntent. Los correos contienen el número de OXXO y un enlace a la página del vale alojada en Stripe. > En los entornos de prueba, los correos electrónicos con instrucciones solo se envían a las direcciones de correo vinculadas a la cuenta de Stripe. ## Vencimiento y cancelación Los vales OXXO vencen después de la marca de tiempo UNIX `expires_after`, y el cliente ya no puede pagar un vale una vez vencido. Los vales OXXO no se pueden cancelar antes de su vencimiento. Después del vencimiento del vale OXXO, el estado del PaymentIntent cambia a `requires_payment_method`. A estas alturas, puedes confirmar el PaymentIntent con otro método de pago o cancelarlo.