|
|
- <?php
- if(!defined('QUINTACMS') ) die('No Quinta.');
-
- if (!defined("USPSREQUEST.CLASS.PHP")){
- define("USPSREQUEST.CLASS.PHP",1);
-
- /**
- * Class USPSRequest - provides shipping requests for USPS via web services
- * Note: This class provides access to the EndiciaRequest as a child request object for
- * some services.
- *
- *Service must be Express, First Class, Priority, Parcel, Library, BPM, Media or ALL for domestic (in US)
- *
- *@author Erik Winn <sidewalksoftware@gmail.com>
- *
- *@version 0.3
- *
- *@package Quinta
- * @subpackage Classes
- */
-
- class USPSRequest extends ShippingRequest{
- /**
- *@var string Indicates enumeration value for size (REGULAR, LARGE, OVERSIZE)
- */
- protected $strSize = "REGULAR";
- /**
- *@var string Indicates enumeration value for FIRST CLASS "type" [LETTER | FLAT | PARCEL]
- */
- protected $strFirstClassMailType = "FLAT";
- /**
- *@var ShippingRequest
- */
- protected $objEndiciaRequest;
-
- /**
- * USPSRequest Constructor
- *
- * @param ShippingMethod objShippingMethod - the method for which to obtain estimate
- */
- public function __construct(ShippingMethod $objShippingMethod){
- try {
- parent::__construct($objShippingMethod);
- } catch (QCallerException $objExc) {
- $objExc->IncrementOffset();
- throw $objExc;
- }
- ///@todo this is currently defined in quinta_config - fixme!!
- $this->RemoteAccountId = USPS_USERID;
- $this->RemotePassword = USPS_PASSWORD;
-
- if($this->blnTestMode){
- $this->strRemoteDomainName = 'testing.shippingapis.com';
- $this->strRemoteCgiUrl = '/ShippingAPITest.dll?';
- }else{
- $this->strRemoteDomainName = 'production.shippingapis.com';
- $this->strRemoteCgiUrl = '/ShippingAPI.dll?';
- }
- $this->UseSsl = false;
- }
- //Public interface ..
- /**
- * Returns a shipping label for this method to the order address
- * Note that we use the Endicia label server for this - it must be enabled
- * and you must have a configured account with Endicia for this to work!
- *@return resource gd image object containing label image
- */
- public function GetLabel(){
- $this->objEndiciaRequest = new EndiciaRequest($this->objShippingMethod);
- $this->objShippingLabelImage = $this->objEndiciaRequest->GetLabel();
- $this->blnHasErrors = $this->objEndiciaRequest->HasErrors;
- $this->strErrors = $this->objEndiciaRequest->Errors;
- $this->aryExtraDocumentImages = $this->objEndiciaRequest->ExtraDocumentImages;
- $this->aryCustomsFormImages = $this->objEndiciaRequest->CustomsFormImages;
- return $this->objShippingLabelImage;
- }
- /**
- * Returns a shipping rate for the order for this method
- *@return image object containing the image code
- */
- public function GetRate(){
- $this->createRequest(ShippingRequestType::Rate, WebRequestType::GET);
- $this->submitRequest();
- return $this->Rate;
- }
-
- //Request string creators
- /**
- * Creates a rate request - if the shipping is international this call createIntlRateRequest instead ..
- */
- protected function createRateRequest(){
- if($this->Order->IsInternational)
- return $this->createIntlRateRequest();
-
- $this->strApiName = 'API=RateV3';
- if($this->blnTestMode){
- $this->OriginZip = '10022';
- $this->DestinationZip = '20008';
- $this->Ounces = 5;
- $this->Pounds = 10;
- $this->Container = 'Flat Rate Box';
- }
-
- $this->strRequest = '&XML=';
- $strXml = '<RateV3Request USERID="' .$this->strRemoteAccountId . '">';
- $strXml .= '<Package ID="0">';
- $strXml .= '<Service>' . $this->ServiceType . '</Service>';
- $strXml .= '<FirstClassMailType>' . $this->strFirstClassMailType . '</FirstClassMailType>';
- $strXml .= '<ZipOrigination>' . $this->OriginZip . '</ZipOrigination>';
- $strXml .= '<ZipDestination>' . $this->DestinationZip . '</ZipDestination>';
- $strXml .= '<Pounds>' . $this->Pounds . '</Pounds>';
- $strXml .= '<Ounces>' . round($this->Ounces, 2) . '</Ounces>';
- $strXml .= '<Container>' . $this->Container .'</Container>';
- $strXml .= '<Size>' . $this->strSize . '</Size>';
- $strXml .= '<Machinable>' . ($this->IsMachinable ? 'True' : 'False') . '</Machinable>';
- $strXml .= '</Package></RateV3Request>';
- $strXml = urlencode($strXml);
- $this->strRequest .= $strXml;
- }
- /**
- * Creates an international shipping rate request
- */
- protected function createIntlRateRequest(){
- //USPS testing servers do not support international - force to production ..
- $this->strRemoteDomainName = 'production.shippingapis.com';
- $this->strRemoteCgiUrl = '/ShippingAPI.dll?';
-
- //neato - USPS has decided that it prefers "Great Britain" and not "United Kingdom" ..
- $strCountry = strtoupper($this->DestinationCountry);
- if($strCountry == "UNITED KINGDOM")
- $strCountry = 'GREAT BRITAIN';
-
- $this->strApiName = 'API=IntlRate';
- $this->strRequest = '&XML=';
- $strXml = '<IntlRateRequest USERID="' . $this->strRemoteAccountId . '">';
- $strXml .= '<Package ID="0">';
- $strXml .= '<Pounds>' . $this->Pounds . '</Pounds>';
- $strXml .= '<Ounces>' . round($this->Ounces, 2) . '</Ounces>';
- $strXml .= '<MailType>Package</MailType>';
- $strXml .= '<Country>' . $strCountry . '</Country>';
- $strXml .= '</Package></IntlRateRequest>';
- $strXml = urlencode($strXml);
- $this->strRequest .= $strXml;
- }
- //Response handlers
- /**
- * Handles a rate request response
- */
- protected function handleRateResponse(){
- if ($this->objShippingMethod->Order->IsInternational)
- $objDomDoc = $this->getDomDocument('IntlRateResponse');
- else
- $objDomDoc = $this->getDomDocument('RateV3Response');
- if($objDomDoc){
- $strErrorMessage = $this->requestErrors($objDomDoc);
- if($strErrorMessage){
- $this->blnIsAvailable = false;
- $this->blnHasErrors = true;
- $this->strErrors = $strErrorMessage;
- $this->Rate = 0;
- } else {
- $this->blnIsAvailable = true;
-
- if( $this->objShippingMethod->Order->IsInternational)
- return $this->handleIntlRateResponse($objDomDoc);
-
- $nodeList = $objDomDoc->getElementsByTagName('Postage');
- $nodeList = $nodeList->item(0)->getElementsByTagName('Rate');
-
- if($nodeList->length > 0)
- $this->Rate = $nodeList->item(0)->nodeValue;
- else
- $this->Rate = 0;
- }
- } else {
- $this->blnIsAvailable = false;
- $this->HasErrors = true;
- $this->Errors = 'Unknown USPS error ..Request:' . $this->strRequest . ' Response:' . $this->strResponse;
- $this->Rate = 0;
- }
- }
- /**
- * Handles an International rate request response.
- * USPS returns multiple rates for some areas (eg. Australia) and we need to parse the DOM to
- * return the correct rate for the method (service type).
- * @todo - more sophisticated and configurable matching by package type; currently we mostly grab the first match ..
- * Here is a typical response for the Service nodes:
-
- <Service id="4"><Pounds>0</Pounds><Ounces>0.07</Ounces><MailType>Package</MailType><Country>ROMANIA</Country>
- <Postage>79.95</Postage><SvcCommitments>1 - 3 Days</SvcCommitments>\
- <SvcDescription>Global Express Guaranteed</SvcDescription><MaxDimensions>Max. length 46", width 35", height 46" and max. length plus girth 108"</MaxDimensions><MaxWeight>70</MaxWeight>
- </Service>
- <Service id="6"><Pounds>0</Pounds><Ounces>0.07</Ounces><MailType>Package</MailType><Country>ROMANIA</Country>
- <Postage>79.95</Postage><SvcCommitments>1 - 3 Days</SvcCommitments>
- <SvcDescription>Global Express Guaranteed Non-Document Rectangular</SvcDescription><MaxDimensions>Max. length 46", width 35", height 46" and max. length plus girth 108"</MaxDimensions><MaxWeight>70</MaxWeight>
- </Service>
- <Service id="7"><Pounds>0</Pounds><Ounces>0.07</Ounces><MailType>Package</MailType><Country>ROMANIA</Country>
- <Postage>79.95</Postage><SvcCommitments>1 - 3 Days</SvcCommitments>
- <SvcDescription>Global Express Guaranteed Non-Document Non-Rectangular</SvcDescription><MaxDimensions>Max. length 46", width 35", height 46" and max. length plus girth 108"</MaxDimensions><MaxWeight>70</MaxWeight>
- </Service>
- <Service id="12"><Pounds>0</Pounds><Ounces>0.07</Ounces><MailType>Package</MailType><Country>ROMANIA</Country>
- <Postage>79.95</Postage><SvcCommitments>1 - 3 Days</SvcCommitments>
- <SvcDescription>USPS GXG Envelopes</SvcDescription><MaxDimensions>Cardboard envelope has a dimension of 9 1/2" X 12 1/2" and GXG tyvek envelope has a dimension of 12 1/2" X 15 1/2"</MaxDimensions><MaxWeight>70</MaxWeight>
- </Service>
- <Service id="1"><Pounds>0</Pounds><Ounces>0.07</Ounces><MailType>Package</MailType><Country>ROMANIA</Country>
- <Postage>25.95</Postage><SvcCommitments>8 Days</SvcCommitments>
- <SvcDescription>Express Mail International (EMS)</SvcDescription><MaxDimensions>Max.length 36", max. length plus girth 79"</MaxDimensions><MaxWeight>70</MaxWeight>
- </Service>
- <Service id="10"><Pounds>0</Pounds><Ounces>0.07</Ounces><MailType>Package</MailType><Country>ROMANIA</Country>
- <Postage>25.95</Postage><SvcCommitments>8 Days</SvcCommitments>
- <SvcDescription>Express Mail International (EMS) Flat-Rate Envelope</SvcDescription><MaxDimensions>9 1/2" X 12 1/2"</MaxDimensions><MaxWeight>70</MaxWeight>
- </Service>
- <Service id="2"><Pounds>0</Pounds><Ounces>0.07</Ounces><MailType>Package</MailType><Country>ROMANIA</Country>
- <Postage>21.50</Postage><SvcCommitments>6 - 10 Days</SvcCommitments>
- <SvcDescription>Priority Mail International</SvcDescription><MaxDimensions>Max. length 42", Max length plus girth combined 79"</MaxDimensions><MaxWeight>70</MaxWeight>
- </Service>
- <Service id="8"><Pounds>0</Pounds><Ounces>0.07</Ounces><MailType>Package</MailType><Country>ROMANIA</Country>
- <Postage>11.95</Postage><SvcCommitments>6 - 10 Days</SvcCommitments>
- <SvcDescription>Priority Mail International Flat-Rate Envelope</SvcDescription><MaxDimensions>USPS-supplied Priority Mail flat-rate envelope 9 1/2" x 12 1/2." Maximum weight 4 pounds.</MaxDimensions><MaxWeight>4</MaxWeight>
- </Service>
- <Service id="9"><Pounds>0</Pounds><Ounces>0.07</Ounces><MailType>Package</MailType><Country>ROMANIA</Country>
- <Postage>38.95</Postage><SvcCommitments>6 - 10 Days</SvcCommitments>
- <SvcDescription>Priority Mail International Flat-Rate Box</SvcDescription><MaxDimensions>USPS-supplied Priority Mail flat-rate box. Maximum weight 20 pounds.</MaxDimensions><MaxWeight>20</MaxWeight>
- </Service>
- <Service id="11"><Pounds>0</Pounds><Ounces>0.07</Ounces><MailType>Package</MailType><Country>ROMANIA</Country>
- <Postage>49.95</Postage><SvcCommitments>6 - 10 Days</SvcCommitments>
- <SvcDescription>Priority Mail International Large Flat-Rate Box</SvcDescription><MaxDimensions>USPS-supplied Priority Mail Large flat-rate box. Maximum weight 20 pounds.</MaxDimensions><MaxWeight>20</MaxWeight>
- </Service>
- <Service id="13"><Pounds>0</Pounds><Ounces>0.07</Ounces><MailType>Package</MailType><Country>ROMANIA</Country>
- <Postage>0.94</Postage><SvcCommitments>Varies</SvcCommitments>
- <SvcDescription>First Class Mail International Letters</SvcDescription><MaxDimensions>Max. length 11.5", height 6 1/8" or more than 1/4" thick</MaxDimensions><MaxWeight>0.2188</MaxWeight>
- </Service>
- <Postage>1.20</Postage><SvcCommitments>Varies</SvcCommitments>
- <SvcDescription>First Class Mail International Large Envelope</SvcDescription><MaxDimensions>Max. length 15", height 12 or more than 3/4" thick</MaxDimensions><MaxWeight>4</MaxWeight>
- </Service>
- <Service id="15"><Pounds>0</Pounds><Ounces>0.07</Ounces><MailType>Package</MailType><Country>ROMANIA</Country>
- <Postage>1.40</Postage><SvcCommitments>Varies</SvcCommitments>
- <SvcDescription>First Class Mail International Package</SvcDescription><MaxDimensions>Max. length 24", max length, height and depth (thickness) combined 36"</MaxDimensions><MaxWeight>4</MaxWeight>
- </Service>
- *
- */
- protected function handleIntlRateResponse($objDomDoc){
- $this->Rate = 0;
- $nodeList = $objDomDoc->getElementsByTagName('Service');
- if($nodeList->length > 0){
- foreach($nodeList as $objNode){
- $nodeSvcDescription = $objNode->getElementsByTagName('SvcDescription');
- $nodePostage = $objNode->getElementsByTagName('Postage');
- if($nodeSvcDescription->length > 0){
- $strSvcDesc = $nodeSvcDescription->item(0)->nodeValue;
- if(false !== stripos($strSvcDesc , $this->ServiceType )){
- //these are examples - not written in stone (they just happen to work for me now ..):
- if('First Class Mail International' == $this->ServiceType ){
- if(false === stripos($strSvcDesc , 'Large Envelope' ))
- continue;
- else{
- $this->Rate = $nodePostage->item(0)->nodeValue;
- break;
- }
- }
- if('Priority Mail International' == $this->ServiceType ){
- if(false === stripos($strSvcDesc , 'Flat-Rate Envelope' ))
- continue;
- else{
- $this->Rate = $nodePostage->item(0)->nodeValue;
- break;
- }
- }
- }
- }
- }
- }
- }
-
- /**
- * Utility function to check for request errors - returns either a string containing
- * server error messages or false if there were none.
- *@param DOMDocument objDomDoc - the server response ..
- *@return string | boolean error messages or false if request succeeded.
- */
- private function requestErrors($objDomDoc){
- $mixToReturn = false;
- $nodeListErrors = $objDomDoc->getElementsByTagName('Error');
- if( $nodeListErrors->length > 0 ){
- $this->blnHasErrors = true;
- $mixToReturn = 'Request: ' . $this->strRequest;
- $nodeListErrorMessages = $objDomDoc->getElementsByTagName('Description');
- if( $nodeListErrorMessages->length)
- $mixToReturn .= ' Message: ' . $nodeListErrorMessages->item(0)->nodeValue;
- }
- return $mixToReturn;
- }
-
- /*************************************************************************************/
- ///@todo - implement me:
- /**
- * Returns an account status report
- *@return string containing the status report
- */
- public function GetAccountStatus()
- {
- throw new QCallerException(sprintf('USPSRequest: Shipping request type %s unsupported! ',
- ShippingRequestType::ToString($this->ShippingRequestType)) );
- }
- /**
- * Returns whether this method is available for the order address
- *@return boolean true if method is available
- */
- public function GetAvailability()
- {
- throw new QCallerException(sprintf('USPSRequest: Shipping request type %s unsupported! ',
- ShippingRequestType::ToString($this->ShippingRequestType)) );
- }
- /**
- * Submits an account credit payment
- *@return boolean true on success
- */
- public function CreditAccount()
- {
- throw new QCallerException(sprintf('USPSRequest: Shipping request type %s unsupported! ',
- ShippingRequestType::ToString($this->ShippingRequestType)) );
- }
-
- //Request string creators
- /**
- * Creates a method available request
- */
- protected function createAvailabilityRequest()
- {
- throw new QCallerException(sprintf('USPSRequest: Shipping request type %s unsupported! ',
- ShippingRequestType::ToString($this->ShippingRequestType)) );
- }
- /**
- * Creates a label printing request
- */
- protected function createLabelRequest()
- {
- throw new QCallerException(sprintf('USPSRequest: Shipping request type %s unsupported! ',
- ShippingRequestType::ToString($this->ShippingRequestType)) );
- }
- /**
- * Creates a request submitting an account credit payment
- */
- protected function createCreditAccountRequest()
- {
- throw new QCallerException(sprintf('USPSRequest: Shipping request type %s unsupported! ',
- ShippingRequestType::ToString($this->ShippingRequestType)) );
- }
- /**
- * Creates an account status request
- */
- protected function createAccountStatusRequest()
- {
- throw new QCallerException(sprintf('USPSRequest: Shipping request type %s unsupported! ',
- ShippingRequestType::ToString($this->ShippingRequestType)) );
- }
-
- /**
- * Handles an account status request
- */
- protected function handleAccountStatusResponse()
- {
- throw new QCallerException(sprintf('USPSRequest: Shipping request type %s unsupported! ',
- ShippingRequestType::ToString($this->ShippingRequestType)) );
- }
- /**
- * Handles a request submitting an account credit payment
- */
- protected function handleCreditAccountResponse()
- {
- throw new QCallerException(sprintf('USPSRequest: Shipping request type %s unsupported! ',
- ShippingRequestType::ToString($this->ShippingRequestType)) );
- }
- /**
- * Handles a method available request
- */
- protected function handleAvailabilityResponse()
- {
- throw new QCallerException(sprintf('USPSRequest: Shipping request type %s unsupported! ',
- ShippingRequestType::ToString($this->ShippingRequestType)) );
- }
- /**
- * Handles a label request
- */
- protected function handleLabelResponse()
- {
- throw new QCallerException(sprintf('USPSRequest: Shipping request type %s unsupported! ',
- ShippingRequestType::ToString($this->ShippingRequestType)) );
- }
-
- /*************************************************************************************/
-
- }//end class
- }//end define
-
- ?>
|