1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10:
11:
12: 13: 14:
15: class IllApps_Shipsync_Model_Shipping_Carrier_Fedex_Ship extends IllApps_Shipsync_Model_Shipping_Carrier_Fedex
16: {
17:
18:
19: protected $_shipRequest;
20: protected $_shipResult;
21: protected $_shipResultError;
22: protected $_shipServiceClient;
23: protected $_shipServiceVersion = '13';
24: protected $_shipServiceWsdlPath = 'ShipService_v13.wsdl';
25: protected $_activeShipment;
26:
27:
28: 29: 30: 31: 32: 33: 34:
35: public function createShipment($request)
36: {
37: $this->_shipServiceClient = $this->_initWebServices($this->_shipServiceWsdlPath);
38:
39:
40: $this->setShipRequest($request);
41:
42:
43: $this->_shipResult = $this->_createShipment();
44:
45:
46: return $this->_shipResult;
47: }
48:
49:
50: 51: 52: 53: 54: 55:
56: public function setShipRequest($request)
57: {
58: $shipRequest = Mage::getModel('shipsync/shipment_request');
59:
60: $shipRequest->setShipmentObject($request->getShipmentObject());
61: $shipRequest->setOrderId($request->getOrderId());
62: $shipRequest->setOrder(Mage::getModel('sales/order')->loadByIncrementId($shipRequest->getOrderId()));
63: $shipRequest->setStore($shipRequest->getOrder()->getStore());
64: $shipRequest->setPackages($request->getPackages());
65: $shipRequest->setMethodCode($request->getMethodCode());
66: $shipRequest->setServiceType($this->getUnderscoreCodeFromCode($shipRequest->getMethodCode()));
67: $shipRequest->setDropoffType($this->getUnderscoreCodeFromCode(Mage::getStoreConfig('carriers/fedex/dropoff')));
68: $shipRequest->setCustomerReference($shipRequest->getOrderId() . '_pkg2' . $request->getPackageId());
69: $shipRequest->setInvoiceNumber('INV' . $shipRequest->getOrderId());
70:
71:
72: $shipperRegionId = Mage::getStoreConfig('shipping/origin/region_id');
73:
74:
75: if (is_numeric($shipperRegionId)) {
76: $shipRequest->setShipperRegionCode(Mage::getModel('directory/region')->load($shipperRegionId)->getCode());
77: }
78:
79:
80: $shipperStreetLines = array(Mage::getStoreConfig('shipping/origin/street_line1'));
81:
82: if (Mage::getStoreConfig('shipping/origin/street_line2') != '') {
83: $shipperStreetLines[] = Mage::getStoreConfig('shipping/origin/street_line2');
84: }
85: if (Mage::getStoreConfig('shipping/origin/street_line3') != '') {
86: $shipperStreetLines[] = Mage::getStoreConfig('shipping/origin/street_line3');
87: }
88:
89: $shipRequest->setShipperStreetLines($shipperStreetLines);
90: $shipRequest->setShipperCity(Mage::getStoreConfig('shipping/origin/city'));
91: $shipRequest->setShipperPostalCode(Mage::getStoreConfig('shipping/origin/postcode'));
92: $shipRequest->setShipperCountryCode(Mage::getStoreConfig('shipping/origin/country_id', $this->getStore()));
93: $shipRequest->setShipperPhone(Mage::getStoreConfig('shipping/origin/phone'));
94: $shipRequest->setShipperStateOrProvinceCode($shipRequest->getShipperRegionCode());
95:
96: $shipRequest->setRecipientAddress($request->getRecipientAddress());
97: $shipRequest->setInsureShipment($request->getInsureShipment());
98:
99:
100: $shipRequest->setWeightUnits(Mage::getModel('shipsync/shipping_carrier_fedex')->getWeightUnits());
101:
102:
103: $shipRequest->setWeightCoefficient(1.0);
104:
105:
106: if ($shipRequest->getWeightUnits() == 'G') {
107: $shipRequest->setWeightUnits('KG');
108: $shipRequest->setWeightCoefficient(0.001);
109: }
110:
111:
112: $shipRequest->setEnableDimensions(Mage::getStoreConfig('carriers/fedex/shipping_dimensions_disable'));
113:
114:
115: $shipRequest->setDimensionUnits(Mage::getModel('shipsync/shipping_carrier_fedex')->getDimensionUnits());
116:
117:
118: $shipRequest->setCustomsValue($shipRequest->getOrder()->getGrandTotal() - $shipRequest->getOrder()->getShippingAmount());
119:
120:
121: if ($request->getInsureAmount() != '') {
122: $shipRequest->setInsureAmount($request->getInsureAmount());
123: } else {
124: $shipRequest->setInsureAmount($shipRequest->getCustomsValue());
125: }
126:
127:
128: $shipRequest->setSignature($request->getSignature());
129:
130:
131: $shipRequest->setSaturdayDelivery($request->getSaturdayDelivery());
132:
133:
134: $shipRequest->setCod($request->getCod());
135:
136:
137: $shipRequest->setRateType(Mage::getStoreConfig('carriers/fedex/rate_type'));
138:
139:
140: $shipRequest->setShipTimestamp(date('c'));
141:
142: if (($request->getAddressValidation() == 'ENABLED') && ($request->getResidenceDelivery() == 'VALIDATE')) {
143: $shipRequest->setResidential($this->getResidential($shipRequest->getRecipientAddress()->getStreet(), $shipRequest->getRecipientAddress()->getPostcode()));
144: }
145: else if ($request->getResidenceDelivery() == 'ENABLED') {
146: $shipRequest->setResidential(true);
147: }
148: else if ($request->getResidenceDelivery() == 'DISABLED') {
149: $shipRequest->setResidential(false);
150: }
151:
152: $shipRequest->setLabelStockType($request->getLabelStockType());
153: $shipRequest->setLabelImageType($request->getLabelImageType());
154: $shipRequest->setLabelPrintingOrientation($request->getLabelPrintingOrientation());
155: $shipRequest->setEnableJavaPrinting($request->getEnableJavaPrinting());
156: $shipRequest->setPrinterName($request->getPrinterName());
157: $shipRequest->setPackingList($request->getPackingList());
158: $shipRequest->setShipperCompany($request->getShipperCompany());
159: $shipRequest->setReturnLabel($request->getReturnLabel());
160:
161: $this->_shipRequest = $shipRequest;
162:
163: return $this;
164: }
165:
166: 167: 168: 169: 170:
171: protected function _createShipment()
172: {
173: $shipRequest = $this->_shipRequest;
174:
175:
176: foreach ($shipRequest->getPackages() as $packageToShip) {
177:
178: $request = $this->_prepareShipmentHeader();
179:
180:
181: $request['RequestedShipment'] = array(
182: 'ShipTimestamp' => $shipRequest->getShipTimestamp(),
183: 'DropoffType' => $shipRequest->getDropoffType(),
184: 'ServiceType' => $shipRequest->getServiceType(),
185: 'PackagingType' => $packageToShip->getContainerCode(),
186: 'TotalWeight' => array(
187: 'Value' => $packageToShip->getWeight(),
188: 'Units' => $shipRequest->getWeightUnits()
189: ),
190: 'Shipper' => $shipRequest->getShipperDetails(),
191: 'Recipient' => $shipRequest->getRecipientDetails(),
192: 'LabelSpecification' => array(
193: 'LabelFormatType' => 'COMMON2D',
194: 'ImageType' => $shipRequest->getLabelImageType(),
195: 'LabelStockType' => $shipRequest->getLabelStockType(),
196: 'LabelPrintingOrientation' => $shipRequest->getLabelPrintingOrientation(),
197: 'CustomerSpecifiedDetail' => array(
198: 'DocTabContent' => array(
199: 'DocTabContentType' => 'STANDARD'
200: )
201: )
202: ),
203: 'RateRequestTypes' => $shipRequest->getRateType(),
204: 'PreferredCurrency' => $this->getCurrencyCode(),
205: 'PackageDetail' => 'INDIVIDUAL_PACKAGES',
206: 'SignatureOptionDetail' => array(
207: 'OptionType' => $shipRequest->getSignature()
208: ),
209: 'ShippingChargesPayment' => array(
210: 'PaymentType' => $shipRequest->getPayorType(),
211: 'Payor' => array(
212: 'ResponsibleParty' => array(
213: 'AccountNumber' => $shipRequest->getPayorAccount(),
214: 'Contact' => null,
215: 'Address' => array(
216: 'CountryCode' => $shipRequest->getPayorAccountCountry()
217: )
218: )
219: )
220: ),
221: 'RequestedPackageLineItems' => array(
222: 'SequenceNumber' => $packageToShip->getSequenceNumber(),
223: 'Weight' => array(
224: 'Value' => $packageToShip->getWeight(),
225: 'Units' => $shipRequest->getWeightUnits()
226: ),
227: 'CustomerReferences' => array(
228: '0' => array(
229: 'CustomerReferenceType' => 'CUSTOMER_REFERENCE',
230: 'Value' => $shipRequest->getCustomerReference()
231: ),
232: '1' => array(
233: 'CustomerReferenceType' => 'INVOICE_NUMBER',
234: 'Value' => $shipRequest->getInvoiceNumber()
235: )
236: ),
237: 'ContentRecords' => $packageToShip->getContents()
238: )
239: );
240:
241: $request['RequestedShipment'] = array_merge($request['RequestedShipment'], $shipRequest->getMPSData());
242:
243:
244: if ($shipRequest->getSaturdayDelivery()) {
245: $specialServiceTypes[] = 'SATURDAY_DELIVERY';
246: }
247:
248:
249: if ($packageToShip['dangerous']) {
250: $request['RequestedShipment']['RequestedPackageLineItems']['SpecialServicesRequested'] = array(
251: 'DangerousGoodsDetail' => array(
252: 'Accessibility' => 'ACCESSIBLE',
253: 'Options' => 'ORM_D'
254: )
255: );
256: $specialServiceTypes[] = 'DANGEROUS_GOODS';
257: }
258:
259:
260: if ($shipRequest->getCod()) {
261: $request['RequestedShipment']['SpecialServicesRequested'] = array(
262: 'CodDetail' => array(
263: 'CodCollectionAmount' => array(
264: 'Amount' => $packageToShip['cod_amount'],
265: 'Currency' => $this->getCurrencyCode()
266: ),
267: 'CollectionType' => 'ANY'
268: )
269: );
270: $specialServiceTypes[] = 'COD';
271: }
272:
273: if (isset($specialServiceTypes)) {
274: $request['RequestedShipment']['RequestedPackageLineItems']['SpecialServicesRequested']['SpecialServiceTypes'] = $specialServiceTypes;
275: }
276:
277:
278: if (($packageToShip->getContainerCode() == "YOUR_PACKAGING") && (!$packageToShip->getEnableDimensions())
279: && ($packageToShip->getRoundedLength() && $packageToShip->getRoundedWidth() && $packageToShip->getRoundedHeight()))
280: {
281: $request['RequestedShipment']['RequestedPackageLineItems']['Dimensions'] = array(
282: 'Length' => $packageToShip->getRoundedLength(),
283: 'Width' => $packageToShip->getRoundedWidth(),
284: 'Height' => $packageToShip->getRoundedHeight(),
285: 'Units' => $shipRequest->getDimensionUnits());
286: }
287:
288:
289: if ($shipRequest->getInsureShipment()) {
290: $request['RequestedShipment']['RequestedPackageLineItems']['InsuredValue'] = array(
291: 'Currency' => $this->getCurrencyCode(),
292: 'Amount' => $shipRequest->getInsureAmount()
293: );
294: }
295:
296:
297: if (Mage::getStoreConfig('carriers/fedex/enable_smartpost')) {
298: $request['RequestedShipment']['SmartPostDetail'] = $shipRequest->getSmartPostDetails();
299: }
300:
301:
302: if ($shipRequest->getTransactionType() == 'International') {
303:
304:
305: if ($this->getConfig('tax_id_number') != '') {
306: $request['TIN'] = $this->getConfig('tax_id_number');
307: }
308:
309: $itemDetails = array();
310:
311:
312: foreach ($packageToShip->getItems() as $_item) {
313:
314:
315: $item = Mage::getModel('sales/order_item')->load($_item['id']);
316:
317: $itemDetails[] = array(
318: 'NumberOfPieces' => 1,
319: 'Description' => $item->getName(),
320: 'CountryOfManufacture' => $shipRequest->getShipperCountryCode(),
321: 'Weight' => array(
322: 'Value' => $item->getWeight() * $shipRequest->getWeightCoefficient(),
323: 'Units' => $shipRequest->getWeightUnits()
324: ),
325: 'Quantity' => $item->getQtyOrdered(),
326: 'QuantityUnits' => 'EA',
327: 'UnitPrice' => array(
328: 'Amount' => sprintf('%01.2f', $item->getPrice()),
329: 'Currency' => $this->getCurrencyCode()
330: ),
331: 'CustomsValue' => array(
332: 'Amount' => sprintf('%01.2f', ($item->getPrice())),
333: 'Currency' => $this->getCurrencyCode()
334: )
335: );
336: }
337:
338: $request['RequestedShipment']['CustomsClearanceDetail'] = array(
339: 'DutiesPayment' => array(
340: 'PaymentType' => 'SENDER',
341: 'Payor' => array(
342: 'ResponsibleParty' => array(
343: 'AccountNumber' => $this->getFedexAccount(),
344: 'Contact' => null,
345: 'Address' => array(
346: 'CountryCode' => $shipRequest->getShipperCountryCode()
347: )
348: )
349: )
350: ),
351: 'DocumentContent' => 'NON_DOCUMENTS',
352: 'CustomsValue' => array(
353: 'Amount' => sprintf('%01.2f', $shipRequest->getCustomsValue()),
354: 'Currency' => $this->getCurrencyCode()
355: ),
356: 'Commodities' => $itemDetails,
357: 'ExportDetail' => array(
358: 'B13AFilingOption' => 'NOT_REQUIRED'
359: )
360: );
361: }
362:
363: $returnLabelImage = '';
364:
365: if ($shipRequest->getReturnLabel()) {
366:
367: $returnRequest = $request;
368:
369: $returnRequest['RequestedShipment']['Recipient'] = $shipRequest->getShipperDetails();
370: $returnRequest['RequestedShipment']['Shipper'] = $shipRequest->getRecipientDetails();
371:
372: try {
373:
374: Mage::Helper('shipsync')->mageLog($returnRequest, 'ship');
375:
376: $returnResponse = $this->_shipServiceClient->processShipment($returnRequest);
377:
378: Mage::Helper('shipsync')->mageLog($returnResponse, 'ship');
379: }
380: catch (SoapFault $ex) {
381: throw Mage::exception('Mage_Shipping', $ex->getMessage());
382: }
383:
384: $returnLabelImage = base64_encode($returnResponse->CompletedShipmentDetail->CompletedPackageDetails->Label->Parts->Image);
385: }
386:
387: try {
388:
389: Mage::Helper('shipsync')->mageLog($request, 'ship');
390:
391: $shipResponse = $this->_shipServiceClient->processShipment($request);
392:
393: Mage::Helper('shipsync')->mageLog($shipResponse, 'ship');
394: }
395: catch (SoapFault $ex) {
396: throw Mage::exception('Mage_Shipping', $ex->getMessage());
397: }
398:
399: $response = Mage::getModel('shipsync/shipment_response')->setResponse($shipResponse);
400:
401: $shipResult = Mage::getModel('shipsync/shipment_result');
402:
403: if ($response->setNotificationsErrors()) {
404: throw Mage::exception('Mage_Shipping', $response->getErrors());
405: } elseif ($response->isWarning()) {
406: throw Mage::exception('Mage_Shipping', $response->incompleteApi());
407: } else {
408:
409: if (!Mage::getStoreConfig('carriers/fedex/third_party')) {
410: $shipResult->setBillingWeightUnits($response->findStructure('Units'));
411: $shipResult->setBillingWeight($response->findStructure('Value'));
412: }
413:
414: $_packages = array();
415:
416: $_packages[] = array(
417: 'package_number' => $response->getSequenceNumber(),
418: 'tracking_number' => $response->getTrackingNumber(),
419: 'masterTrackingId' => $response->getMasterTrackingId(),
420: 'label_image_format' => $shipRequest->getLabelImageType(),
421: 'label_image' => base64_encode($shipResponse->CompletedShipmentDetail->CompletedPackageDetails->Label->Parts->Image),
422: 'return_label_image' => $returnLabelImage,
423: 'cod_label_image' => $response->getCodLabelImage()
424: );
425:
426: $shipResult->setPackages($_packages);
427: }
428:
429:
430:
431: foreach ($shipResult->getPackages() as $packageShipped) {
432: $convertor = Mage::getModel('sales/convert_order');
433:
434: if ($packageShipped['masterTrackingId'] != false) {
435: $shipRequest->setMasterTrackingId($packageShipped['masterTrackingId']);
436: }
437:
438: if ($packageShipped['package_number'] == 1) {
439: $shipment = $convertor->toShipment($shipRequest->getOrder());
440: }
441:
442: foreach ($this->getItemsById($packageToShip) as $itemToShip) {
443: $orderItem = $shipRequest->getOrder()->getItemById($itemToShip['id']);
444: $item = $convertor->itemToShipmentItem($orderItem);
445: $item->setQty($itemToShip['qty_to_ship']);
446: $shipment->addItem($item);
447: }
448:
449: $track = Mage::getModel('sales/order_shipment_track')
450: ->setTitle($this->getCode('method', $shipRequest->getServiceType(), true))
451: ->setCarrierCode('fedex')
452: ->setNumber($packageShipped['tracking_number'])
453: ->setShipment($shipment);
454:
455: if ($packageShipped['package_number'] == $shipRequest->getPackageCount()) {
456: $shipment->addTrack($track);
457: $shipment->register();
458: $shipment->getOrder()->setIsInProcess(true);
459:
460: $transactionSave = Mage::getModel('core/resource_transaction')->addObject($shipment)->addObject($shipment->getOrder())->save();
461:
462: $this->sendEmail($shipment, $packageToShip, $packageShipped);
463: } else {
464: $shipment->addTrack($track);
465: }
466:
467:
468: if ($shipRequest->getLabelImageType() == 'PDF' &&
469: $shipRequest->getLabelStockType() == 'PAPER_7X4.75' &&
470: $shipRequest->getLabelPrintingOrientation() == 'BOTTOM_EDGE_OF_TEXT_FIRST' &&
471: $shipRequest->getPackingList()) {
472:
473:
474: $pdf = Zend_Pdf::parse(base64_decode($packageShipped['label_image']));
475:
476:
477: $font = Zend_Pdf_Font::fontWithName(Zend_Pdf_Font::FONT_HELVETICA);
478:
479:
480: $pdf->pages[0]->setFont($font, 8);
481:
482:
483: $yPosition = 360;
484:
485:
486: $pdf->pages[0]->drawText('ID', 30, $yPosition);
487: $pdf->pages[0]->drawText('SKU', 60, $yPosition);
488: $pdf->pages[0]->drawText('Name', 180, $yPosition);
489: $pdf->pages[0]->drawText('Qty', 560, $yPosition);
490:
491:
492: $pdf->pages[0]->drawLine(30, $yPosition-3, 575, $yPosition-3);
493:
494:
495: $cursor = 12;
496:
497:
498: $items = $this->getItemsById($packageToShip);
499:
500: foreach ($items as $item) {
501:
502:
503: $yPosition -= $cursor;
504:
505:
506: $pdf->pages[0]->drawText($item['product_id'], 30, $yPosition);
507: $pdf->pages[0]->drawText($item['sku'], 60, $yPosition);
508: $pdf->pages[0]->drawText($item['name'], 180, $yPosition);
509: $pdf->pages[0]->drawText($item['qty_to_ship'], 560, $yPosition);
510:
511:
512: $pdf->pages[0]->drawLine(30, $yPosition-3, 575, $yPosition-3);
513: }
514:
515:
516: $labelImage = base64_encode($pdf->render());
517: }
518: else {
519: $labelImage = $packageShipped['label_image'];
520: }
521:
522: $pkg = Mage::getModel('shipping/shipment_package')
523: ->setOrderIncrementId($shipRequest->getOrder()->getIncrementId())
524: ->setOrderShipmentId($shipment->getEntityId())
525: ->setPackageItems($this->jsonPackageItems($packageToShip))
526: ->setCarrier('fedex')
527: ->setShippingMethod($track->getTitle())
528: ->setPackageType($this->getCode('packaging', $packageToShip->getContainerCode(), true))
529: ->setCarrierShipmentId($shipResult->getShipmentIdentificationNumber())
530: ->setWeightUnits($shipResult->getBillingWeightUnits())
531: ->setDimensionUnits($packageToShip->getDimensionUnitCode())
532: ->setWeight($shipResult->getBillingWeight())
533: ->setLength($packageToShip->getLength())
534: ->setWidth($packageToShip->getWidth())
535: ->setHeight($packageToShip->getHeight())
536: ->setTrackingNumber($packageShipped['tracking_number'])
537: ->setCurrencyUnits($shipResult->getCurrencyUnits())
538: ->setTransportationCharge($shipResult->getTransportationShippingCharges())
539: ->setServiceOptionCharge($shipResult->getServiceOptionsShippingCharges())
540: ->setShippingTotal($shipResult->getTotalShippingCharges())
541: ->setNegotiatedTotal($shipResult->getNegotiatedTotalShippingCharges())
542: ->setLabelFormat($packageShipped['label_image_format'])
543: ->setLabelImage($labelImage)
544: ->setReturnLabelImage($packageShipped['return_label_image'])
545: ->setCodLabelImage($packageShipped['cod_label_image'])
546: ->setDateShipped(date('Y-m-d H:i:s'))
547: ->save();
548:
549: $retval[] = $pkg;
550: }
551:
552: if (Mage::getStoreConfig('carriers/fedex/mps_shipments')) {
553: foreach ($retval as $pkg) {
554: $pkg->setOrderShipmentId($shipment->getEntityId())->save();
555: }
556: }
557: }
558: return $retval;
559: }
560:
561: public function sendEmail($shipment, $packageToShip, $packageShipped)
562: {
563: if ($packageToShip->getData('confirmation')) {
564: $shipment->sendEmail();
565: }
566: return $shipment;
567: }
568:
569: public function jsonPackageItems($packageToShip)
570: {
571: $ret = array();
572:
573: foreach ($this->getItemsById($packageToShip) as $item) {
574: $ret[] = array(
575: 'i' => $item['product_id'],
576: 'q' => $item['qty_to_ship']
577: );
578: }
579:
580: return json_encode($ret);
581: }
582:
583: public function getItemsById($packageToShip)
584: {
585: $itemsById = array();
586:
587: foreach ($packageToShip->getItems() as $itemToShip) {
588: $id = $itemToShip['id'];
589: $count = isset($itemsById[$id]['qty_to_ship']) ? $itemsById[$id]['qty_to_ship'] : 0;
590: $itemToShip['qty_to_ship'] = 1 + $count;
591: $itemsById[$id] = $itemToShip;
592: }
593:
594: return $itemsById;
595: }
596:
597: 598: 599: 600: 601:
602: protected function ()
603: {
604: $shipRequest = $this->_shipRequest;
605:
606: $request['WebAuthenticationDetail'] = array(
607: 'UserCredential' => array(
608: 'Key' => $this->getFedexKey(),
609: 'Password' => $this->getFedexPassword()
610: )
611: );
612:
613: $request['ClientDetail'] = array(
614: 'AccountNumber' => $this->getFedexAccount(),
615: 'MeterNumber' => $this->getFedexMeter()
616: );
617:
618: $transactionType = $shipRequest->getTransactionType();
619:
620: $transactionMethod = $shipRequest->getTransactionMethod();
621:
622: $request['TransactionDetail']['CustomerTransactionId'] = "*** $transactionMethod $transactionType Shipping Request v$this->_shipServiceVersion using PHP ***";
623: $request['Version'] = array(
624: 'ServiceId' => 'ship',
625: 'Major' => $this->_shipServiceVersion,
626: 'Intermediate' => '0',
627: 'Minor' => '0'
628: );
629:
630: return $request;
631: }
632:
633: 634: 635: 636: 637: 638: 639:
640: protected function _setSpecialServices($request, $package)
641: {
642: }
643:
644: }
645: