jonathan8312/wompi-colombia-laravel

Community Laravel SDK for the public Wompi Colombia API

Maintainers

Package info

github.com/Jonathan8312/wompi-colombia-laravel

pkg:composer/jonathan8312/wompi-colombia-laravel

Transparency log

Statistics

Installs: 3

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.1.0 2026-08-25 20:25 UTC

This package is auto-updated.

Last update: 2026-08-25 20:44:42 UTC


README

CI Packagist License

Community Laravel SDK for the public Wompi Colombia REST API.

This is not an official Wompi package. It is not built, maintained, endorsed, or supported by Wompi S.A. Use at your own risk and always verify critical behavior (amounts, transaction status, signature verification) against the official documentation at https://docs.wompi.co before relying on it in production.

What this package does

  • A thin, typed client over Wompi's REST API: merchants, card/Nequi tokenization, payment sources, transactions, PSE financial institutions, and payment links.
  • Verification of the SHA-256 checksum Wompi sends with every webhook event, plus an optional route + Laravel events so you can react to transaction.updated and related events without writing the signature-checking code yourself.
  • Typed exceptions per HTTP failure mode (validation, auth, not found, rate limit, server, connection) instead of generic HTTP client exceptions.

What this package does NOT do

  • It does not render the Wompi Widget/Checkout Web or any frontend UI — that stays in your views/JS, as Wompi documents.
  • It does not store transactions, payment sources, or webhook events in your database — that's your app's responsibility; this package only calls the API and, for webhooks, dispatches a Laravel event with the parsed payload.
  • It does not implement every single endpoint in the Wompi API (e.g. 3DS-specific flows, batch payment link operations). Contributions are welcome for anything missing.

Requirements

Requirement Version
PHP ^8.2
Laravel ^12.0 | ^13.0

Installation

composer require jonathan8312/wompi-colombia-laravel

The service provider is auto-discovered. Publish the config file if you want to customize it:

php artisan vendor:publish --tag=wompi-config

Configuration

Set your Wompi keys in .env. You can find them at comercios.wompi.co, under your merchant's settings.

Env variable Purpose
WOMPI_PUBLIC_KEY Public key. Safe to use client-side; required for every request.
WOMPI_PRIVATE_KEY Private key. Required for creating transactions, payment sources, and payment links. Never expose it client-side.
WOMPI_EVENTS_SECRET Used only to verify incoming webhook signatures.
WOMPI_INTEGRITY_SECRET Required to create transactions — Wompi rejects POST /transactions without an integrity checksum. This package computes and attaches it automatically.
WOMPI_ENVIRONMENT sandbox (default) or production. Controls which base URL is used.
WOMPI_WEBHOOKS_ENABLED true to auto-register the webhook route. Defaults to false.
WOMPI_WEBHOOKS_PATH Path for the auto-registered webhook route. Defaults to webhooks/wompi.

See docs/configuration.md for the full list, including timeouts and retry behavior, and docs/authentication.md for how the public/private key pair is used per endpoint and how to scope credentials per merchant.

Quick start

use Jonathan8312\Wompi\DataTransferObjects\Requests\PaymentMethod\CardPaymentMethod;
use Jonathan8312\Wompi\DataTransferObjects\Requests\TransactionRequest;
use Jonathan8312\Wompi\Wompi;

$wompi = app(Wompi::class); // or resolve via the 'wompi' container alias

// 1. Get the merchant's acceptance token (required on every transaction).
$merchant = $wompi->merchants()->find();
$acceptanceToken = $merchant->data()['presigned_acceptance']['acceptance_token'];

// 2. Tokenize a card (uses the public key — safe to run from a controller
//    that received the raw card data over your own HTTPS form, though in
//    production you should tokenize directly from the browser instead).
$token = $wompi->tokens()->card(new \Jonathan8312\Wompi\DataTransferObjects\Requests\CardTokenRequest(
    number: '4242424242424242',
    cvc: '123',
    expMonth: '12',
    expYear: '29',
    cardHolder: 'Jane Doe',
))->data()['id'];

// 3. Create the transaction with the private key.
$transaction = $wompi->transactions()->create(new TransactionRequest(
    amountInCents: 4490000,
    reference: 'ORDER-1234',
    customerEmail: 'buyer@example.com',
    paymentMethod: new CardPaymentMethod(token: $token),
    acceptanceToken: $acceptanceToken,
));

$transaction->data()['id'];     // e.g. "1234-1600000-abcde"
$transaction->data()['status']; // "PENDING" | "APPROVED" | "DECLINED" | ...

Available resources

