1<?php
2class ModelExtensionShippingUps extends Model {
3	function getQuote($address) {
4		$this->load->language('extension/shipping/ups');
5
6		$query = $this->db->query("SELECT * FROM " . DB_PREFIX . "zone_to_geo_zone WHERE geo_zone_id = '" . (int)$this->config->get('shipping_ups_geo_zone_id') . "' AND country_id = '" . (int)$address['country_id'] . "' AND (zone_id = '" . (int)$address['zone_id'] . "' OR zone_id = '0')");
7
8		if (!$this->config->get('shipping_ups_geo_zone_id')) {
9			$status = true;
10		} elseif ($query->num_rows) {
11			$status = true;
12		} else {
13			$status = false;
14		}
15
16		$method_data = array();
17
18		if ($status) {
19			$weight = $this->weight->convert($this->cart->getWeight(), $this->config->get('config_weight_class_id'), $this->config->get('shipping_ups_weight_class_id'));
20			$weight_code = strtoupper($this->weight->getUnit($this->config->get('shipping_ups_weight_class_id')));
21
22			if ($weight_code == 'KG') {
23				$weight_code = 'KGS';
24			} elseif ($weight_code == 'LB') {
25				$weight_code = 'LBS';
26			}
27
28			$weight = ($weight < 0.1 ? 0.1 : $weight);
29
30			$length = $this->length->convert($this->config->get('shipping_ups_length'), $this->config->get('config_length_class_id'), $this->config->get('shipping_ups_length_class_id'));
31			$width = $this->length->convert($this->config->get('shipping_ups_width'), $this->config->get('config_length_class_id'), $this->config->get('shipping_ups_length_class_id'));
32			$height = $this->length->convert($this->config->get('shipping_ups_height'), $this->config->get('config_length_class_id'), $this->config->get('shipping_ups_length_class_id'));
33
34			$length_code = strtoupper($this->length->getUnit($this->config->get('shipping_ups_length_class_id')));
35
36			$service_code = array(
37				// US Origin
38				'US' => array(
39					'01' => $this->language->get('text_us_origin_01'),
40					'02' => $this->language->get('text_us_origin_02'),
41					'03' => $this->language->get('text_us_origin_03'),
42					'07' => $this->language->get('text_us_origin_07'),
43					'08' => $this->language->get('text_us_origin_08'),
44					'11' => $this->language->get('text_us_origin_11'),
45					'12' => $this->language->get('text_us_origin_12'),
46					'13' => $this->language->get('text_us_origin_13'),
47					'14' => $this->language->get('text_us_origin_14'),
48					'54' => $this->language->get('text_us_origin_54'),
49					'59' => $this->language->get('text_us_origin_59'),
50					'65' => $this->language->get('text_us_origin_65')
51				),
52				// Canada Origin
53				'CA' => array(
54					'01' => $this->language->get('text_ca_origin_01'),
55					'02' => $this->language->get('text_ca_origin_02'),
56					'07' => $this->language->get('text_ca_origin_07'),
57					'08' => $this->language->get('text_ca_origin_08'),
58					'11' => $this->language->get('text_ca_origin_11'),
59					'12' => $this->language->get('text_ca_origin_12'),
60					'13' => $this->language->get('text_ca_origin_13'),
61					'14' => $this->language->get('text_ca_origin_14'),
62					'54' => $this->language->get('text_ca_origin_54'),
63					'65' => $this->language->get('text_ca_origin_65')
64				),
65				// European Union Origin
66				'EU' => array(
67					'07' => $this->language->get('text_eu_origin_07'),
68					'08' => $this->language->get('text_eu_origin_08'),
69					'11' => $this->language->get('text_eu_origin_11'),
70					'54' => $this->language->get('text_eu_origin_54'),
71					'65' => $this->language->get('text_eu_origin_65'),
72					// next five services Poland domestic only
73					'82' => $this->language->get('text_eu_origin_82'),
74					'83' => $this->language->get('text_eu_origin_83'),
75					'84' => $this->language->get('text_eu_origin_84'),
76					'85' => $this->language->get('text_eu_origin_85'),
77					'86' => $this->language->get('text_eu_origin_86')
78				),
79				// Puerto Rico Origin
80				'PR' => array(
81					'01' => $this->language->get('text_pr_origin_01'),
82					'02' => $this->language->get('text_pr_origin_02'),
83					'03' => $this->language->get('text_pr_origin_03'),
84					'07' => $this->language->get('text_pr_origin_07'),
85					'08' => $this->language->get('text_pr_origin_08'),
86					'14' => $this->language->get('text_pr_origin_14'),
87					'54' => $this->language->get('text_pr_origin_54'),
88					'65' => $this->language->get('text_pr_origin_65')
89				),
90				// Mexico Origin
91				'MX' => array(
92					'07' => $this->language->get('text_mx_origin_07'),
93					'08' => $this->language->get('text_mx_origin_08'),
94					'54' => $this->language->get('text_mx_origin_54'),
95					'65' => $this->language->get('text_mx_origin_65')
96				),
97				// All other origins
98				'other' => array(
99					// service code 7 seems to be gone after January 2, 2007
100					'07' => $this->language->get('text_other_origin_07'),
101					'08' => $this->language->get('text_other_origin_08'),
102					'11' => $this->language->get('text_other_origin_11'),
103					'54' => $this->language->get('text_other_origin_54'),
104					'65' => $this->language->get('text_other_origin_65')
105				)
106			);
107
108			$xml  = '<?xml version="1.0"?>';
109			$xml .= '<AccessRequest xml:lang="en-US">';
110			$xml .= '	<AccessLicenseNumber>' . $this->config->get('shipping_ups_key') . '</AccessLicenseNumber>';
111			$xml .= '	<UserId>' . $this->config->get('shipping_ups_username') . '</UserId>';
112			$xml .= '	<Password>' . $this->config->get('shipping_ups_password') . '</Password>';
113			$xml .= '</AccessRequest>';
114			$xml .= '<?xml version="1.0"?>';
115			$xml .= '<RatingServiceSelectionRequest xml:lang="en-US">';
116			$xml .= '	<Request>';
117			$xml .= '		<TransactionReference>';
118			$xml .= '			<CustomerContext>Bare Bones Rate Request</CustomerContext>';
119			$xml .= '			<XpciVersion>1.0001</XpciVersion>';
120			$xml .= '		</TransactionReference>';
121			$xml .= '		<RequestAction>Rate</RequestAction>';
122			$xml .= '		<RequestOption>shop</RequestOption>';
123			$xml .= '	</Request>';
124			$xml .= '   <PickupType>';
125			$xml .= '       <Code>' . $this->config->get('shipping_ups_pickup') . '</Code>';
126			$xml .= '   </PickupType>';
127
128			if ($this->config->get('shipping_ups_country') == 'US' && $this->config->get('shipping_ups_pickup') == '11') {
129				$xml .= '   <CustomerClassification>';
130				$xml .= '       <Code>' . $this->config->get('shipping_ups_classification') . '</Code>';
131				$xml .= '   </CustomerClassification>';
132			}
133
134			$xml .= '	<Shipment>';
135			$xml .= '		<Shipper>';
136			$xml .= '			<Address>';
137			$xml .= '				<City>' . $this->config->get('shipping_ups_city') . '</City>';
138			$xml .= '				<StateProvinceCode>' . $this->config->get('shipping_ups_state') . '</StateProvinceCode>';
139			$xml .= '				<CountryCode>' . $this->config->get('shipping_ups_country') . '</CountryCode>';
140			$xml .= '				<PostalCode>' . $this->config->get('shipping_ups_postcode') . '</PostalCode>';
141			$xml .= '			</Address>';
142			$xml .= '		</Shipper>';
143			$xml .= '		<ShipTo>';
144			$xml .= '			<Address>';
145			$xml .= ' 				<City>' . $address['city'] . '</City>';
146			$xml .= '				<StateProvinceCode>' . $address['zone_code'] . '</StateProvinceCode>';
147			$xml .= '				<CountryCode>' . $address['iso_code_2'] . '</CountryCode>';
148			$xml .= '				<PostalCode>' . $address['postcode'] . '</PostalCode>';
149
150			if ($this->config->get('shipping_ups_quote_type') == 'residential') {
151				$xml .= '				<ResidentialAddressIndicator />';
152			}
153
154			$xml .= '			</Address>';
155			$xml .= '		</ShipTo>';
156			$xml .= '		<ShipFrom>';
157			$xml .= '			<Address>';
158			$xml .= '				<City>' . $this->config->get('shipping_ups_city') . '</City>';
159			$xml .= '				<StateProvinceCode>' . $this->config->get('shipping_ups_state') . '</StateProvinceCode>';
160			$xml .= '				<CountryCode>' . $this->config->get('shipping_ups_country') . '</CountryCode>';
161			$xml .= '				<PostalCode>' . $this->config->get('shipping_ups_postcode') . '</PostalCode>';
162			$xml .= '			</Address>';
163			$xml .= '		</ShipFrom>';
164
165			$xml .= '		<Package>';
166			$xml .= '			<PackagingType>';
167			$xml .= '				<Code>' . $this->config->get('shipping_ups_packaging') . '</Code>';
168			$xml .= '			</PackagingType>';
169
170			$xml .= '		    <Dimensions>';
171			$xml .= '				<UnitOfMeasurement>';
172			$xml .= '					<Code>' . $length_code . '</Code>';
173			$xml .= '				</UnitOfMeasurement>';
174			$xml .= '				<Length>' . $length . '</Length>';
175			$xml .= '				<Width>' . $width . '</Width>';
176			$xml .= '				<Height>' . $height . '</Height>';
177			$xml .= '			</Dimensions>';
178
179			$xml .= '			<PackageWeight>';
180			$xml .= '				<UnitOfMeasurement>';
181			$xml .= '					<Code>' . $weight_code . '</Code>';
182			$xml .= '				</UnitOfMeasurement>';
183			$xml .= '				<Weight>' . $weight . '</Weight>';
184			$xml .= '			</PackageWeight>';
185
186			if ($this->config->get('shipping_ups_insurance')) {
187				$xml .= '           <PackageServiceOptions>';
188				$xml .= '               <InsuredValue>';
189				$xml .= '                   <CurrencyCode>' . $this->session->data['currency'] . '</CurrencyCode>';
190				$xml .= '                   <MonetaryValue>' . $this->currency->format($this->cart->getSubTotal(), $this->session->data['currency'], false, false) . '</MonetaryValue>';
191				$xml .= '               </InsuredValue>';
192				$xml .= '           </PackageServiceOptions>';
193			}
194
195			$xml .= '		</Package>';
196
197			$xml .= '	</Shipment>';
198			$xml .= '</RatingServiceSelectionRequest>';
199
200			if (!$this->config->get('shipping_ups_test')) {
201				$url = 'https://onlinetools.ups.com/ups.app/xml/Rate';
202			} else {
203				$url = 'https://wwwcie.ups.com/ups.app/xml/Rate';
204			}
205
206			$curl = curl_init($url);
207
208			curl_setopt($curl, CURLOPT_HEADER, 0);
209			curl_setopt($curl, CURLOPT_POST, 1);
210			curl_setopt($curl, CURLOPT_TIMEOUT, 60);
211			curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
212			curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
213			curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
214			curl_setopt($curl, CURLOPT_POSTFIELDS, $xml);
215
216			$result = curl_exec($curl);
217
218			curl_close($curl);
219
220			$error = '';
221
222			$quote_data = array();
223
224			if ($result) {
225				if ($this->config->get('shipping_ups_debug')) {
226					$this->log->write("UPS DATA SENT: " . $xml);
227					$this->log->write("UPS DATA RECV: " . $result);
228				}
229
230				$previous_value = libxml_use_internal_errors(true);
231
232				$dom = new DOMDocument('1.0', 'UTF-8');
233				$dom->loadXml($result);
234
235				libxml_use_internal_errors($previous_value);
236
237				if (libxml_get_errors()) {
238					return false;
239				}
240
241				$rating_service_selection_response = $dom->getElementsByTagName('RatingServiceSelectionResponse')->item(0);
242
243				$response = $rating_service_selection_response->getElementsByTagName('Response')->item(0);
244
245				$response_status_code = $response->getElementsByTagName('ResponseStatusCode');
246
247				if ($response_status_code->item(0)->nodeValue != '1') {
248					$error = $response->getElementsByTagName('Error')->item(0)->getElementsByTagName('ErrorCode')->item(0)->nodeValue . ': ' . $response->getElementsByTagName('Error')->item(0)->getElementsByTagName('ErrorDescription')->item(0)->nodeValue;
249				} else {
250					$rated_shipments = $rating_service_selection_response->getElementsByTagName('RatedShipment');
251
252					foreach ($rated_shipments as $rated_shipment) {
253						$service = $rated_shipment->getElementsByTagName('Service')->item(0);
254
255						$code = $service->getElementsByTagName('Code')->item(0)->nodeValue;
256
257						$total_charges = $rated_shipment->getElementsByTagName('TotalCharges')->item(0);
258
259						$cost = $total_charges->getElementsByTagName('MonetaryValue')->item(0)->nodeValue;
260
261						$currency = $total_charges->getElementsByTagName('CurrencyCode')->item(0)->nodeValue;
262
263						if (!($code && $cost)) {
264							continue;
265						}
266
267						if ($this->config->get('shipping_ups_' . strtolower($this->config->get('shipping_ups_origin')) . '_' . $code)) {
268							$quote_data[$code] = array(
269								'code'         => 'ups.' . $code,
270								'title'        => $service_code[$this->config->get('shipping_ups_origin')][$code],
271								'cost'         => $this->currency->convert($cost, $currency, $this->config->get('config_currency')),
272								'tax_class_id' => $this->config->get('shipping_ups_tax_class_id'),
273								'text'         => $this->currency->format($this->tax->calculate($this->currency->convert($cost, $currency, $this->session->data['currency']), $this->config->get('shipping_ups_tax_class_id'), $this->config->get('config_tax')), $this->session->data['currency'], 1.0000000)
274							);
275						}
276					}
277				}
278			}
279
280			$title = $this->language->get('text_title');
281
282			if ($this->config->get('shipping_ups_display_weight')) {
283				$title .= ' (' . $this->language->get('text_weight') . ' ' . $this->weight->format($weight, $this->config->get('shipping_ups_weight_class_id')) . ')';
284			}
285
286			if ($quote_data || $error) {
287				$method_data = array(
288					'code'       => 'ups',
289					'title'      => $title,
290					'quote'      => $quote_data,
291					'sort_order' => $this->config->get('shipping_ups_sort_order'),
292					'error'      => $error
293				);
294			}
295		}
296
297		return $method_data;
298	}
299}
300