baks-dev/ozon-orders
Laravel/PHP модуль для интеграции заказов Ozon (FBS/DBS). Установка через Composer, команды консоли для добавления типа профиля, оплаты и доставки для Ozon. Поддерживает PHP 8.4+, включает тесты (группа ozon-orders).
Install the Package
composer require baks-dev/ozon-orders
Ensure your project uses Laravel 10+ and PHP 8.4+.
Publish Configuration (if needed)
Check for config files (e.g., config/ozon-orders.php) and publish them:
php artisan vendor:publish --provider="BaksDev\OzonOrders\OzonOrdersServiceProvider"
Set Up Ozon Credentials
Add your Ozon API credentials (e.g., OZON_API_KEY, OZON_SECRET_KEY) to your .env:
OZON_FBS_API_KEY=your_fbs_key
OZON_DBS_API_KEY=your_dbs_key
Run Initialization Commands Choose either FBS or DBS (or both):
# For FBS
php artisan baks:users-profile-type:ozon-fbs
php artisan baks:payment:ozon-fbs
php artisan baks:delivery:ozon-fbs
# For DBS
php artisan baks:users-profile-type:ozon-dbs
php artisan baks:payment:ozon-dbs
php artisan baks:delivery:ozon-dbs
Set Up Webhook Endpoint
Create a route to handle Ozon webhooks (e.g., routes/web.php):
Route::post('/ozon/webhook', [OzonWebhookController::class, 'handle']);
Implement OzonWebhookController to process incoming webhook events (see Gotchas).
Test with Sandbox Run PHPUnit tests to validate basic functionality:
php artisan test --group=ozon-orders
To create an order in Ozon via the package:
use BaksDev\OzonOrders\Facades\OzonOrder;
$orderData = [
'external_id' => 'your_order_id_123',
'items' => [
['external_id' => 'sku_456', 'price' => 1000, 'quantity' => 2],
],
'buyer' => ['email' => 'customer@example.com', 'phone' => '+79123456789'],
];
$ozonOrder = OzonOrder::create($orderData, 'fbs'); // or 'dbs'
OzonOrder::create() with fbs/dbs mode.order.status_changed events (webhook-triggered).baks:payment:ozon-{fbs|dbs}).payment.status_changed events in your controller.
public function handlePaymentWebhook(Request $request) {
$event = OzonWebhook::parse($request->json()->all());
if ($event->type === 'payment.status_changed') {
Payment::syncWithOzon($event->data);
}
}
baks:delivery:ozon-dbs).delivery.status_changed triggers sync:
public function handleDeliveryWebhook(Request $request) {
$event = OzonWebhook::parse($request->json()->all());
if ($event->type === 'delivery.status_changed') {
Delivery::updateTracking($event->data);
}
}
Service Providers
Bind the package’s services in AppServiceProvider:
$this->app->singleton(OzonOrder::class, function ($app) {
return new OzonOrder($app->make(OzonClient::class));
});
Queue Jobs for Async Processing Offload webhook handling to queues:
public function handleWebhook(Request $request) {
OzonWebhookJob::dispatch($request->json()->all());
}
Events and Listeners Dispatch custom events for order/payment lifecycle:
// In OzonOrder::create()
event(new OrderCreated($ozonOrder));
// Listen in EventServiceProvider
protected $listen = [
OrderCreated::class => [
SyncInventory::class,
NotifyCustomer::class,
],
];
API Client Customization
Extend OzonClient for retries/timeouts:
$client = new OzonClient([
'timeout' => 30,
'retry' => 3,
]);
OZON_SANDBOX=true # Enable sandbox mode in .env
Override the client in AppServiceProvider:
$client = config('ozon.sandbox')
? new OzonClient(['sandbox' => true])
: new OzonClient();
Webhook Idempotency
public function handle(Request $request) {
$signature = $request->header('X-Ozon-Signature');
if (!OzonWebhook::validateSignature($request->json()->all(), $signature)) {
abort(403, 'Invalid signature');
}
// Process only if not already handled
if (!OzonWebhook::isProcessed($request->json()->all())) {
OzonWebhook::markAsProcessed($request->json()->all());
// ... handle logic
}
}
Schema Assumptions
users_profile_types, payments, and deliveries. If your schema differs:
ozon_orders:
Schema::create('ozon_orders', function (Blueprint $table) {
$table->id();
$table->string('external_id')->unique();
$table->string('ozon_id')->nullable();
$table->enum('mode', ['fbs', 'dbs']);
$table->json('metadata');
$table->timestamps();
});
CLI Command Idempotency
// In your command
if (ProfileType::where('name', 'ozon_fbs')->exists()) {
$this->info('Profile type already exists.');
return;
}
Rate Limiting
OzonClient:
use Symfony\Component\HttpClient\RetryableHttpClient;
$client = new RetryableHttpClient([
'max_retries' => 3,
'delay' => 1000,
'multiplier' => 2,
]);
Timezone Mismatches
APP_TIMEZONE=UTC
Enable Debug Logging
Add to config/logging.php:
'channels' => [
'ozon' => [
'driver' => 'single',
'path' => storage_path('logs/ozon.log'),
'level' => 'debug',
],
],
Then log requests/responses in OzonClient:
\Log::channel('ozon')->debug('Ozon API Request', [
'url' => $url,
'data' => $data,
'response' => $response->getContent(),
]);
Validate API Responses
Use Laravel’s Validator to check Ozon responses:
use Illuminate\Support\Facades\Validator;
$validator = Validator::make($response->json(), [
'result' => 'required|boolean',
'data' => 'sometimes|array',
'errors' => 'sometimes|array',
]);
if ($validator->fails()) {
\Log::error('Ozon API validation failed', $validator->errors());
throw new \RuntimeException('Ozon API error');
}
Sandbox Testing Test thoroughly in Ozon’s sandbox before going live:
How can I help you explore Laravel packages today?