Resource Docs
$wompi->merchants() docs/merchants.md
$wompi->tokens() docs/tokens.md
$wompi->paymentSources() docs/payment-sources.md
$wompi->transactions() docs/transactions.md
$wompi->pse() docs/pse.md
$wompi->paymentLinks() docs/payment-links.md

Every resource method returns a Jonathan8312\Wompi\Http\WompiResponse, which exposes ->status(), ->successful(), ->json(), and ->data() (a shortcut for the data key Wompi wraps every successful response in).

Webhooks

Wompi notifies your app of transaction status changes via webhooks. This package can verify the signature and dispatch a Laravel event for you:

WOMPI_EVENTS_SECRET=your_events_secret
WOMPI_WEBHOOKS_ENABLED=true
WOMPI_WEBHOOKS_PATH=webhooks/wompi
use Jonathan8312\Wompi\Webhooks\Events\TransactionUpdated;

// In a listener, e.g. EventServiceProvider
public function handle(TransactionUpdated $event): void
{
    $transaction = $event->payload->transaction();

    // ... update your order based on $transaction['id'] / $transaction['status']
}

Prefer to wire the route yourself? Set WOMPI_WEBHOOKS_ENABLED=false and use Jonathan8312\Wompi\Webhooks\WebhookSignatureVerifier directly. Full details in docs/webhooks.md.

Multi-merchant usage

Wompi is registered as an immutable singleton. withCredentials(), withPublicKey(), and withPrivateKey() always return a new instance rather than mutating the shared one, so it's safe to scope a request to a different merchant's keys (e.g. a SaaS platform with per-tenant Wompi accounts) without leaking credentials across requests:

$tenantWompi = app(Wompi::class)->withCredentials(
    new \Jonathan8312\Wompi\Credentials($tenant->wompi_public_key, $tenant->wompi_private_key)
);

See docs/authentication.md for why this is safe under Octane and where credentials are (and are not) stored.

Why not a Facade?

This package doesn't ship a static Illuminate\Support\Facades\Wompi facade — you resolve Wompi::class from the container (or its 'wompi' alias) directly, as shown throughout this README. Two reasons:

  1. Immutable multi-merchant scoping. withCredentials(), withPublicKey(), and withPrivateKey() return a new instance rather than mutating the shared singleton (see Multi-merchant usage above). A static facade makes it easy to call Wompi::withPublicKey(...) and assume it changed the app-wide instance, when really the return value is what you needed to keep.
  2. Testability without facade mocking. Every resource goes through Illuminate\Http\Client, so Http::fake() already covers testing (see Testing your own application) — there's no need for Wompi::shouldReceive(...)-style facade mocks, which would encourage mocking the SDK's own methods instead of the actual HTTP boundary.

Full rationale in docs/authentication.md.

Error handling

Every non-2xx response is translated into a typed exception, all extending Jonathan8312\Wompi\Exceptions\WompiException:

Exception HTTP status
ValidationException 422
AuthenticationException 401, 403
NotFoundException 404
RateLimitException 429 (exposes retryAfterSeconds())
ServerException 5xx
ConnectionException transport failure (timeout, DNS, TLS...)
RequestException anything else
use Jonathan8312\Wompi\Exceptions\ValidationException;
use Jonathan8312\Wompi\Exceptions\WompiException;

try {
    $wompi->transactions()->create($request);
} catch (ValidationException $e) {
    return back()->withErrors($e->errors());
} catch (WompiException $e) {
    report($e);
    return back()->with('error', 'No pudimos procesar tu pago, intenta de nuevo.');
}

See docs/errors.md for the full shape of errors().

Testing your own application

Every resource is built on Illuminate\Http\Client, so Http::fake() works out of the box:

use Illuminate\Support\Facades\Http;

Http::fake([
    'sandbox.wompi.co/*' => Http::response(['data' => ['id' => 'txn_1', 'status' => 'APPROVED']], 201),
]);

More patterns, including faking webhook signatures in Feature tests, are in docs/testing.md.

Security

  • Never log or expose WOMPI_PRIVATE_KEY, WOMPI_EVENTS_SECRET, or WOMPI_INTEGRITY_SECRET.
  • Webhook signature verification uses hash_equals() (constant-time comparison) — never bypass WebhookSignatureVerifier to parse a webhook body directly.
  • This package never follows HTTP redirects (withoutRedirecting()) as a defense against SSRF-style redirect abuse from a compromised or misconfigured base_url.

If you discover a security vulnerability in this package, please open a private security advisory on GitHub rather than a public issue.

Known limitations

See docs/known-issues.md.

Contributing

Issues and PRs are welcome. Please run composer format, composer analyse, and composer test before submitting.

Author

Jonathan Torres

License

MIT. See LICENSE.