Add "native" FedEx tracking
This commit is contained in:
parent
02a9646964
commit
ac5ac2da00
@ -50,6 +50,8 @@ $SETTINGS = [
|
||||
"ups_access_key" => "",
|
||||
"ups_user_account" => "",
|
||||
"ups_password" => "",
|
||||
"fedex_apikey" => "",
|
||||
"fedex_secret" => "",
|
||||
"shippo_key" => "",
|
||||
"easypost_key" => "",
|
||||
];
|
@ -29,6 +29,8 @@ class Tracking {
|
||||
return Tracking_USPS::track($barcode->getSanitized());
|
||||
case "ups":
|
||||
return Tracking_UPS::track($barcode->getSanitized());
|
||||
case "fedex":
|
||||
return Tracking_FedEx::track($barcode->getSanitized());
|
||||
default:
|
||||
return Tracking_EasyPost::track($barcode->getSanitized());
|
||||
//return Tracking_Shippo::track($barcode->getSanitized());
|
||||
|
@ -255,4 +255,73 @@ class TrackingStatus {
|
||||
}
|
||||
}
|
||||
|
||||
public static function FedExEventTypeToStatus(string $eventcode) {
|
||||
switch ($eventcode) {
|
||||
case "OC":
|
||||
case "OX":
|
||||
case "PD":
|
||||
case "RP":
|
||||
case "RG":
|
||||
case "SH":
|
||||
return TrackingStatus::TRACKING_STATUS_PRE_TRANSIT;
|
||||
case "AA":
|
||||
case "AC":
|
||||
case "AD":
|
||||
case "AF":
|
||||
case "AP":
|
||||
case "AR":
|
||||
case "AX":
|
||||
case "CH":
|
||||
case "DD":
|
||||
case "DP":
|
||||
case "DR":
|
||||
case "DS":
|
||||
case "EA":
|
||||
case "ED":
|
||||
case "EO":
|
||||
case "EP":
|
||||
case "FD":
|
||||
case "HL":
|
||||
case "IT":
|
||||
case "IX":
|
||||
case "LO":
|
||||
case "OD":
|
||||
case "OF":
|
||||
case "PF":
|
||||
case "PL":
|
||||
case "PM":
|
||||
case "PU":
|
||||
case "PX":
|
||||
case "SF":
|
||||
case "TR":
|
||||
case "CC":
|
||||
case "CD":
|
||||
case "CP":
|
||||
case "EA":
|
||||
case "CA":
|
||||
case "CU":
|
||||
case "BR":
|
||||
case "TP":
|
||||
case "IP":
|
||||
case "DO": // dropped off
|
||||
return TrackingStatus::TRACKING_STATUS_TRANSIT;
|
||||
case "RC": // Recipient
|
||||
case "DL": // Delivered
|
||||
case "HP": // Ready for pickup
|
||||
return TrackingStatus::TRACKING_STATUS_DELIVERED;
|
||||
case "RS":
|
||||
return TrackingStatus::TRACKING_STATUS_RETURNED;
|
||||
case "CA":
|
||||
case "DE":
|
||||
case "DY":
|
||||
case "LP":
|
||||
case "RD":
|
||||
case "SE":
|
||||
return TrackingStatus::TRACKING_STATUS_FAILURE;
|
||||
case "SP":
|
||||
default:
|
||||
return TrackingStatus::TRACKING_STATUS_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
187
lib/Tracking_FedEx.lib.php
Normal file
187
lib/Tracking_FedEx.lib.php
Normal file
@ -0,0 +1,187 @@
|
||||
<?php
|
||||
|
||||
class Tracking_FedEx {
|
||||
|
||||
public static function getAuthToken() {
|
||||
$headers = [
|
||||
'Content-Type' => 'application/x-www-form-urlencoded'
|
||||
];
|
||||
|
||||
$postdata = http_build_query([
|
||||
"grant_type" => "client_credentials",
|
||||
"client_id" => env("fedex_apikey", ""),
|
||||
"client_secret" => env("fedex_secret", "")
|
||||
]);
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 45);
|
||||
//curl_setopt($ch, CURLOPT_URL, "https://apis-sandbox.fedex.com/oauth/token"); // TEST
|
||||
curl_setopt($ch, CURLOPT_URL, "https://apis.fedex.com/oauth/token"); // PROD
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata);
|
||||
$response = curl_exec($ch);
|
||||
|
||||
$data = json_decode($response, true);
|
||||
|
||||
if (isset($data["access_token"])) {
|
||||
return [$data["access_token"], $data["expires_in"]];
|
||||
}
|
||||
throw new Exception("Couldn't get FedEx access token.");
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $code
|
||||
* @return \TrackingInfo
|
||||
* @throws TrackingException
|
||||
*/
|
||||
public static function track(string $code, string $carrier = ""): TrackingInfo {
|
||||
global $memcache;
|
||||
$barcode = new TrackingBarcode($code);
|
||||
|
||||
$fedexauthtoken = $memcache->get("logistics.tracking.fedex_auth_token");
|
||||
if ($fedexauthtoken == false) {
|
||||
$tokendata = Tracking_FedEx::getAuthToken();
|
||||
$memcache->set("logistics.tracking.fedex_auth_token", $tokendata[0], $tokendata[1] - 120);
|
||||
$fedexauthtoken = $tokendata[0];
|
||||
}
|
||||
|
||||
try {
|
||||
$trackrequest = [
|
||||
"includeDetailedScans" => true,
|
||||
"trackingInfo" => [
|
||||
[
|
||||
//"shipDateBegin" => date("Y-m-d", strtotime("now - 3 months")),
|
||||
"trackingNumberInfo" => [
|
||||
"trackingNumber" => $barcode->getCode()
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
$headers = [
|
||||
"Authorization: Bearer $fedexauthtoken",
|
||||
'X-locale: en_US',
|
||||
'Content-Type: application/json'
|
||||
];
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 45);
|
||||
//curl_setopt($ch, CURLOPT_URL, "https://apis-sandbox.fedex.com/track/v1/trackingnumbers"); // TEST
|
||||
curl_setopt($ch, CURLOPT_URL, "https://apis.fedex.com/track/v1/trackingnumbers"); // PROD
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_POST, 1);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($trackrequest));
|
||||
curl_setopt($ch, CURLOPT_ENCODING, "");
|
||||
$response = curl_exec($ch);
|
||||
|
||||
// CHECK TO SEE IF WE GOT AN ERROR
|
||||
if ((curl_errno($ch)) && (curl_errno($ch) != 0)) {
|
||||
throw new TrackingException(curl_error($ch));
|
||||
}
|
||||
|
||||
$result = json_decode($response, true);
|
||||
|
||||
if (isset($result["errors"]) || !empty($result["errors"])) {
|
||||
if (count($result["errors"]) > 0) {
|
||||
throw new TrackingException($result["errors"][0]["message"]);
|
||||
}
|
||||
throw new TrackingException("The FedEx tracking system responded with an error. Try again later.");
|
||||
}
|
||||
|
||||
if (!empty($result["output"]["completeTrackResults"]) && !empty($result["output"]["completeTrackResults"][0]["trackResults"])) {
|
||||
$trackinfo = $result["output"]["completeTrackResults"][0]["trackResults"][0];
|
||||
} else {
|
||||
throw new TrackingException("No tracking details found.");
|
||||
}
|
||||
if (!empty($result["output"]["completeTrackResults"][0]["trackResults"][0]["error"])) {
|
||||
throw new TrackingException($result["output"]["completeTrackResults"][0]["trackResults"][0]["error"]["message"]);
|
||||
}
|
||||
} catch (TrackingException $ex) {
|
||||
throw $ex;
|
||||
} catch (Exception $ex) {
|
||||
throw new TrackingException("There was a server problem. This code cannot be tracked right now.");
|
||||
}
|
||||
|
||||
$info = new TrackingInfo();
|
||||
|
||||
$info->setCode($trackinfo["trackingNumberInfo"]["trackingNumber"]);
|
||||
|
||||
$info->setCarrier("fedex");
|
||||
$info->setService(new Service($trackinfo["serviceDetail"]["type"], $trackinfo["serviceDetail"]["description"]));
|
||||
|
||||
// Set carrier info: Ground, Express, Freight, etc
|
||||
$carrierid = "fedex";
|
||||
switch ($trackinfo["trackingNumberInfo"]["carrierCode"]) {
|
||||
case "FEDEX_GROUND":
|
||||
case "FEDEX_EXPRESS":
|
||||
case "FEDEX_FREIGHT":
|
||||
default:
|
||||
$carrierid = "fedex";
|
||||
break;
|
||||
}
|
||||
$info->setCarrierAttributionText(CarrierAssets::getAttribution(Carriers::getCarrierCode($carrierid)));
|
||||
$info->setCarrierLogo(CarrierAssets::getLogo(Carriers::getCarrierCode($carrierid)));
|
||||
|
||||
if (count($trackinfo["scanEvents"]) > 0) {
|
||||
$current = $trackinfo["scanEvents"][0];
|
||||
$current_status = new TrackingEntry(
|
||||
TrackingStatus::FedExEventTypeToStatus($current["eventType"]),
|
||||
($current["eventDescription"] ?? "Unknown")
|
||||
. (TrackingStatus::FedExEventTypeToStatus($current["eventType"]) == TrackingStatus::TRACKING_STATUS_UNKNOWN ? " " . $current["eventType"] : ""),
|
||||
date("c", strtotime($current["date"]))
|
||||
);
|
||||
|
||||
$current_location = new Location();
|
||||
// FedEx docs say it should be $current["scanLocation"]["locationContactAndAddress"]["address"]["...}] but it's not I guess
|
||||
$current_location->city = $current["scanLocation"]["city"] ?? "";
|
||||
$current_location->state = $current["scanLocation"]["stateOrProvinceCode"] ?? "";
|
||||
$current_location->zip = $current["scanLocation"]["postalCode"] ?? "";
|
||||
$current_location->country = $current["scanLocation"]["countryCode"] ?? "";
|
||||
$current_status->setLocation($current_location);
|
||||
|
||||
$info->setCurrentStatus($current_status);
|
||||
}
|
||||
|
||||
|
||||
$to = new Location();
|
||||
$to->city = $trackinfo["recipientInformation"]["address"]["city"] ?? "";
|
||||
$to->state = $trackinfo["recipientInformation"]["address"]["stateOrProvinceCode"] ?? "";
|
||||
$to->zip = $trackinfo["recipientInformation"]["address"]["postalCode"] ?? "";
|
||||
$to->country = $trackinfo["recipientInformation"]["address"]["countryCode"] ?? "";
|
||||
$info->setTo($to);
|
||||
|
||||
$from = new Location();
|
||||
$from->city = $trackinfo["shipperInformation"]["address"]["city"] ?? "";
|
||||
$from->state = $trackinfo["shipperInformation"]["address"]["stateOrProvinceCode"] ?? "";
|
||||
$from->zip = $trackinfo["shipperInformation"]["address"]["postalCode"] ?? "";
|
||||
$from->country = $trackinfo["shipperInformation"]["address"]["countryCode"] ?? "";
|
||||
$info->setFrom($from);
|
||||
|
||||
foreach ($trackinfo["scanEvents"] as $history) {
|
||||
$location = new Location();
|
||||
$location->city = $history["scanLocation"]["city"] ?? "";
|
||||
$location->state = $history["scanLocation"]["stateOrProvinceCode"] ?? "";
|
||||
$location->zip = $history["scanLocation"]["postalCode"] ?? "";
|
||||
$location->country = $history["scanLocation"]["countryCode"] ?? "";
|
||||
if (!empty($history["date"])) {
|
||||
$datetimestring = date("c", strtotime($history["date"]));
|
||||
} else {
|
||||
$datetimestring = "";
|
||||
}
|
||||
$info->appendHistoryEntry(new TrackingEntry(
|
||||
TrackingStatus::FedExEventTypeToStatus($history["eventType"]),
|
||||
($history["eventDescription"] ?? "Unknown")
|
||||
. (TrackingStatus::FedExEventTypeToStatus($history["eventType"]) == TrackingStatus::TRACKING_STATUS_UNKNOWN ? " " . $history["eventType"] : ""),
|
||||
$datetimestring,
|
||||
$location));
|
||||
}
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user