added RETAIL handling
This commit is contained in:
@@ -161,7 +161,6 @@ class Usps_Api_Bridge extends Module
|
|||||||
// 3. Map Old Code to New API Enum
|
// 3. Map Old Code to New API Enum
|
||||||
$newApiClass = $this->mapServiceCodeToApiClass($methodCode);
|
$newApiClass = $this->mapServiceCodeToApiClass($methodCode);
|
||||||
if (!$newApiClass) {
|
if (!$newApiClass) {
|
||||||
$this->log("Mapping failed for legacy code: " . $methodCode);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,10 +172,15 @@ class Usps_Api_Bridge extends Module
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Initialize API Client
|
// 5. Initialize Client & Settings
|
||||||
$client = new UspsV3Client($token, (bool)Configuration::get('USPS_BRIDGE_LIVE_MODE'));
|
$client = new UspsV3Client($token, (bool)Configuration::get('USPS_BRIDGE_LIVE_MODE'));
|
||||||
$totalPrice = 0;
|
$totalPrice = 0;
|
||||||
|
|
||||||
|
// Determine Price Type from Old Module Settings
|
||||||
|
// 0 = Regular (Retail), 1 = Commercial, 2 = Commercial Plus
|
||||||
|
$legacyPriceSetting = (int)Configuration::get('USPSL_COMMERCIAL');
|
||||||
|
$requestedPriceType = ($legacyPriceSetting > 0) ? 'COMMERCIAL' : 'RETAIL';
|
||||||
|
|
||||||
// 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);
|
||||||
@@ -188,26 +192,23 @@ class Usps_Api_Bridge extends Module
|
|||||||
// 7. Loop through boxes
|
// 7. Loop through boxes
|
||||||
foreach ($packedBoxes as $packedBox) {
|
foreach ($packedBoxes as $packedBox) {
|
||||||
|
|
||||||
// Weight Conversion (Grams -> Pounds)
|
// 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;
|
||||||
|
|
||||||
// USPS requires minimum 0.001 lbs. 0 causes errors.
|
// Dimensions (Inches)
|
||||||
if ($weightInLbs <= 0) $weightInLbs = 0.1;
|
|
||||||
|
|
||||||
// Dimensions (mm -> 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);
|
||||||
|
|
||||||
// Determine Processing Category (Crucial for V3 API)
|
// Processing Category Logic
|
||||||
// Machinable: Length <= 22", Width <= 18", Height <= 15", Weight >= 6oz (0.375lbs) and <= 25lbs
|
|
||||||
$category = 'MACHINABLE';
|
$category = 'MACHINABLE';
|
||||||
if ($length > 22 || $width > 18 || $height > 15 || $weightInLbs > 25 || $weightInLbs < 0.375) {
|
if ($length > 22 || $width > 18 || $height > 15 || $weightInLbs > 25) {
|
||||||
$category = 'NONSTANDARD';
|
$category = 'NONSTANDARD';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build Payload
|
// Build Base Payload
|
||||||
$payload = [
|
$payload = [
|
||||||
'originZIPCode' => $originZip,
|
'originZIPCode' => $originZip,
|
||||||
'weight' => $weightInLbs,
|
'weight' => $weightInLbs,
|
||||||
@@ -215,39 +216,31 @@ class Usps_Api_Bridge extends Module
|
|||||||
'width' => $width,
|
'width' => $width,
|
||||||
'height' => $height,
|
'height' => $height,
|
||||||
'mailClass' => $newApiClass,
|
'mailClass' => $newApiClass,
|
||||||
'priceType' => 'COMMERCIAL',
|
'priceType' => $requestedPriceType,
|
||||||
'mailingDate' => date('Y-m-d', strtotime('+1 day')),
|
'mailingDate' => date('Y-m-d', strtotime('+1 day')),
|
||||||
'processingCategory' => $category,
|
'processingCategory' => $category,
|
||||||
'rateIndicator' => 'SP' // Single Piece
|
'rateIndicator' => 'SP'
|
||||||
];
|
];
|
||||||
|
|
||||||
// Flat Rate Override
|
// Flat Rate Override
|
||||||
$flatRateIndicator = $this->mapBoxToRateIndicator($box->getReference());
|
$flatRateIndicator = $this->mapBoxToRateIndicator($box->getReference());
|
||||||
if ($flatRateIndicator) {
|
if ($flatRateIndicator) {
|
||||||
$payload['rateIndicator'] = $flatRateIndicator;
|
$payload['rateIndicator'] = $flatRateIndicator;
|
||||||
// Dimensions technically ignored for Flat Rate, but required by API schema
|
|
||||||
// Processing category usually irrelevant for Flat Rate but must be valid Enum
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($isInternational) {
|
// --- API REQUEST LOGIC WITH RETRY ---
|
||||||
$payload['destinationCountryCode'] = Country::getIsoById($destAddress->id_country);
|
$response = $this->sendApiRequest($client, $payload, $isInternational, $destAddress, $destZip);
|
||||||
$payload['originZIPCode'] = $originZip;
|
|
||||||
// Remove domestic specific fields
|
|
||||||
unset($payload['destinationEntryFacilityType']);
|
|
||||||
unset($payload['destinationZIPCode']);
|
|
||||||
|
|
||||||
$response = $client->getInternationalRate($payload);
|
// If Failed AND we tried COMMERCIAL, try falling back to RETAIL
|
||||||
} else {
|
if (isset($response['error']) && $payload['priceType'] === 'COMMERCIAL') {
|
||||||
$payload['destinationZIPCode'] = $destZip;
|
$this->log("Commercial rate failed (" . $response['error'] . "). Retrying with RETAIL.");
|
||||||
$payload['destinationEntryFacilityType'] = 'NONE';
|
$payload['priceType'] = 'RETAIL';
|
||||||
|
$response = $this->sendApiRequest($client, $payload, $isInternational, $destAddress, $destZip);
|
||||||
$response = $client->getDomesticRate($payload);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log Payload on Error for Debugging
|
// Final Error Check
|
||||||
if (isset($response['error'])) {
|
if (isset($response['error'])) {
|
||||||
$this->log("API Error: " . $response['error']);
|
$this->log("API Fatal Error: " . $response['error']);
|
||||||
$this->log("Payload causing error: " . json_encode($payload));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,7 +250,7 @@ class Usps_Api_Bridge extends Module
|
|||||||
} elseif (isset($response['rateOptions'][0]['totalBasePrice'])) {
|
} elseif (isset($response['rateOptions'][0]['totalBasePrice'])) {
|
||||||
$totalPrice += (float)$response['rateOptions'][0]['totalBasePrice'];
|
$totalPrice += (float)$response['rateOptions'][0]['totalBasePrice'];
|
||||||
} else {
|
} else {
|
||||||
$this->log("API Response missing price. Full response: " . json_encode($response));
|
$this->log("API Response missing price.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -265,6 +258,27 @@ class Usps_Api_Bridge extends Module
|
|||||||
return $totalPrice + $shipping_cost;
|
return $totalPrice + $shipping_cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper to send request and handle Domestic vs International switching
|
||||||
|
*/
|
||||||
|
private function sendApiRequest($client, $payload, $isInternational, $destAddress, $destZip)
|
||||||
|
{
|
||||||
|
if ($isInternational) {
|
||||||
|
$payload['destinationCountryCode'] = Country::getIsoById($destAddress->id_country);
|
||||||
|
// Cleanup domestic fields
|
||||||
|
unset($payload['destinationEntryFacilityType']);
|
||||||
|
unset($payload['destinationZIPCode']);
|
||||||
|
|
||||||
|
return $client->getInternationalRate($payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Domestic
|
||||||
|
$payload['destinationZIPCode'] = $destZip;
|
||||||
|
$payload['destinationEntryFacilityType'] = 'NONE';
|
||||||
|
|
||||||
|
return $client->getDomesticRate($payload);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple Unit Converter to replace the dependency on the old module's class
|
* Simple Unit Converter to replace the dependency on the old module's class
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user