1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
26:
27: 28: 29: 30: 31: 32: 33:
34: class Mage_GoogleCheckout_Model_Api_Xml_Checkout extends Mage_GoogleCheckout_Model_Api_Xml_Abstract
35: {
36: 37: 38:
39: const ITEM_WEIGHT_UNIT = 'LB';
40:
41: 42: 43:
44: const ITEM_SIZE_UNIT = 'IN';
45:
46: 47: 48:
49: const CHECKOUT_SHOPPING_CART_XMLNS = 'http://checkout.google.com/schema/2';
50:
51: 52: 53: 54: 55:
56: protected $_currency;
57:
58: 59: 60: 61: 62:
63: protected $_shippingCalculated = false;
64:
65: 66: 67: 68: 69:
70: protected function _getApiUrl()
71: {
72: $url = $this->_getBaseApiUrl();
73: $url .= 'merchantCheckout/Merchant/' . $this->getMerchantId();
74: return $url;
75: }
76:
77: 78: 79: 80: 81:
82: public function checkout()
83: {
84: $quote = $this->getQuote();
85: if (!($quote instanceof Mage_Sales_Model_Quote)) {
86: Mage::throwException('Invalid quote');
87: }
88:
89: $xmlns = self::CHECKOUT_SHOPPING_CART_XMLNS;
90: $xml = <<<EOT
91: <checkout-shopping-cart xmlns="{$xmlns}">
92: <shopping-cart>
93: {$this->_getItemsXml()}
94: {$this->_getMerchantPrivateDataXml()}
95: {$this->_getCartExpirationXml()}
96: </shopping-cart>
97: <checkout-flow-support>
98: {$this->_getMerchantCheckoutFlowSupportXml()}
99: </checkout-flow-support>
100: <order-processing-support>
101: {$this->_getRequestInitialAuthDetailsXml()}
102: </order-processing-support>
103: </checkout-shopping-cart>
104: EOT;
105:
106: $result = $this->_call($xml);
107: $this->setRedirectUrl($result->{'redirect-url'});
108:
109: return $this;
110: }
111:
112: 113: 114: 115: 116:
117: protected function _getItemsXml()
118: {
119: $xml = <<<EOT
120: <items>
121:
122: EOT;
123:
124: foreach ($this->getQuote()->getAllItems() as $item) {
125: if ($item->getParentItem()) {
126: continue;
127: }
128: $taxClass = ($item->getTaxClassId() == 0) ? 'none' : $item->getTaxClassId();
129: $weight = (float) $item->getWeight();
130: $weightUnit = self::ITEM_WEIGHT_UNIT;
131:
132: $unitPrice = $item->getBaseCalculationPrice();
133: if (Mage::helper('weee')->includeInSubtotal()) {
134: $unitPrice += $item->getBaseWeeeTaxAppliedAmount();
135: }
136:
137: $xml .= <<<EOT
138: <item>
139: <merchant-item-id><![CDATA[{$item->getSku()}]]></merchant-item-id>
140: <item-name><![CDATA[{$item->getName()}]]></item-name>
141: <item-description><![CDATA[{$item->getDescription()}]]></item-description>
142: <unit-price currency="{$this->getCurrency()}">{$unitPrice}</unit-price>
143: <quantity>{$item->getQty()}</quantity>
144: <item-weight unit="{$weightUnit}" value="{$weight}" />
145: <tax-table-selector>{$taxClass}</tax-table-selector>
146: {$this->_getDigitalContentXml($item->getIsVirtual())}
147: {$this->_getMerchantPrivateItemDataXml($item)}
148: </item>
149:
150: EOT;
151: }
152:
153: $billingAddress = $this->getQuote()->getBillingAddress();
154: $shippingAddress = $this->getQuote()->getShippingAddress();
155:
156: $shippingDiscount = (float)$shippingAddress->getBaseDiscountAmount();
157: $billingDiscount = (float)$billingAddress->getBaseDiscountAmount();
158: $discount = $billingDiscount + $shippingDiscount;
159:
160:
161:
162: $discount += $shippingAddress->getBaseShippingDiscountAmount();
163:
164: $discountItem = new Varien_Object(array(
165: 'price' => $discount,
166: 'name' => $this->__('Cart Discount'),
167: 'description' => $this->__('A virtual item to reflect the discount total')
168: ));
169:
170: Mage::dispatchEvent('google_checkout_discount_item_price', array(
171: 'quote' => $this->getQuote(),
172: 'discount_item' => $discountItem
173: ));
174:
175: $discount = $discountItem->getPrice();
176: if ($discount) {
177: $xml .= <<<EOT
178: <item>
179: <merchant-item-id>_INTERNAL_DISCOUNT_</merchant-item-id>
180: <item-name>{$discountItem->getName()}</item-name>
181: <item-description>{$discountItem->getDescription()}</item-description>
182: <unit-price currency="{$this->getCurrency()}">{$discount}</unit-price>
183: <quantity>1</quantity>
184: <item-weight unit="{$weightUnit}" value="0.00" />
185: <tax-table-selector>none</tax-table-selector>
186: {$this->_getDigitalContentXml($this->getQuote()->isVirtual())}
187: </item>
188:
189: EOT;
190: }
191:
192: $hiddenTax = $shippingAddress->getBaseHiddenTaxAmount() + $billingAddress->getBaseHiddenTaxAmount();
193: if ($hiddenTax) {
194: $xml .= <<<EOT
195: <item>
196: <merchant-item-id>_INTERNAL_TAX_</merchant-item-id>
197: <item-name>{$this->__('Discount Tax')}</item-name>
198: <item-description>{$this->__('A virtual item to reflect the tax total')}</item-description>
199: <unit-price currency="{$this->getCurrency()}">{$hiddenTax}</unit-price>
200: <quantity>1</quantity>
201: <item-weight unit="{$weightUnit}" value="0.00" />
202: <tax-table-selector>none</tax-table-selector>
203: {$this->_getDigitalContentXml($this->getQuote()->isVirtual())}
204: </item>
205: EOT;
206: }
207: $xml .= <<<EOT
208: </items>
209: EOT;
210:
211: return $xml;
212: }
213:
214: 215: 216: 217: 218: 219:
220: protected function _getDigitalContentXml($isVirtual)
221: {
222: if (!$isVirtual) {
223: return '';
224: }
225:
226: $storeId = $this->getQuote()->getStoreId();
227: $active = Mage::getStoreConfigFlag(Mage_GoogleCheckout_Helper_Data::XML_PATH_SHIPPING_VIRTUAL_ACTIVE, $storeId);
228: if (!$active) {
229: return '';
230: }
231:
232: $schedule = Mage::getStoreConfig(Mage_GoogleCheckout_Helper_Data::XML_PATH_SHIPPING_VIRTUAL_SCHEDULE, $storeId);
233: $method = Mage::getStoreConfig(Mage_GoogleCheckout_Helper_Data::XML_PATH_SHIPPING_VIRTUAL_METHOD, $storeId);
234:
235: $xml = "<display-disposition>{$schedule}</display-disposition>";
236:
237: if ($method == 'email') {
238: $xml .= '<email-delivery>true</email-delivery>';
239: } elseif ($method == 'key_url') {
240: } elseif ($method == 'description_based') {
241: }
242:
243: $xml = "<digital-content>{$xml}</digital-content>";
244:
245: return $xml;
246: }
247:
248: 249: 250: 251: 252: 253:
254: protected function _getMerchantPrivateItemDataXml($item)
255: {
256: $xml = <<<EOT
257: <merchant-private-item-data>
258: <quote-item-id>{$item->getId()}</quote-item-id>
259: </merchant-private-item-data>
260: EOT;
261: return $xml;
262: }
263:
264: 265: 266: 267: 268:
269: protected function _getMerchantPrivateDataXml()
270: {
271: $xml = <<<EOT
272: <merchant-private-data>
273: <quote-id><![CDATA[{$this->getQuote()->getId()}]]></quote-id>
274: <store-id><![CDATA[{$this->getQuote()->getStoreId()}]]></store-id>
275: </merchant-private-data>
276: EOT;
277: return $xml;
278: }
279:
280: 281: 282: 283: 284:
285: protected function _getCartExpirationXml()
286: {
287: $xml = <<<EOT
288: EOT;
289: return $xml;
290: }
291:
292: /**
293: * Retrieve merchant checkout flow support XML
294: *
295: * @return string
296: */
297: protected function _getMerchantCheckoutFlowSupportXml()
298: {
299: $xml = <<<EOT
300: <merchant-checkout-flow-support>
301: <edit-cart-url><![CDATA[{$this->_getEditCartUrl()}]]></edit-cart-url>
302: <continue-shopping-url><![CDATA[{$this->_getContinueShoppingUrl()}]]></continue-shopping-url>
303: {$this->_getRequestBuyerPhoneNumberXml()}
304: {$this->_getMerchantCalculationsXml()}
305: {$this->_getShippingMethodsXml()}
306: {$this->_getAllTaxTablesXml()}
307: {$this->_getParameterizedUrlsXml()}
308: {$this->_getPlatformIdXml()}
309: {$this->_getAnalyticsDataXml()}
310: </merchant-checkout-flow-support>
311: EOT;
312: return $xml;
313: }
314:
315: 316: 317: 318: 319:
320: protected function _getRequestBuyerPhoneNumberXml()
321: {
322: $requestPhone = Mage::getStoreConfig(
323: Mage_GoogleCheckout_Helper_Data::XML_PATH_REQUEST_PHONE,
324: $this->getQuote()->getStoreId()
325: );
326: $requestPhone = $requestPhone ? 'true' : 'false';
327: $xml = <<<EOT
328: <request-buyer-phone-number>{$requestPhone}</request-buyer-phone-number>
329: EOT;
330: return $xml;
331: }
332:
333: 334: 335: 336: 337:
338: protected function _getMerchantCalculationsXml()
339: {
340: $xml = <<<EOT
341: <merchant-calculations>
342: <merchant-calculations-url><![CDATA[{$this->_getCalculationsUrl()}]]></merchant-calculations-url>
343: </merchant-calculations>
344: EOT;
345: return $xml;
346: }
347:
348: 349: 350: 351: 352:
353: protected function _getVirtualOrderShippingXml()
354: {
355: $title = Mage::helper('googlecheckout')->__('Free Shipping');
356:
357: $xml = <<<EOT
358: <shipping-methods>
359: <flat-rate-shipping name="{$title}">
360: <shipping-restrictions><allowed-areas><world-area /></allowed-areas></shipping-restrictions>
361: <price currency="{$this->getCurrency()}">0</price>
362: </flat-rate-shipping>
363: </shipping-methods>
364: EOT;
365: return $xml;
366: }
367:
368: 369: 370: 371: 372:
373: protected function _getShippingMethodsXml()
374: {
375: if ($this->_isOrderVirtual()) {
376: return $this->_getVirtualOrderShippingXml();
377: }
378:
379: $xml = <<<EOT
380: <shipping-methods>
381: {$this->_getCarrierCalculatedShippingXml()}
382: {$this->_getFlatRateShippingXml()}
383: {$this->_getMerchantCalculatedShippingXml()}
384: {$this->_getPickupXml()}
385: </shipping-methods>
386: EOT;
387: return $xml;
388: }
389:
390: 391: 392: 393: 394:
395: protected function _getCarrierCalculatedShippingXml()
396: {
397: 398: 399:
400: if ($this->_shippingCalculated) {
401: return '';
402: }
403:
404: $storeId = $this->getQuote()->getStoreId();
405: $active = Mage::getStoreConfigFlag(Mage_GoogleCheckout_Helper_Data::XML_PATH_SHIPPING_CARRIER_ACTIVE, $storeId);
406: $methods = Mage::getStoreConfig(Mage_GoogleCheckout_Helper_Data::XML_PATH_SHIPPING_CARRIER_METHODS, $storeId);
407:
408: if (!$active || !$methods) {
409: return '';
410: }
411:
412: $country = Mage::getStoreConfig(Mage_Shipping_Model_Config::XML_PATH_ORIGIN_COUNTRY_ID, $storeId);
413: $region = Mage::getStoreConfig(Mage_Shipping_Model_Config::XML_PATH_ORIGIN_REGION_ID, $storeId);
414: $postcode = Mage::getStoreConfig(Mage_Shipping_Model_Config::XML_PATH_ORIGIN_POSTCODE, $storeId);
415: $city = Mage::getStoreConfig(Mage_Shipping_Model_Config::XML_PATH_ORIGIN_CITY, $storeId);
416:
417: $defPrice = (float)Mage::getStoreConfig(
418: Mage_GoogleCheckout_Helper_Data::XML_PATH_SHIPPING_CARRIER_DEFAULT_PRICE,
419: $storeId
420: );
421: $width = Mage::getStoreConfig(
422: Mage_GoogleCheckout_Helper_Data::XML_PATH_SHIPPING_CARRIER_DEFAULT_WIDTH,
423: $storeId
424: );
425: $height = Mage::getStoreConfig(
426: Mage_GoogleCheckout_Helper_Data::XML_PATH_SHIPPING_CARRIER_DEFAULT_HEIGHT,
427: $storeId
428: );
429: $length = Mage::getStoreConfig(
430: Mage_GoogleCheckout_Helper_Data::XML_PATH_SHIPPING_CARRIER_DEFAULT_LENGTH,
431: $storeId
432: );
433: $sizeUnit = self::ITEM_SIZE_UNIT;
434:
435: $addressCategory = Mage::getStoreConfig(
436: Mage_GoogleCheckout_Helper_Data::XML_PATH_SHIPPING_CARRIER_ADDRESS_CATEGORY,
437: $storeId
438: );
439: $defPrice = (float) Mage::helper('tax')->getShippingPrice($defPrice, false, false);
440:
441: $this->getQuote()->getShippingAddress()
442: ->setCountryId($country)
443: ->setCity($city)
444: ->setPostcode($postcode)
445: ->setRegionId($region)
446: ->setCollectShippingRates(true);
447:
448: $address = $this->getQuote()->getShippingAddress();
449: $address->collectShippingRates();
450: $shipments = $address->getGroupedAllShippingRates();
451:
452: $shippingMethodsList = array();
453: foreach (explode(',', $methods) as $method) {
454: list($company, $type) = explode('/', $method);
455: $shippingMethodsList[$method] = array('company' => $company, 'type' => $type);
456: }
457:
458: $freeMethodsList = array();
459: foreach ($this->_getGoogleCarriersMap() as $mageCode => $map) {
460: if (!isset($shipments[$mageCode])) {
461: continue;
462: }
463: $freeMethod = Mage::getStoreConfig('carriers/' . $mageCode . '/free_method', $storeId);
464:
465: foreach ($shipments[$mageCode] as $rate) {
466: $mageRateCode = $rate->getMethod();
467: if ($mageRateCode != $freeMethod) {
468: continue;
469: }
470:
471: $googleRateCode = isset($map['methods'][$mageRateCode]) ? $map['methods'][$mageRateCode] : false;
472: if (false == $googleRateCode || $rate->getPrice() != 0) {
473: continue;
474: }
475:
476: $methodName = $map['googleCarrierCompany'] . '/'. $googleRateCode;
477: if (empty($shippingMethodsList[$methodName])) {
478: continue;
479: }
480: $freeMethodsList[$methodName] = array(
481: 'company' => $map['googleCarrierCompany'],
482: 'type' => $googleRateCode
483: );
484: unset($shippingMethodsList[$methodName]);
485: }
486: }
487:
488: $xml = '';
489: $sendShipMethods = (bool)count($shippingMethodsList) > 0;
490: if ($sendShipMethods) {
491: $xml .= <<<EOT
492: <carrier-calculated-shipping>
493: <shipping-packages>
494: <shipping-package>
495: <ship-from id="Origin">
496: <city>{$city}</city>
497: <region>{$region}</region>
498: <postal-code>{$postcode}</postal-code>
499: <country-code>{$country}</country-code>
500: </ship-from>
501: <width unit="{$sizeUnit}" value="{$width}"/>
502: <height unit="{$sizeUnit}" value="{$height}"/>
503: <length unit="{$sizeUnit}" value="{$length}"/>
504: <delivery-address-category>{$addressCategory}</delivery-address-category>
505: </shipping-package>
506: </shipping-packages>
507: EOT;
508: $xml .= '<carrier-calculated-shipping-options>';
509:
510: foreach ($shippingMethodsList as $method) {
511: $xml .= <<<EOT
512: <carrier-calculated-shipping-option>
513: <shipping-company>{$method['company']}</shipping-company>
514: <shipping-type>{$method['type']}</shipping-type>
515: <price currency="{$this->getCurrency()}">{$defPrice}</price>
516: </carrier-calculated-shipping-option>
517: EOT;
518: }
519: $xml .= '</carrier-calculated-shipping-options>';
520: $xml .= '</carrier-calculated-shipping>';
521: }
522:
523: foreach ($freeMethodsList as $method) {
524: $xml .= <<<EOT
525: <flat-rate-shipping name="{$method['company']} {$method['type']}">
526: <price currency="{$this->getCurrency()}">0.00</price></flat-rate-shipping>
527: EOT;
528: }
529:
530: $this->_shippingCalculated = true;
531: return $xml;
532: }
533:
534: 535: 536: 537: 538:
539: protected function _getFlatRateShippingXml()
540: {
541: 542: 543:
544: if ($this->_shippingCalculated) {
545: return '';
546: }
547:
548: $storeId = $this->getQuote()->getStoreId();
549: if (!Mage::getStoreConfigFlag(Mage_GoogleCheckout_Helper_Data::XML_PATH_SHIPPING_FLATRATE_ACTIVE, $storeId)) {
550: return '';
551: }
552:
553:
554: $nodeName = 'merchant-calculated-shipping';
555: if (!$this->_getTaxClassForShipping($this->getQuote())) {
556: $nodeName = 'flat-rate-shipping';
557: }
558:
559: $xml = '';
560: for ($i = 1; $i <= 3; $i++) {
561: $title = Mage::getStoreConfig('google/checkout_shipping_flatrate/title_' . $i, $storeId);
562: $price = (float)Mage::getStoreConfig('google/checkout_shipping_flatrate/price_' . $i, $storeId);
563: $price = number_format($price, 2, '.', '');
564: $price = (float)Mage::helper('tax')->getShippingPrice($price, false, false);
565: $allowSpecific = Mage::getStoreConfigFlag(
566: 'google/checkout_shipping_flatrate/sallowspecific_' . $i,
567: $storeId
568: );
569: $specificCountries = Mage::getStoreConfig(
570: 'google/checkout_shipping_flatrate/specificcountry_' . $i,
571: $storeId
572: );
573: $allowedAreasXml = $this->_getAllowedCountries($allowSpecific, $specificCountries);
574:
575: if (empty($title) || $price <= 0) {
576: continue;
577: }
578:
579: $xml .= <<<EOT
580: <{$nodeName} name="{$title}">
581: <shipping-restrictions>
582: <allowed-areas>
583: {$allowedAreasXml}
584: </allowed-areas>
585: </shipping-restrictions>
586: <price currency="{$this->getCurrency()}">{$price}</price>
587: </{$nodeName}>
588: EOT;
589: }
590:
591: $this->_shippingCalculated = true;
592:
593: return $xml;
594: }
595:
596: 597: 598: 599: 600: 601: 602:
603: protected function _getAllowedCountries($allowSpecific, $specific)
604: {
605: $xml = '';
606: if ($allowSpecific == 1) {
607: if ($specific) {
608: foreach (explode(',', $specific) as $country) {
609: $xml .= "<postal-area><country-code>{$country}</country-code></postal-area>\n";
610: }
611: }
612: }
613: if ($xml) {
614: return $xml;
615: }
616:
617: return '<world-area />';
618: }
619:
620: 621: 622: 623: 624:
625: protected function _getMerchantCalculatedShippingXml()
626: {
627: 628: 629:
630: if ($this->_shippingCalculated) {
631: return '';
632: }
633:
634: $storeId = $this->getQuote()->getStoreId();
635: $active = Mage::getStoreConfigFlag(
636: Mage_GoogleCheckout_Helper_Data::XML_PATH_SHIPPING_MERCHANT_ACTIVE,
637: $storeId
638: );
639: $methods = Mage::getStoreConfig(
640: Mage_GoogleCheckout_Helper_Data::XML_PATH_SHIPPING_MERCHANT_ALLOWED_METHODS,
641: $storeId
642: );
643:
644: if (!$active || !$methods) {
645: return '';
646: }
647:
648: $xml = '';
649: $methods = unserialize($methods);
650: $taxHelper = Mage::helper('tax');
651: $shippingModel = Mage::getModel('shipping/shipping');
652:
653: foreach ($methods['method'] as $i => $method) {
654: if (!$i || !$method) {
655: continue;
656: }
657: list($carrierCode, $methodCode) = explode('/', $method);
658: if ($carrierCode) {
659: $carrier = $shippingModel->getCarrierByCode($carrierCode);
660: if ($carrier) {
661: $allowedMethods = $carrier->getAllowedMethods();
662:
663: if (isset($allowedMethods[$methodCode])) {
664: $method = Mage::getStoreConfig('carriers/' . $carrierCode . '/title', $storeId);
665: $method .= ' - '.$allowedMethods[$methodCode];
666: }
667:
668: $defaultPrice = (float) $methods['price'][$i];
669: $defaultPrice = $taxHelper->getShippingPrice($defaultPrice, false, false);
670:
671: $allowedAreasXml = $this->_getAllowedCountries(
672: $carrier->getConfigData('sallowspecific'),
673: $carrier->getConfigData('specificcountry')
674: );
675:
676: $xml .= <<<EOT
677: <merchant-calculated-shipping name="{$method}">
678: <address-filters>
679: <allowed-areas>
680: {$allowedAreasXml}
681: </allowed-areas>
682: </address-filters>
683: <price currency="{$this->getCurrency()}">{$defaultPrice}</price>
684: </merchant-calculated-shipping>
685: EOT;
686: }
687: }
688: }
689: $this->_shippingCalculated = true;
690:
691: return $xml;
692: }
693:
694: 695: 696: 697: 698:
699: protected function _getPickupXml()
700: {
701: $storeId = $this->getQuote()->getStoreId();
702: if (!Mage::getStoreConfig(Mage_GoogleCheckout_Helper_Data::XML_PATH_SHIPPING_PICKUP_ACTIVE, $storeId)) {
703: return '';
704: }
705:
706: $title = Mage::getStoreConfig(Mage_GoogleCheckout_Helper_Data::XML_PATH_SHIPPING_PICKUP_TITLE, $storeId);
707: $price = Mage::getStoreConfig(Mage_GoogleCheckout_Helper_Data::XML_PATH_SHIPPING_PICKUP_PRICE, $storeId);
708: $price = (float) Mage::helper('tax')->getShippingPrice($price, false, false);
709:
710: $xml = <<<EOT
711: <pickup name="{$title}">
712: <price currency="{$this->getCurrency()}">{$price}</price>
713: </pickup>
714: EOT;
715:
716: return $xml;
717: }
718:
719: 720: 721: 722: 723: 724: 725:
726: protected function _getTaxTableXml($rules, $type)
727: {
728: $xml = '';
729: if (is_array($rules)) {
730: foreach ($rules as $group => $taxRates) {
731: if ($type != 'default') {
732: $nameAttribute = "name=\"{$group}\"";
733: $standaloneAttribute = "standalone=\"true\"";
734: $rulesTag = "{$type}-tax-rules";
735: $shippingTaxed = false;
736: } else {
737: $nameAttribute = '';
738: $standaloneAttribute = '';
739: $rulesTag = 'tax-rules';
740: $shippingTaxed = true;
741: }
742:
743: $xml .= <<<EOT
744: <{$type}-tax-table {$nameAttribute} {$standaloneAttribute}>
745: <{$rulesTag}>
746: EOT;
747: if (is_array($taxRates)) {
748: foreach ($taxRates as $rate) {
749: $xml .= <<<EOT
750: <{$type}-tax-rule>
751: <tax-areas>
752:
753: EOT;
754: if ($rate['country'] === Mage_Usa_Model_Shipping_Carrier_Abstract::USA_COUNTRY_ID) {
755: if (!empty($rate['postcode']) && $rate['postcode'] !== '*') {
756: $rate['postcode'] = Mage::helper('googlecheckout')
757: ->zipRangeToZipPattern($rate['postcode']);
758: foreach ($rate['postcode'] as $postcode) {
759: $xml .= <<<EOT
760: <us-zip-area>
761: <zip-pattern>$postcode</zip-pattern>
762: </us-zip-area>
763:
764: EOT;
765: }
766: } else if (!empty($rate['state'])) {
767: $xml .= <<<EOT
768: <us-state-area>
769: <state>{$rate['state']}</state>
770: </us-state-area>
771:
772: EOT;
773: } else {
774: $xml .= <<<EOT
775: <us-zip-area>
776: <zip-pattern>*</zip-pattern>
777: </us-zip-area>
778:
779: EOT;
780: }
781: } else {
782: if (!empty($rate['country'])) {
783: $xml .= <<<EOT
784: <postal-area>
785: <country-code>{$rate['country']}</country-code>
786: EOT;
787: if (!empty($rate['postcode']) && $rate['postcode'] !== '*') {
788: $xml .= <<<EOT
789: <postal-code-pattern>{$rate['postcode']}</postal-code-pattern>
790:
791: EOT;
792: }
793: $xml .= <<<EOT
794: </postal-area>
795:
796: EOT;
797: }
798: }
799: $xml .= <<<EOT
800: </tax-areas>
801: <rate>{$rate['value']}</rate>
802: EOT;
803: if ($shippingTaxed) {
804: $xml .= '<shipping-taxed>true</shipping-taxed>';
805: }
806: $xml .= "</{$type}-tax-rule>";
807: }
808:
809: } else {
810: $taxRate = $taxRates/100;
811: $xml .= <<<EOT
812: <{$type}-tax-rule>
813: <tax-area>
814: <world-area/>
815: </tax-area>
816: <rate>{$taxRate}</rate>
817: EOT;
818: if ($shippingTaxed) {
819: $xml .= '<shipping-taxed>true</shipping-taxed>';
820: }
821: $xml .= "</{$type}-tax-rule>";
822: }
823:
824: $xml .= <<<EOT
825: </$rulesTag>
826: </{$type}-tax-table>
827: EOT;
828: }
829: } else {
830: if (is_numeric($rules)) {
831: $taxRate = $rules / 100;
832: $xml .= <<<EOT
833: <{$type}-tax-table>
834: <tax-rules>
835: <{$type}-tax-rule>
836: <tax-area>
837: <world-area/>
838: </tax-area>
839: <rate>{$taxRate}</rate>
840: <shipping-taxed>true</shipping-taxed>
841: </{$type}-tax-rule>
842: </tax-rules>
843: </{$type}-tax-table>
844: EOT;
845: }
846: }
847:
848: return $xml;
849: }
850:
851: 852: 853: 854: 855:
856: protected function _getAllTaxTablesXml()
857: {
858: $isDefaultTaxTablesDisabled = Mage::getStoreConfigFlag(
859: Mage_GoogleCheckout_Helper_Data::XML_PATH_DISABLE_DEFAULT_TAX_TABLES,
860: $this->getQuote()->getStoreId()
861: );
862: if ($isDefaultTaxTablesDisabled) {
863: return '<tax-tables merchant-calculated="true" />';
864: }
865:
866: $xml = <<<EOT
867: <tax-tables merchant-calculated="true">
868: {$this->_getTaxTableXml($this->_getShippingTaxRules(), 'default')}
869:
870: <!-- default-tax-table>
871: <tax-rules>
872: <default-tax-rule>
873: </default-tax-rule>
874: </tax-rules>
875: </default-tax-table -->
876:
877: <alternate-tax-tables>
878: <alternate-tax-table name="none" standalone="true">
879: <alternate-tax-rules>
880: <alternate-tax-rule>
881: <tax-area>
882: <world-area/>
883: </tax-area>
884: <rate>0</rate>
885: </alternate-tax-rule>
886: </alternate-tax-rules>
887: </alternate-tax-table>
888: {$this->_getTaxTableXml($this->_getTaxRules(), 'alternate')}
889: </alternate-tax-tables>
890: </tax-tables>
891: EOT;
892: return $xml;
893: }
894:
895: 896: 897: 898: 899:
900: protected function _getCustomerTaxClass()
901: {
902: $customerGroup = $this->getQuote()->getCustomerGroupId();
903: if (!$customerGroup) {
904: $customerGroup = Mage::helper('customer')->getDefaultCustomerGroupId($this->getQuote()->getStoreId());
905: }
906: return Mage::getModel('customer/group')->load($customerGroup)->getTaxClassId();
907: }
908:
909: 910: 911: 912: 913:
914: protected function _getShippingTaxRules()
915: {
916: $customerTaxClass = $this->_getCustomerTaxClass();
917: $shippingTaxClass = Mage::getStoreConfig(
918: Mage_Tax_Model_Config::CONFIG_XML_PATH_SHIPPING_TAX_CLASS,
919: $this->getQuote()->getStoreId()
920: );
921: $taxCalculationModel = Mage::getSingleton('tax/calculation');
922:
923: if ($shippingTaxClass) {
924: if (Mage::helper('tax')->getTaxBasedOn() == 'origin') {
925: $request = $taxCalculationModel->getRateRequest();
926: $request
927: ->setCustomerClassId($customerTaxClass)
928: ->setProductClassId($shippingTaxClass);
929:
930: return $taxCalculationModel->getRate($request);
931: }
932: $customerRules = $taxCalculationModel->getRatesByCustomerAndProductTaxClasses(
933: $customerTaxClass,
934: $shippingTaxClass
935: );
936: $rules = array();
937: foreach ($customerRules as $rule) {
938: $rules[$rule['product_class']][] = $rule;
939: }
940:
941: return $rules;
942: }
943:
944: return array();
945: }
946:
947: 948: 949: 950: 951:
952: protected function _getTaxRules()
953: {
954: $customerTaxClass = $this->_getCustomerTaxClass();
955: $taxCalculationModel = Mage::getSingleton('tax/calculation');
956:
957: if (Mage::helper('tax')->getTaxBasedOn() == 'origin') {
958: $request = $taxCalculationModel->getRateRequest()->setCustomerClassId($customerTaxClass);
959: return $taxCalculationModel->getRatesForAllProductTaxClasses($request);
960: }
961:
962: $customerRules = $taxCalculationModel->getRatesByCustomerTaxClass($customerTaxClass);
963: $rules = array();
964: foreach ($customerRules as $rule) {
965: $rules[$rule['product_class']][] = $rule;
966: }
967:
968: return $rules;
969: }
970:
971: 972: 973: 974: 975:
976: protected function _getRequestInitialAuthDetailsXml()
977: {
978: $xml = <<<EOT
979: <request-initial-auth-details>true</request-initial-auth-details>
980: EOT;
981: return $xml;
982: }
983:
984: 985: 986: 987: 988:
989: protected function _getParameterizedUrlsXml()
990: {
991: return '';
992: $xml = <<<EOT
993: <parameterized-urls>
994: <parameterized-url url="{$this->_getParameterizedUrl()}" />
995: </parameterized-urls>
996: EOT;
997: return $xml;
998: }
999:
1000: 1001: 1002: 1003: 1004:
1005: protected function _getPlatformIdXml()
1006: {
1007: $xml = <<<EOT
1008: <platform-id>473325629220583</platform-id>
1009: EOT;
1010: return $xml;
1011: }
1012:
1013: 1014: 1015: 1016: 1017:
1018: protected function _getAnalyticsDataXml()
1019: {
1020: if (!($analytics = $this->getApi()->getAnalyticsData())) {
1021: return '';
1022: }
1023: $xml = <<<EOT
1024: <analytics-data><![CDATA[{$analytics}]]></analytics-data>
1025: EOT;
1026: return $xml;
1027: }
1028:
1029: 1030: 1031: 1032: 1033:
1034: protected function _getEditCartUrl()
1035: {
1036: return Mage::getUrl('googlecheckout/redirect/cart');
1037: }
1038:
1039: 1040: 1041: 1042: 1043:
1044: protected function _getContinueShoppingUrl()
1045: {
1046: return Mage::getUrl('googlecheckout/redirect/continue');
1047: }
1048:
1049: 1050: 1051: 1052: 1053:
1054: protected function _getNotificationsUrl()
1055: {
1056: return $this->_getCallbackUrl();
1057: }
1058:
1059: 1060: 1061: 1062: 1063:
1064: protected function _getCalculationsUrl()
1065: {
1066: return $this->_getCallbackUrl();
1067: }
1068:
1069: 1070: 1071: 1072: 1073:
1074: protected function _getParameterizedUrl()
1075: {
1076: return Mage::getUrl('googlecheckout/api/beacon');
1077: }
1078:
1079: 1080: 1081: 1082: 1083:
1084: protected function _isOrderVirtual()
1085: {
1086: foreach ($this->getQuote()->getAllItems() as $item) {
1087: if (!$item->getIsVirtual()) {
1088: return false;
1089: }
1090: }
1091: return true;
1092: }
1093:
1094: 1095: 1096: 1097: 1098:
1099: protected function _getGoogleCarriersMap() {
1100: return array(
1101: 'ups' => array(
1102: 'googleCarrierCompany' => 'UPS',
1103: 'methods' => array(
1104: 'GND' => Mage::helper('usa')->__('Ground'),
1105: '1DA' => Mage::helper('usa')->__('Next Day Air'),
1106: '1DM' => Mage::helper('usa')->__('Next Day Air Early AM'),
1107: '1DP' => Mage::helper('usa')->__('Next Day Air Saver'),
1108: '2DA' => Mage::helper('usa')->__('2nd Day Air'),
1109: '2DM' => Mage::helper('usa')->__('2nd Day Air AM'),
1110: '3DS' => Mage::helper('usa')->__('3 Day Select'),
1111: '03' => Mage::helper('usa')->__('Ground'),
1112: '01' => Mage::helper('usa')->__('Next Day Air'),
1113: '14' => Mage::helper('usa')->__('Next Day Air Early AM'),
1114: '13' => Mage::helper('usa')->__('Next Day Air Saver'),
1115: '02' => Mage::helper('usa')->__('2nd Day Air'),
1116: '59' => Mage::helper('usa')->__('2nd Day Air AM'),
1117: '12' => Mage::helper('usa')->__('3 Day Select')
1118: )
1119: ),
1120: 'usps' => array(
1121: 'googleCarrierCompany' => 'USPS',
1122: 'methods' => array(
1123: 'Express Mail' => Mage::helper('usa')->__('Express Mail'),
1124: 'Priority Mail' => Mage::helper('usa')->__('Priority Mail'),
1125: 'Parcel Post' => Mage::helper('usa')->__('Parcel Post'),
1126: 'Media Mail' => Mage::helper('usa')->__('Media Mail')
1127: )
1128: ),
1129: 'fedex' => array(
1130: 'googleCarrierCompany' => 'FedEx',
1131: 'methods' => array(
1132: 'FEDEX_GROUND' => Mage::helper('usa')->__('Ground'),
1133: 'GROUND_HOME_DELIVERY' => Mage::helper('usa')->__('Home Delivery'),
1134: 'FEDEX_EXPRESS_SAVER' => Mage::helper('usa')->__('Express Saver'),
1135: 'FIRST_OVERNIGHT' => Mage::helper('usa')->__('First Overnight'),
1136: 'PRIORITY_OVERNIGHT' => Mage::helper('usa')->__('Priority Overnight'),
1137: 'STANDARD_OVERNIGHT' => Mage::helper('usa')->__('Standard Overnight'),
1138: 'FEDEX_2_DAY' => Mage::helper('usa')->__('2Day')
1139: )
1140: )
1141: );
1142: }
1143: }
1144: