Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Chargily V2 Laravel Package

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.

View on GitHub
Deep Wiki
Context7

Getting Started

  • Install with composer require chargily/epay-symfony (confirm the exact package name from Packagist — the release note only states "Chargily V2 Epay for symfony").
  • Read the README first, specifically for the config keys (API key/secret, mode sandbox vs live, base URL) and the entry-point class that creates a checkout. In a Symfony bundle this is usually a *Client or *Api service registered via a bundle extension, not a Laravel facade.
  • Because this ships as a Symfony bundle, the fastest path in Laravel is not to register the bundle. Instead, instantiate the underlying client/service directly in a small Laravel service class, or bind it in AppServiceProvider's register() so you can inject it.
  • First use case: create a checkout for a fixed amount, redirect the customer to the returned payment URL, and expose a webhook route. Get that end-to-end loop working in sandbox before touching fulfillment logic.
  • Look at the bundle's DependencyInjection/ folder to see which constructor arguments the client expects — that tells you exactly what to bind in Laravel.

Implementation Patterns

Bind the client in a service provider

// AppServiceProvider::register()
$this->app->singleton(ChargilyClient::class, fn () => new ChargilyClient(
    config('services.chargily.secret'),
    config('services.chargily.mode'), // 'test' | 'live'
));

Keep credentials in config/services.php and .env, never in the package config file.

Wrap it in your own gateway class

Don't call the package client from controllers. Create App\Services\ChargilyGateway with methods like createCheckout(Order $order): CheckoutResult and verifyWebhook(Request $request): bool. This isolates the Symfony-ism and gives you one place to swap implementations or add retries/logging.

Checkout flow

  1. Persist an order/payment record in pending state with a generated idempotency key.
  2. Call the client to create a checkout, passing amount, currency, success/cancel URLs, and your reference/metadata.
  3. Store the returned checkout ID against your payment record before redirecting.
  4. Redirect the user with redirect()->away($checkoutUrl) — do not use a relative redirect, the URL is external.

Webhook handling

Route::post('/webhooks/chargily', ChargilyWebhookController::class)
    ->withoutMiddleware([VerifyCsrfToken::class]);

Then, in the controller:

  • Verify the signature header against the raw request body ($request->getContent()), not the parsed array.
  • Reject on mismatch with a 403 and log it.
  • Look up your payment record by the checkout/invoice ID in the payload, not by customer-supplied data.
  • Make the handler idempotent — gate on current status (if ($payment->status === 'paid') return response()->noContent();).
  • Return 200 quickly; dispatch a queued job for anything slow (emails, provisioning, invoice generation).

Status reconciliation

Never trust the redirect/success URL alone — the customer can hit it without paying. Treat the webhook as the source of truth, and optionally add a chargily:reconcile artisan command that polls pending payments older than N minutes.

Testing

Since there's no Laravel fake provided, wrap the client behind your ChargilyGateway interface and bind a fake in tests. For webhook tests, build a payload, compute the signature with your test secret, and $this->call('POST', ..., [], [], [], ['HTTP_Signature' => $sig], $json).

Gotchas and Tips

  • It's a Symfony bundle, not a Laravel package. There is (per the release note) no service provider, facade, publishable config, or Http client integration. Don't run php artisan vendor:publish expecting anything. Manual wiring is required, and bundle auto-discovery won't help you.
  • Two HTTP stacks. If the package uses Symfony's HttpClient, you won't get Laravel's Http fake, retry macros, or event hooks. Wrap calls and add your own timeout/retry (->retry(3, 200) on a Laravel-side wrapper, or configure the Symfony client's max_duration).
  • Amount units — verify this explicitly. Chargily (like most DZD gateways) generally expects the smallest currency unit. Confirm in the README whether 5000 means 50.00 DZD or 5000 DZD. Getting this wrong by 100x is the single most common integration bug.
  • Signature verification is easy to get wrong. Laravel will happily parse JSON into $request->all(), which re-encodes differently and breaks HMACs. Always hash $request->getContent(). Also confirm the exact header name and hash algorithm from the docs — do not guess.
  • Webhook route and CSRF. Easy to forget withoutMiddleware; you'll see 419 errors in logs and assume the gateway is broken.
  • No Laravel events. You'll want to fire your own (PaymentSucceeded, PaymentFailed) from the webhook handler rather than relying on package callbacks.
  • Config caching. If you read credentials at construction time, make sure config() calls happen in a closure or a booted callback — reading env vars directly in a package constructor breaks under php artisan config:cache.
  • Sandbox vs live. Check whether mode is a constructor arg, a config value, or encoded in the API key. Mixing them silently produces 401s that look like auth bugs.
  • Redirect URLs must be absolute and reachable from the internet. APP_URL misconfiguration (e.g. http://localhost) will pass in sandbox testing but break webhooks in production — use route() with a properly configured APP_URL or ngrok/expose locally.
  • Version pinning. v1.0.1 is a patch release with no changelog detail beyond the package description. Pin to ^1.0 and read the diff between tags before upgrading — there's no evidence yet of a stable BC policy.
  • Extension points are thin. Expect to extend nothing and wrap everything. That's fine — a 30-line ChargilyGateway adapter is cheaper than fighting a bundle's DI container inside Laravel.
  • If this stalls, the fallback is trivial: the Epay V2 API is a small REST surface (create checkout, retrieve checkout, list products/prices). A direct Http::withToken(...) implementation is a reasonable escape hatch and removes the Symfony dependency entirely.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin