Yuno One-Time Token (OTT)
Summary
The One-Time Token is an opaque string that the Yuno SDK generates in the user's browser as soon as the card data is confirmed. It represents the active payment session, is single-use, and expires when consumed or when the checkout session expires.
The OTT is the mechanism that prevents sensitive card data — PAN, CVV, expiration date — from passing through Publica.la servers. The SDK collects them inside an iframe served from the Yuno domain and returns only the token to the frontend. The backend receives that token and sends it to the Yuno API to create the payment.
Since Yuno acts as an orchestrator (routing the payment to the actual provider based on country, BIN, and payment method), it also needs the OTT for operations prior to the charge such as cross-border currency conversion, where Yuno queries the card BIN against the provider before quoting.
Differentiator Compared to Other Gateways
The OTT flow is what makes Yuno structurally different from the other Farfalla gateways. Stripe redirects to its own Checkout and the data stays in its domain. MercadoPago also redirects to the provider's site. PayU generates backend-signed parameters but the card data is collected by PayU.
Yuno is the only gateway where the card form lives inside the publisher's page (via a secure iframe) while at the same time sensitive data does not transit through our backend. What reaches the backend is the OTT, an opaque reference to the session.
OTT Lifecycle
The OTT is created when the user completes the card form inside the SDK iframe. The SDK emits an event that the Alpine/Livewire layer captures, and from there the token travels to the backend together with the checkout session ID and the payment method type.
In the backend, the OTT travels through the Yuno service layer until the payment payload is assembled. It ends up in the token field of the payment method within the request to the Yuno API. It is the only field in the request that represents the user's card.
OTT vs Vaulted Token
The OTT and the vaulted token are different strings with different purposes, and it is important not to confuse them.
The OTT lives for a single payment. It is emitted by the SDK in the browser, is not persisted in Farfalla, and expires when consumed. It is used both for one-off payments and for the first charge of a non-trial subscription.
The vaulted token is persistent: it is returned by the Yuno API when a one-off payment is created with vaulting enabled. It is associated with the customer within Yuno and represents the stored card for future charges. It is the token Farfalla uses when creating the subscription and the one Yuno uses internally for subsequent recurring charges.
For subscriptions with a trial, the OTT does not participate: the SDK starts in enrollment mode, collects the card data, and returns a vaulted token directly without generating a charge, and the subscription is created with that token. For non-trial subscriptions, on the other hand, the OTT is used first — the first cycle is charged as a one-off with vaulting enabled and the subscription is created only afterwards with the resulting vaulted token. That workaround is explained in the subscriptions doc.
Currency Conversion (Cross-Border)
For cross-border currencies configured in Farfalla (currently CLP and MXN, listed in the payments config), the actual provider behind Yuno is MercadoPago, which charges the cardholder in USD even though the merchant sells in local currency.
Before creating the payment, the backend makes a currency conversion call to Yuno passing the OTT, the amount in local currency, and the provider. Yuno queries the card BIN against MercadoPago and returns a quote object with an identifier, the USD amount that will be shown to the cardholder, and the applied rate. Farfalla includes that identifier and the USD amount inside the payment amount block, and Yuno validates that the quote is still valid when processing.
The flow has two fallbacks. If the Yuno API responds with a USD amount of zero but with a valid rate (something observed in the MercadoPago sandbox), Farfalla calculates the amount locally by multiplying by the rate and records a warning in the yuno_api channel. If the currency conversion call fails completely — API down, rate unavailable, network error — the code does not throw an exception: it records the error in yuno_api and sends the payment without the conversion block. The sale is not lost, but since the MercadoPago cross-border path is not used, Yuno routes the payment through another available gateway (currently Stripe) according to the routing configured in the Yuno dashboard, which reduces the commercial margin compared to processing it via MercadoPago cross-border.
For non-cross-border currencies, the currency conversion call is not made: the amount block is assembled with the currency and the order value and nothing else. The OTT is accepted in the signature for uniformity but is ignored on that path.
Adding or removing cross-border currencies requires no code changes: it is enough to edit the currencies array in the payments config.
Code References
| File | Responsibility |
|---|---|
app/Domains/Commerce/Gateways/Yuno/YunoBaseService.php | Amount block assembly, cross-border resolution, OTT masking, metadata |
app/Domains/Commerce/Gateways/Yuno/YunoService.php | Payment creation with OTT, payload assembly, request execution |
app/Domains/Commerce/Gateways/Yuno/YunoOneOffPaymentService.php | One-off flow with OTT and checkout session creation |
app/Domains/Commerce/Gateways/Yuno/YunoRecurringPaymentService.php | Subscription creation with vaulted token, vaulted token retrieval after the first payment |
app/Domains/Commerce/Support/Yuno/YunoConnector.php | HTTP client toward Yuno, OTT masking in outgoing requests |
app/Domains/Commerce/Support/Yuno/YunoPayment.php | Reading the vaulted token from the payment response |
app/Domains/Commerce/Support/Yuno/YunoCurrencyConversion.php | Reading USD amount and rate from the currency conversion response |
app/Http/Livewire/CheckoutV2/YunoPaymentForm.php | OTT reception from the frontend |
config/payments.php | Cross-border currencies, settlement currency, and provider |
tests/Feature/Domains/Commerce/YunoGatewayTest.php | Tests for amount assembly, currency conversion, and payment creation |