Adding a “Pay with Yappy” button is the visible part. What prevents headaches is the invisible part: the amount is calculated on the server, the order has clear states, and the system knows what to do if the customer closes the app mid-payment.
This guide describes a backend-first pattern with Laravel. If your storefront is WordPress or WooCommerce, the CMS stays as the shopfront; sensitive logic lives outside the theme. The same approach works for Yappy (Banco General), BAC Credomatic, Paguelo Fácil, and unified gateways.
Why it matters in Panama
Yappy is a widely used payment method. A poorly designed flow does not just “fail in staging”: it creates ghost sales, charges without orders, or paid orders nobody can prove to support or accounting.
- Trust: the customer needs to know whether they paid, without ambiguity.
- Operations: the team must reconcile bank vs orders without endless spreadsheets.
- Security: if the browser decides the price, someone will manipulate it.
- Scalability: tomorrow you may want BAC or Paguelo Fácil without rewriting the store.
What Yappy looks like in practice
Think of Yappy as a digital teller window: your server requests a charge intent, the customer completes payment in the app or redirect, and your system receives confirmation through a trusted channel (not only the return URL).
- Merchant onboarding and credentials (
merchantId/ secret) in the commercial portal. - The server generates a payment URL or intent with the correct amount.
- The user completes payment in the Yappy flow (app / redirect).
- Redirect + endpoint notification update the order after signature validation.
Golden rule: payment starts in the backend
Before showing the button, the server must do the heavy lifting:
- Create or retrieve the order with items, currency, and taxes.
- Calculate the total on the server (never trust the browser JSON).
- Save a payment record in
pendingstate with an internalorder_id. - Request the payment URL / token from Yappy with those figures.
- Return to the front end only what is needed to continue (redirect or minimal data).
WordPress / WooCommerce without polluting the theme
On sites with Elementor, custom themes, or WooCommerce, secrets must not live in functions.php or page-builder snippets. That is like taping the safe key to the shop window.
- WooCommerce creates the local order.
- A thin endpoint or plugin calls the Laravel API (gateway).
- Laravel talks to Yappy / BAC / Paguelo Fácil.
- WordPress reflects the state when the backend confirms.
Laravel implementation (steps)
Order+Paymentmodels with normalized states.PaymentGatewayservice with adapters behind an interface.- Protected endpoint to start payment: validates cart, calculates total, persists
pending. - Callback/IPN endpoint: verifies signature, is idempotent, dispatches reconciliation job.
- Return page that queries DB state; does not mark
paidfrom the query string. - Queue for retries when the bank notifies late.
- Secrets only in host env (Coolify: service variables, not
.envin Git).
Normalized states
| Internal state | Meaning |
|---|---|
pending | Intent created; no reliable confirmation yet |
paid | Charge confirmed by callback / signature validation |
rejected | Rejected by the provider |
cancelled | User aborted |
expired | Operational timeout |
Common production mistakes
- Confirming a sale only because the user reached
/pago-exitoso. - Leaving the secret in a WordPress plugin versioned in Git.
- Mixing Yappy, BAC, and Paguelo Fácil logic in one giant
if. - Forgetting the “user paid and closed the app” case with no visible callback.
- Deploying with the
latesttag and secrets baked into the Docker image. - Not persisting the provider payload: impossible to audit later.
Technical checklist
- Credentials only in environment variables.
- Sandbox and production separated.
- Idempotency: the same
order_iddoes not create two charges. - Persist payload for auditing.
- Validate what the provider sends back (signature / fields).
- Jobs for reconciliation retries.
- Logs without secrets or card data.
- Result page that queries the backend.
- Healthcheck and workers alive on deploy.
- Runbook for secret rotation and IPN reprocessing.
This integration connects with Docker, CI/CD, and Coolify, security auditing, and online payments .