apiKey = config('courier.api_key'); $this->baseUrl = config('courier.api_base_url', 'https://api.shiplogic.com/api'); } /** * Create a shipment with Shiplogic * * @param string $orderId * @param float $width Width in cm * @param float $length Length in cm * @param float $weight Weight in kg * @return array{shipment_id: string, waybill_id: string, tracking_number: string} * @throws \Exception */ public function createShipment(string $orderId, float $width, float $length, float $weight): array { if (! $this->isConfigured()) { throw new \Exception('Courier API not configured'); } if ($width <= 0 || $length <= 0 || $weight <= 0) { throw new \Exception('Invalid dimensions or weight: all must be greater than 0'); } try { // Build shipment payload for Shiplogic $payload = [ 'parcel' => [ 'weight' => $weight, 'height' => 10, // TODO: Update when height is captured separately 'width' => $width, 'length' => $length, ], 'destination' => [ // TODO: Get from order's shipping address ], 'reference' => $orderId, ]; $response = Http::withHeaders([ 'Authorization' => "Bearer {$this->apiKey}", ])->post("{$this->baseUrl}/shipments", $payload); if (! $response->successful()) { $errorMessage = $response->json('error.message', 'Unknown error'); throw new \Exception("Courier API error: {$errorMessage}"); } $data = $response->json(); return [ 'shipment_id' => $data['id'] ?? null, 'waybill_id' => $data['waybill_number'] ?? null, 'tracking_number' => $data['tracking_number'] ?? null, ]; } catch (\Exception $e) { Log::error('Failed to create shipment with courier', [ 'order_id' => $orderId, 'error' => $e->getMessage(), ]); throw $e; } } /** * Fetch shipping label/sticker PDF from Shiplogic */ public function fetchSticker(string $shipmentId, string $orderId): ?string { if (! $this->isConfigured()) { return null; } try { $response = Http::withHeaders([ 'Authorization' => "Bearer {$this->apiKey}", ])->get("{$this->baseUrl}/shipments/{$shipmentId}/sticker"); if ($response->successful()) { $path = "shipments/{$orderId}/sticker.pdf"; Storage::disk('public')->put($path, $response->body()); return $path; } Log::warning('Failed to fetch sticker from courier', ['shipment_id' => $shipmentId]); return null; } catch (\Exception $e) { Log::error('Exception fetching sticker', ['error' => $e->getMessage()]); return null; } } /** * Fetch waybill PDF from Shiplogic */ public function fetchWaybill(string $shipmentId, string $orderId): ?string { if (! $this->isConfigured()) { return null; } try { $response = Http::withHeaders([ 'Authorization' => "Bearer {$this->apiKey}", ])->get("{$this->baseUrl}/shipments/{$shipmentId}/label"); if ($response->successful()) { $path = "shipments/{$orderId}/waybill.pdf"; Storage::disk('public')->put($path, $response->body()); return $path; } Log::warning('Failed to fetch waybill from courier', ['shipment_id' => $shipmentId]); return null; } catch (\Exception $e) { Log::error('Exception fetching waybill', ['error' => $e->getMessage()]); return null; } } /** * Check if courier is configured */ protected function isConfigured(): bool { return ! empty($this->apiKey); } }