added apiRuntimeCache
This commit is contained in:
@@ -8,6 +8,9 @@ use Symfony\Component\HttpClient\HttpClient;
|
|||||||
|
|
||||||
class Usps_Api_Bridge extends Module
|
class Usps_Api_Bridge extends Module
|
||||||
{
|
{
|
||||||
|
// Runtime cache to prevent duplicate API calls during a single page load
|
||||||
|
private $apiRuntimeCache = [];
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->name = 'usps_api_bridge';
|
$this->name = 'usps_api_bridge';
|
||||||
@@ -139,7 +142,7 @@ class Usps_Api_Bridge extends Module
|
|||||||
return $helper->generateForm([$fields_form]);
|
return $helper->generateForm([$fields_form]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function calculateRate($params, $shipping_cost, $products, $originalModule)
|
public function calculateRate($params, $shipping_cost, $products, $originalModule)
|
||||||
{
|
{
|
||||||
require_once(dirname(__FILE__) . '/classes/UspsV3Client.php');
|
require_once(dirname(__FILE__) . '/classes/UspsV3Client.php');
|
||||||
|
|
||||||
@@ -155,7 +158,7 @@ public function calculateRate($params, $shipping_cost, $products, $originalModul
|
|||||||
$methodCode = Db::getInstance()->getValue($sql);
|
$methodCode = Db::getInstance()->getValue($sql);
|
||||||
|
|
||||||
if (!$methodCode) {
|
if (!$methodCode) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Map Old Code to New API Enum
|
// 3. Map Old Code to New API Enum
|
||||||
@@ -166,7 +169,7 @@ public function calculateRate($params, $shipping_cost, $products, $originalModul
|
|||||||
|
|
||||||
// 4. Pack Products
|
// 4. Pack Products
|
||||||
$packedBoxes = $originalModule->getHelper()->getCarrierHelper()->packProducts($products, $params->id);
|
$packedBoxes = $originalModule->getHelper()->getCarrierHelper()->packProducts($products, $params->id);
|
||||||
|
|
||||||
if (empty($packedBoxes)) {
|
if (empty($packedBoxes)) {
|
||||||
$this->log("Box packer returned empty.");
|
$this->log("Box packer returned empty.");
|
||||||
return false;
|
return false;
|
||||||
@@ -184,20 +187,20 @@ public function calculateRate($params, $shipping_cost, $products, $originalModul
|
|||||||
// 6. Address Data
|
// 6. Address Data
|
||||||
$originZip = $this->getOriginZip($originalModule);
|
$originZip = $this->getOriginZip($originalModule);
|
||||||
$destAddress = new Address($params->id_address_delivery);
|
$destAddress = new Address($params->id_address_delivery);
|
||||||
|
|
||||||
$originZip = substr(preg_replace('/[^0-9]/', '', $originZip), 0, 5);
|
$originZip = substr(preg_replace('/[^0-9]/', '', $originZip), 0, 5);
|
||||||
$destZip = substr(preg_replace('/[^0-9]/', '', $destAddress->postcode), 0, 5);
|
$destZip = substr(preg_replace('/[^0-9]/', '', $destAddress->postcode), 0, 5);
|
||||||
$isInternational = ($destAddress->id_country != Country::getByIso('US'));
|
$isInternational = ($destAddress->id_country != Country::getByIso('US'));
|
||||||
|
|
||||||
// 7. Loop through boxes
|
// 7. Loop through boxes
|
||||||
foreach ($packedBoxes as $packedBox) {
|
foreach ($packedBoxes as $packedBox) {
|
||||||
|
|
||||||
// Weight (Lbs) - Ensure minimum 0.1
|
// Weight (Lbs) - Ensure minimum 0.1
|
||||||
$weightInLbs = $this->convertUnit($packedBox->getWeight(), 'g', 'lbs', 3);
|
$weightInLbs = $this->convertUnit($packedBox->getWeight(), 'g', 'lbs', 3);
|
||||||
if ($weightInLbs < 0.1) $weightInLbs = 0.1;
|
if ($weightInLbs < 0.1) $weightInLbs = 0.1;
|
||||||
|
|
||||||
// Dimensions (Inches)
|
// Dimensions (Inches)
|
||||||
$box = $packedBox->getBox();
|
$box = $packedBox->getBox();
|
||||||
$length = $this->convertUnit($box->getOuterLength(), 'mm', 'in', 2);
|
$length = $this->convertUnit($box->getOuterLength(), 'mm', 'in', 2);
|
||||||
$width = $this->convertUnit($box->getOuterWidth(), 'mm', 'in', 2);
|
$width = $this->convertUnit($box->getOuterWidth(), 'mm', 'in', 2);
|
||||||
$height = $this->convertUnit($box->getOuterDepth(), 'mm', 'in', 2);
|
$height = $this->convertUnit($box->getOuterDepth(), 'mm', 'in', 2);
|
||||||
@@ -259,24 +262,65 @@ public function calculateRate($params, $shipping_cost, $products, $originalModul
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper to send request and handle Domestic vs International switching
|
* Helper to send request with Runtime Caching & Domestic/Intl switching
|
||||||
*/
|
*/
|
||||||
private function sendApiRequest($client, $payload, $isInternational, $destAddress, $destZip)
|
private function sendApiRequest($client, $payload, $isInternational, $destAddress, $destZip)
|
||||||
{
|
{
|
||||||
|
// 1. Prepare the specific payload for the cache key
|
||||||
|
// We simulate the modifications we are about to do to ensure the key is accurate
|
||||||
|
$cachePayload = $payload;
|
||||||
|
|
||||||
if ($isInternational) {
|
if ($isInternational) {
|
||||||
$payload['destinationCountryCode'] = Country::getIsoById($destAddress->id_country);
|
$cachePayload['destinationCountryCode'] = Country::getIsoById($destAddress->id_country);
|
||||||
// Cleanup domestic fields
|
$cachePayload['originZIPCode'] = $payload['originZIPCode']; // Ensure consistency
|
||||||
unset($payload['destinationEntryFacilityType']);
|
unset($cachePayload['destinationEntryFacilityType']);
|
||||||
unset($payload['destinationZIPCode']);
|
unset($cachePayload['destinationZIPCode']);
|
||||||
|
$endpointType = 'INT';
|
||||||
return $client->getInternationalRate($payload);
|
} else {
|
||||||
}
|
$cachePayload['destinationZIPCode'] = $destZip;
|
||||||
|
$cachePayload['destinationEntryFacilityType'] = 'NONE';
|
||||||
// Domestic
|
$endpointType = 'DOM';
|
||||||
$payload['destinationZIPCode'] = $destZip;
|
}
|
||||||
$payload['destinationEntryFacilityType'] = 'NONE';
|
|
||||||
|
// 2. Generate Hash
|
||||||
return $client->getDomesticRate($payload);
|
// We include the endpoint type to ensure uniqueness
|
||||||
|
$cacheKey = md5(json_encode($cachePayload) . $endpointType);
|
||||||
|
|
||||||
|
// 3. Check Cache
|
||||||
|
if (isset($this->apiRuntimeCache[$cacheKey])) {
|
||||||
|
// Uncomment for deep debugging if needed
|
||||||
|
// $this->log("Returning cached rate for key: " . $cacheKey);
|
||||||
|
return $this->apiRuntimeCache[$cacheKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Perform Request
|
||||||
|
if ($isInternational) {
|
||||||
|
$response = $client->getInternationalRate($cachePayload);
|
||||||
|
} else {
|
||||||
|
$response = $client->getDomesticRate($cachePayload);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. Determine if we should cache
|
||||||
|
// We DO cache API errors (like 400 Bad Request) because retrying them won't fix invalid data.
|
||||||
|
// We DO NOT cache Network/Transport errors (timeouts) so they can be retried.
|
||||||
|
$shouldCache = true;
|
||||||
|
|
||||||
|
if (isset($response['error'])) {
|
||||||
|
// Check for Guzzle/Symfony Transport errors strings defined in UspsV3Client
|
||||||
|
if (
|
||||||
|
strpos($response['error'], 'Network') !== false ||
|
||||||
|
strpos($response['error'], 'Connection') !== false ||
|
||||||
|
strpos($response['error'], 'Transport') !== false
|
||||||
|
) {
|
||||||
|
$shouldCache = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($shouldCache) {
|
||||||
|
$this->apiRuntimeCache[$cacheKey] = $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user