_errorMap[self::ERROR_SHIPPER_COUNTRY_IS_NOT_US] = 'Shipper Country Code must be US';
$this->_errorMap[self::ERROR_COUNTRY_CODE] = 'Country Code is not valid';
return $this;
}
public function getRate()
{
return $this->_getServiceResponse();
}
protected function _getServiceResponse()
{
if (null == $this->_response->getData()) {
if (true === ($errors = $this->_validateRateFields())) { // The origin address(shipper) must be only in USA
try {
$this->_prepareXml();
if (!($serviceResponse = $this->_callService()) instanceof Qs_Exception) {
$this->_response->setShipToCountryCode($this->getOption('shipToCountry'));
$this->_response->prepareServiceResponse($serviceResponse);
} else {
$this->_response->setIsSuccess(false)->setData([
'errorCode' => self::ERROR_SERVICE_CONNECTION,
'errorText' => sprintf(
$this->_errorMap[self::ERROR_SERVICE_CONNECTION],
$this->getServiceName()
),
]);
}
} catch (App_Service_Shipping_Usps_Exception $e) {
$this->_response->setIsSuccess(false)->setData([
'errorCode' => $e->getCode(),
'errorText' => $e->getMessage(),
]);
}
} else {
$this->_response->setIsSuccess(false)->setData([
'errorCode' => self::ERROR_VALIDATE_REQUIRED_PARAMS,
'errorText' => implode('
', $errors),
]);
}
}
return $this->_response;
}
/**
* Documentation:
* https://www.usps.com/webtools/htm/Rate-Calculators-v1-5.htm - not found
* https://www.usps.com/business/web-tools-apis/price-calculators.htm
*/
protected function _prepareXml()
{
if ($this->_isUSCountry($this->getOption('shipToCountry'))) {
$mainWriter = new SimpleXMLElement('');
$mainWriter->addAttribute('USERID', $this->getConfig()->userId);
/**
* According to usps v4 documentation
* For full RateV4 functionality use Revision='2'
*/
$mainWriter->addChild('Revision', self::RATE_V4_REVISION);
foreach ($this->_getPackagesInformation() as $key => $packageInformation) {
$packageWriter = $mainWriter->addChild('Package');
$packageWriter->addAttribute('ID', $key);
$service = $this->getOption('serviceCode');
if (in_array($this->getConfig()->container, $this->_priorityContainers)) {
$service = self::SERVICE_PRIORITY;
}
$packageWriter->addChild('Service', $service);
// no matter Letter, Flat or Parcel, use Parcel
if (in_array($this->getOption('serviceCode'), $this->_parcelFirstClassMailTypeServices)) {
$packageWriter->addChild('FirstClassMailType', self::FIRST_CLASS_MAIL_TYPE_PARCEL);
}
$packageWriter->addChild('ZipOrigination', $this->getOption('shipperPostalCode'));
$packageWriter->addChild('ZipDestination', $this->getOption('shipToPostalCode'));
$weight = $this->_prepareWeight($packageInformation['weight']);
$packageWriter->addChild('Pounds', floor($weight));
$packageWriter->addChild('Ounces', Zend_Locale_Math::round(16 * ($weight - floor($weight)), 2));
// Because some methods don't accept VARIABLE and (NON)RECTANGULAR containers
$packageWriter->addChild('Container', $this->getConfig()->container);
$packageWriter->addChild('Size', $this->getConfig()->size);
if ($this->getConfig()->size == self::SIZE_LARGE) {
$packageWriter->addChild('Width', $this->getOption('width'));
$packageWriter->addChild('Length', $this->getOption('length'));
$packageWriter->addChild('Height', $this->getOption('height'));
if (in_array($this->getConfig()->container, $this->_girthContainers)) {
$packageWriter->addChild('Girth', $this->getOption('girth'));
}
}
$packageWriter->addChild('Machinable', $this->getConfig()->machinable);
}
} else {
$mainWriter = new SimpleXMLElement('');
$mainWriter->addAttribute('USERID', $this->getConfig()->userId);
/**
* According to usps v4 documentation
* For full RateV4 functionality use Revision='2'
*/
$mainWriter->addChild('Revision', self::RATE_V4_REVISION);
$packageWriter = $mainWriter->addChild('Package');
$packageWriter->addAttribute('ID', 0);
$weight = 0; //NEED CHANGED FOR INTERNATIONAL SHIPPING !!!
$packageWriter->addChild('Pounds', floor($weight));
$packageWriter->addChild('Ounces', Zend_Locale_Math::round(16 * ($weight - floor($weight)), 2));
$packageWriter->addChild('MailType', $this->getConfig()->mailType);
$packageWriter->addChild('ValueOfContents', $this->getOption('valueOfContents'));
$packageWriter->addChild('Country', $this->_getUSPSCountryName($this->getOption('shipToCountry')));
$packageWriter->addChild('Container', $this->getConfig()->container);
$packageWriter->addChild('Size', $this->getConfig()->size);
$width = $length = $height = $girth = 0;
if ($this->getConfig()->size == self::SIZE_LARGE) {
$width = $this->getOption('width');
$length = $this->getOption('length');
$height = $this->getOption('height');
if ($this->getConfig()->container == self::CONTAINER_NONRECTANGULAR) {
$girth = $this->getOption('girth');
}
}
$packageWriter->addChild('Width', $width);
$packageWriter->addChild('Length', $length);
$packageWriter->addChild('Height', $height);
$packageWriter->addChild('Girth', $girth);
}
$this->_xml = $mainWriter->asXML();
return $this;
}
protected function _getUSPSCountryName($countryCode)
{
$countries = $this->getConfig()->countries->toArray();
if (!array_key_exists($countryCode, $countries)) {
throw new App_Service_Shipping_Usps_Exception(
$this->_errorMap[self::ERROR_COUNTRY_CODE],
self::ERROR_COUNTRY_CODE
);
}
return $countries[$countryCode];
}
protected function _callService()
{
try {
$client = new Zend_Http_Client();
$client->setUri($this->getConfig()->location);
$client->setConfig($this->getConfig()->httpOptions->toArray());
$client->setParameterGet(
'API',
$this->_isUSCountry($this->getOption('shipToCountry'))
? $this->getConfig()->US_API : $this->getConfig()->NOT_US_API
);
$client->setParameterGet('XML', $this->_xml);
$response = $client->request();
if ($response->getStatus() == self::HTTP_CODE_OK) {
$response = $response->getBody();
} else {
return new App_Service_Shipping_Usps_Exception(
$this->_errorMap[self::ERROR_SERVICE_CONNECTION],
self::ERROR_SERVICE_CONNECTION
);
}
} catch (App_Service_Shipping_Usps_Exception $e) {
return $e;
}
return $response;
}
protected function _validateRateFields()
{
$errors = $this->_validateRequiredRateFields();
if (!$this->_isUSCountry($this->getOption('shipperCountry'))) {
$shipperCountryError = $this->_errorMap[self::ERROR_SHIPPER_COUNTRY_IS_NOT_US];
$errors = $this->_prepareErrors($errors, $shipperCountryError);
}
$countries = $this->getConfig()->countries->toArray();
if (!array_key_exists($this->getOption('shipToCountry'), $countries)) {
$shipToCountryError = $this->_errorMap[self::ERROR_COUNTRY_CODE];
$errors = $this->_prepareErrors($errors, $shipToCountryError);
}
return $errors;
}
protected function _prepareErrors($errors, $newError)
{
if (is_array($errors)) {
$errors[] = $newError;
} else {
$errors = [$newError];
}
return $errors;
}
protected function _isUSCountry($countryCode)
{
return ($countryCode == self::COUNTRY_CODE_US) ? true : false;
}
}