> ## Documentation Index
> Fetch the complete documentation index at: https://waffo.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Frequently asked questions (FAQ)

> Common questions and answers about Waffo integration, payments, and security.

## Integration

> **Which integration method is recommended?**
>
> If you want to go live quickly, use **Checkout integration**. You don't need to handle sensitive card data and the integration effort is minimal.

> **What is the difference between ONE\_TIME\_PAYMENT and DIRECT\_PAYMENT?**
>
> `DIRECT_PAYMENT` is an early product that is largely unused today. New merchants should integrate `ONE_TIME_PAYMENT` directly.
>
> At the system level, the two are identical. The difference is in the business relationship:
>
> * **ONE\_TIME\_PAYMENT**: Waffo acts as PSP, providing full acquiring services (information flow + fund settlement)
> * **DIRECT\_PAYMENT**: Waffo acts as ISV/PG, providing only system connectivity (no fund handling)

> **Why does the amount need to be a String type?**
>
> To avoid floating-point precision issues. For example, `0.1 + 0.2 = 0.30000000000000004`, which is unacceptable in financial scenarios.

> **What are the currency precision requirements?**
>
> * **Same-currency orders**: Most currencies require 2 decimal places per ISO 4217, but `IDR`, `COP`, `KES`, and `TWD` **must not have decimals**
> * **Cross-currency orders**: All currency amounts must conform to ISO 4217 precision, with no exceptions

> **How do I test Webhooks locally?**
>
> Use a tunneling tool such as cloudflared or ngrok to expose your local port as a public URL.

> **What is the HTTP Keep-Alive timeout?**
>
> The Waffo API's HTTP Keep-Alive idle timeout is 60 seconds. We recommend configuring your client connection pool to close idle connections before 60 seconds. Configure DNS cache duration and per-request timeouts separately.

## Parameters

> **How should I pass payMethodType and payMethodName?**
>
> * **Omit both**: The user selects a payment method on the Waffo checkout page
> * **Card payments**: Pass `payMethodType="CREDITCARD,DEBITCARD"` and omit `payMethodName`. Waffo automatically determines the card network from the card BIN the user enters, supporting Visa/Mastercard and credit/debit cards in a single order
> * **VA (virtual account)**: Pass `payMethodType="VA"` and omit `payMethodName`; the user selects a bank on the checkout page
> * **Specify a particular method**: Pass both `payMethodType` and `payMethodName`. You can look up the exact values on the Payin page in the Portal
>
> For detailed parameter rules, see [Cashier integration - Customization options](/docs/en/developer-docs/integration/checkout/customization.md).

> **Can I omit userEmail?**
>
> `userEmail` is required when creating an order.
>
> If the merchant has not collected the user's email, send it in the `userId@examples.com` format (replace `userId` with the actual user ID).
>
> You can also contact Waffo and have Waffo overwrite it to this format on your behalf (merchant authorization is required).
>
> After going live, we recommend passing the real email address. Avoid using strings such as `test` or sharing the same email across multiple users, as this may trigger risk controls.

> **Should I pass orderExpiredAt?**
>
> It is optional. The field controls the time window within which the user can submit an order on the checkout page (must be UTC+0). Once the order is submitted to the payment channel, the expiry is controlled by the payment method itself. A small number of payment methods support passing a channel-side expiry time; check the Payin page in the Portal for details.

> **What is the difference between same-currency and cross-currency orders?**
>
> * **Same-currency**: The merchant's pricing currency matches the user's local currency (e.g., IDR pricing → Indonesian user pays in IDR)
> * **Cross-currency**: The merchant's pricing currency differs from the user's payment currency (e.g., USD pricing → Indonesian user pays in IDR via DANA)
>
> Cross-currency orders require passing `payMethodCountry` when either `payMethodType` or `payMethodName` is not specified. `userCurrency` is optional.

> **When should I pass payMethodCountry?**
>
> Pass it when you want the checkout to display only the payment methods of a **specific country**. If omitted, all available payment methods across all countries in the merchant's contract are shown.
>
> * **Global cards** (CREDITCARD/DEBITCARD): **Do not pass** this field—global cards do not belong to any specific country.
>
> For detailed parameter rules, see [Cashier integration - Customization options](/docs/en/developer-docs/integration/checkout/customization.md).

## Payments

> **Which should I use, webUrl or deeplinkUrl from orderAction?**
>
> Determine based on `orderAction.actionType`:
>
> * `actionType = "WEB"` → use `webUrl`
> * `actionType = "DEEPLINK"` → use `deeplinkUrl`
>
> In most cases only `webUrl` is present. If you pass `userTerminal=APP`, some wallet payment methods that require external authorization return a deeplink.
>
> > In the sandbox, deeplinks cannot launch real wallet apps because a simulator is used. Verify this behavior in production.

> **What should I do if the order creation returns orderStatus = AUTHORIZATION\_REQUIRED?**
>
> Redirect the user to the external authorization page. The URL comes from `orderAction`; use `webUrl` or `deeplinkUrl` based on `actionType`.

