A modest collection of PHP libraries used at SparkFun.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

654 lines
20 KiB

<?php
namespace SparkLib\UPS;
use SparkLib\UPS\Ship\AddressType,
SparkLib\UPS\Ship\BillShipperType,
SparkLib\UPS\Ship\CodeDescriptionType,
SparkLib\UPS\Ship\ContactType,
SparkLib\UPS\Ship\CurrencyMonetaryType,
SparkLib\UPS\Ship\DimensionsType,
SparkLib\UPS\Ship\InternationalFormType,
SparkLib\UPS\Ship\LabelImageFormatType,
SparkLib\UPS\Ship\LabelStockSizeType,
SparkLib\UPS\Ship\LabelSpecificationType,
SparkLib\UPS\Ship\PackageDeclaredValueType,
SparkLib\UPS\Ship\PackageServiceOptionsType,
SparkLib\UPS\Ship\PackageType,
SparkLib\UPS\Ship\PackageWeightType,
SparkLib\UPS\Ship\PaymentInfoType,
SparkLib\UPS\Ship\PhoneType,
SparkLib\UPS\Ship\ProductType,
SparkLib\UPS\Ship\ProducerType,
SparkLib\UPS\Ship\ProductWeightType,
SparkLib\UPS\Ship\RateInfoType,
SparkLib\UPS\Ship\ReferenceNumberType,
SparkLib\UPS\Ship\RequestType,
SparkLib\UPS\Ship\ServiceAccessToken,
SparkLib\UPS\Ship\ServiceType,
SparkLib\UPS\Ship\ShipperType,
SparkLib\UPS\Ship\ShipAddressType,
SparkLib\UPS\Ship\ShipFromType,
SparkLib\UPS\Ship\ShipToType,
SparkLib\UPS\Ship\ShipmentChargeType,
SparkLib\UPS\Ship\ShipmentType,
SparkLib\UPS\Ship\ShipmentRequest,
SparkLib\UPS\Ship\ShipmentServiceOptionsType,
SparkLib\UPS\Ship\SoldToType,
SparkLib\UPS\Ship\UltimateConsigneeType,
SparkLib\UPS\Ship\UnitOfMeasurementType,
SparkLib\UPS\Ship\UnitType,
SparkLib\UPS\Ship\UPSSecurity,
SparkLib\UPS\Ship\UsernameToken;
use Exception,
SoapClient,
SoapHeader,
SoapFault,
DOMDocument;
class Ship {
private $_wsdl = UPS_SHIP_WSDL;
private $_schema = UPS_SCHEMA;
private $_client;
private $_options;
private $_request;
private $_response;
private $_destination;
private $_lineItems;
private $_serviceType;
private $_shipper;
private $_international;
private $_PAK = false;
private $_shipFrom;
private $_shipTo;
private $_shipmentMethod;
private $_payment;
private $_label;
private $_totalValue;
private $_package;
private $_packages = [];
private $_products = [];
private $_rates = [];
public $upsCodes = [
1 => 'Next Day Air',
2 => '2nd Day Air',
3 => 'Ground',
7 => 'Worldwide Express',
8 => 'Worldwide Expedited',
11 => 'Standard',
12 => '3 Day Select',
13 => 'Next Day Air Saver',
14 => 'Next Day Air Early AM',
59 => '2nd Day Air AM',
54 => 'Worldwide Express Plus',
65 => 'UPS Saver'
];
public function __construct() {
$Request = new RequestType();
$Shipment = new ShipmentType();
$LabelSpecification = new LabelSpecificationType();
$this->_request = new ShipmentRequest($Request, $Shipment, $LabelSpecification);
$this->_totalValue = 0;
}
public function setDestination($dest) {
$this->_destination = $dest;
}
public function allowPakRates() {
$this->_PAK = true;
}
public function createPackage() {
if ($this->_package instanceOf PackageType)
throw new Exception ('Add current package before creating a new one.');
$this->_package = new PackageType();
}
public function setPackageSize($l, $w, $h, $units = 'IN') {
if ($this->_package == null)
throw new Exception ('Create package before setting size.');
if ($this->_international === null)
throw new Exception ('Set shipment destination before adding packages');
$weight = $this->_package->PackageWeight->Weight;
if (! isset($weight))
throw new Exception ('Set package weight before setting size');
if ($this->_PAK && $this->_international && $weight <= constant('\PAK_RATE_THRESHOLD')) {
$this->_package->setPackaging(new CodeDescriptionType('04'));
} else {
$this->_package->setPackaging(new CodeDescriptionType('02'));
$this->_package->setDimensions(
new DimensionsType(new CodeDescriptionType($units), $l, $w, $h)
);
}
}
public function setPackageWeight($weight, $units = 'LBS') {
if ($this->_package == null)
throw new Exception ('Create package before setting weight.');
$this->_package->setPackageWeight(
new PackageWeightType(new CodeDescriptionType($units), $weight)
);
}
public function setPackageValue($value = null) {
if ($this->_package == null)
throw new Exception ('Create package before setting value.');
$DeclaredValue = new PackageDeclaredValueType();
$DeclaredValue->setCurrencyCode('USD');
if ($value)
$DeclaredValue->setMonetaryValue($value);
else
$DeclaredValue->setMonetaryValue($this->_totalValue);
$PackageServiceOptions = new PackageServiceOptionsType();
$PackageServiceOptions->setDeclaredValue($DeclaredValue);
$this->_package->setPackageServiceOptions($PackageServiceOptions);
}
public function setReferenceNumber($num) {
$ReferenceNumber = new ReferenceNumberType();
$ReferenceNumber->setValue($num);
$ReferenceNumber->setBarCodeIndicator(true);
if ($this->_international) {
$this->_request->Shipment->setReferenceNumber($ReferenceNumber);
} else if (count($this->_packages) == 0) {
throw new Exception ('Add packages before setting reference number.');
} else {
foreach ($this->_packages as &$package)
$package->setReferenceNumber($ReferenceNumber);
}
}
public function addPackage() {
array_push($this->_packages, $this->_package);
$this->_package = null;
}
public function addItem($value, $qty = 1, $desc = 'Merchandise',
$tariff = '', $origin = 'US') {
if (count($this->_products) < 50) {
// Sanitize description
$desc = substr(preg_replace("/[^\w\d ]/i", '', $desc), 0, 35);
// Make sure value isn't too precise
$value = round($value, 6);
$this->_totalValue += $value;
$product = new ProductType();
$measure = new UnitOfMeasurementType('PCS');
$units = new UnitType($qty, $measure, $value);
$product->setDescription($desc);
$product->setUnit($units);
$product->setCommodityCode($tariff);
$product->setOriginCountryCode($origin);
array_push($this->_products, $product);
}
}
/**
* Functions for handling Shipper node.
*/
private function initShipper() {
if (!isset($this->_shipper))
$this->_shipper = new ShipperType();
}
public function setShipperAddress($street, $city, $state, $postal,
$country, $account) {
$this->initShipper();
$this->initForms();
$address = new ShipAddressType($street, $city, $state, $postal, $country);
$this->_shipper->setAddress($address);
$this->_shipper->setShipperNumber($account);
$Address = new AddressType($street, $city, $state, null, $postal, $country);
$this->_request->Shipment
->ShipmentServiceOptions
->InternationalForms
->Contacts
->Producer
->setAddress($Address);
}
public function setShipperPhone($phone) {
$phone = preg_replace('/[^0-9]/', '', $phone);
$this->initShipper();
$this->_shipper->setPhone(new PhoneType($phone));
}
public function setShipperName($name, $company = null) {
$this->initShipper();
$this->initForms();
if ($company) {
$this->_shipper->setName($company);
$this->_shipper->setAttentionName($name);
$this->_shipper->setCompanyDisplayableName($company);
$this->_request->Shipment
->ShipmentServiceOptions
->InternationalForms
->Contacts
->Producer
->setCompanyName($company);
$this->_request->Shipment
->ShipmentServiceOptions
->InternationalForms
->Contacts
->Producer
->setAttentionName($name);
} else {
$this->_shipper->setName($name);
$this->_shipper->setAttentionName($name);
$this->_shipper->setCompanyDisplayableName($name);
$this->_request->Shipment
->ShipmentServiceOptions
->InternationalForms
->Contacts
->Producer
->setCompanyName($name);
$this->_request->Shipment
->ShipmentServiceOptions
->InternationalForms
->Contacts
->Producer
->setAttentionName($name);
}
}
public function setShipperTaxID($taxId) {
$this->initShipper();
$this->_shipper->setTaxIdentificationNumber($taxId);
}
public function setShipperEmail($email) {
$this->initShipper();
$this->_shipper->setEMailAddress($email);
}
/**
* Functions for handling ShipFrom node.
*/
private function initShipFrom() {
if (!isset($this->_shipFrom))
$this->_shipFrom = new ShipFromType();
}
public function setShipFromAddress($street, $city, $state, $postal,
$country) {
$this->initShipFrom();
$address = new ShipAddressType($street, $city, $state, $postal, $country);
$this->_shipFrom->setAddress($address);
}
public function setShipFromPhone($phone) {
$phone = preg_replace('/[^0-9]/', '', $phone);
$this->initShipFrom();
$this->_shipFrom->setPhone(new PhoneType($phone));
}
public function setShipFromName($name, $company = null) {
$this->initShipFrom();
if ($company) {
$this->_shipFrom->setName($company);
$this->_shipFrom->setAttentionName($name);
$this->_shipFrom->setCompanyDisplayableName($company);
} else {
$this->_shipFrom->setName($name);
$this->_shipFrom->setAttentionName($name);
$this->_shipFrom->setCompanyDisplayableName($name);
}
}
public function setShipFromTaxID($taxId) {
$this->initShipFrom();
$this->_shipFrom->setTaxIdentificationNumber($taxId);
}
/**
* Functions for handling ShipTo node.
*/
private function initShipTo() {
if (!isset($this->_shipTo))
$this->_shipTo = new ShipToType();
}
public function setShipToAddress($street, $city, $state, $postal, $country) {
$this->initShipTo();
$this->initForms();
// Do some really basic validation on the postal code
if ($country == 'US') {
$postal = substr(preg_replace('/[^0-9]+/', '', $postal), 0, 5);
$this->_international = false;
} else if ($country == 'CA') {
$postal = substr(preg_replace('/[^0-9A-Za-z]+/', '', $postal), 0, 6);
$this->_international = true;
} else {
$postal = substr(preg_replace('/[^0-9A-Za-z]+/', '', $postal), 0, 9);
$this->_international = true;
}
// Street cannot be more than 35 characters long
if (is_array($street))
foreach ($street as &$s)
$s = substr($s, 0, 35);
else
$street = substr($street, 0, 35);
// Only US and Canada should have the state field set.
// Ireland should be set to IE because they don't have postal codes.
if ($country == 'IE')
$state = 'IE';
else if (! ($country == 'US' || $country == 'CA'))
$state = null;
$ShipAddress = new ShipAddressType($street, $city, $state, $postal, $country);
$this->_shipTo->setAddress($ShipAddress);
$UltimateConsigneeAddress = new AddressType($street, $city, $state, null, $postal, $country);
$this->_request->Shipment
->ShipmentServiceOptions
->InternationalForms
->Contacts
->UltimateConsignee
->setAddress($UltimateConsigneeAddress);
$SoldToAddress = new AddressType($street, $city, $state, null, $postal, $country);
$this->_request->Shipment
->ShipmentServiceOptions
->InternationalForms
->Contacts
->SoldTo
->setAddress($SoldToAddress);
}
public function setShipToPhone($phone) {
$phone = preg_replace('/[^0-9]/', '', $phone);
if ($phone) {
$this->initShipTo();
$this->_shipTo->setPhone(new PhoneType($phone));
}
}
public function setShipToName($name, $company = null) {
$this->initShipTo();
$this->initForms();
$name = substr($name, 0, 35);
if ($company) {
$company = substr($company, 0, 35);
$this->_shipTo->setName($company);
$this->_shipTo->setAttentionName($name);
$this->_shipTo->setCompanyDisplayableName($company);
$this->_request->Shipment
->ShipmentServiceOptions
->InternationalForms
->Contacts
->UltimateConsignee
->setCompanyName($company);
$this->_request->Shipment
->ShipmentServiceOptions
->InternationalForms
->Contacts
->SoldTo
->setName($company);
$this->_request->Shipment
->ShipmentServiceOptions
->InternationalForms
->Contacts
->SoldTo
->setAttentionName($name);
} else {
$this->_shipTo->setName($name);
$this->_shipTo->setAttentionName($name);
$this->_shipTo->setCompanyDisplayableName($name);
$this->_request->Shipment
->ShipmentServiceOptions
->InternationalForms
->Contacts
->UltimateConsignee
->setCompanyName($name);
$this->_request->Shipment
->ShipmentServiceOptions
->InternationalForms
->Contacts
->SoldTo
->setName($name);
$this->_request->Shipment
->ShipmentServiceOptions
->InternationalForms
->Contacts
->SoldTo
->setAttentionName($name);
}
}
public function setShipToEmail($email) {
$this->initShipTo();
$this->_shipTo->setEMailAddress($email);
}
public function addShipmentAccount($account) {
$transportation = new ShipmentChargeType();
$transportation->setType('01');
$transportation->setBillShipper(new BillShipperType($account));
$this->_payment = new PaymentInfoType($transportation);
}
public function setShippingMethod($serviceCode) {
$this->_serviceType = new ServiceType($serviceCode);
}
private function initForms() {
if (!isset($this->_request->Shipment->ShipmentServiceOptions->InternationalForms)) {
$Producer = new ProducerType();
$UltimateConsignee = new UltimateConsigneeType();
$SoldTo = new SoldToType();
$Contacts = new ContactType();
$Contacts->setProducer($Producer);
$Contacts->setUltimateConsignee($UltimateConsignee);
$Contacts->setSoldTo($SoldTo);
$InternationalForm = new InternationalFormType();
$InternationalForm->setFormType('01');
$InternationalForm->setReasonForExport('SALE');
$InternationalForm->setCurrencyCode('USD');
$InternationalForm->setContacts($Contacts);
$ShipmentServiceOptions = new ShipmentServiceOptionsType();
$ShipmentServiceOptions->setInternationalForms($InternationalForm);
$this->_request->Shipment->setShipmentServiceOptions($ShipmentServiceOptions);
}
}
public function setInvoice($date = null, $number = '') {
$this->initForms();
if ($date == null)
$date = date('Ymd');
else if (is_string($date))
$date = date('Ymd', strtotime($date));
else
$date = date('Ymd', $date);
$InternationalForm = new InternationalFormType();
$InternationalForm->setFormType('01');
$ShipmentServiceOptions = new ShipmentServiceOptionsType();
$ShipmentServiceOptions->setInternationalForms($InternationalForm);
$this->_request->Shipment
->ShipmentServiceOptions
->InternationalForms
->setInvoiceDate($date);
$this->_request->Shipment
->ShipmentServiceOptions
->InternationalForms
->setInvoiceNumber($number);
}
public function useNegotiatedRates() {
$rateInfo = new RateInfoType();
$rateInfo->setNegotiatedRatesIndicator(true);
$this->_request->Shipment->setShipmentRatingOptions($rateInfo);
}
private function setTotal() {
if ($this->_destination == 'CA') {
$invoiceLineTotal = new CurrencyMonetaryType();
$invoiceLineTotal->setCurrencyCode('USD');
$invoiceLineTotal->setMonetaryValue(ceil($this->_totalValue));
$this->_request->Shipment->setInvoiceLineTotal($invoiceLineTotal);
}
}
public function ship() {
$this->_request->Request->setRequestOption('validate');
$this->initForms();
$this->_request->Shipment->setService($this->_serviceType);
$this->_request->Shipment->setDescription('Electronics');
$this->_request->Shipment->setShipper($this->_shipper);
$this->_request->Shipment->setShipFrom($this->_shipFrom);
$this->_request->Shipment->setShipTo($this->_shipTo);
$this->_request->Shipment->setPackage($this->_packages);
$this->_request->Shipment->setPaymentInformation($this->_payment);
$this->_request->Shipment
->ShipmentServiceOptions
->InternationalForms
->setProduct($this->_products);
$this->setTotal();
$UsernameToken = new UsernameToken();
$ServiceAccessToken = new ServiceAccessToken();
$UPSSecurity = new UPSSecurity($UsernameToken, $ServiceAccessToken);
$UsernameToken->setUsername(UPS_USERID);
$UsernameToken->setPassword(UPS_USERPASS);
$ServiceAccessToken->setAccessLicenseNumber(UPS_APIKEY);
$header = new SoapHeader($this->_schema, 'UPSSecurity', $UPSSecurity);
$this->_options = [
'soap_version' => 'SOAP_1_1',
'exceptions' => true,
'trace' => true,
'location' => UPS_SHIP_SERVER
];
$wsdl = $this->_wsdl;
$this->_client = new SoapClient($wsdl, $this->_options);
$this->_client->__setSoapHeaders($header);
try {
$this->_response = $this->_client->ProcessShipment($this->_request, $this->_options);
} catch (SoapFault $s) {
if (isset($s->detail)) {
$err = $s->detail->Errors->ErrorDetail->PrimaryErrorCode->Description;
throw new Exception($err);
}
}
}
public function setLabelFormat($formatCode = 'ZPL') {
// This is _required_, with these specific values, but has no effect
$LabelStockSize = new LabelStockSizeType('6', '4');
$LabelImageFormat = new LabelImageFormatType($formatCode);
$this->_request->LabelSpecification->setLabelImageFormat($LabelImageFormat);
$this->_request->LabelSpecification->setLabelStockSize($LabelStockSize);
}
public function getLabelImage() {
if ($this->_response) {
$img = $this->_response->ShipmentResults->PackageResults->ShippingLabel->GraphicImage;
return base64_decode($img);
}
}
public function getTrackingNumber() {
if ($this->_response)
return $this->_response->ShipmentResults->PackageResults->TrackingNumber;
}
public function getCharge() {
if ($this->_response)
return $this->_response->ShipmentResults->PackageResults->ServiceOptionsCharges->MonetaryValue;
}
public function getInvoice() {
if ($this->_response) {
$img = $this->_response->ShipmentResults->Form->Image->GraphicImage;
return base64_decode($img);
}
}
public function getLastRequest() {
$request = $this->_client->__getLastRequest();
if ($request) {
$dom = new DOMDocument;
$dom->preserveWhiteSpace = FALSE;
$dom->formatOutput = TRUE;
$dom->loadXML($request);
return $dom->saveXml();
}
}
public function getLastResponse() {
$response = $this->_client->__getLastResponse();
if ($response) {
$dom = new DOMDocument;
$dom->preserveWhiteSpace = FALSE;
$dom->formatOutput = TRUE;
$dom->loadXML($response);
return $dom->saveXml();
}
}
}