> ## 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

<AccordionGroup>
  <Accordion title="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.
  </Accordion>

  <Accordion title="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)
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="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
  </Accordion>

  <Accordion title="How do I test Webhooks locally?">
    Use a tunneling tool such as cloudflared or ngrok to expose your local port as a public URL.
  </Accordion>
</AccordionGroup>

## Parameters

<AccordionGroup>
  <Accordion title="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](/en/developer-docs/integration/checkout/customization).
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="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](/en/developer-docs/integration/checkout/customization).
  </Accordion>
</AccordionGroup>

## Payments

<AccordionGroup>
  <Accordion title="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.
  </Accordion>

  <Accordion title="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`.
  </Accordion>

  <Accordion title="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](/en/developer-docs/core-concepts/error-handling).
  </Accordion>

  <Accordion title="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](/en/developer-docs/tools-and-references/developer-tools/sandbox-simulator)
    * `A0011` and refund `A0003` are not triggered by special amounts. They are triggered by request parameter combinations
  </Accordion>

  <Accordion title="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. Verify that the response includes the `X-SIGNATURE` header
    5. Proactively call the inquiry API to get the latest status
    6. If you still don't receive it, contact Waffo technical support
  </Accordion>

  <Accordion title="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
  </Accordion>

  <Accordion title="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.
  </Accordion>
</AccordionGroup>

## Signature & security

<AccordionGroup>
  <Accordion title="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
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>
</AccordionGroup>

## App integration

<AccordionGroup>
  <Accordion title="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](/en/developer-docs/tools-and-references/references/payment-method-integration-notes)
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>
</AccordionGroup>