> **What should I do if I receive an UnknownStatus exception?**
>
> This exception occurs because of a network timeout when calling the payment channel—it is unclear whether the order was created successfully.
>
> * **When creating an order**: If you can confirm the user cannot complete payment under the error condition (e.g., payment methods that require returning a checkout URL), you may abandon the order.
> * **When refunding**: You **must** retry with the same `refundRequestId`. Do not abandon the request.
>
> See [Error handling](/docs/en/developer-docs/core-concepts/error-handling.md).

> **Why do some sandbox amounts immediately return C0005, C0001, or E0001?**
>
> This is expected behavior for sandbox acceptance and exception testing. The current acceptance templates use a set of special amounts to intentionally trigger channel rejection, system unavailable, and Unknown Status responses.
>
> * If you only want to test the normal success/failure flow, avoid these amounts
> * If you want to reproduce a specific exception, use the matching amount from [Sandbox simulator](/docs/en/developer-docs/tools-and-references/developer-tools/sandbox-simulator.md)
> * `A0011` and refund `A0003` are not triggered by special amounts. They are triggered by request parameter combinations

> **The user paid successfully but I didn't receive a Webhook—what should I do?**
>
> 1. Verify that `notifyUrl` is HTTPS and publicly reachable
> 2. Verify that the callback port is 80 or 443 (Waffo production only accepts standard ports)
> 3. Verify that the response body is `{"message": "success"}` and Content-Type is `application/json`
> 4. Proactively call the inquiry API to get the latest status
> 5. If you still don't receive it, contact Waffo technical support

> **Is the inquiry API required?**
>
> Strongly recommended. Use cases:
>
> * Query proactively when the user lands on a success/failure page to give the smoothest experience
> * Retrieve the result for historical orders
> * Fall back to the inquiry API when Webhook signature verification fails

> **How long is a Receipt valid?**
>
> A Receipt is valid for 3 years. If an order supports a Receipt, use the `userReceiptUrl` returned by the order inquiry response to open and download it again.

> **Can I use multiple payment methods at the same time?**
>
> If you do not specify `payMethodType` / `payMethodName`, the checkout displays all available payment methods for the user to choose from.

## Signature & security

> **What are the common reasons for signature verification failures?**
>
> 1. **Incorrect private key format**: The key must be in PKCS#8 format
> 2. **Incorrect signing content**: The entire HTTP body must be signed; you cannot sign only selected fields

> **What are the minimum requirements for RSA keys?**
>
> A 2048-bit RSA key pair using the SHA256WithRSA (RSASSA-PKCS1-v1\_5 + SHA-256) signature algorithm.

> **Can the sandbox and production environments use the same set of keys?**
>
> Not recommended. Sandbox and production should use different API keys and RSA key pairs.

## App integration

> **What should I pay attention to when integrating the checkout in a merchant App?**
>
> * Confirm that the App and WebView allow opening external Apps or external browser pages
> * Confirm that the App and WebView support download, copy, and long-press save behavior. QR, OTC, and bank-transfer style payment methods may depend on these capabilities
> * Confirm that query parameters are preserved when URLs are passed between the native App and WebView
> * When loading via WebView, set `userTerminal` to `APP`
> * For detailed limitations, see [Payment method integration notes](/docs/en/developer-docs/tools-and-references/references/payment-method-integration-notes.md)

> **What should I do if Android WebView shows ERR\_UNKNOWN\_URL\_SCHEME or Forbidden when opening a wallet?**
>
> First, use WebView navigation logs or remote debugging to capture the last failed URL. If it uses a non-HTTP(S) scheme, the payment page is trying to launch a wallet App. The host App must intercept that navigation and hand it to the operating system. This is normally a WebView external-launch capability issue, not a Waffo order creation failure, and it should not be diagnosed from the device model or Android version alone.
>
> If the failed URL behind the `Forbidden` page is still HTTPS, do not attribute it directly to a custom scheme. Preserve the complete URL and query parameters, record the time and order ID, and contact Waffo technical support.
>
> See the [App WebView section of the Checkout integration steps](/docs/en/developer-docs/integration/checkout/steps.md#app-webview-integration-considerations) for integration requirements and official Android and iOS references.

> **Can merchants integrate Google Pay / Apple Pay on their own?**
>
> Not recommended. Use the GP/AP capabilities built into the Waffo checkout directly.
>
> | Comparison | Using Waffo checkout | Self-integration |
> | - | - | - |
> | GP/AP developer account | Not required | Required |
> | Domain registration and verification | Required | Required |
> | Managing encryption certificates/keys | Handled by Waffo | Managed by merchant |
> | Server-side token processing/decryption | Handled by Waffo | Managed by merchant |
> | PCI DSS compliance | Not required | May be required |
> | Checkout UI | Provided by Waffo | Built by merchant |
> | **Integration complexity** | **Low** | **High** |
>
> If you have a specific requirement to self-integrate, contact Waffo technical support for a detailed integration guide.

> **Does PayMe payment launch the App?**
>
> Yes, it launches the PayMe App. If the user does not have it installed, they will be prompted to download it.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.