webUrl and deeplinkUrl are mutually exclusive — what rule decides which one I get?
Two conditions have to hold, in this order.
First, the payment step has to be a redirect at all. Redirect fields are
produced only when the payment method the order routed to returns one of these
action forms:
An app-push flow produces no URL at all — neither
webUrl nor
deeplinkUrl. Nothing has gone wrong; there is simply nothing for you to open.
Second, if redirect fields are produced, the URL’s own type decides the pair:
That is why exactly one of the two is ever present:
actionType and the URL
field are set together, from the same branch.
So can I ask for a deeplink instead of a web URL?
No.actionType is not a parameter and not a merchant setting. It is
determined by the shape of the redirect artifact that the payment method this
specific transaction actually routed to hands back.
Practically, that means two orders of yours can differ in actionType for
reasons that are invisible to you at creation time — a different payment method
chosen by the customer on the checkout, or the same method behaving differently
for a different customer device. Your integration has to tolerate that.
What is the correct way to read the redirect, then?
Branch onorderAction.actionType. Never predict it.
- Treat “no
actionTypeand no URL” as a valid outcome, not an error. - Do not infer the URL field from the payment method you think the order used, from the customer’s device, or from what the same payment method returned last week.
- A redirect landing on your page is not proof of a successful payment. The authoritative result is the payment notification (webhook) or an order inquiry — always.
Is actionType related to userInfo.userTerminal?
They are two independent dimensions. actionType describes the shape of the
redirect artifact; userTerminal describes the customer’s device type. Neither
determines the other.
There is, however, a real indirect link, and it is worth understanding
because it is the source of most of the confusion:
- Some payment methods use
userTerminalto decide which flow to open at all. A method may show a QR code when the customer is on a PC and launch a wallet app when the customer is on a phone. - Those two flows produce different artifacts. An app launch yields a scheme
URL, so you get
actionType = DEEPLINK. A QR-code display is not a redirect at all, so it yields noactionTypeand no URL — the code is rendered on the Waffo checkout page instead.
userTerminal can influence what you end up receiving, via the payment
method’s own behaviour. What it does not do is let you predict it:
- Under the same
userTerminal, different payment methods return differentactionTypevalues. - Not every payment method looks at
userTerminalat all.
userTerminal is an input that describes your customer honestly.
actionType is an output you read at runtime. Do not use the first to guess
the second.
What does userTerminal actually do, then?
Its primary, documented job is eligibility: not every payment method
supports every terminal type, so the value is used to check whether a given
method can be offered to this customer at all. A method that does not support
the terminal you sent will not appear on the checkout.
Send the value that is true for the session. Sending
WEB for a customer who
is actually inside a wallet app does not unlock anything; it just gives the
platform wrong information to filter with.
Can customers switch country on the checkout themselves?
Yes, with two conditions.
The selector only exists on the payment-method selection step. Once the
customer has chosen a method and moved on, there is no country switch.
Switching country reloads the payment-method list for that country. Anything
tied to the previous selection — such as an entered promotion code — is
cleared by the switch, so the customer re-enters it if they still want it.
Which country is selected by default?
Resolved in this order:- If the customer already switched tabs in this session, that tab.
- Otherwise, the country inferred from the customer’s IP — if that country is one of the order’s resolved tabs.
- Otherwise, the Global tab, if the order has one.
- Otherwise, the first tab in the list. Tabs are ordered alphabetically, with Global placed first when present, so this is the alphabetically first country.
For a one-time payment, can I pin the country and payment methods by parameter?
Partly. On order creation:payMethodCountry is a filter, not a country lock — passing one country does
not reduce the page to that country’s methods only, because global methods
survive the filter by design. The full behaviour, including what happens to the
country tabs and what happens when nothing survives the filter, is documented
in
Checkout Payment Method Display Rules.
For a subscription, can I pin the country and payment methods by parameter?
Yes — the same three filters exist on/api/v1/subscription/create, under
paymentInfo, and they behave the same way as on a one-time order:
Two things specific to subscriptions:
- The country you pass is stored on the subscription and re-applied every time Waffo re-resolves the eligible payment methods for it — for example when the customer adds or changes a payment method later. A subscription created for one country therefore keeps offering that country’s local methods (plus global ones) for its whole life.
payMethodCountryis a filter, not a lock, exactly as for one-time orders: passing one country does not reduce the page to that country’s methods only, because global methods survive the filter by design.
payMethodCountry, narrow the methods with payMethodType / payMethodName,
and set the language with cashierLanguage. If you want a strictly
single-country experience with no global methods, express it as a method
restriction — name the methods you want offered — because a country filter
alone will not remove global methods.
Do my Cashier Ranking settings apply to my subscription checkout too?
No. Ranking and display configuration are stored against two dimensions: country and product type.ONE_TIME_PAYMENT and SUBSCRIPTION are
separate product types, so each country has one configuration for one-time
payments and a separate one for subscriptions. They do not inherit from each
other in either direction.
At checkout time, the configuration looked up is the one matching the order’s
country and the order’s product type. If no configuration exists for that
pair, the platform default ranking applies for that pair — a customized
one-time ranking does not leak into the subscription checkout, and vice versa.
One consequence to plan for: configuring your one-time checkout is not
configuring your subscription checkout. If you offer both, set the ranking
twice, once per product type, in the Merchant Portal under
Cashier Customization → Cashier Ranking.
When product type is not specified at all in a configuration lookup, it
defaults to ONE_TIME_PAYMENT — which is another reason a subscription
checkout will look untouched until you configure it explicitly.
I created the order in one currency and the customer was charged in another. Why?
Because a single payment method can be configured for several payment currencies under your agreements, and the checkout shows one entry per payment method, not one entry per currency. Something has to choose which of the configured currencies that entry uses — and the currency you passed as the order currency is not automatically the winner. The order currency you passed is still the currency of your order and of your settlement view; what changes is the currency the customer actually pays in, with the conversion shown to them on the checkout page.Which currency wins when a payment method is configured in several?
The candidates for that one method are narrowed level by level. At each level: exactly one match ends the process; several matches narrow the pool and continue; no match leaves the pool untouched and continues.
Worked example, and the one that generates most of these tickets:
You create an order withThe order currency only decides the outcome at level 3 — that is, only when no candidate matched the method’s own local currency and none matched the customer’s IP currency. This is deliberate: for a local payment method, the currency the customer’s own account is denominated in is a better outcome than the currency you happened to invoice in. This convergence is platform behaviour and is not merchant-configurable.currency = HKD. Your customer’s IP resolves to China. The eWallet-type method they want belongs to China and is configured under your agreements in both USD and CNY.
- Level 1 — the method’s home country is China, whose local currency is CNY. Of the two candidates, exactly one matches. Resolved.
- The customer pays in CNY, even though you sent HKD.
How do I avoid the surprise entirely?
Two things make it predictable rather than mysterious:- Read the payment currency from the order, do not assume it. The checkout displays the customer payment amount and the conversion breakdown, and the same values are on the order — see Checkout Page Lifecycle & Receipt.
- Narrow the methods you offer with
payMethodType/payMethodNameif a specific payment currency is a business requirement. Restricting the method restricts the candidate set the convergence runs over.