Skip to main content
This page answers the integration questions that come up once an order exists: which URL your app should open, whether you can steer the checkout by request parameter, and why the currency the customer is charged in is sometimes not the one you sent. For ranking, grouping, folding and unavailable methods, see Checkout Payment Method Display Rules. For the display language, see Checkout Language.

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. 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 on orderAction.actionType. Never predict it.
Three rules that keep this robust:
  • Treat “no actionType and 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.
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 userTerminal to 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 no actionType and no URL — the code is rendered on the Waffo checkout page instead.
So 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 different actionType values.
  • Not every payment method looks at userTerminal at all.
Conclusion: 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:
  1. If the customer already switched tabs in this session, that tab.
  2. Otherwise, the country inferred from the customer’s IP — if that country is one of the order’s resolved tabs.
  3. Otherwise, the Global tab, if the order has one.
  4. Otherwise, the first tab in the list. Tabs are ordered alphabetically, with Global placed first when present, so this is the alphabetically first country.
Note that step 3 and step 4 pick a tab, not a location. The tab that gets selected does not tell you where the customer is — which is why the language decision deliberately uses a different notion of “the customer’s country”. See Checkout Language.

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.
  • payMethodCountry is 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.
So the honest answer to “can I specify the country and its payment methods for a subscription checkout” is: yes for both — narrow the country with 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 with 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.
The 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.

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 / payMethodName if a specific payment currency is a business requirement. Restricting the method restricts the candidate set the convergence runs over.

Why does the same payment method never appear twice on the checkout?

Because the convergence above runs per method name: multiple currency configurations of one method collapse to a single entry before the page is built. The customer sees one tile per method and cannot pick “the USD version” of it. Card brands are not affected by this collapse — the convergence only chooses among configurations that share a name, so different card brands each keep their own entry, and the card group looks the same on a country tab as on the Global tab.