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

Smoney Laravel Package

spyrit/smoney

sMoney is a Laravel package for working with monetary values and currencies, providing helpers to format, convert, and calculate money so pricing and financial data stay consistent and precise across your application.

View on GitHub
Deep Wiki
Context7

Getting Started

spyrit/smoney is a thin PHP wrapper around the S-Money (S-Money by Natixis) REST API. It is a raw client, not a Laravel package — expect no service provider, no facade, and no config file. With 0 stars and 0 dependents, treat it as a starting point to vendor/fork, not as a maintained dependency.

Minimal install:

composer require spyrit/smoney

If Composer refuses to resolve it against your Laravel version, inspect the constraints before fighting them:

composer show spyrit/smoney --all
composer why-not spyrit/smoney

Typical blockers are an old PHP floor (^5.6 || ^7.0) and a Guzzle major version that conflicts with guzzlehttp/guzzle pulled in by Laravel/Socialite/etc. If so, either run it in a separate small service or fork it and bump composer.json (see Gotchas).

Where to look first, in this order:

  1. vendor/spyrit/smoney/README.md and any examples/ directory — the official S-Money docs are the only real API reference and may no longer be online.
  2. vendor/spyrit/smoney/src/ — confirm the actual FQCN of the client, the exception classes, and how credentials are passed (constructor vs. setter).
  3. The base URI constants — you need the sandbox and production hosts explicitly. Hardcode both in your own config; do not rely on a default.
  4. Your S-Money merchant dashboard for client_id / client_secret (or API key) and the sandbox account.

Your first use case should be read-only: instantiate the client against sandbox, authenticate, and perform a GET — list payments, fetch a user, or read a wallet balance. Do not start with payment creation; a successful read proves credentials, base URL, and TLS are correct without moving money.

// config/smoney.php
return [
    'base_uri'    => env('SMONEY_BASE_URI', 'https://sandbox.s-money.fr/...'),
    'client_id'   => env('SMONEY_CLIENT_ID'),
    'client_secret' => env('SMONEY_CLIENT_SECRET'),
    'timeout'     => env('SMONEY_TIMEOUT', 15),
];

Implementation Patterns

Bind the client as a singleton. Since the package has no provider, write your own and keep the vendor client out of your application code:

// app/Providers/SmoneyServiceProvider.php
public function register(): void
{
    $this->app->singleton(\SMoney\Client::class, fn () => new \SMoney\Client(
        config('smoney.base_uri'),
        config('smoney.client_id'),
        config('smoney.client_secret'),
    ));
}

(Verify the real class name and signature in src/ — the repo is a fork of the official v1 client and the constructor may take an options array or a Guzzle client.)

Wrap it in a domain service, not in controllers. Every call site should go through one class so the eventual fork/replacement is a one-file change:

final class SmoneyGateway
{
    public function __construct(private \SMoney\Client $client) {}

    public function createPayment(PaymentIntent $intent): PaymentResult
    {
        // map your domain object to the vendor payload here
    }
}

Queue anything that mutates money. Payment creation, refunds, and payouts should be jobs with retries and a stored idempotency key so a redelivered job doesn't double-charge.

Put incoming notifications behind a dedicated route. S-Money pushes payment/transfer status via HTTP callbacks. Keep the controller tiny: verify signature/secret, persist the raw payload, dispatch a job, return 200 quickly. Store the raw body — you will need it for replay when debugging.

Keep amounts as integers in minor units end-to-end. Convert at the boundary only. Floating-point euros in your DB will eventually disagree with the provider by a cent.

Test with a Guzzle mock handler, not the real API:

$mock = new \GuzzleHttp\Handler\MockHandler([new \GuzzleHttp\Psr7\Response(200, [], '{"..."}')]);

Inject the HandlerStack into the client in a test binding. If the package hides its Guzzle client, use Mockery on the wrapper instead — this is a strong argument for the SmoneyGateway seam.

Gotchas and Tips

  • The API is the risk, not the code. S-Money's platform has been folded into Natixis Payments and the public v1 API docs are effectively gone. Confirm with the provider that your account and endpoints are still live before building against it. If they are not, this package is dead weight.
  • Assume unmaintained. Pin an exact version (composer require spyrit/smoney:1.x.y), commit composer.lock, and vendor the source or fork it into packages/ with a path repository so you can patch it when PHP/Guzzle move.
  • Guzzle version conflicts are the most likely install failure. Forking and relaxing the constraint is usually faster than downgrading the rest of your app.
  • Exceptions are coarse. The client may throw on any non-2xx and hand you a decoded body or a raw string inconsistently. Wrap every call in a try/catch, normalize into your own exception hierarchy, and always log the status code plus the provider's error code — never the client_secret.
  • Timeouts and retries belong to Guzzle, not the package. Set timeout and connect_timeout explicitly; the default is "wait forever", which is unacceptable on a checkout path. Retry only idempotent GETs automatically.
  • Base URI trailing slashes are a classic 404 source when the client concatenates paths naively. Test the exact production URL string, not just sandbox.
  • Callback verification. Don't trust the payload's status field. Verify the shared secret/signature if one is provided, and re-fetch the resource from the API before marking an order paid.
  • Sandbox and production credentials are not interchangeable, and sandbox responses are often syntactically different (missing fields, different statuses). Don't build parsers that assume every field is present.
  • Extension points are limited to subclassing and decoration — there is no event system. Keep your SmoneyGateway thin so a replacement (PayPlug, Mangopay, Stripe) is a swap, not a rewrite.
  • Log hygiene: payment payloads contain PII and account identifiers. Redact before writing to logs and never dump the full request/response in production.
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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource