gepur-it/one-c-client
A Laravel/PHP client for integrating applications with 1C:Enterprise. It provides a simple, configurable interface for sending requests to 1C services and handling responses, helping streamline synchronization and data exchange between your app and 1C.
gepur-it/one-c-client is a thin transport-layer wrapper for talking to a 1C:Enterprise web service from Laravel. It does not model 1C entities for you — it gives you a configured client so you stop hand-rolling SoapClient/Guzzle calls in every controller. Treat it as plumbing, not as an ORM.
Install and configure
composer require gepur-it/one-c-client
php artisan vendor:publish --provider="GepurIt\\OneCClient\\OneCClientServiceProvider"
The published config is where the real work starts. You will be filling in the 1C endpoint (base URI or WSDL), the infobase name, credentials, and a timeout. Mirror those in .env so staging and production point at different 1C instances:
ONE_C_HOST=https://1c.internal.example
ONE_C_BASE=erp_demo
ONE_C_USER=api_user
ONE_C_PASSWORD=secret
ONE_C_TIMEOUT=30
Where to look first
Read the package service provider before anything else — with a package this small the provider and the client class are the documentation. Confirm the binding name you should type-hint, confirm the config key names, and confirm the Composer constraints on illuminate/* before you plan around it.
The v5.2.0 release (fixed tests and update php 8) tells you two useful things: the package is not abandoned, and its test suite is green on PHP 8. What it does not tell you is how far forward the Laravel constraint goes — a PHP 8 bump usually means Laravel 8/9-era support, not necessarily 10/11. Run composer why-not gepur-it/one-c-client against your target framework version, and check the php constraint in composer.json to see whether it demands ^8.0 or something narrower than your runtime. If it blocks your upgrade, the surface area is small enough to fork into app/Support/OneC.
First use case
The lowest-risk first call is a read: pull a catalog, price list, or stock balance from 1C and dump the raw payload. Do this in php artisan tinker or a one-off command, not in a controller. You want to see the actual response shape — element names, namespaces, encoding — before writing a single mapping class.
$client = app(\GepurIt\OneCClient\OneCClient::class);
$raw = $client->request('GetPrices', ['date' => now()->toDateString()]);
dump($raw);
Only once that returns real data do you build anything on top of it.
Wrap it, never inject it into controllers. The package's client is a low-level dependency and its API is still unversioned in spirit — the 5.2.0 release was a maintenance bump, not a feature release, so nothing about the public surface has been stabilised for you. Put a domain service between your app and the package:
class OneCPriceRepository
{
public function __construct(private OneCClient $client) {}
public function pricesFor(Carbon $date): Collection
{
$response = $this->client->request('GetPrices', [
'date' => $date->format('Y-m-d\THH:i:s'),
]);
return collect($response['Price'] ?? [])
->map(fn (array $row) => new PriceDto(
sku: (string) $row['Code'],
amount: (float) $row['Sum'],
));
}
}
Now the rest of the app speaks in PriceDto, and the day the package dies you swap one class.
Push operations belong in jobs. Any write to 1C (create order, post invoice, update counterparty) should be a queued job with $tries = 3, backoff() and a unique key derived from your own record ID so retries do not duplicate documents in 1C:
class PushOrderTo1C implements ShouldQueue
{
public int $tries = 3;
public array $backoff = [10, 60, 300];
public function __construct(public int $orderId) {}
public function handle(OneCOrderService $service): void
{
$service->upsert(Order::findOrFail($this->orderId));
}
public function uniqueId(): string
{
return (string) $this->orderId;
}
}
Cache the reads. 1C is slow and your catalog endpoint gets hit constantly. Cache::remember("1c.prices.{$date}", 900, ...) in front of the repository removes most of the pain. Invalidate on the queue job that knows data changed.
Test with a fake binding, not a real 1C. Register a stub implementation of your OneCPriceRepository interface in the test container. If the package client is concrete, bind a mock via $this->mock(OneCClient::class) and assert the request name and payload arguments. Never let CI depend on a reachable 1C instance. Since 5.2.0 targets PHP 8, run your own suite on the same PHP minor your production container uses — the package's "fixed tests" claim says nothing about the PHP 8.2/8.3 deprecations you may hit in your code around it.
Keep environment differences in config, not code. The 1C test infobase and production infobase almost always differ in document numbering and permissions. One config key, two sets of .env values.
composer.json now says ^8.0, ^8.1, or higher, and which illuminate/* majors it allows. Pin the exact version ("gepur-it/one-c-client": "5.2.0") in composer.json and commit the lock file; do not use a floating constraint.200 OK frequently carries an <error> or diagnostic payload inside the body. Validate the response structure before you trust it; a try/catch around the transport call will not save you here.mb_convert_encoding($value, 'UTF-8', 'Windows-1251') and check whether the package already does this for you. Note that PHP 8's stricter string/type handling can surface encoding bugs that were silently tolerated on PHP 7.ext-soap may be required. If the package wraps a SOAP/WSDL endpoint, php -m | grep soap in the container before debugging anything else. WSDL caching behavior is worth a config flag in dev. If you upgraded the base image to get PHP 8, re-check that the SOAP extension came with it — slim images often drop it.Bottom line: 5.2.0 removes the biggest historical objection — it runs on PHP 8 and its tests pass — so it is a reasonable starting point for a greenfield 1C integration on a Laravel 8/9-era stack. It does not add features or fix integration quirks, so still budget time for reading the source, wrap the client in your own service, and keep a forking plan in your back pocket.
How can I help you explore Laravel packages today?