Reputation: 507
I'm trying to integrate UPS shipping label printing functionality into a custom crm/shopping cart app. I'm forming the xml document using a php stdClass object. I pass the method an array containing the package(s) variables ex.
$pkgs = Array ( [1] => Array ( [length] => 6 [width] => 8 [height] => 11 [weight] => 5 ) [2] => Array ( [length] => 5 [width] => 14 [height] => 10 [weight] => 9 ) )
My xml building method looks like this
public function assemble_xml($pkgs){
$xmlRequest = new stdClass();
$xmlRequest->header="<?xml version='1.0'?>
<AccessRequest xml:lang='en-US'>
<AccessLicenseNumber>HIDDEN</AccessLicenseNumber>
<UserId>HIDDEN</UserId>
<Password>HIDDEN</Password>
</AccessRequest>
<?xml version='1.0'?>
<ShipmentConfirmRequest xml:lang='en-US'>
<Request>
<TransactionReference>
<CustomerContext>Customer Comment</CustomerContext>
<XpciVersion/>
</TransactionReference>
<RequestAction>ShipConfirm</RequestAction>
<RequestOption>validate</RequestOption>
</Request>
<LabelSpecification>
<LabelPrintMethod>
<Code>GIF</Code>
<Description>gif file</Description>
</LabelPrintMethod>
<HTTPUserAgent>Mozilla/4.5</HTTPUserAgent>
<LabelImageFormat>
<Code>GIF</Code>
<Description>gif</Description>
</LabelImageFormat>
</LabelSpecification>
<Shipment>
<RateInformation>
<NegotiatedRatesIndicator/>
</RateInformation>
<Description/>
<Shipper>
<Name>HIDDEN</Name>
<PhoneNumber>HIDDEN</PhoneNumber>
<ShipperNumber>HIDDEN</ShipperNumber>
<TaxIdentificationNumber>HIDDEN</TaxIdentificationNumber>
<Address>
<AddressLine1>HIDDEN</AddressLine1>
<City>HIDDEN</City>
<StateProvinceCode>HIDDEN</StateProvinceCode>
<PostalCode>HIDDEN</PostalCode>
<PostcodeExtendedLow></PostcodeExtendedLow>
<CountryCode>HIDDEN</CountryCode>
</Address>
</Shipper>";
$xmlRequest->shipto="<ShipTo>
<CompanyName>HIDDEN</CompanyName>
<AttentionName>HIDDEN</AttentionName>
<PhoneNumber></PhoneNumber>
<Address>
<AddressLine1>HIDDEN</AddressLine1>
<City>HIDDEN</City>
<StateProvinceCode>HIDDEN</StateProvinceCode>
<PostalCode>HIDDEN</PostalCode>
<CountryCode>HIDDEN</CountryCode>
</Address>
</ShipTo>";
$xmlRequest->shipper="<ShipFrom>
<CompanyName>HIDDEN</CompanyName>
<AttentionName></AttentionName>
<PhoneNumber>HIDDEN</PhoneNumber>
<TaxIdentificationNumber>HIDDEN</TaxIdentificationNumber>
<Address>
<AddressLine1>HIDDEN</AddressLine1>
<City>HIDDEN</City>
<StateProvinceCode>HIDDEN</StateProvinceCode>
<PostalCode>HIDDEN</PostalCode>
<CountryCode>HIDDEN</CountryCode>
</Address>
</ShipFrom>";
$xmlRequest->payment="<PaymentInformation>
<Prepaid>
<BillShipper>
<AccountNumber>HIDDEN</AccountNumber>
</BillShipper>
</Prepaid>
</PaymentInformation>";
$xmlRequest->service="<Service>
<Code>03</Code>
<Description>Ground</Description>
</Service>";
for($i = 1; $i <= count($pkgs); $i++) {
$xmlRequest->$i ="<Package>
<PackagingType>
<Code>02</Code>
<Description>Customer Supplied</Description>
</PackagingType>
<Description>Package</Description>
<ReferenceNumber>
<Code></Code>
<Value></Value>
</ReferenceNumber>
<Dimensions>
<UnitOfMeasurement>
<Code>IN</Code>
</UnitOfMeasurement>
<Length>22</Length>
<Width>20</Width>
<Height>18</Height>
</Dimensions>
<PackageWeight>
<Weight>14.1</Weight>
</PackageWeight>
<AdditionalHandling>0</AdditionalHandling>
</Package>";
}
$xmlRequest->footer="</Shipment>
</ShipmentConfirmRequest>";
return $xmlRequest;
Cool that works. Now I feed it thru a few other functions to get my digest.
public function ups_send($assemble_xml){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://wwwcie.ups.com/ups.app/xml/ShipConfirm");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $assemble_xml);
curl_setopt($ch, CURLOPT_TIMEOUT, 3600);
$xmlResponse = curl_exec ($ch);
return $xmlResponse;
public function get_confirm_response($xmlResponse){
preg_match_all( "/\<ShipmentConfirmResponse\>(.*?)\<\/ShipmentConfirmResponse\>/s",
$xmlResponse, $bookblocks );
foreach( $bookblocks[1] as $block )
{
preg_match_all( "/\<ShipmentDigest\>(.*?)\<\/ShipmentDigest\>/",
$block, $author ); // SHIPPING DIGEST
$digest = $author[1][0];
$this->decode_label($digest);
}
}
public function decode_label($digest){
$xmlRequest1="<?xml version='1.0' encoding='ISO-8859-1'?>
<AccessRequest>
<AccessLicenseNumber>HIDDEN</AccessLicenseNumber>
<UserId>HIDDEN</UserId>
<Password>HIDDEN</Password>
</AccessRequest>
<?xml version=”1.0? encoding=”ISO-8859-1??>
<ShipmentAcceptRequest>
<Request>
<TransactionReference>
<CustomerContext>Customer Comment</CustomerContext>
</TransactionReference>
<RequestAction>ShipAccept</RequestAction>
<RequestOption>1</RequestOption>
</Request>
<ShipmentDigest>$digest</ShipmentDigest>
</ShipmentAcceptRequest>";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "https://wwwcie.ups.com/ups.app/xml/ShipAccept");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlRequest1);
curl_setopt($ch, CURLOPT_TIMEOUT, 3600);
$xmlResponse = curl_exec ($ch); // SHIP ACCEPT RESPONSE
$xml = $xmlResponse;
preg_match_all( "/\<ShipmentAcceptResponse\>(.*?)\<\/ShipmentAcceptResponse\>/s",
$xml, $bookblocks );
foreach( $bookblocks[1] as $block )
{
preg_match_all( "/\<GraphicImage\>(.*?)\<\/GraphicImage\>/",
$block, $author ); // GET LABEL
for($l=0; $l<=count($author[0])-1; $l++){
echo '<img src="data:image/gif;base64,'. $author[1][$l]. '"/>';
}
}
}
This all works with 1 or 2 labels, the labels are successfully decoded into label 1 of 2 and 2 of 2. BUT when I try to make 3 or more labels I get a successful response xml from UPS but I no labels are generated. I have been banging my head against my desk for days over this and could really use the expertise of SO to give me a nudge in the right direction about what I'm doing wrong. Why does 1 or 2 labels work but 3 or more doesn't? WHAT GIVES!
If its the regex thats wrong then why does it work if only 2 labels are requested?
There is a postscript you might be interested in.
Here is a pastebin of the xml response from UPS containing the labels.
Upvotes: 0
Views: 251
Reputation: 507
After reading the links you folks provided, I learned that not only was I losing my mind trying to do this when clearly a more appropriate solution was available but also
"Giving in to Them and their blasphemous ways which doom us all to inhuman toil for the One whose Name cannot be expressed." ~bobince
I replaced this unholy weeping child
preg_match_all( "/\<ShipmentAcceptResponse\>(.*?)\<\/ShipmentAcceptResponse\>/s",
$xml, $bookblocks );
foreach( $bookblocks[1] as $block )
{
preg_match_all( "/\<GraphicImage\>(.*?)\<\/GraphicImage\>/",
$block, $author ); // GET LABEL
for($l=0; $l<=count($author[0])-1; $l++){
echo '<img src="data:image/gif;base64,'. $author[1][$l]. '"/>';
}
}
with this beautiful solution
$label_resp = new SimpleXMLElement($xml);
foreach($label_resp->ShipmentResults->PackageResults as $package ){
echo '<img src="data:image/gif;base64,'. $package->LabelImage->GraphicImage. '"/>';
}
Not only does it worked perfectly, it also runs circles around the original solution speed wise.
Thank you, saviors of mankind, for your push in the right direction.
Upvotes: 1