jonathan8312 / wompi-colombia-laravel
Community Laravel SDK for the public Wompi Colombia API
Package info
github.com/Jonathan8312/wompi-colombia-laravel
pkg:composer/jonathan8312/wompi-colombia-laravel
Requires
- php: ^8.2
- ext-json: *
- illuminate/contracts: ^12.0|^13.0
- illuminate/http: ^12.0|^13.0
- illuminate/support: ^12.0|^13.0
Requires (Dev)
- larastan/larastan: ^3.0
- laravel/pint: ^1.0
- orchestra/testbench: ^10.0|^11.0
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^11.5.50|^12.5.8|^13.0.0
- vlucas/phpdotenv: ^5.6
README
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.updatedand 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:
- Immutable multi-merchant scoping.
withCredentials(),withPublicKey(), andwithPrivateKey()return a new instance rather than mutating the shared singleton (see Multi-merchant usage above). A static facade makes it easy to callWompi::withPublicKey(...)and assume it changed the app-wide instance, when really the return value is what you needed to keep. - Testability without facade mocking. Every resource goes through
Illuminate\Http\Client, soHttp::fake()already covers testing (see Testing your own application) — there's no need forWompi::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, orWOMPI_INTEGRITY_SECRET. - Webhook signature verification uses
hash_equals()(constant-time comparison) — never bypassWebhookSignatureVerifierto parse a webhook body directly. - This package never follows HTTP redirects (
withoutRedirecting()) as a defense against SSRF-style redirect abuse from a compromised or misconfiguredbase_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
License
MIT. See LICENSE.