1<?php
2// (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
3//
4// All Rights Reserved. See copyright.txt for details and a complete list of authors.
5// Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
6// $Id$
7
8require_once 'lib/shipping/shippinglib.php';
9
10class ShippingProvider_Ups implements ShippingProvider
11{
12	private $username;
13	private $password;
14	private $license;
15
16	function __construct(array $config)
17	{
18		$this->username = $config['username'];
19		$this->password = $config['password'];
20		$this->license = $config['license'];
21	}
22
23	function getRates(array $from, array $to, array $packages)
24	{
25		if ($dom = $this->obtain($from, $to, $packages)) {
26			$rates = [];
27
28			foreach ($dom->getElementsByTagName('RatedShipment') as $node) {
29				$rates[] = $this->readShipment($node);
30			}
31
32			return $rates;
33		} else {
34			return [];
35		}
36	}
37
38	private function obtain($from, $to, $packages, $service)
39	{
40		try {
41			$auth = $this->getAuth();
42			$request = $this->getRequest($from, $to, $packages, $service);
43
44			$client = TikiLib::lib('tiki')->get_http_client();
45			$client->setUri('https://www.ups.com/ups.app/xml/Rate');
46			$client->setRawBody($auth . $request);
47
48			$client->setMethod(Zend\Http\Request::METHOD_POST);
49			$response = $client->send();
50			$body = $response->getBody();
51
52			$dom = new DOMDocument;
53			$dom->loadXML($body);
54
55			return $dom;
56		} catch (Zend\Http\Exception\ExceptionInterface $e) {
57			return null;
58		}
59	}
60
61	private function readShipment($node)
62	{
63		$xp = new DOMXPath($node->ownerDocument);
64		return [
65			'provider' => 'UPS',
66			'service' => 'UPS_CODE_' . $xp->query('Service/Code', $node)->item(0)->textContent,
67			'readable' => tr('UPS_CODE_%0', $xp->query('Service/Code', $node)->item(0)->textContent),
68			'cost' => $xp->query('TotalCharges/MonetaryValue', $node)->item(0)->textContent,
69			'currency' => $xp->query('TotalCharges/CurrencyCode', $node)->item(0)->textContent,
70		];
71	}
72
73	private function getAuth()
74	{
75		$dom = new DOMDocument('1.0');
76		$dom->appendChild($root = $dom->createElement('AccessRequest'));
77
78		$root->appendChild($license = $dom->createElement('AccessLicenseNumber'));
79		$root->appendChild($username = $dom->createElement('UserId'));
80		$root->appendChild($password = $dom->createElement('Password'));
81
82		$license->appendChild($dom->createTextNode($this->license));
83		$username->appendChild($dom->createTextNode($this->username));
84		$password->appendChild($dom->createTextNode($this->password));
85
86		return $dom->saveXML();
87	}
88
89	private function getRequest($from, $to, $packages)
90	{
91		$dom = new DOMDocument('1.0');
92		$dom->appendChild($root = $dom->createElement('RatingServiceSelectionRequest'));
93		$root->appendChild($request = $dom->createElement('Request'));
94
95		$request->appendChild($ref = $dom->createElement('TransactionReference'));
96		$ref->appendChild($dom->createElement('CustomerContext', 'Tiki'));
97		$ref->appendChild($dom->createElement('XpciVersion', '1.0001'));
98		$request->appendChild($dom->createElement('RequestAction', 'Shop'));
99		$request->appendChild($dom->createElement('RequestOption', 'Shop'));
100		$root->appendChild($pickup = $dom->createElement('PickupType'));
101		$root->appendChild($shipment = $dom->createElement('Shipment'));
102
103		$pickup->appendChild($dom->createElement('Code', '01'));
104
105		$this->addAddress($shipment, 'Shipper', $from);
106		$this->addAddress($shipment, 'ShipTo', $to);
107		//$this->addAddress( $shipment, 'ShipFrom', $from );
108
109		foreach ($packages as $package) {
110			$this->addPackage($shipment, $package);
111		}
112
113		return $dom->saveXML();
114	}
115
116	private function addAddress($root, $name, $data)
117	{
118		$dom = $root->ownerDocument;
119
120		$root->appendChild($node = $dom->createElement($name));
121		$node->appendChild($address = $dom->createElement('Address'));
122		$address->appendChild($zip = $dom->createElement('PostalCode'));
123		$address->appendChild($country = $dom->createElement('CountryCode'));
124
125		$zip->appendChild($dom->createTextNode($data['zip']));
126		$country->appendChild($dom->createTextNode($data['country']));
127	}
128
129	private function addPackage($root, $data)
130	{
131		$dom = $root->ownerDocument;
132
133		$root->appendChild($package = $dom->createElement('Package'));
134		$package->appendChild($type = $dom->createElement('PackagingType'));
135		$type->appendChild($dom->createElement('Code', '00'));
136		$package->appendChild($packageWeight = $dom->createElement('PackageWeight'));
137		$packageWeight->appendChild($unit = $dom->createElement('UnitOfMeasurement'));
138		$unit->appendChild($code = $dom->createElement('Code', 'LBS'));
139		$packageWeight->appendChild($weight = $dom->createElement('Weight'));
140
141		$weight->appendChild($dom->createTextNode($data['weight'] * 2.20462262));
142	}
143}
144