diff --git a/classes/Carrier/SendCloud/SendCloudApi.php b/classes/Carrier/SendCloud/SendCloudApi.php index 9099f8de..18f87bff 100644 --- a/classes/Carrier/SendCloud/SendCloudApi.php +++ b/classes/Carrier/SendCloud/SendCloudApi.php @@ -28,16 +28,21 @@ class SendCloudApi $this->private_key = $private_key; } + /** + * @throws SendcloudApiException + */ public function GetSenderAddresses(): array { $uri = self::PROD_BASE_URI . '/user/addresses/sender'; $response = $this->sendRequest($uri); - $res = array(); - foreach ($response->sender_addresses as $item) + foreach ($response['body']->sender_addresses as $item) $res[] = SenderAddress::fromApiResponse($item); - return $res; + return $res ?? []; } + /** + * @throws SendcloudApiException + */ public function GetShippingProducts(string $sourceCountry, ?string $targetCountry = null, ?int $weight = null, ?int $height = null, ?int $length = null, ?int $width = null): array { @@ -60,26 +65,36 @@ class SendCloudApi $params['width_unit'] = 'centimeter'; } $response = $this->sendRequest($uri, $params); - return array_map(fn($x) => ShippingProduct::fromApiResponse($x), $response ?? []); + return array_map(fn($x) => ShippingProduct::fromApiResponse($x), $response['body'] ?? []); } + /** + * @throws SendcloudApiException + */ public function CreateParcel(ParcelCreation $parcel): ParcelResponse|string|null { $uri = self::PROD_BASE_URI . '/parcels'; - $response = $this->sendRequest($uri, null, true, [ - 'parcel' => $parcel->toApiRequest() - ]); - try { - if (isset($response->parcel)) - return ParcelResponse::fromApiResponse($response->parcel); - if (isset($response->error)) - return $response->error->message; - } catch (Exception $e) { - return $e->getMessage(); - } - return null; + $response = $this->sendRequest($uri, null, true, ['parcel' => $parcel->toApiRequest()], [200,400]); + switch ($response['code']) { + case 200: + if (isset($response->parcel)) + try { + return ParcelResponse::fromApiResponse($response->parcel); + } catch (Exception $e) { + throw new SendcloudApiException(previous: $e); + } + break; + case 400: + if (isset($response->error)) + return $response->error->message; + break; + } + throw SendcloudApiException::fromResponse($response); } + /** + * @throws SendcloudApiException + */ public function DownloadDocument(Document $document): string { $curl = curl_init(); @@ -90,10 +105,18 @@ class SendCloudApi "Authorization: Basic " . base64_encode($this->public_key . ':' . $this->private_key) ], ]); - return curl_exec($curl); + $output = curl_exec($curl); + $code = curl_getinfo($curl, CURLINFO_RESPONSE_CODE); + if ($code != 200) + throw SendcloudApiException::fromResponse(['code' => $code, 'body' => $output]); + return $output; } - function sendRequest(string $uri, array $query_params = null, bool $post = false, array $postFields = null) + /** + * @throws SendcloudApiException + */ + function sendRequest(string $uri, array $query_params = null, bool $post = false, array $postFields = null, + array $allowedResponseCodes = [200]): ?array { if (empty($this->public_key) || empty($this->private_key)) return null; @@ -117,9 +140,18 @@ class SendCloudApi ]); } - $output = curl_exec($curl); + $output = json_decode(curl_exec($curl)); + $code = curl_getinfo($curl, CURLINFO_RESPONSE_CODE); curl_close($curl); - return json_decode($output); + $ret = [ + 'code' => $code, + 'body' => $output, + ]; + + if (!in_array($code, $allowedResponseCodes)) + throw SendcloudApiException::fromResponse($ret); + + return $ret; } } \ No newline at end of file diff --git a/classes/Carrier/SendCloud/SendcloudApiException.php b/classes/Carrier/SendCloud/SendcloudApiException.php new file mode 100644 index 00000000..247fa9af --- /dev/null +++ b/classes/Carrier/SendCloud/SendcloudApiException.php @@ -0,0 +1,18 @@ +error->message ?? '', + $response['body']->error->code ?? 0 + ); + } +} \ No newline at end of file diff --git a/www/lib/versandarten/sendcloud.php b/www/lib/versandarten/sendcloud.php index 1b426290..a14e6225 100644 --- a/www/lib/versandarten/sendcloud.php +++ b/www/lib/versandarten/sendcloud.php @@ -8,6 +8,7 @@ use Xentral\Carrier\SendCloud\SendCloudApi; use Xentral\Carrier\SendCloud\Data\SenderAddress; use Xentral\Carrier\SendCloud\Data\ShippingProduct; use Xentral\Carrier\SendCloud\Data\ShippingMethod; +use Xentral\Carrier\SendCloud\SendcloudApiException; require_once dirname(__DIR__) . '/class.versanddienstleister.php'; @@ -22,6 +23,32 @@ class Versandart_sendcloud extends Versanddienstleister if (!isset($this->id)) return; $this->api = new SendCloudApi($this->settings->public_key, $this->settings->private_key); + } + + protected function FetchOptionsFromApi() + { + if (isset($this->options)) + return; + try { + $list = $this->api->GetSenderAddresses(); + foreach ($list as $item) { + /* @var SenderAddress $item */ + $senderAddresses[$item->Id] = $item; + } + $senderCountry = $senderAddresses[$this->settings->sender_address]->Country ?? 'DE'; + $list = $this->api->GetShippingProducts($senderCountry); + foreach ($list as $item) { + /* @var ShippingProduct $item */ + $shippingProducts[$item->Code] = $item; + } + } catch (SendcloudApiException $e) { + $this->app->Tpl->addMessage('error', $e->getMessage()); + } + $this->options['senders'] = array_map(fn(SenderAddress $x) => strval($x), $senderAddresses ?? []); + $this->options['products'] = array_map(fn(ShippingProduct $x) => $x->Name, $shippingProducts ?? []); + $this->options['products'][0] = ''; + $this->options['selectedProduct'] = $shippingProducts[$this->settings->shipping_product] ?? []; + natcasesort($this->options['products']); $this->options['customs_shipment_types'] = [ 0 => 'Geschenk', 1 => 'Dokumente', @@ -31,27 +58,6 @@ class Versandart_sendcloud extends Versanddienstleister ]; } - protected function FetchOptionsFromApi() - { - $list = $this->api->GetSenderAddresses(); - foreach ($list as $item) { - /* @var SenderAddress $item */ - $senderAddresses[$item->Id] = $item; - } - $senderCountry = $senderAddresses[$this->settings->sender_address]->Country ?? 'DE'; - $list = $this->api->GetShippingProducts($senderCountry); - foreach ($list as $item) { - /* @var ShippingProduct $item */ - $shippingProducts[$item->Code] = $item; - } - - $this->options['senders'] = array_map(fn(SenderAddress $x) => strval($x), $senderAddresses ?? []); - $this->options['products'] = array_map(fn(ShippingProduct $x) => $x->Name, $shippingProducts ?? []); - $this->options['products'][0] = ''; - $this->options['selectedProduct'] = $shippingProducts[$this->settings->shipping_product] ?? []; - natcasesort($this->options['products']); - } - public function AdditionalSettings(): array { $this->FetchOptionsFromApi(); @@ -102,29 +108,33 @@ class Versandart_sendcloud extends Versanddienstleister $parcel->ParcelItems[] = $item; } $parcel->Weight = floatval($json->weight) * 1000; - $result = $this->api->CreateParcel($parcel); - if ($result instanceof ParcelResponse) { - $sql = "INSERT INTO versand - (adresse, lieferschein, versandunternehmen, gewicht, tracking, tracking_link, anzahlpakete) - VALUES - ({$address['addressId']}, {$address['lieferscheinId']}, '$this->type', - '$json->weight', '$result->TrackingNumber', '$result->TrackingUrl', 1)"; - $this->app->DB->Insert($sql); - $response['messages'][] = ['class' => 'info', 'text' => "Paketmarke wurde erfolgreich erstellt: $result->TrackingNumber"]; + try { + $result = $this->api->CreateParcel($parcel); + if ($result instanceof ParcelResponse) { + $sql = "INSERT INTO versand + (adresse, lieferschein, versandunternehmen, gewicht, tracking, tracking_link, anzahlpakete) + VALUES + ({$address['addressId']}, {$address['lieferscheinId']}, '$this->type', + '$json->weight', '$result->TrackingNumber', '$result->TrackingUrl', 1)"; + $this->app->DB->Insert($sql); + $response['messages'][] = ['class' => 'info', 'text' => "Paketmarke wurde erfolgreich erstellt: $result->TrackingNumber"]; - $doc = $result->GetDocumentByType(Document::TYPE_LABEL); - $filename = $this->app->erp->GetTMP() . join('_', ['Sendcloud', $doc->Type, $doc->Size, $result->TrackingNumber]) . '.pdf'; - file_put_contents($filename, $this->api->DownloadDocument($doc)); - $this->app->printer->Drucken($this->labelPrinterId, $filename); + $doc = $result->GetDocumentByType(Document::TYPE_LABEL); + $filename = $this->app->erp->GetTMP() . join('_', ['Sendcloud', $doc->Type, $doc->Size, $result->TrackingNumber]) . '.pdf'; + file_put_contents($filename, $this->api->DownloadDocument($doc)); + $this->app->printer->Drucken($this->labelPrinterId, $filename); - $doc = $result->GetDocumentByType(Document::TYPE_CN23); - $filename = $this->app->erp->GetTMP() . join('_', ['Sendcloud', $doc->Type, $doc->Size, $result->TrackingNumber]) . '.pdf'; - file_put_contents($filename, $this->api->DownloadDocument($doc)); - $this->app->printer->Drucken($this->documentPrinterId, $filename); - } else { - $response['messages'][] = ['class' => 'error', 'text' => $result]; + $doc = $result->GetDocumentByType(Document::TYPE_CN23); + $filename = $this->app->erp->GetTMP() . join('_', ['Sendcloud', $doc->Type, $doc->Size, $result->TrackingNumber]) . '.pdf'; + file_put_contents($filename, $this->api->DownloadDocument($doc)); + $this->app->printer->Drucken($this->documentPrinterId, $filename); + } else { + $response['messages'][] = ['class' => 'error', 'text' => $result]; + } + echo json_encode($response); + } catch (SendcloudApiException $e) { + $this->app->Tpl->addMessage('error', $e->getMessage()); } - echo json_encode($response); $this->app->ExitXentral(); } } diff --git a/www/pages/versandarten.php b/www/pages/versandarten.php index 01cbd46d..a7651401 100644 --- a/www/pages/versandarten.php +++ b/www/pages/versandarten.php @@ -209,6 +209,7 @@ class Versandarten { WHERE `id` = $id LIMIT 1" ); + $this->app->Tpl->Set('MESSAGE', ''); $this->app->Tpl->addMessage('success', "Die Daten wurden erfolgreich gespeichert!"); } }