Accept an OXXO payment
Learn how to accept OXXO, a common payment method in Mexico.
Caution
We recommend that you follow the Accept a payment guide unless you need to use manual server-side confirmation, or your integration requires presenting payment methods separately. If you’ve already integrated with Elements, see the Payment Element migration guide.
Accepting OXXO in your app consists of displaying a webview to show the OXXO voucher. Customers pay by providing an OXXO voucher with a generated number and cash payment at an OXXO convenience store. Stripe notifies you when the payment is completed.
Set up StripeServer-sideClient-side
Server-side 
This integration requires endpoints on your server that talk to the Stripe API. Use our official libraries for access to the Stripe API from your server:
Client-side 
The React Native SDK is open source and fully documented. Internally, it uses the native iOS and Android SDKs. To install Stripe’s React Native SDK, run one of the following commands in your project’s directory (depending on which package manager you use):
Next, install some other necessary dependencies:
- For iOS, navigate to the ios directory and run
pod install
to ensure that you also install the required native dependencies. - For Android, there are no more dependencies to install.
Stripe initialization
To initialize Stripe in your React Native app, either wrap your payment screen with the StripeProvider
component, or use the initStripe
initialization method. Only the API publishable key in publishableKey
is required. The following example shows how to initialize Stripe using the StripeProvider
component.
import React, { useState, useEffect } from 'react'; import { StripeProvider } from '@stripe/stripe-react-native'; function App() { const [publishableKey, setPublishableKey] = useState(''); const fetchPublishableKey = async () => { const key = await fetchKey(); // fetch key from your server here setPublishableKey(key); }; useEffect(() => { fetchPublishableKey(); }, []); return ( <StripeProvider publishableKey={publishableKey} merchantIdentifier="merchant.identifier" // required for Apple Pay urlScheme="your-url-scheme" // required for 3D Secure and bank redirects > // Your app code here </StripeProvider> ); }
Create a PaymentIntentServer-sideClient-side
A PaymentIntent is an object that represents your intent to collect payment from a customer and tracks the lifecycle of the payment process through each stage.
Server-side
Create a PaymentIntent on your server with an amount and the mxn
currency (OXXO does not support other currencies). If you already have an integration using the Payment Intents API, add oxxo
to the list of payment method types for your PaymentIntent
.
Additional payment method options
You can specify an optional expires_
parameter in the payment method options for your PaymentIntent
that sets the number of calendar days before an OXXO voucher expires. For example, if you create an OXXO voucher on Monday and you set expires_
to 2, the OXXO voucher will expire on Wednesday at 23:59 America/Mexico_City (UTC-6) time. The expires_
parameter can be set from 1 to 7 days. The default is 3 days.
Client-side
On the client, request a PaymentIntent from your server and store its client secret.
const fetchPaymentIntentClientSecret = async () => { const response = await fetch(`${API_URL}/create-payment-intent`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ email, currency: 'mxn', payment_method_types: ['oxxo'], }), }); const {clientSecret, error} = await response.json(); return {clientSecret, error}; };
Collect payment method detailsClient-side
In your app, collect your customer’s full name and email address.
export default function OxxoPaymentScreen() { const [name, setName] = useState(); const [email, setEmail] = useState(); const handlePayPress = async () => { // ... }; return ( <Screen> <TextInput placeholder="Name" onChange={(value) => setName(value.nativeEvent.text)} /> <TextInput placeholder="E-mail" onChange={(value) => setEmail(value.nativeEvent.text)} /> </Screen> ); }
Submit the payment to StripeClient-side
Retrieve the client secret from the PaymentIntent you created and call confirmPayment
. This presents a webview to display the OXXO voucher.
export default function OxxoPaymentScreen() { const [name, setName] = useState(); const [email, setEmail] = useState(); const handlePayPress = async () => { const billingDetails: PaymentMethodCreateParams.BillingDetails = { name, email, }; const { error, paymentIntent } = await confirmPayment(clientSecret, { paymentMethodType: 'Oxxo', paymentMethodData: { billingDetails, } }); if (error) { Alert.alert(`Error code: ${error.code}`, error.message); console.log('Payment confirmation error', error.message); } else if (paymentIntent) { if (paymentIntent.status === PaymentIntents.Status.RequiresAction) { Alert.alert( 'Success', `The OXXO voucher was created successfully. Awaiting payment from customer.` ); } else { Alert.alert('Payment intent status:', paymentIntent.status); } } }; return ( <Screen> <TextInput placeholder="Name" onChange={(value) => setName(value.nativeEvent.text)} /> <TextInput placeholder="E-mail" onChange={(value) => setEmail(value.nativeEvent.text)} /> </Screen> ); }
Optional: Email voucher link to your customer
Stripe sends a payment_intent.requires_action event when an OXXO voucher is created successfully. If you need to email your customers the voucher link, you can retrieve the PaymentIntent to get the link upon receiving the event. The hosted_
field in payment_intent.next_action.oxxo_display_details contains the link to the voucher.
Optional: Customize your voucher
Stripe allows customization of customer-facing UIs on the Branding Settings page.
The following brand settings can be applied to the voucher:
- Icon—your brand image and public business name
- Accent color—used as the color of the Copy Number button
- Brand color—used as the background color
Handle post-payment eventsServer-side
OXXO is a delayed notification payment method, so funds are not immediately available. Customers might not pay for the OXXO voucher at an OXXO convenience store immediately after checking out.
Stripe sends a payment_intent.succeeded event on the next business day (Monday through Friday excluding Mexican holidays) for each OXXO voucher that was paid. Use the Dashboard or build a webhook handler to receive these events and run actions (for example, sending an order confirmation email to your customer, logging the sale in a database, or starting a shipping workflow).
After the expiry date, the PaymentIntent’s status transitions to processing
and the customer can no longer pay for the expired OXXO voucher. If the OXXO voucher was not paid for before 23:59 America/Mexico_City (UTC-6) on the expiry date, Stripe sends a payment_intent.payment_failed event within 10 calendar days after the expiry date (in most cases, this event is sent within 7 calendar days). For example, if the OXXO voucher expires on September 1, this event is sent by September 10 at the latest.
Event | Description | Next steps |
---|---|---|
payment_ | The OXXO voucher is created successfully. | Wait for the customer to pay for the OXXO voucher. |
payment_ | The customer can no longer pay for the OXXO voucher. | Wait for the payment to succeed or fail. |
payment_ | The customer paid for the OXXO voucher before expiration. | Fulfill the goods or services that the customer purchased. |
payment_ | The customer did not pay for the OXXO voucher before expiration. | Contact the customer through email or push notification and request another payment method. |
Receive events and run business actions
Manually
Use the Stripe Dashboard to view all your Stripe payments, send email receipts, handle payouts, or retry failed payments.
Custom Code
Build a webhook handler to listen for events and build custom asynchronous payment flows. Test and debug your webhook integration locally with the Stripe CLI.
Test the integration
In a sandbox, use the following emails when you call confirmPayment
to test different scenarios.
Description | |
---|---|
| Simulates an OXXO voucher which a customer pays after 3 minutes and the Example: fulano@test.com |
| Simulates an OXXO voucher which a customer pays immediately and the Example: succeed_immediately@test.com |
| Simulates an OXXO voucher which expires before a customer pays and the The Example: expire_immediately@test.com |
| Simulates an OXXO voucher which expires before a customer pays and the The Example: expire_with_delay@test.com |
| Simulates an OXXO voucher which expires before a customer pays and the Example: fill_never@test.com |
Expiration and cancellation
OXXO vouchers expire after the expires_
UNIX timestamp and a customer can’t pay an OXXO voucher once it has expired. OXXO vouchers can’t be canceled before expiration.
After an OXXO voucher expires, the PaymentIntent’s status changes to requires_
. At this point, you can confirm the PaymentIntent with another payment method or cancel.