kiakaha/chargily-v2
Laravel package for integrating Chargily Pay v2, Algeria's online payment gateway. Provides a simple API for creating checkout sessions, handling payments and verifying webhooks, so you can accept CIB and Edahabia card payments in your PHP application with minimal setup.
Architecture fit. Chargily ePay V2 is a hosted-checkout / redirect payment gateway (CIB and Edahabia cards, DZD settlement, Algerian merchant market). The package wraps the V2 API surface — checkout session creation plus webhook notification handling. That is the right shape for a Laravel application: no card data touches our servers, PCI scope stays at SAQ A/A-EP, and the integration is a small bounded adapter around our order state machine.
The material caveat is the release title itself: "Chargily V2 Epay for symfony." This is packaged as a Symfony bundle, not a Laravel package. There is no evidence of Laravel auto-discovery, a publishable config, a facade, or Laravel-idiomatic exception types. We can still consume it — the container and the HTTP client abstractions are compatible enough — but it introduces bridging glue into our payment path, and payment paths are the worst place for bespoke glue.
Integration feasibility. Feasible. Composer-installable, PSR-4, presumably depends on symfony/http-client and possibly symfony/event-dispatcher. Realistic effort for a Laravel team is one to two engineer-days for a sandbox spike, one week for a production-grade integration including webhooks, reconciliation, and observability. The blockers are not conceptual; they are the usual unknowns of a young package.
Technical risk. Ranked:
signature header (HMAC-SHA256 over the raw request body, timing-safe comparison). If it verifies a parsed/re-serialized payload instead of the raw bytes, signature checks will intermittently fail or, worse, be bypassable. This is the single highest-severity thing to read line by line before adoption.Key questions. (Send these to the maintainer / answer in the spike.)
composer.json constraints: PHP version, Laravel versions supported, Symfony component version ranges. Any conflicts with our current lockfile?config/app.php?hash_equals?int minor units or float Decimal?Stack fit. Assume PHP 8.1+, Laravel 10/11/12, and a Symfony HTTP client underneath. Two viable shapes:
ChargilyServiceProvider in our app, bind a Laravel-configured client instance into the Symfony container, and call it only from a single ChargilyGateway class implementing our own PaymentGateway interface.PaymentGateway contract and DTOs (CheckoutRequest, CheckoutResult, WebhookEvent) and implement a ChargilyV2Adapter that delegates to the package. This costs maybe a day and buys us the ability to swap in a hand-rolled HTTP client or an official Laravel package without touching domain code.Do not let the package's types appear in controllers, models, jobs, or event listeners. The blast radius of a v1.x payment dependency must be one file.
Migration path. Treat this as a greenfield integration unless we are replacing a legacy Chargily V1 integration, in which case the vendor migration is the real project and the package is a detail:
payment_events table with a unique constraint on the gateway event ID, and queued processing.Compatibility. Before writing any code: composer why-not against our lockfile for symfony/http-client, symfony/event-dispatcher, and psr/http-client. Check whether it conflicts with our existing HTTP client (we likely already have Guzzle via Laravel). If both land, confirm the Symfony client does not silently use a different transport with different timeout/retry defaults than the rest of the app. Verify behavior under Laravel Octane: long-lived workers plus a Symfony container binding is a known source of stale-config bugs.
Sequencing. Spike (2 days) → adapter + config (2 days) → webhook pipeline with signature verification and idempotency (3 days) → reconciliation + observability (2 days) → shadow run (1–2 weeks of real traffic) → cutover. Front-load the webhook signature review; if it is wrong, adopt a plan where we verify signatures ourselves and treat the package as a serializer only.
Maintenance. Pin to an exact version, not a caret range. Keep a fork-ready posture: vendored patch capability, an internal README noting the diff between upstream and our fork if one appears. Watch the upstream repository for releases — given the release-note quality, budget for reading actual diffs rather than changelogs. Assume breaking changes may arrive inside a minor version until the project demonstrates otherwise; a v1.0.1 is pre-stability in practice regardless of what semver says.
Support. No vendor SLA is evidenced. Support is GitHub issues, in a timezone and language context that may not match our on-call rotation. Operationally that means we are the support tier for this package: our on-call must be able to read the source, and we should have an incident playbook that does not begin with "wait for upstream." Financially, Chargily's merchant support and our use of the package are separate concerns — KYC, settlement disputes, and refunds route through the PSP, not the library.
Scaling. The package will not be the bottleneck. Throughput is bounded by Chargily's rate limits and settlement windows, not by PHP. The parts that scale non-linearly with order volume are ours: webhook ingestion (must be queued, not inline), the payment_events table (partition or archive), and reconciliation polling (batch, off-peak). Redirect-based checkout means our request path holds no long-lived connections, which is a real advantage under load.
Failure modes. Design for these explicitly:
APP_ENV disagree.Ramp-up. One to two engineer-days for a Laravel developer already comfortable with payments; add roughly half a day for the Symfony-bundle bridging and another half-day for the webhook raw-body subtlety. On-call needs a written runbook covering: how to verify a webhook by hand, how to force a reconciliation, how to rotate keys, how to identify which orders are pending in the gateway, and who to contact at Chargily. Finance needs a documented daily reconciliation report before the first live transaction — not after the first discrepancy.
How can I help you explore Laravel packages today?