Zippi uses Wompi as its payment gateway for card, PSE, and cash payments in the Colombian market. The integration builds a hosted checkout URL, redirects the customer, and listens forDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/CRISTIANCAMACH34/Zippi/llms.txt
Use this file to discover all available pages before exploring further.
transaction.updated webhook events to confirm or cancel orders automatically.
Environment Setup
Sandbox vs Production
- Sandbox
- Production
Integration Setup
Create a Wompi account and get your keys
Register at wompi.co, create an application, and copy the public key, private key, integrity secret, and events secret for your target environment (sandbox or production) into your
.env.Register the webhook URL in Wompi
In the Wompi merchant dashboard, go to Developers → Webhooks and add:Select the
transaction.updated event. Wompi will send a signed POST to this URL whenever a transaction status changes.Initiate checkout from an order
When a customer chooses Wompi as payment method, call the checkout creation endpoint. The backend builds a signed redirect URL pointing to Response includes
https://checkout.wompi.co/p/ with the integrity signature embedded:checkout_url — redirect the customer to that URL.Customer completes payment
Wompi hosts the payment form. After the customer pays (or the link expires), Wompi redirects to
WOMPI_REDIRECT_URL and sends a webhook event to your backend.Process the webhook
Zippi verifies the signature, matches the reference to an internal order, and transitions the order state:
APPROVED→ order moves toconfirmed, payment record createdDECLINED→ order moves tocancelado, no payment recordVOIDED→ treated asexpiredERROR→ transaction markederror, order stays inpending_payment
Webhook Payload Structure
Wompi sends aPOST request with the following JSON body:
X-Event-Checksum header may also carry the checksum value. Zippi reads from whichever is present.
Signature Verification
Zippi rebuilds the expected checksum usingWOMPI_EVENTS_SECRET and compares with secrets.compare_digest to prevent timing attacks:
WOMPI_EVENTS_SECRET is not configured the endpoint returns HTTP 500 immediately — it will never accept an unverifiable event.
Idempotency
Both checkout creation and webhook processing are idempotent:- Checkout creation: pass an
Idempotency-Keyheader. A second call with the same key returns the original response and creates no extra database rows. A second call with a different payload but the same key returns HTTP 409. - Webhook delivery: if Wompi delivers the same
transaction.idtwice, the second delivery returns{"duplicate": true}without re-running the state machine or creating a second payment record.
backend/tests/unit/test_wompi_payments.py.
Testing the Webhook Locally
Use the fixture script to send a correctly signed webhook to your local backend:Transaction State Mapping
Wompi statuses are normalized to internal states before persisting:| Wompi status | Internal state |
|---|---|
CREATED | created |
PENDING | pending |
APPROVED | approved |
DECLINED | declined |
VOIDED | expired |
ERROR | error |
Reconciliation
Every Wompi checkout carries areference in the format WOMPI-{order_code}-{timestamp}-{hex_suffix}. The cashier module matches incoming webhook events to internal TransaccionPagoPedido rows by this reference, links them to the corresponding PagoPedido, and updates the parent order’s payment status. Amount mismatches (where the webhook amount_in_cents differs from the expected total) mark the transaction as error and keep the order in pending_payment for manual review.