OpenXE/classes/Carrier/SendCloud/SendCloudApi.php

190 lines
5.6 KiB
PHP
Raw Normal View History

<?php
2023-02-28 13:36:25 +01:00
/*
2024-07-21 12:19:29 +02:00
* SPDX-FileCopyrightText: 2022-2024 Andreas Palm
2023-02-28 13:36:25 +01:00
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
namespace Xentral\Carrier\SendCloud;
use Exception;
use Xentral\Carrier\SendCloud\Data\Document;
use Xentral\Carrier\SendCloud\Data\ParcelCreation;
use Xentral\Carrier\SendCloud\Data\ParcelResponse;
use Xentral\Carrier\SendCloud\Data\SenderAddress;
use Xentral\Carrier\SendCloud\Data\ShippingProduct;
2024-07-21 12:19:29 +02:00
use Xentral\Modules\ShippingMethod\Model\ShipmentStatus;
class SendCloudApi
{
/**
* @var ?string $public_key
*/
protected ?string $public_key;
/**
* @var ?string $private_key
*/
protected ?string $private_key;
const PROD_BASE_URI = 'https://panel.sendcloud.sc/api/v2';
public function __construct($public_key, $private_key)
{
$this->public_key = $public_key;
$this->private_key = $private_key;
}
2022-11-02 22:37:04 +01:00
/**
* @throws SendcloudApiException
*/
public function GetSenderAddresses(): array
{
$uri = self::PROD_BASE_URI . '/user/addresses/sender';
$response = $this->sendRequest($uri);
2022-11-02 22:37:04 +01:00
foreach ($response['body']->sender_addresses as $item)
$res[] = SenderAddress::fromApiResponse($item);
2022-11-02 22:37:04 +01:00
return $res ?? [];
}
2022-11-02 22:37:04 +01:00
/**
* @throws SendcloudApiException
*/
public function GetShippingProducts(string $sourceCountry, ?string $targetCountry = null, ?int $weight = null,
?int $height = null, ?int $length = null, ?int $width = null): array
{
$uri = self::PROD_BASE_URI . '/shipping-products';
$params = ['from_country' => $sourceCountry];
if ($targetCountry !== null)
$params['to_country'] = $targetCountry;
if ($weight !== null && $weight > 0)
$params['weight'] = $weight;
if ($height !== null && $height > 0) {
$params['height'] = $height;
$params['height_unit'] = 'centimeter';
}
if ($length !== null && $length > 0) {
$params['length'] = $length;
$params['length_unit'] = 'centimeter';
}
if ($width !== null && $width > 0) {
$params['width'] = $width;
$params['width_unit'] = 'centimeter';
}
$response = $this->sendRequest($uri, $params);
2022-11-02 22:37:04 +01:00
return array_map(fn($x) => ShippingProduct::fromApiResponse($x), $response['body'] ?? []);
}
2022-11-02 22:37:04 +01:00
/**
* @throws SendcloudApiException
*/
public function CreateParcel(ParcelCreation $parcel): ParcelResponse|string|null
{
$uri = self::PROD_BASE_URI . '/parcels?errors=verbose-carrier';
2022-11-02 22:37:04 +01:00
$response = $this->sendRequest($uri, null, true, ['parcel' => $parcel->toApiRequest()], [200,400]);
switch ($response['code']) {
case 200:
2023-01-29 21:11:12 +01:00
if (isset($response['body']->parcel))
2022-11-02 22:37:04 +01:00
try {
2023-01-29 21:11:12 +01:00
return ParcelResponse::fromApiResponse($response['body']->parcel);
2022-11-02 22:37:04 +01:00
} catch (Exception $e) {
throw new SendcloudApiException(previous: $e);
}
break;
case 400:
if (isset($response['body']->error))
return $response['body']->error->message;
2022-11-02 22:37:04 +01:00
break;
}
throw SendcloudApiException::fromResponse($response);
}
2022-11-02 22:37:04 +01:00
/**
* @throws SendcloudApiException
*/
public function DownloadDocument(Document $document): string
{
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $document->Link,
CURLOPT_HTTPHEADER => [
"Authorization: Basic " . base64_encode($this->public_key . ':' . $this->private_key)
],
]);
2022-11-02 22:37:04 +01:00
$output = curl_exec($curl);
$code = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
if ($code != 200)
throw SendcloudApiException::fromResponse(['code' => $code, 'body' => $output]);
return $output;
}
2024-07-21 12:19:29 +02:00
/**
* @throws SendcloudApiException
*/
public function GetTrackingStatus(string $trackingNumber): ShipmentStatus|null
{
$uri = self::PROD_BASE_URI . '/tracking/' . $trackingNumber;
$response = $this->sendRequest($uri);
$highest = null;
foreach ($response['body']->statuses as $status) {
switch ($status->parent_status) {
case 'announcing':
case 'ready-to-send':
if ($highest === null) $highest = ShipmentStatus::Announced;
break;
case 'to-sorting':
case 'at-sorting-centre':
case 'shipment-on-route':
case 'driver-on-route':
$highest = ShipmentStatus::EnRoute;
2024-07-21 21:53:25 +02:00
break;
2024-07-21 12:19:29 +02:00
case 'delivered': return ShipmentStatus::Delivered;
}
}
return $highest;
}
2022-11-02 22:37:04 +01:00
/**
* @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;
$curl = curl_init();
if (is_array($query_params)) {
$uri .= '?' . http_build_query($query_params);
}
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_URL => $uri,
CURLOPT_HTTPHEADER => [
"Authorization: Basic " . base64_encode($this->public_key . ':' . $this->private_key),
'Content-Type: application/json'
],
]);
if ($post === true) {
curl_setopt_array($curl, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($postFields)
]);
}
2022-11-02 22:37:04 +01:00
$output = json_decode(curl_exec($curl));
$code = curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
curl_close($curl);
2022-11-02 22:37:04 +01:00
$ret = [
'code' => $code,
'body' => $output,
];
if (!in_array($code, $allowedResponseCodes))
throw SendcloudApiException::fromResponse($ret);
return $ret;
}
}