Skip to main content

Unofficial python cleint for Wompi to create transactions.

Project description

pywompi

Cliente Python no oficial para la API de Wompi El Salvador (api.wompi.sv).

Wompi El Salvador es un producto distinto a Wompi Colombia: se autentica con OAuth2 Client Credentials en vez de public/private key, y firma sus webhooks con un esquema HMAC diferente. Este paquete está escrito específicamente para el producto salvadoreño — si necesitás Wompi Colombia, buscá otro cliente.

No es un paquete oficial de Wompi ni de Bancolombia. Es mantenido de forma independiente por Roque Studios.

Instalación

pip install pywompi

Requiere Python 3.9+.

Quickstart

import os
from pywompi import WompiClient

client = WompiClient(
    client_id=os.environ["WOMPI_CLIENT_ID"],       # App ID del panel de Wompi
    client_secret=os.environ["WOMPI_CLIENT_SECRET"], # API Secret del panel de Wompi
)

enlace = client.create_payment_link({
    "identificadorEnlaceComercio": "PEDIDO-123",
    "nombreProducto": "Consulta CloudClinic",
    "monto": 25.00,
})

print(enlace["urlEnlace"])       # URL para redirigir al cliente
print(enlace["urlQrCodeEnlace"]) # QR del enlace de pago

client.close()

O como context manager, para que el cliente HTTP interno se cierre solo:

with WompiClient(client_id=..., client_secret=...) as client:
    transaccion = client.get_transaction("SV-1720800000-abc123")
    print(transaccion["estado"])

El access token de OAuth2 se pide y se cachea en memoria automáticamente; no hace falta manejarlo a mano ni refrescarlo vos mismo.

Endpoints sin wrappear todavía

client.py solo wrappea los endpoints que están confirmados contra la documentación oficial (Enlace de Pago, Transacción de Compra). Para cualquier otro endpoint del Swagger de Wompi (tokenización, cargos recurrentes, datos de negocio, etc.), usá el método genérico ya autenticado:

resultado = client.request("GET", "DatosNegocio")
resultado = client.request("POST", "EnlacePagoRecurrente", json={...})

Validar webhooks

Wompi firma cada webhook con el header wompi_hash: el HMAC-SHA256 del body crudo de la petición, usando tu API Secret como llave. Nunca proceses un webhook sin validar esta firma primero — cualquiera puede mandarte un POST diciendo que una transacción fue aprobada si no la validás.

from pywompi import parse_event, WompiWebhookError

def wompi_webhook_view(request):
    try:
        event = parse_event(
            raw_body=request.body,  # bytes CRUDOS, no el dict ya parseado
            received_hash=request.headers.get("wompi_hash", ""),
            api_secret=os.environ["WOMPI_CLIENT_SECRET"],
        )
    except WompiWebhookError:
        return HttpResponse(status=400)

    if event["data"]["transaccion"]["estado"] == "APROBADA":
        ...

⚠️ El punto que más rompe integraciones: el HMAC se calcula sobre el body tal cual llegó por la red, byte por byte. Si tu framework ya parseó el JSON a un dict y vos hacés json.dumps() para "reconstruirlo", el hash casi seguro no va a matchear — el orden de las llaves o los espacios pueden cambiar en la re-serialización. Siempre usá el body crudo:

Framework Cómo obtener el body crudo
Django request.body (bytes, antes de acceder a request.POST)
FastAPI await request.body() (no uses un parámetro Body() tipado)
Flask request.get_data()

Ver examples/ para integraciones completas de Django y FastAPI.

Ambientes (sandbox / producción)

A diferencia de Wompi Colombia, la documentación pública de Wompi El Salvador no expone subdominios separados de sandbox/producción — el ambiente se determina por el App ID / API Secret que uses (cada aplicativo se marca como productivo o no desde el panel). Si tu cuenta sí tiene URLs distintas, pasalas explícitamente:

client = WompiClient(
    client_id=...,
    client_secret=...,
    token_url="https://id.wompi.sv/connect/token",
    api_base_url="https://api.wompi.sv",
)

Manejo de errores

from pywompi.exceptions import (
    WompiError,           # excepción base
    WompiAuthError,       # falló la autenticación OAuth2
    WompiConnectionError, # error de red / timeout
    WompiAPIError,        # Wompi respondió con status >= 400
    WompiWebhookError,    # firma de webhook inválida
)

try:
    client.create_payment_link({...})
except WompiAPIError as e:
    print(e.status_code, e.payload)  # inspeccionar la respuesta de error
except WompiConnectionError:
    # reintentar, encolar para retry, etc.
    ...

Desarrollo

git clone https://github.com/roquestudios/pywompi
cd pywompi
pip install -e ".[dev]"

ruff check .
ruff format .
mypy src/pywompi
pytest

Licencia

GPL — ver LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pywompi-0.1.0.tar.gz (29.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pywompi-0.1.0-py3-none-any.whl (23.5 kB view details)

Uploaded Python 3

File details

Details for the file pywompi-0.1.0.tar.gz.

File metadata

  • Download URL: pywompi-0.1.0.tar.gz
  • Upload date:
  • Size: 29.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pywompi-0.1.0.tar.gz
Algorithm Hash digest
SHA256 70ca7e02f919fc1d0ae9d5150474ab87dbd8b2f17a416448d971bb77624424fc
MD5 35a9d1438f0686c1be7b7932319117f4
BLAKE2b-256 3c6333ccdbe87656d77c25f2da6c1fcf81c887db8374a3c742931cbe8ca609f1

See more details on using hashes here.

Provenance

The following attestation bundles were made for pywompi-0.1.0.tar.gz:

Publisher: ci.yml on Roque-Studios/pywompi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pywompi-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pywompi-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 23.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pywompi-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c7931f1588c2fc1b61e53c78b9c7e7f4a28bd19ccded636ce2b5dbbfe7076a94
MD5 345eb3b4db5c12769455f6049829cd79
BLAKE2b-256 5e572de991ef697f6135e7bdf46b576576a945ab206bd72a698a48618f751a8b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pywompi-0.1.0-py3-none-any.whl:

Publisher: ci.yml on Roque-Studios/pywompi

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page