data.netsyms.net/lib/Tracking_USPS.lib.php

148 lines
6.5 KiB
PHP

<?php
class Tracking_USPS {
/**
* Sometimes the API returns a city but no state or ZIP. This is a lookup table of city => state
* so the API can return a more complete response.
*/
public const STATELESS_CITIES = [
"LOS ANGELES" => "CA",
"SAN FRANCISCO" => "CA",
"NEW YORK" => "NY",
"CHICAGO" => "IL",
"MIAMI" => "FL"
];
/**
*
* @param string $code
* @return \TrackingInfo
* @throws TrackingException
*/
public static function track(string $code, string $carrier = ""): TrackingInfo {
$barcode = new TrackingBarcode($code);
try {
$resp = USPSAPIs::getAPIRequest("tracking/v3/tracking/$code?expand=DETAIL");
$resp = str_replace("<SUP>reg;</SUP>", "®", $resp);
$resp = str_replace("<SUP>&reg;</SUP>", "®", $resp);
$resp = str_replace("<SUP>&#153;</SUP>", "", $resp);
$json = json_decode($resp, true);
if (!empty($json["error"])) {
if (!empty($json["error"]["errors"]) && $json["error"]["errors"][0]["code"] == "150001") {
// Tracking number not found
throw new TrackingException(str_replace("12: ", "", $json["error"]["errors"][0]["title"]));
}
if (!empty($json["error"]["message"])) {
throw new TrackingException("The USPS tracking system is having problems: \"" . trim($json["error"]["message"]) . "\"");
}
throw new TrackingException("The USPS tracking system is having problems. Try again later.");
}
$trackinfo = $json;
} catch (TrackingException $ex) {
throw $ex;
} catch (Exception $ex) {
throw new TrackingException("There was a server error. This code cannot be tracked right now. Try again later.");
}
$info = new TrackingInfo();
try {
$info->setCode($trackinfo["trackingNumber"]);
} catch (Exception $ex) {
throw new TrackingException("The USPS tracking system returned an invalid response. Try again later.");
}
$info->setCarrier("usps");
$info->setService(new Service((string) $trackinfo["mailClass"], (string) $trackinfo["mailClass"]));
$info->setCarrierAttributionText(CarrierAssets::getAttribution(Carriers::getCarrierCode($info->getCarrier())));
$info->setCarrierLogo(CarrierAssets::getLogo(Carriers::getCarrierCode($info->getCarrier())));
// Current status
if (count($trackinfo["trackingEvents"]) > 0) {
$index = 0;
$evt = $trackinfo["trackingEvents"][$index];
$current_status = new TrackingEntry(
TrackingStatus::USPSEventCodeToStatus($evt["eventCode"]),
($evt["eventType"] ?? "Unknown") . (TrackingStatus::USPSEventCodeToStatus($evt["eventCode"]) == TrackingStatus::TRACKING_STATUS_UNKNOWN ? " " . $evt["eventCode"] : ""),
date("Y-m-d\TH:i:s", strtotime($evt["eventTimestamp"])),
null,
TrackingStatus::isUSPSEventCodeContainerScan($evt["eventCode"])
);
$current_location = new Location();
$current_location->city = (string) $evt["eventCity"] ?? "";
$current_location->state = (string) $evt["eventState"] ?? "";
$current_location->zip = (string) $evt["eventZIP"] ?? "";
$current_location->country = (string) $evt["eventCountry"] ?? "";
/*
* Fill in state from list above when it's missing from the API response
*/
if ($current_location->state == "" && $current_location->zip == "") {
if (array_key_exists(strtoupper($current_location->city), self::STATELESS_CITIES)) {
$current_location->state = self::STATELESS_CITIES[$current_location->city];
}
}
} else {
$current_status = new TrackingEntry(
TrackingStatus::TRACKING_STATUS_PRE_TRANSIT,
($trackinfo["statusSummary"] ?? "Unknown"),
date("Y-m-d\TH:i:s", strtotime("now")),
null,
false
);
$current_location = new Location();
}
$current_status->setLocation($current_location);
$info->setCurrentStatus($current_status);
$from = new Location();
$from->city = (string) $trackinfo["originCity"] ?? "";
$from->state = (string) $trackinfo["originState"] ?? "";
$from->zip = (string) $trackinfo["originZIP"] ?? "";
$from->country = (string) (isset($trackinfo["originCountry"]) ? $trackinfo["originCountry"] : "");
$info->setFrom($from);
$to = new Location();
$to->city = (string) $trackinfo["destinationCity"] ?? "";
$to->state = (string) $trackinfo["destinationState"] ?? "";
$to->zip = (string) $trackinfo["destinationZIP"] ?? "";
$to->country = (string) (isset($trackinfo["destinationCountry"]) ? $trackinfo["destinationCountry"] : "");
$info->setTo($to);
for ($i = 0; $i < count($trackinfo["trackingEvents"]); $i++) {
$history = $trackinfo["trackingEvents"][$i];
$location = new Location();
$location->city = (string) $history["eventCity"] ?? "";
$location->state = (string) $history["eventState"] ?? "";
$location->zip = (string) $history["eventZIP"] ?? "";
$location->country = (string) $history["eventCountry"] ?? "";
/*
* Fill in state from list above when it's missing from the API response
*/
if ($location->state == "" && $location->zip == "") {
if (array_key_exists(strtoupper($location->city), self::STATELESS_CITIES)) {
$location->state = self::STATELESS_CITIES[$location->city];
}
}
$info->appendHistoryEntry(new TrackingEntry(
TrackingStatus::USPSEventCodeToStatus((string) $history["eventCode"]),
$history["eventType"] . (TrackingStatus::USPSEventCodeToStatus((string) $history["eventCode"]) == TrackingStatus::TRACKING_STATUS_UNKNOWN ? " " . (string) $history["eventCode"] : ""),
$history["eventTimestamp"],
$location,
TrackingStatus::isUSPSEventCodeContainerScan((string) $history["eventCode"])));
}
return $info;
}
}