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: class Mage_GoogleCheckout_Model_Api_Xml_Callback extends Mage_GoogleCheckout_Model_Api_Xml_Abstract
28: {
29: protected $_cachedShippingInfo = array();
30:
31: 32: 33: 34:
35: public function process()
36: {
37:
38: $xmlResponse = isset($GLOBALS['HTTP_RAW_POST_DATA']) ?
39: $GLOBALS['HTTP_RAW_POST_DATA'] : file_get_contents("php://input");
40: if (get_magic_quotes_gpc()) {
41: $xmlResponse = stripslashes($xmlResponse);
42: }
43:
44: $debugData = array('request' => $xmlResponse, 'dir' => 'in');
45:
46: if (empty($xmlResponse)) {
47: $this->getApi()->debugData($debugData);
48: return false;
49: }
50:
51: list($root, $data) = $this->getGResponse()->GetParsedXML($xmlResponse);
52:
53: $this->getGResponse()->SetMerchantAuthentication($this->getMerchantId(), $this->getMerchantKey());
54: $status = $this->getGResponse()->HttpAuthentication();
55:
56: if (!$status || empty($data[$root])) {
57: exit;
58: }
59:
60: $this->setRootName($root)->setRoot($data[$root]);
61: $serialNumber = $this->getData('root/serial-number');
62: $this->getGResponse()->setSerialNumber($serialNumber);
63:
64: 65: 66:
67: $notification = Mage::getModel('googlecheckout/notification')
68: ->setSerialNumber($serialNumber)
69: ->loadNotificationData();
70:
71: if ($notification->getStartedAt()) {
72: if ($notification->isProcessed()) {
73: $this->getGResponse()->SendAck();
74: return;
75: }
76: if ($notification->isTimeout()) {
77: $notification->updateProcess();
78: } else {
79: $this->getGResponse()->SendServerErrorStatus();
80: return;
81: }
82: } else {
83: $notification->startProcess();
84: }
85:
86: $method = '_response' . uc_words($root, '', '-');
87: if (method_exists($this, $method)) {
88: ob_start();
89:
90: try {
91: $this->$method();
92: $notification->stopProcess();
93: } catch (Exception $e) {
94: $this->getGResponse()->log->logError($e->__toString());
95: }
96:
97: $debugData['result'] = ob_get_flush();
98: $this->getApi()->debugData($debugData);
99: } else {
100: $this->getGResponse()->SendBadRequestStatus("Invalid or not supported Message");
101: }
102:
103: return $this;
104: }
105:
106: 107: 108: 109: 110:
111: protected function _loadQuote()
112: {
113: $quoteId = $this->getData('root/shopping-cart/merchant-private-data/quote-id/VALUE');
114: $storeId = $this->getData('root/shopping-cart/merchant-private-data/store-id/VALUE');
115: $quote = Mage::getModel('sales/quote')
116: ->setStoreId($storeId)
117: ->load($quoteId);
118: if ($quote->isVirtual()) {
119: $quote->getBillingAddress()->setPaymentMethod('googlecheckout');
120: } else {
121: $quote->getShippingAddress()->setPaymentMethod('googlecheckout');
122: }
123: return $quote;
124: }
125:
126: protected function _getApiUrl()
127: {
128: return null;
129: }
130:
131: protected function getGoogleOrderNumber()
132: {
133: return $this->getData('root/google-order-number/VALUE');
134: }
135:
136: protected function _responseRequestReceived()
137: {
138:
139: }
140:
141: protected function _responseError()
142: {
143:
144: }
145:
146: protected function _responseDiagnosis()
147: {
148:
149: }
150:
151: protected function _responseCheckoutRedirect()
152: {
153:
154: }
155:
156: 157: 158:
159: protected function _responseMerchantCalculationCallback()
160: {
161: $merchantCalculations = new GoogleMerchantCalculations($this->getCurrency());
162:
163: $quote = $this->_loadQuote();
164:
165: $billingAddress = $quote->getBillingAddress();
166: $address = $quote->getShippingAddress();
167:
168: $googleAddress = $this->getData('root/calculate/addresses/anonymous-address');
169:
170: $googleAddresses = array();
171: if ( isset( $googleAddress['id'] ) ) {
172: $googleAddresses[] = $googleAddress;
173: } else {
174: $googleAddresses = $googleAddress;
175: }
176:
177: $methods = Mage::getStoreConfig('google/checkout_shipping_merchant/allowed_methods', $this->getStoreId());
178: $methods = unserialize($methods);
179: $limitCarrier = array();
180: foreach ($methods['method'] as $method) {
181: if ($method) {
182: list($carrierCode, $methodCode) = explode('/', $method);
183: $limitCarrier[$carrierCode] = $carrierCode;
184: }
185: }
186: $limitCarrier = array_values($limitCarrier);
187:
188: foreach($googleAddresses as $googleAddress) {
189: $addressId = $googleAddress['id'];
190: $regionCode = $googleAddress['region']['VALUE'];
191: $countryCode = $googleAddress['country-code']['VALUE'];
192: $regionModel = Mage::getModel('directory/region')->loadByCode($regionCode, $countryCode);
193: $regionId = $regionModel->getId();
194:
195: $address->setCountryId($countryCode)
196: ->setRegion($regionCode)
197: ->setRegionId($regionId)
198: ->setCity($googleAddress['city']['VALUE'])
199: ->setPostcode($googleAddress['postal-code']['VALUE'])
200: ->setLimitCarrier($limitCarrier);
201: $billingAddress->setCountryId($countryCode)
202: ->setRegion($regionCode)
203: ->setRegionId($regionId)
204: ->setCity($googleAddress['city']['VALUE'])
205: ->setPostcode($googleAddress['postal-code']['VALUE'])
206: ->setLimitCarrier($limitCarrier);
207:
208: $billingAddress->collectTotals();
209: $shippingTaxClass = $this->_getTaxClassForShipping($quote);
210:
211: $gRequestMethods = $this->getData('root/calculate/shipping/method');
212: if ($gRequestMethods) {
213:
214: if (array_key_exists('VALUE', $gRequestMethods)) {
215: $gRequestMethods = array($gRequestMethods);
216: }
217:
218:
219: $rates = array();
220: $address->setCollectShippingRates(true)
221: ->collectShippingRates();
222: foreach ($address->getAllShippingRates() as $rate) {
223: if ($rate instanceof Mage_Shipping_Model_Rate_Result_Error) {
224: continue;
225: }
226: $methodName = sprintf('%s - %s', $rate->getCarrierTitle(), $rate->getMethodTitle());
227: $rates[$methodName] = $rate;
228: }
229:
230: foreach ($gRequestMethods as $method) {
231: $result = new GoogleResult($addressId);
232: $methodName = $method['name'];
233:
234: if (isset($rates[$methodName])) {
235: $rate = $rates[$methodName];
236:
237: $address->setShippingMethod($rate->getCode())
238: ->setLimitCarrier($rate->getCarrier())
239: ->setCollectShippingRates(true)
240: ->collectTotals();
241: $shippingRate = $address->getBaseShippingAmount() - $address->getBaseShippingDiscountAmount();
242: $result->SetShippingDetails($methodName, $shippingRate, 'true');
243:
244: if ($this->getData('root/calculate/tax/VALUE') == 'true') {
245: $taxAmount = $address->getBaseTaxAmount();
246: $taxAmount += $billingAddress->getBaseTaxAmount();
247: $result->setTaxDetails($taxAmount);
248: }
249: } else {
250: if ($shippingTaxClass &&
251: $this->getData('root/calculate/tax/VALUE') == 'true') {
252: $i = 1;
253: $price = Mage::getStoreConfig(
254: 'google/checkout_shipping_flatrate/price_'.$i,
255: $quote->getStoreId()
256: );
257: $price = number_format($price, 2, '.','');
258: $price = (float) Mage::helper('tax')->getShippingPrice($price, false, false);
259: $address->setShippingMethod(null);
260: $address->setCollectShippingRates(true)->collectTotals();
261: $billingAddress->setCollectShippingRates(true)->collectTotals();
262: $address->setBaseShippingAmount($price);
263: $address->setShippingAmount(
264: $this->_reCalculateToStoreCurrency($price, $quote)
265: );
266: $this->_applyShippingTaxClass($address, $shippingTaxClass);
267: $taxAmount = $address->getBaseTaxAmount();
268: $taxAmount += $billingAddress->getBaseTaxAmount();
269: $result->SetShippingDetails(
270: $methodName,
271: $price - $address->getBaseShippingDiscountAmount(),
272: 'true'
273: );
274: $result->setTaxDetails($taxAmount);
275: $i++;
276: } else {
277: $result->SetShippingDetails($methodName, 0, 'false');
278: }
279: }
280: $merchantCalculations->AddResult($result);
281: }
282:
283: } else if ($this->getData('root/calculate/tax/VALUE') == 'true') {
284: $address->setShippingMethod(null);
285: $address->setCollectShippingRates(true)->collectTotals();
286: $billingAddress->setCollectShippingRates(true)->collectTotals();
287: if (!Mage::helper('googlecheckout')->isShippingCarrierActive($this->getStoreId())) {
288: $this->_applyShippingTaxClass($address, $shippingTaxClass);
289: }
290:
291: $taxAmount = $address->getBaseTaxAmount();
292: $taxAmount += $billingAddress->getBaseTaxAmount();
293:
294: $result = new GoogleResult($addressId);
295: $result->setTaxDetails($taxAmount);
296: $merchantCalculations->addResult($result);
297: }
298: }
299:
300: $this->getGResponse()->ProcessMerchantCalculations($merchantCalculations);
301: }
302:
303: 304: 305: 306: 307: 308:
309: protected function _applyShippingTaxClass($qAddress, $shippingTaxClass)
310: {
311: if (!$shippingTaxClass) {
312: return;
313: }
314:
315: $quote = $qAddress->getQuote();
316: $taxCalculationModel = Mage::getSingleton('tax/calculation');
317: $request = $taxCalculationModel->getRateRequest($qAddress);
318: $rate = $taxCalculationModel->getRate($request->setProductClassId($shippingTaxClass));
319:
320: if (!Mage::helper('tax')->shippingPriceIncludesTax()) {
321: $shippingTax = $qAddress->getShippingAmount() * $rate/100;
322: $shippingBaseTax= $qAddress->getBaseShippingAmount() * $rate/100;
323: } else {
324: $shippingTax = $qAddress->getShippingTaxAmount();
325: $shippingBaseTax= $qAddress->getBaseShippingTaxAmount();
326: }
327:
328: $shippingTax = $quote->getStore()->roundPrice($shippingTax);
329: $shippingBaseTax= $quote->getStore()->roundPrice($shippingBaseTax);
330:
331: $qAddress->setTaxAmount($qAddress->getTaxAmount() + $shippingTax);
332: $qAddress->setBaseTaxAmount($qAddress->getBaseTaxAmount() + $shippingBaseTax);
333: }
334:
335: 336: 337: 338:
339: protected function _responseNewOrderNotification()
340: {
341: $this->getGResponse()->SendAck();
342:
343:
344: $orders = Mage::getModel('sales/order')->getCollection()
345: ->addAttributeToFilter('ext_order_id', $this->getGoogleOrderNumber());
346: if (count($orders)) {
347: return;
348: }
349:
350:
351:
352: $quote = $this->_loadQuote();
353: $quote->setIsActive(true)->reserveOrderId();
354:
355: Mage::dispatchEvent('googlecheckout_create_order_before', array('quote' => $quote));
356: if ($quote->getErrorMessage()) {
357: $this->getGRequest()->SendCancelOrder($this->getGoogleOrderNumber(),
358: $this->__('Order creation error'),
359: $quote->getErrorMessage()
360: );
361: return;
362: }
363:
364: $storeId = $quote->getStoreId();
365:
366: Mage::app()->setCurrentStore(Mage::app()->getStore($storeId));
367: if ($quote->getQuoteCurrencyCode() != $quote->getBaseCurrencyCode()) {
368: Mage::app()->getStore()->setCurrentCurrencyCode($quote->getQuoteCurrencyCode());
369: }
370:
371: $billing = $this->_importGoogleAddress($this->getData('root/buyer-billing-address'));
372: $quote->setBillingAddress($billing);
373:
374: $shipping = $this->_importGoogleAddress($this->getData('root/buyer-shipping-address'));
375:
376: $quote->setShippingAddress($shipping);
377:
378: $this->_importGoogleTotals($quote->getShippingAddress());
379:
380: $quote->getPayment()->importData(array('method'=>'googlecheckout'));
381:
382: $taxMessage = $this->_applyCustomTax($quote->getShippingAddress());
383:
384:
385: $convertQuote = Mage::getSingleton('sales/convert_quote');
386:
387:
388: $order = $convertQuote->toOrder($quote);
389:
390: if ($quote->isVirtual()) {
391: $convertQuote->addressToOrder($quote->getBillingAddress(), $order);
392: } else {
393: $convertQuote->addressToOrder($quote->getShippingAddress(), $order);
394: }
395:
396: $order->setExtOrderId($this->getGoogleOrderNumber());
397: $order->setExtCustomerId($this->getData('root/buyer-id/VALUE'));
398:
399: if (!$order->getCustomerEmail()) {
400: $order->setCustomerEmail($billing->getEmail())
401: ->setCustomerPrefix($billing->getPrefix())
402: ->setCustomerFirstname($billing->getFirstname())
403: ->setCustomerMiddlename($billing->getMiddlename())
404: ->setCustomerLastname($billing->getLastname())
405: ->setCustomerSuffix($billing->getSuffix());
406: }
407:
408: $order->setBillingAddress($convertQuote->addressToOrderAddress($quote->getBillingAddress()));
409:
410: if (!$quote->isVirtual()) {
411: $order->setShippingAddress($convertQuote->addressToOrderAddress($quote->getShippingAddress()));
412: }
413:
414:
415: foreach ($quote->getAllItems() as $item) {
416: $orderItem = $convertQuote->itemToOrderItem($item);
417: if ($item->getParentItem()) {
418: $orderItem->setParentItem($order->getItemByQuoteItemId($item->getParentItem()->getId()));
419: }
420: $order->addItem($orderItem);
421: }
422:
423: 424: 425: 426:
427: $payment = Mage::getModel('sales/order_payment')
428: ->setMethod('googlecheckout')
429: ->setTransactionId($this->getGoogleOrderNumber())
430: ->setIsTransactionClosed(false);
431: $order->setPayment($payment);
432: $payment->addTransaction(Mage_Sales_Model_Order_Payment_Transaction::TYPE_AUTH);
433: $order->setCanShipPartiallyItem(false);
434:
435: $emailAllowed = ($this->getData('root/buyer-marketing-preferences/email-allowed/VALUE') === 'true');
436:
437: $emailStr = $emailAllowed ? $this->__('Yes') : $this->__('No');
438: $message = $this->__('Google Order Number: %s', '<strong>' . $this->getGoogleOrderNumber() . '</strong><br />')
439: . $this->__('Google Buyer ID: %s', '<strong>' . $this->getData('root/buyer-id/VALUE') . '</strong><br />')
440: . $this->__('Is Buyer Willing to Receive Marketing Emails: %s', '<strong>' . $emailStr . '</strong>');
441: if ($taxMessage) {
442: $message .= $this->__('<br />Warning: <strong>%s</strong><br />', $taxMessage);
443: }
444:
445: $order->addStatusToHistory($order->getStatus(), $message);
446: $order->place();
447: $order->save();
448: $order->sendNewOrderEmail();
449: Mage::dispatchEvent('googlecheckout_save_order_after', array('order' => $order));
450:
451: $quote->setIsActive(false)->save();
452:
453: if ($emailAllowed) {
454: $customer = $quote->getCustomer();
455: if ($customer && $customer->getId()) {
456: $customer->setIsSubscribed(true);
457: Mage::getModel('newsletter/subscriber')->subscribeCustomer($customer);
458: } else {
459: Mage::getModel('newsletter/subscriber')->subscribe($order->getCustomerEmail());
460: }
461: }
462:
463: Mage::dispatchEvent('checkout_submit_all_after', array('order' => $order, 'quote' => $quote));
464:
465: $this->getGRequest()->SendMerchantOrderNumber($order->getExtOrderId(), $order->getIncrementId());
466: }
467:
468: 469: 470: 471: 472: 473: 474:
475: protected function _applyCustomTax($qAddress)
476: {
477: $quote = $qAddress->getQuote();
478: $qTaxAmount = $qAddress->getBaseTaxAmount();
479: $newTaxAmount = $this->getData('root/order-adjustment/total-tax/VALUE');
480:
481: if ($qTaxAmount != $newTaxAmount) {
482: $taxQuotient = (int) $qTaxAmount ? $newTaxAmount/$qTaxAmount : $newTaxAmount;
483:
484: $qAddress->setTaxAmount(
485: $this->_reCalculateToStoreCurrency($newTaxAmount, $quote)
486: );
487: $qAddress->setBaseTaxAmount($newTaxAmount);
488:
489: $grandTotal = $qAddress->getBaseGrandTotal() - $qTaxAmount + $newTaxAmount;
490: $qAddress->setGrandTotal(
491: $this->_reCalculateToStoreCurrency($grandTotal, $quote)
492: );
493: $qAddress->setBaseGrandTotal($grandTotal);
494:
495: $subtotalInclTax = $qAddress->getSubtotalInclTax() - $qTaxAmount + $newTaxAmount;
496: $qAddress->setSubtotalInclTax($subtotalInclTax);
497:
498: foreach ($quote->getAllVisibleItems() as $item) {
499: if ($item->getParentItem()) {
500: continue;
501: }
502: if ($item->getTaxAmount()) {
503: $item->setTaxAmount($item->getTaxAmount()*$taxQuotient);
504: $item->setBaseTaxAmount($item->getBaseTaxAmount()*$taxQuotient);
505: $taxPercent = round(($item->getTaxAmount()/$item->getRowTotal())*100);
506: $item->setTaxPercent($taxPercent);
507: }
508: }
509:
510: $grandTotal = $quote->getBaseGrandTotal() - $qTaxAmount + $newTaxAmount;
511: $quote->setGrandTotal(
512: $this->_reCalculateToStoreCurrency($grandTotal, $quote)
513: );
514: $quote->setBaseGrandTotal($grandTotal);
515:
516: $message = $this->__('The tax amount has been applied based on the information received from Google Checkout, because tax amount received from Google Checkout is different from the calculated tax amount');
517: return $message;
518: }
519:
520: return false;
521: }
522:
523: 524: 525: 526: 527: 528: 529:
530: protected function _importGoogleAddress($gAddress, Varien_Object $qAddress=null)
531: {
532: if (is_array($gAddress)) {
533: $gAddress = new Varien_Object($gAddress);
534: }
535:
536: if (!$qAddress) {
537: $qAddress = Mage::getModel('sales/quote_address');
538: }
539: $nameArr = $gAddress->getData('structured-name');
540: if ($nameArr) {
541: $qAddress->setFirstname($nameArr['first-name']['VALUE'])
542: ->setLastname($nameArr['last-name']['VALUE']);
543: } else {
544: $nameArr = explode(' ', $gAddress->getData('contact-name/VALUE'), 2);
545: $qAddress->setFirstname($nameArr[0]);
546: if (!empty($nameArr[1])) {
547: $qAddress->setLastname($nameArr[1]);
548: }
549: }
550: $region = Mage::getModel('directory/region')->loadByCode(
551: $gAddress->getData('region/VALUE'),
552: $gAddress->getData('country-code/VALUE')
553: );
554:
555: $qAddress->setCompany($gAddress->getData('company-name/VALUE'))
556: ->setEmail($gAddress->getData('email/VALUE'))
557: ->setStreet(trim($gAddress->getData('address1/VALUE') . "\n" . $gAddress->getData('address2/VALUE')))
558: ->setCity($gAddress->getData('city/VALUE'))
559: ->setRegion($gAddress->getData('region/VALUE'))
560: ->setRegionId($region->getId())
561: ->setPostcode($gAddress->getData('postal-code/VALUE'))
562: ->setCountryId($gAddress->getData('country-code/VALUE'))
563: ->setTelephone($gAddress->getData('phone/VALUE'))
564: ->setFax($gAddress->getData('fax/VALUE'));
565:
566: return $qAddress;
567: }
568:
569: 570: 571: 572: 573: 574: 575:
576: protected function _getShippingInfos($storeId = null)
577: {
578: $cacheKey = ($storeId === null) ? 'nofilter' : $storeId;
579: if (!isset($this->_cachedShippingInfo[$cacheKey])) {
580:
581: $shipping = Mage::getModel('shipping/shipping');
582: $carriers = Mage::getStoreConfig('carriers', $storeId);
583: $infos = array();
584:
585: foreach (array_keys($carriers) as $carrierCode) {
586: $carrier = $shipping->getCarrierByCode($carrierCode);
587: if (!$carrier) {
588: continue;
589: }
590:
591: if ($carrierCode == 'googlecheckout') {
592:
593: $methods = array_merge($carrier->getAllowedMethods(), $carrier->getInternallyAllowedMethods());
594: $carrierName = 'Google Checkout';
595: } else {
596: $methods = $carrier->getAllowedMethods();
597: $carrierName = Mage::getStoreConfig('carriers/' . $carrierCode . '/title', $storeId);
598: }
599:
600: foreach ($methods as $methodCode => $methodName) {
601: $code = $carrierCode . '_' . $methodCode;
602: $name = sprintf('%s - %s', $carrierName, $methodName);
603: $infos[$code] = array(
604: 'code' => $code,
605: 'name' => $name,
606: 'carrier' => $carrierCode,
607: 'carrier_title' => $carrierName,
608: 'method' => $methodCode,
609: 'method_title' => $methodName
610: );
611: }
612: }
613: $this->_cachedShippingInfo[$cacheKey] = $infos;
614: }
615:
616: return $this->_cachedShippingInfo[$cacheKey];
617: }
618:
619: 620: 621: 622: 623: 624: 625:
626: protected function _getShippingMethodByName($name, $storeId = null)
627: {
628: $code = false;
629: $infos = $this->_getShippingInfos($storeId);
630: foreach ($infos as $info) {
631: if ($info['name'] == $name) {
632: $code = $info['code'];
633: break;
634: }
635: }
636: return $code;
637: }
638:
639: 640: 641: 642: 643: 644: 645: 646:
647: protected function _createShippingRate($code, $storeId = null)
648: {
649: $rate = Mage::getModel('sales/quote_address_rate')
650: ->setCode($code);
651:
652: $infos = $this->_getShippingInfos($storeId);
653: if (isset($infos[$code])) {
654: $info = $infos[$code];
655: $rate->setCarrier($info['carrier'])
656: ->setCarrierTitle($info['carrier_title'])
657: ->setMethod($info['method'])
658: ->setMethodTitle($info['method_title']);
659: }
660:
661: return $rate;
662: }
663:
664: 665: 666: 667: 668:
669: protected function _importGoogleTotals($qAddress)
670: {
671: $quote = $qAddress->getQuote();
672: $qAddress->setTaxAmount(
673: $this->_reCalculateToStoreCurrency($this->getData('root/order-adjustment/total-tax/VALUE'), $quote)
674: );
675: $qAddress->setBaseTaxAmount($this->getData('root/order-adjustment/total-tax/VALUE'));
676:
677: $method = null;
678: $prefix = 'root/order-adjustment/shipping/';
679: if (null !== ($shipping = $this->getData($prefix . 'carrier-calculated-shipping-adjustment'))) {
680: $method = 'googlecheckout_carrier';
681: } else if (null !== ($shipping = $this->getData($prefix . 'merchant-calculated-shipping-adjustment'))) {
682: $method = 'googlecheckout_merchant';
683: } else if (null !== ($shipping = $this->getData($prefix . 'flat-rate-shipping-adjustment'))) {
684: $method = 'googlecheckout_flatrate';
685: } else if (null !== ($shipping = $this->getData($prefix . 'pickup-shipping-adjustment'))) {
686: $method = 'googlecheckout_pickup';
687: }
688:
689: if ($method) {
690: Mage::getSingleton('tax/config')->setShippingPriceIncludeTax(false);
691: $rate = $this->_createShippingRate($method)
692: ->setMethodTitle($shipping['shipping-name']['VALUE'])
693: ->setPrice($shipping['shipping-cost']['VALUE']);
694: $qAddress->addShippingRate($rate)
695: ->setShippingMethod($method)
696: ->setShippingDescription($shipping['shipping-name']['VALUE']);
697:
698: $qAddress->setShippingAmountForDiscount(0);
699:
700: 701: 702: 703: 704: 705: 706: 707: 708: 709: 710: 711: 712: 713: 714:
715: } else {
716: $qAddress->setShippingMethod(null);
717: }
718:
719:
720: $qAddress->setGrandTotal(
721: $this->_reCalculateToStoreCurrency($this->getData('root/order-total/VALUE'), $quote)
722: );
723: $qAddress->setBaseGrandTotal($this->getData('root/order-total/VALUE'));
724: }
725:
726: 727: 728: 729: 730:
731: public function getOrder()
732: {
733: if (!$this->hasData('order')) {
734: $order = Mage::getModel('sales/order')
735: ->loadByAttribute('ext_order_id', $this->getGoogleOrderNumber());
736: if (!$order->getId()) {
737: Mage::throwException('Invalid Order: ' . $this->getGoogleOrderNumber());
738: }
739: $this->setData('order', $order);
740: }
741: return $this->getData('order');
742: }
743:
744: protected function _responseRiskInformationNotification()
745: {
746: $this->getGResponse()->SendAck();
747:
748: $order = $this->getOrder();
749: $payment = $order->getPayment();
750:
751: $order
752: ->setRemoteIp($this->getData('root/risk-information/ip-address/VALUE'));
753:
754: $payment
755: ->setCcLast4($this->getData('root/risk-information/partial-cc-number/VALUE'))
756: ->setCcAvsStatus($this->getData('root/risk-information/avs-response/VALUE'))
757: ->setCcCidStatus($this->getData('root/risk-information/cvn-response/VALUE'));
758:
759: $msg = $this->__('Google Risk Information:');
760: $msg .= '<br />' . $this->__('IP Address: %s', '<strong>' . $order->getRemoteIp() . '</strong>');
761: $msg .= '<br />' . $this->__('CC Partial: xxxx-%s', '<strong>' . $payment->getCcLast4() . '</strong>');
762: $msg .= '<br />' . $this->__('AVS Status: %s', '<strong>' . $payment->getCcAvsStatus() . '</strong>');
763: $msg .= '<br />' . $this->__('CID Status: %s', '<strong>' . $payment->getCcCidStatus() . '</strong>');
764: $msg .= '<br />' . $this->__('Eligible for Protection: %s', '<strong>' . ($this->getData('root/risk-information/eligible-for-protection/VALUE')=='true' ? 'Yes' : 'No') . '</strong>');
765: $msg .= '<br />' . $this->__('Buyer Account Age: %s days', '<strong>' . $this->getData('root/risk-information/buyer-account-age/VALUE') . '</strong>');
766:
767: $order->addStatusToHistory($order->getStatus(), $msg);
768: $order->save();
769: }
770:
771: 772: 773:
774: protected function _responseAuthorizationAmountNotification()
775: {
776: $this->getGResponse()->SendAck();
777:
778: $order = $this->getOrder();
779: $payment = $order->getPayment();
780:
781: $payment->setAmountAuthorized($this->getData('root/authorization-amount/VALUE'));
782:
783: $expDate = $this->getData('root/authorization-expiration-date/VALUE');
784: $expDate = new Zend_Date($expDate);
785: $msg = $this->__('Google Authorization:');
786: $msg .= '<br />' . $this->__('Amount: %s', '<strong>' . $this->_formatAmount($payment->getAmountAuthorized()) . '</strong>');
787: $msg .= '<br />' . $this->__('Expiration: %s', '<strong>' . $expDate->toString() . '</strong>');
788:
789: $order->addStatusToHistory($order->getStatus(), $msg);
790:
791: $order->setPaymentAuthorizationAmount($payment->getAmountAuthorized());
792: $timestamp = Mage::getModel('core/date')->gmtTimestamp(
793: $this->getData('root/authorization-expiration-date/VALUE')
794: );
795: $order->setPaymentAuthorizationExpiration(
796: $timestamp ? $timestamp : Mage::getModel('core/date')->gmtTimestamp()
797: );
798:
799: $order->save();
800: }
801:
802: 803: 804: 805:
806: protected function _responseChargeAmountNotification()
807: {
808: $this->getGResponse()->SendAck();
809:
810: $order = $this->getOrder();
811: $payment = $order->getPayment();
812:
813: $latestCharged = $this->getData('root/latest-charge-amount/VALUE');
814: $totalCharged = $this->getData('root/total-charge-amount/VALUE');
815: $payment->setAmountCharged($totalCharged);
816: $order->setIsInProcess(true);
817:
818: $msg = $this->__('Google Charge:');
819: $msg .= '<br />' . $this->__('Latest Charge: %s', '<strong>' . $this->_formatAmount($latestCharged) . '</strong>');
820: $msg .= '<br />' . $this->__('Total Charged: %s', '<strong>' . $this->_formatAmount($totalCharged) . '</strong>');
821:
822: if (!$order->hasInvoices() && abs($order->getBaseGrandTotal() - $latestCharged) < .0001) {
823: $invoice = $this->_createInvoice();
824: $msg .= '<br />' . $this->__('Invoice Auto-Created: %s', '<strong>' . $invoice->getIncrementId() . '</strong>');
825: }
826:
827: $this->_addChildTransaction(Mage_Sales_Model_Order_Payment_Transaction::TYPE_CAPTURE);
828:
829: $open = Mage_Sales_Model_Order_Invoice::STATE_OPEN;
830: foreach ($order->getInvoiceCollection() as $orderInvoice) {
831: if ($orderInvoice->getState() == $open && $orderInvoice->getBaseGrandTotal() == $latestCharged) {
832: $orderInvoice->setState(Mage_Sales_Model_Order_Invoice::STATE_PAID)
833: ->setTransactionId($this->getGoogleOrderNumber())
834: ->save();
835: break;
836: }
837: }
838:
839: $order->addStatusToHistory($order->getStatus(), $msg);
840: $order->save();
841: }
842:
843: protected function _createInvoice()
844: {
845: $order = $this->getOrder();
846:
847: $invoice = $order->prepareInvoice()
848: ->setTransactionId($this->getGoogleOrderNumber())
849: ->addComment(Mage::helper('googlecheckout')->__('Auto-generated from GoogleCheckout Charge'))
850: ->register()
851: ->pay();
852:
853: $transactionSave = Mage::getModel('core/resource_transaction')
854: ->addObject($invoice)
855: ->addObject($invoice->getOrder());
856:
857: $transactionSave->save();
858:
859: return $invoice;
860: }
861:
862: protected function _createShipment()
863: {
864: $order = $this->getOrder();
865: $shipment = $order->prepareShipment();
866: if ($shipment) {
867: $shipment->register();
868:
869: $order->setIsInProcess(true);
870:
871: $transactionSave = Mage::getModel('core/resource_transaction')
872: ->addObject($shipment)
873: ->addObject($shipment->getOrder())
874: ->save();
875: }
876:
877: return $shipment;
878: }
879:
880: 881: 882:
883: protected function _responseChargebackAmountNotification()
884: {
885: $this->getGResponse()->SendAck();
886:
887: $latestChargeback = $this->getData('root/latest-chargeback-amount/VALUE');
888: $totalChargeback = $this->getData('root/total-chargeback-amount/VALUE');
889:
890: $order = $this->getOrder();
891: if ($order->getBaseGrandTotal() == $totalChargeback) {
892: $creditmemo = Mage::getModel('sales/service_order', $order)
893: ->prepareCreditmemo()
894: ->setPaymentRefundDisallowed(true)
895: ->setAutomaticallyCreated(true)
896: ->register();
897:
898: $creditmemo->addComment($this->__('Credit memo has been created automatically'));
899: $creditmemo->save();
900: }
901: $msg = $this->__('Google Chargeback:');
902: $msg .= '<br />' . $this->__('Latest Chargeback: %s', '<strong>' . $this->_formatAmount($latestChargeback) . '</strong>');
903: $msg .= '<br />' . $this->__('Total Chargeback: %s', '<strong>' . $this->_formatAmount($totalChargeback) . '</strong>');
904:
905: $this->_addChildTransaction(Mage_Sales_Model_Order_Payment_Transaction::TYPE_REFUND,
906: Mage_Sales_Model_Order_Payment_Transaction::TYPE_CAPTURE);
907:
908: $order->addStatusToHistory($order->getStatus(), $msg);
909: $order->save();
910: }
911:
912: 913: 914:
915: protected function _responseRefundAmountNotification()
916: {
917: $this->getGResponse()->SendAck();
918:
919: $latestRefunded = $this->getData('root/latest-refund-amount/VALUE');
920: $totalRefunded = $this->getData('root/total-refund-amount/VALUE');
921:
922: $order = $this->getOrder();
923: $amountRefundLeft = $order->getBaseGrandTotal() - $order->getBaseTotalRefunded()
924: - $order->getBaseAdjustmentNegative();
925: if (abs($amountRefundLeft) < .0001) {
926: return;
927: }
928: if ($amountRefundLeft < $latestRefunded) {
929: $latestRefunded = $amountRefundLeft;
930: $totalRefunded = $order->getBaseGrandTotal();
931: }
932:
933: if ($order->getBaseTotalRefunded() > 0) {
934: $adjustment = array('adjustment_positive' => $latestRefunded);
935: } else {
936: $adjustment = array('adjustment_negative' => $order->getBaseGrandTotal() - $latestRefunded);
937: }
938:
939: $creditmemo = Mage::getModel('sales/service_order', $order)
940: ->prepareCreditmemo($adjustment)
941: ->setPaymentRefundDisallowed(true)
942: ->setAutomaticallyCreated(true)
943: ->register()
944: ->addComment($this->__('Credit memo has been created automatically'))
945: ->save();
946:
947: $msg = $this->__('Google Refund:');
948: $msg .= '<br />' . $this->__('Latest Refund: %s', '<strong>' . $this->_formatAmount($latestRefunded) . '</strong>');
949: $msg .= '<br />' . $this->__('Total Refunded: %s', '<strong>' . $this->_formatAmount($totalRefunded) . '</strong>');
950:
951: $this->_addChildTransaction(Mage_Sales_Model_Order_Payment_Transaction::TYPE_REFUND,
952: Mage_Sales_Model_Order_Payment_Transaction::TYPE_CAPTURE);
953:
954: $order->addStatusToHistory($order->getStatus(), $msg);
955: $order->save();
956: }
957:
958: protected function _responseOrderStateChangeNotification()
959: {
960: $this->getGResponse()->SendAck();
961:
962: $prevFinancial = $this->getData('root/previous-financial-order-state/VALUE');
963: $newFinancial = $this->getData('root/new-financial-order-state/VALUE');
964: $prevFulfillment = $this->getData('root/previous-fulfillment-order-state/VALUE');
965: $newFulfillment = $this->getData('root/new-fulfillment-order-state/VALUE');
966:
967: $msg = $this->__('Google Order Status Change:');
968: if ($prevFinancial!=$newFinancial) {
969: $msg .= "<br />" . $this->__('Financial: %s -> %s', '<strong>' . $prevFinancial . '</strong>', '<strong>' . $newFinancial . '</strong>');
970: }
971: if ($prevFulfillment!=$newFulfillment) {
972: $msg .= "<br />" . $this->__('Fulfillment: %s -> %s', '<strong>' . $prevFulfillment . '</strong>', '<strong>' . $newFulfillment . '</strong>');
973: }
974: $this->getOrder()
975: ->addStatusToHistory($this->getOrder()->getStatus(), $msg)
976: ->save();
977:
978: $method = '_orderStateChangeFinancial' . uc_words(strtolower($newFinancial), '', '_');
979: if (method_exists($this, $method)) {
980: $this->$method();
981: }
982:
983: $method = '_orderStateChangeFulfillment' . uc_words(strtolower($newFulfillment), '', '_');
984: if (method_exists($this, $method)) {
985: $this->$method();
986: }
987: }
988:
989: 990: 991: 992: 993: 994: 995:
996: protected function _addChildTransaction(
997: $typeTarget,
998: $typeParent = Mage_Sales_Model_Order_Payment_Transaction::TYPE_AUTH)
999: {
1000: $payment = $this->getOrder()->getPayment();
1001: $googleOrderId = $this->getGoogleOrderNumber();
1002: $parentTransactionId = $googleOrderId;
1003:
1004: if ($typeParent != Mage_Sales_Model_Order_Payment_Transaction::TYPE_AUTH) {
1005: $parentTransactionId .= '-' . $typeParent;
1006: } else {
1007: $payment->setIsTransactionClosed(false);
1008: }
1009:
1010: $parentTransaction = $payment->getTransaction($parentTransactionId);
1011:
1012: if ($parentTransaction) {
1013: $payment->setParentTransactionId($parentTransactionId)
1014: ->setTransactionId($googleOrderId . '-' . $typeTarget)
1015: ->addTransaction($typeTarget);
1016:
1017: if ($this->getOrder()->getTotalDue() < .0001) {
1018: $parentTransaction->setIsClosed(true)
1019: ->save();
1020: }
1021: }
1022:
1023: return $this;
1024: }
1025:
1026: protected function _orderStateChangeFinancialReviewing()
1027: {
1028:
1029: }
1030:
1031: protected function _orderStateChangeFinancialChargeable()
1032: {
1033:
1034:
1035: }
1036:
1037: protected function _orderStateChangeFinancialCharging()
1038: {
1039:
1040: }
1041:
1042: protected function _orderStateChangeFinancialCharged()
1043: {
1044:
1045: }
1046:
1047: protected function _orderStateChangeFinancialPaymentDeclined()
1048: {
1049:
1050: }
1051:
1052: protected function _orderStateChangeFinancialCancelled()
1053: {
1054: $this->getOrder()->setBeingCanceledFromGoogleApi(true)->cancel()->save();
1055: }
1056:
1057: protected function _orderStateChangeFinancialCancelledByGoogle()
1058: {
1059: $this
1060: ->getOrder()
1061: ->setBeingCanceledFromGoogleApi(true)
1062: ->cancel()
1063: ->save();
1064:
1065: $this
1066: ->getGRequest()
1067: ->SendBuyerMessage($this->getGoogleOrderNumber(), "Sorry, your order is cancelled by Google", true);
1068: }
1069:
1070: protected function _orderStateChangeFulfillmentNew()
1071: {
1072:
1073: }
1074:
1075: protected function _orderStateChangeFulfillmentProcessing()
1076: {
1077:
1078: }
1079:
1080: protected function _orderStateChangeFulfillmentDelivered()
1081: {
1082: $shipment = $this->_createShipment();
1083: if (!is_null($shipment))
1084: $shipment->save();
1085: }
1086:
1087: protected function _orderStateChangeFulfillmentWillNotDeliver()
1088: {
1089:
1090: }
1091:
1092: 1093: 1094: 1095: 1096: 1097:
1098: protected function _formatAmount($amount)
1099: {
1100:
1101: return Mage::helper('core')->currency($amount, true, false);
1102: }
1103:
1104: }
1105: