00001 <?php
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 class Mage_AmazonPayments_Model_Api_Cba extends Mage_AmazonPayments_Model_Api_Abstract
00033 {
00034     protected static $HMAC_SHA1_ALGORITHM = "sha1";
00035     protected $_paymentCode = 'amazonpayments_cba';
00036 
00037     protected $_carriers;
00038     protected $_address;
00039 
00040     const STANDARD_SHIPMENT_RATE    = 'Standard';
00041     const EXPEDITED_SHIPMENT_RATE   = 'Expedited';
00042     const ONEDAY_SHIPMENT_RATE      = 'OneDay';
00043     const TWODAY_SHIPMENT_RATE      = 'TwoDay';
00044 
00045     protected $_shippingRates = array(
00046         self::STANDARD_SHIPMENT_RATE,
00047         self::EXPEDITED_SHIPMENT_RATE,
00048         self::ONEDAY_SHIPMENT_RATE,
00049         self::TWODAY_SHIPMENT_RATE,
00050     );
00051 
00052     protected $_configShippingRates = null;
00053 
00054 
00055 
00056 
00057 
00058 
00059     public function getMerchantId()
00060     {
00061         return Mage::getStoreConfig('payment/amazonpayments_cba/merchant_id');
00062     }
00063 
00064 
00065 
00066 
00067 
00068 
00069     public function getAmazonRedirectUrl()
00070     {
00071         #$_url = $this->getCbaPaymentUrl();
00072         $_url = $this->getPayServiceUrl();
00073         $_merchantId = Mage::getStoreConfig('payment/amazonpayments_cba/merchant_id');
00074         return $_url.$_merchantId;
00075     }
00076 
00077     public function getConfigShippingRates()
00078     {
00079         if (is_null($this->_configShippingRates)) {
00080             $this->_configShippingRates = array();
00081             foreach ($this->_shippingRates as $_rate) {
00082                 $_carrier = unserialize(Mage::getStoreConfig('payment/amazonpayments_cba/' . strtolower($_rate) . '_rate'));
00083                 if ($_carrier['method'] && $_carrier['method'] != 'None') {
00084                     $_carrierInfo = explode('/', $_carrier['method']);
00085                     $this->_configShippingRates[$_rate] = array(
00086                         'carrier' => $_carrierInfo[0],
00087                         'method' => $_carrierInfo[1]
00088                     );
00089                 }
00090             }
00091         }
00092         return $this->_configShippingRates;
00093     }
00094 
00095 
00096 
00097 
00098 
00099 
00100 
00101 
00102 
00103 
00104     public function calculateSignature($data, $secretKey)
00105     {
00106         $stringData = '';
00107         if (is_array($data)) {
00108             ksort($data);
00109             foreach ($data as $key => $value) {
00110                 $stringData .= $key.'='.rawurlencode($value).'&';
00111             }
00112         } elseif (is_string($data)) {
00113             $stringData = $data;
00114         } else {
00115             $stringData = $data;
00116         }
00117 
00118         
00119         $rawHmac = hash_hmac(self::$HMAC_SHA1_ALGORITHM, $stringData, $secretKey, true);
00120 
00121         
00122         return base64_encode($rawHmac);
00123     }
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131     public function formatAmount($amount)
00132     {
00133         return Mage::helper('amazonpayments')->formatAmount($amount);
00134     }
00135 
00136 
00137 
00138 
00139 
00140 
00141 
00142     public function getXmlCart(Mage_Sales_Model_Quote $quote)
00143     {
00144         $_xml = '<?xml version="1.0" encoding="UTF-8"?>'."\n"
00145                 .'<Order xmlns="http://payments.amazon.com/checkout/2008-11-30/">'."\n";
00146         if (!$quote->hasItems()) {
00147             return false;
00148         }
00149         $_xml .= " <ClientRequestId>{$quote->getId()}</ClientRequestId>\n"; 
00150         #        ."<ExpirationDate></ExpirationDate>";
00151 
00152         $_xml .= " <Cart>\n"
00153                 ."   <Items>\n";
00154 
00155         foreach ($quote->getAllVisibleItems() as $_item) {
00156             $_xml .= "   <Item>\n"
00157                 ."    <SKU>{$_item->getSku()}/{$_item->getId()}</SKU>\n"
00158                 ."    <MerchantId>{$this->getMerchantId()}</MerchantId>\n"
00159                 ."    <Title>{$_item->getName()}</Title>\n"
00160                 ."    <Price>\n"
00161                 ."     <Amount>{$this->formatAmount($_item->getPrice())}</Amount>\n"
00162                 ."     <CurrencyCode>{$quote->getBaseCurrencyCode()}</CurrencyCode>\n"
00163                 ."    </Price>\n"
00164                 ."    <Quantity>{$_item->getQty()}</Quantity>\n"
00165                 ."    <Weight>\n"
00166                 ."      <Amount>{$this->formatAmount($_item->getWeight())}</Amount>\n"
00167                 ."       <Unit>lb</Unit>\n"
00168                 ."     </Weight>\n";
00169             $_xml .= "   </Item>\n";
00170 
00171         }
00172         $_xml .= "   </Items>\n"
00173                 ."   <CartPromotionId>cart-total-discount</CartPromotionId>\n"
00174                 ." </Cart>\n";
00175 
00176         $_xml .= " <IntegratorId>A2ZZYWSJ0WMID8MAGENTO</IntegratorId>\n"
00177                 ." <IntegratorName>Varien</IntegratorName>\n";
00178         $_xml .= " <OrderCalculationCallbacks>\n"
00179                 ."   <CalculateTaxRates>true</CalculateTaxRates>\n"
00180                 ."   <CalculatePromotions>true</CalculatePromotions>\n"
00181                 ."   <CalculateShippingRates>true</CalculateShippingRates>\n"
00182                 ."   <OrderCallbackEndpoint>".Mage::getUrl('amazonpayments/cba/callback', array('_secure' => true))."</OrderCallbackEndpoint>\n"
00183                 ."   <ProcessOrderOnCallbackFailure>true</ProcessOrderOnCallbackFailure>\n"
00184                 ." </OrderCalculationCallbacks>\n";
00185 
00186         $_xml .= "</Order>\n";
00187         return $_xml;
00188 
00189     }
00190 
00191 
00192 
00193 
00194 
00195 
00196 
00197     protected function _getCheckoutTaxXml(Mage_Sales_Model_Quote $quote)
00198     {
00199         $xml = '';
00200 
00201         
00202         
00203         
00204 
00205         $xml .= "<TaxTables>\n";
00206 
00207         
00208         $xml .= $this->_getTaxTablesXml($quote, $this->_getTaxRules($quote));
00209 
00210         
00211         $xml .= "   <TaxTable>\n"
00212              ."      <TaxTableId>none</TaxTableId>\n"
00213              ."      <TaxRules>\n"
00214              ."        <TaxRule>\n"
00215              ."          <Rate>0</Rate>\n"
00216              ."          <PredefinedRegion>WorldAll</PredefinedRegion>\n"
00217              ."        </TaxRule>\n"
00218              ."      </TaxRules>\n"
00219              ."    </TaxTable>\n";
00220 
00221         $xml .= "</TaxTables>\n";
00222 
00223 
00224         return $xml;
00225     }
00226 
00227 
00228 
00229 
00230 
00231 
00232 
00233 
00234 
00235 
00236     protected function _getTaxTablesXml($quote, $rules, $isShipping = false, $addTo = null)
00237     {
00238         $xml = '';
00239         if ($isShipping) {
00240             $isShippingTaxed = 'true';
00241             $taxTableTag = 'DefaultTaxTable';
00242         } else {
00243             $isShippingTaxed = 'false';
00244             $taxTableTag = 'TaxTable';
00245         }
00246 
00247         if (is_array($rules)) {
00248             if ($addTo) {
00249                 $_tables = $addTo->addChild('TaxTables');
00250             }
00251 
00252             foreach ($rules as $group=>$taxRates) {
00253                 $isShippingTaxed = ($isShipping ? 'true' : 'false');
00254                 if ($isShipping) {
00255                     $tableName = 'default-tax-table';
00256                 } else {
00257                     $tableName = "tax_{$group}";
00258                     if ($group == $this->_getShippingTaxClassId($quote)) {
00259                         $isShippingTaxed = 'true';
00260                     }
00261                 }
00262                 if ($addTo) {
00263                     
00264                     $_table = $_tables->addChild($taxTableTag);
00265                     $_table->addChild('TaxTableId', $tableName);
00266                     $_rules = $_table->addChild('TaxRules');
00267                 } else {
00268                     $xml .= " <{$taxTableTag}>\n";
00269                     $xml .= "  <TaxTableId>{$tableName}</TaxTableId>\n";
00270                     $xml .= "  <TaxRules>\n";
00271                 }
00272 
00273                 if (is_array($taxRates)) {
00274                     foreach ($taxRates as $rate) {
00275                         if ($addTo) {
00276                             $_rule = $_rules->addChild('TaxRule');
00277                             $_rule->addChild('Rate', $rate['value']);
00278                             $_rule->addChild('IsShippingTaxed', $isShippingTaxed);
00279                         } else {
00280                             $xml .= "   <TaxRule>\n";
00281                             $xml .= "    <Rate>{$rate['value']}</Rate>\n";
00282                             $xml .= "    <IsShippingTaxed>{$isShippingTaxed}</IsShippingTaxed>\n";
00283                         }
00284 
00285                         if ($rate['country']==='US') {
00286                             if (!empty($rate['postcode']) && $rate['postcode']!=='*') {
00287                                 if ($addTo) {
00288                                     $_rule->addChild('USZipRegion', $rate['postcode']);
00289                                 } else {
00290                                     $xml .= "    <USZipRegion>{$rate['postcode']}</USZipRegion>\n";
00291                                 }
00292                             } else if (!empty($rate['state']) && $rate['state']!=='*') {
00293                                 if ($addTo) {
00294                                     $_rule->addChild('USStateRegion', $rate['state']);
00295                                 } else {
00296                                     $xml .= "    <USStateRegion>{$rate['state']}</USStateRegion>\n";
00297                                 }
00298                             } else {
00299                                 if ($addTo) {
00300                                     $_rule->addChild('PredefinedRegion', 'USAll');
00301                                 } else {
00302                                     $xml .= "    <PredefinedRegion>USAll</PredefinedRegion>\n";
00303                                 }
00304                             }
00305                         } else {
00306                             if ($addTo) {
00307                                 $_region = $_rule->addChild('WorldRegion');
00308                                 $_region->addChild('CountryCode', $rate['country']);
00309                                 if (!empty($rate['postcode']) && $rate['postcode']!=='*') {
00310                                     $_region->addChild('PostalRegion', $rate['postcode']);
00311                                 }
00312                             } else {
00313                                 $xml .= "    <WorldRegion>\n";
00314                                 $xml .= "     <CountryCode>{$rate['country']}</CountryCode>\n";
00315                                 if (!empty($rate['postcode']) && $rate['postcode']!=='*') {
00316                                     $xml .= "     <PostalRegion>{$rate['postcode']}</PostalRegion>\n";
00317                                 }
00318                                 $xml .= "    </WorldRegion>\n";
00319                             }
00320                         }
00321 
00322                         $xml .= "   </TaxRule>\n";
00323                     }
00324                 } else {
00325                     $taxRate = $taxRates/100;
00326                     if ($addTo) {
00327                         $_rule = $_rules->addChild('TaxRule');
00328                         $_rule->addChild('Rate', $taxRate);
00329                         $_rule->addChild('IsShippingTaxed', $isShippingTaxed);
00330                         $_rule->addChild('PredefinedRegion', 'WorldAll');
00331                     } else {
00332                         $xml .= "   <TaxRule>\n";
00333                         $xml .= "    <Rate>{$taxRate}</Rate>\n";
00334                         $xml .= "    <IsShippingTaxed>{$isShippingTaxed}</IsShippingTaxed>\n";
00335                         $xml .= "    <PredefinedRegion>WorldAll</PredefinedRegion>\n";
00336                         $xml .= "   </TaxRule>\n";
00337                     }
00338                 }
00339 
00340                 $xml .= "  </TaxRules>\n";
00341                 $xml .= " </{$taxTableTag}>\n";
00342             }
00343 
00344         } else {
00345             if (is_numeric($rules)) {
00346                 $taxRate = $rules/100;
00347 
00348                 if ($addTo) {
00349                     $_table = $addTo->addChild($taxTableTag);
00350                     $_rules = $_table->addChild('TaxRules');
00351                     $_rule = $_rules->addChild('TaxRule');
00352                     $_rule->addChild('Rate', $taxRate);
00353                     $_rule->addChild('IsShippingTaxed', $isShippingTaxed);
00354                     $_rule->addChild('PredefinedRegion', 'WorldAll');
00355                 } else {
00356                     $xml .= " <{$taxTableTag}>\n";
00357                     $xml .= "  <TaxRules>\n";
00358                     $xml .= "   <TaxRule>\n";
00359                     $xml .= "    <Rate>{$taxRate}</Rate>\n";
00360                     $xml .= "    <IsShippingTaxed>{$isShippingTaxed}</IsShippingTaxed>\n";
00361                     $xml .= "    <PredefinedRegion>WorldAll</PredefinedRegion>\n";
00362                     $xml .= "   </TaxRule>\n";
00363                     $xml .= "  </TaxRules>\n";
00364                     $xml .= " </{$taxTableTag}>\n";
00365                 }
00366             }
00367         }
00368 
00369         if ($addTo) {
00370             return $addTo;
00371         }
00372 
00373         return $xml;
00374     }
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 
00383     protected function _getTaxRules(Mage_Sales_Model_Quote $quote)
00384     {
00385         $customerTaxClass = $this->_getCustomerTaxClass($quote);
00386         if (Mage::helper('tax')->getTaxBasedOn() == 'origin') {
00387             $request = Mage::getSingleton('tax/calculation')->getRateRequest();
00388             return Mage::getSingleton('tax/calculation')->getRatesForAllProductTaxClasses($request->setCustomerClassId($customerTaxClass));
00389         } else {
00390             $customerRules = Mage::getSingleton('tax/calculation')->getRatesByCustomerTaxClass($customerTaxClass);
00391             $rules = array();
00392             foreach ($customerRules as $rule) {
00393                 $rules[$rule['product_class']][] = $rule;
00394             }
00395             return $rules;
00396         }
00397     }
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405     protected function _getShippingTaxRules(Mage_Sales_Model_Quote $quote)
00406     {
00407         $customerTaxClass = $this->_getCustomerTaxClass($quote);
00408         if ($shippingTaxClass = $this->_getShippingTaxClassId($quote)) {
00409             if (Mage::helper('tax')->getTaxBasedOn() == 'origin') {
00410                 $request = Mage::getSingleton('tax/calculation')->getRateRequest();
00411                 $request
00412                     ->setCustomerClassId($customerTaxClass)
00413                     ->setProductClassId($shippingTaxClass);
00414 
00415                 return Mage::getSingleton('tax/calculation')->getRate($request);
00416             }
00417             $customerRules = Mage::getSingleton('tax/calculation')->getRatesByCustomerAndProductTaxClasses($customerTaxClass, $shippingTaxClass);
00418             $rules = array();
00419             foreach ($customerRules as $rule) {
00420                 $rules[$rule['product_class']][] = $rule;
00421             }
00422             return $rules;
00423         } else {
00424             return array();
00425         }
00426     }
00427 
00428 
00429 
00430 
00431 
00432 
00433 
00434     protected function _getShippingTaxClassId(Mage_Sales_Model_Quote $quote)
00435     {
00436         return Mage::getStoreConfig(Mage_Tax_Model_Config::CONFIG_XML_PATH_SHIPPING_TAX_CLASS, $quote->getStoreId());
00437     }
00438 
00439 
00440 
00441 
00442 
00443 
00444 
00445     protected function _getCustomerTaxClass(Mage_Sales_Model_Quote $quote)
00446     {
00447         $customerGroup = $quote->getCustomerGroupId();
00448         if (!$customerGroup) {
00449             $customerGroup = Mage::getStoreConfig('customer/create_account/default_group', $quote->getStoreId());
00450         }
00451         return Mage::getModel('customer/group')->load($customerGroup)->getTaxClassId();
00452     }
00453 
00454 
00455 
00456 
00457 
00458     public function handleXmlCallback($xmlRequest, $session)
00459     {
00460         $_address = $this->_parseRequestAddress($xmlRequest);
00461 
00462         #$quoteId = $session->getAmazonQuoteId();
00463         $quoteId = $_address['ClientRequestId'];
00464         $quote = Mage::getModel('sales/quote')->load($quoteId);
00465 
00466         $baseCurrency = $session->getQuote()->getBaseCurrencyCode();
00467         $currency = Mage::app()->getStore($session->getQuote()->getStoreId())->getBaseCurrency();
00468 
00469         $billingAddress = $quote->getBillingAddress();
00470         $address = $quote->getShippingAddress();
00471 
00472         $this->_address = $_address;
00473 
00474         $regionModel = Mage::getModel('directory/region')->loadByCode($_address['regionCode'], $_address['countryCode']);
00475         $_regionId = $regionModel->getId();
00476 
00477         $address->setCountryId($_address['countryCode'])
00478             ->setRegion($_address['regionCode'])
00479             ->setRegionId($_regionId)
00480             ->setCity($_address['city'])
00481             ->setStreet($_address['street'])
00482             ->setPostcode($_address['postCode']);
00483         $billingAddress->setCountryId($_address['countryCode'])
00484             ->setRegion($_address['regionCode'])
00485             ->setRegionId($_regionId)
00486             ->setCity($_address['city'])
00487             ->setStreet($_address['street'])
00488             ->setPostcode($_address['postCode']);
00489 
00490         $quote->setBillingAddress($billingAddress);
00491         $quote->setShippingAddress($address);
00492         $quote->save();
00493 
00494         $address->setCollectShippingRates(true)->collectShippingRates();
00495 
00496         $errors = array();
00497         $_carriers = array();
00498         foreach ($this->getConfigShippingRates() as $_cfgRate) {
00499             if ($carrier = Mage::getStoreConfig('carriers/' . $_cfgRate['carrier'], $this->getStoreId())) {
00500                 if (isset($carrier['title']) && $carrier['active'] && !in_array($_cfgRate['carrier'], $_carriers)) {
00501                     $_carriers[] = $_cfgRate['carrier'];
00502                 }
00503             }
00504         }
00505 
00506         $result = Mage::getModel('shipping/shipping')
00507             ->collectRatesByAddress($address, $_carriers)
00508             ->getResult();
00509         $rateCodes = array();
00510         foreach ($this->getConfigShippingRates() as $_cfgRateLevel => $_cfgRate) {
00511             if ($rates = $result->getRatesByCarrier($_cfgRate['carrier'])) {
00512                 foreach ($rates as $rate) {
00513                     if (!$rate instanceof Mage_Shipping_Model_Rate_Result_Error && $rate->getMethod() == $_cfgRate['method']) {
00514                         if ($address->getFreeShipping()) {
00515                             $price = 0;
00516                         } else {
00517                             $price = $rate->getPrice();
00518                         }
00519                         if ($price) {
00520                             $price = Mage::helper('tax')->getShippingPrice($price, true, $address);
00521                         }
00522                         $this->_carriers[] = array(
00523                             'service_level' => $_cfgRateLevel,
00524                             'code'          => $rate->getCarrier() . '_' . $rate->getMethod(),
00525                             'price'         => $price,
00526                             'currency'      => $currency['currency_code'],
00527                             'description'   => $rate->getCarrierTitle() . ' - ' . $rate->getMethodTitle() . ' (Amazon ' . $_cfgRateLevel . ' Service Level)'
00528                         );
00529                     }
00530                 }
00531             }
00532         }
00533 
00534         if ($_extShippingInfo = unserialize($quote->getExtShippingInfo())) {
00535             $_extShippingInfo = array_merge($_extShippingInfo, array('amazon_service_level' => $this->_carriers));
00536         } else {
00537             $_extShippingInfo = array('amazon_service_level' => $this->_carriers);
00538         }
00539         $quote->setExtShippingInfo(serialize($_extShippingInfo));
00540 
00541         $_items = $this->_parseRequestItems($xmlRequest);
00542         $xml = $this->_generateXmlResponse($quote, $_items);
00543 
00544         $session->getQuote()
00545             ->setForcedCurrency($currency)
00546             ->collectTotals()
00547             ->save();
00548         $quote->save();
00549         return $xml;
00550     }
00551 
00552 
00553 
00554 
00555 
00556 
00557     public function parseOrder($xmlData)
00558     {
00559         $parsedOrder = array();
00560         if (strlen(trim($xmlData)) > 0) {
00561             $xml = simplexml_load_string($xmlData, 'Varien_Simplexml_Element');
00562             $parsedOrder = array(
00563                 'NotificationReferenceId'   => (string) $xml->descend("NotificationReferenceId"),
00564                 'amazonOrderID'     => (string) $xml->descend("ProcessedOrder/AmazonOrderID"),
00565                 'orderDate'         => (string) $xml->descend("ProcessedOrder/OrderDate"),
00566                 'orderChannel'      => (string) $xml->descend("ProcessedOrder/OrderChannel"),
00567                 'buyerName'         => (string) $xml->descend("ProcessedOrder/BuyerInfo/BuyerName"),
00568                 'buyerEmailAddress' => (string) $xml->descend("ProcessedOrder/BuyerInfo/BuyerEmailAddress"),
00569                 'ShippingLevel'     => (string) $xml->descend("ProcessedOrder/ShippingServiceLevel"),
00570                 'shippingAddress'   => array(
00571                     'name'          => (string) $xml->descend("ProcessedOrder/ShippingAddress/Name"),
00572                     'street'        => (string) $xml->descend("ProcessedOrder/ShippingAddress/AddressFieldOne"),
00573                     'city'          => (string) $xml->descend("ProcessedOrder/ShippingAddress/City"),
00574                     'regionCode'    => (string) $xml->descend("ProcessedOrder/ShippingAddress/State"),
00575                     'postCode'      => (string) $xml->descend("ProcessedOrder/ShippingAddress/PostalCode"),
00576                     'countryCode'   => (string) $xml->descend("ProcessedOrder/ShippingAddress/CountryCode"),
00577                 ),
00578                 'items'             => array(),
00579             );
00580 
00581             $_total = $_shipping = $_tax = $_shippingTax = $_subtotalPromo = $_shippingPromo = $_subtotal = 0;
00582             $_itemsCount = $_itemsQty = 0;
00583             foreach ($xml->descend("ProcessedOrder/ProcessedOrderItems/ProcessedOrderItem") as $_item) {
00584                 $parsedOrder['ClientRequestId'] = (string) $_item->ClientRequestId;
00585                 $_compositeSku = explode('/', (string) $_item->SKU);
00586                 $_sku = '';
00587                 if (isset($_compositeSku[0])) {
00588                     $_sku = $_compositeSku[0];
00589                 }
00590                 $_itemId = '';
00591                 if ($_compositeSku[1]) {
00592                     $_itemId = $_compositeSku[1];
00593                 }
00594                 $_itemQty = (string) $_item->Quantity;
00595                 $_itemsQty += $_itemQty;
00596                 $_itemsCount++;
00597                 $parsedOrder['items'][$_itemId] = array(
00598                     'AmazonOrderItemCode' => (string) $_item->AmazonOrderItemCode,
00599                     'sku'   => $_sku,
00600                     'title' => (string) $_item->Title,
00601                     'price' => array(
00602                         'amount'       => (string) $_item->Price->Amount,
00603                         'currencyCode' => (string) $_item->Price->CurrencyCode,
00604                         ),
00605                     'qty' => $_itemQty,
00606                     'weight' => array(
00607                         'amount' => (string) $_item->Weight->Amount,
00608                         'unit'   => (string) $_item->Weight->Unit,
00609                         ),
00610                 );
00611                 $_itemSubtotal = 0;
00612                 foreach ($_item->ItemCharges->Component as $_component) {
00613                     switch ((string) $_component->Type) {
00614                         case 'Principal':
00615                             $_itemSubtotal  += (string) $_component->Charge->Amount;
00616                             $parsedOrder['items'][$_itemId]['subtotal'] = $_itemSubtotal;
00617                             break;
00618                         case 'Shipping':
00619                             $_shipping      += (string) $_component->Charge->Amount;
00620                             $parsedOrder['items'][$_itemId]['shipping'] = (string) $_component->Charge->Amount;
00621                             break;
00622                         case 'Tax':
00623                             $_tax           += (string) $_component->Charge->Amount;
00624                             $parsedOrder['items'][$_itemId]['tax'] = (string) $_component->Charge->Amount;
00625                             break;
00626                         case 'ShippingTax':
00627                             $_shippingTax   += (string) $_component->Charge->Amount;
00628                             $parsedOrder['items'][$_itemId]['shipping_tax'] = (string) $_component->Charge->Amount;
00629                             break;
00630                         case 'PrincipalPromo':
00631                             $_subtotalPromo += (string) $_component->Charge->Amount;
00632                             $parsedOrder['items'][$_itemId]['principal_promo'] = (string) $_component->Charge->Amount;
00633                             break;
00634                         case 'ShippingPromo':
00635                             $_shippingPromo += (string) $_component->Charge->Amount;
00636                             $parsedOrder['items'][$_itemId]['shipping_promo'] = (string) $_component->Charge->Amount;
00637                             break;
00638                     }
00639                 }
00640                 $_subtotal += $_itemSubtotal;
00641             }
00642 
00643             $parsedOrder['itemsCount'] = $_itemsCount;
00644             $parsedOrder['itemsQty'] = $_itemsQty;
00645 
00646             $parsedOrder['subtotal'] = $_subtotal;
00647             $parsedOrder['shippingAmount'] = $_shipping;
00648             $parsedOrder['tax'] = $_tax + $_shippingTax;
00649             $parsedOrder['shippingTax'] = $_shippingTax;
00650             $parsedOrder['discount'] = $_subtotalPromo + $_shippingPromo;
00651             $parsedOrder['discountShipping'] = $_shippingPromo;
00652 
00653             $parsedOrder['total'] = $_subtotal + $_shipping + $_tax + $_shippingTax - abs($_subtotalPromo) - abs($_shippingPromo);
00654         }
00655         return $parsedOrder;
00656     }
00657 
00658 
00659 
00660 
00661 
00662 
00663 
00664     public function parseOrderReadyToShipNotification($xmlData)
00665     {
00666         $readyToShipData = array();
00667         if (strlen(trim($xmlData))) {
00668             $xml = simplexml_load_string($xmlData, 'Varien_Simplexml_Element');
00669             $aOrderId = (string) $xml->descend('ProcessedOrder/AmazonOrderID');
00670             $readyToShipData['amazon_order_id'] = $aOrderId;
00671             $readyToShipData['items'] = array();
00672             foreach ($xml->descend('ProcessedOrder/ProcessedOrderItems/ProcessedOrderItem') as $item) {
00673                 $readyToShipData['items'][(string)$item->AmazonOrderItemCode] = (string)$item->Quantity;
00674             }
00675         }
00676         return $readyToShipData;
00677     }
00678 
00679     public function parseCancelNotification($xmlData)
00680     {
00681         $cancelData = array();
00682         if (strlen(trim($xmlData))) {
00683             $xml = simplexml_load_string($xmlData, 'Varien_Simplexml_Element');
00684             $aOrderId = (string) $xml->descend('ProcessedOrder/AmazonOrderID');
00685             $cancelData['amazon_order_id'] = $aOrderId;
00686         }
00687         return $cancelData;
00688     }
00689 
00690 
00691 
00692 
00693 
00694 
00695     protected function _parseRequestAddress($xmlResponse)
00696     {
00697         $address = array();
00698         if (strlen(trim($xmlResponse)) > 0) {
00699             $xml = simplexml_load_string($xmlResponse, 'Varien_Simplexml_Element');
00700 
00701             $address = array(
00702                 'addressId'         => (string) $xml->descend("CallbackOrders/CallbackOrder/Address/AddressId"),
00703                 'regionCode'        => (string) $xml->descend("CallbackOrders/CallbackOrder/Address/State"),
00704                 'countryCode'       => (string) $xml->descend("CallbackOrders/CallbackOrder/Address/CountryCode"),
00705                 'city'              => (string) $xml->descend("CallbackOrders/CallbackOrder/Address/City"),
00706                 'street'            => (string) $xml->descend("CallbackOrders/CallbackOrder/Address/AddressFieldOne"),
00707                 'postCode'          => (string) $xml->descend("CallbackOrders/CallbackOrder/Address/PostalCode"),
00708                 'ClientRequestId'   => (string) $xml->descend("ClientRequestId"),
00709             );
00710         } else {
00711             $address = array(
00712                 'addressId'   => '',
00713                 'regionCode'  => '',
00714                 'countryCode' => '',
00715                 'city'        => '',
00716                 'street'      => '',
00717                 'postCode'    => '',
00718             );
00719         }
00720         return $address;
00721     }
00722 
00723 
00724 
00725 
00726 
00727 
00728     protected function _parseRequestItems($xmlResponse)
00729     {
00730         $items = array();
00731         if (strlen(trim($xmlResponse)) > 0) {
00732             $xml = simplexml_load_string($xmlResponse, 'Varien_Simplexml_Element');
00733             $itemsXml = $xml->descend("Cart/Items");
00734             foreach ($itemsXml->Item as $_item) {
00735                 $sku = '';
00736                 $compositeSku = explode('/', (string)$_item->SKU);
00737                 if (isset($compositeSku[0])) {
00738                     $sku = $compositeSku[0];
00739                 }
00740                 $items[(string)$_item->SKU] = $sku;
00741             }
00742         } else {
00743             return false;
00744         }
00745         return $items;
00746     }
00747 
00748 
00749 
00750 
00751 
00752 
00753     protected function _generateXmlResponse($quote, $items = array())
00754     {
00755 
00756         $_xmlString = <<<XML
00757 <?xml version="1.0" encoding="UTF-8"?>
00758 <OrderCalculationsResponse xmlns="http://payments.amazon.com/checkout/2008-11-30/">
00759 </OrderCalculationsResponse>
00760 XML;
00761 
00762         $xml = new SimpleXMLElement($_xmlString);
00763 
00764         if (count($this->_carriers) > 0) {
00765             $_xmlResponse = $xml->addChild('Response');
00766             $_xmlCallbackOrders = $_xmlResponse->addChild('CallbackOrders');
00767             $_xmlCallbackOrder = $_xmlCallbackOrders->addChild('CallbackOrder');
00768 
00769             $_xmlAddress = $_xmlCallbackOrder->addChild('Address');
00770             $_xmlAddressId = $_xmlAddress->addChild('AddressId', $this->_address['addressId']);
00771 
00772             $_xmlCallbackOrderItems = $_xmlCallbackOrder->addChild('CallbackOrderItems');
00773             foreach ($items as $_itemSku) {
00774                 $_quoteItem = null;
00775                 foreach ($quote->getAllItems() as $_item) {
00776                     if ($_item->getSku() == $_itemSku) {
00777                         $_quoteItem = $_item;
00778                         break;
00779                     }
00780                 }
00781                 if (is_null($_quoteItem)) {
00782                     Mage::throwException($this->__('Item specified in callback request XML was not found in quote.'));
00783                 }
00784 
00785                 $_xmlCallbackOrderItem = $_xmlCallbackOrderItems->addChild('CallbackOrderItem');
00786                 $_xmlCallbackOrderItem->addChild('SKU', $_itemSku . '/' . $_quoteItem->getId());
00787                 $_xmlCallbackOrderItem->addChild('TaxTableId', 'tax_'.$_quoteItem->getTaxClassId());
00788 
00789 
00790 
00791                 $_xmlShippingMethodIds = $_xmlCallbackOrderItem->addChild('ShippingMethodIds');
00792                 foreach ($this->_carriers as $_carrier) {
00793                     $_xmlShippingMethodIds->addChild('ShippingMethodId', $_carrier['code']);
00794                 }
00795             }
00796 
00797             $this->_appendTaxTables($xml, $quote, $this->_getTaxRules($quote));
00798             $this->_appendDiscounts($xml, $quote);
00799 
00800             $_xmlShippingMethods = $xml->addChild('ShippingMethods');
00801             foreach ($this->_carriers as $_carrier) {
00802                 $_xmlShippingMethod = $_xmlShippingMethods->addChild('ShippingMethod');
00803 
00804                 $_xmlShippingMethod->addChild('ShippingMethodId', $_carrier['code']);
00805                 $_xmlShippingMethod->addChild('ServiceLevel', $_carrier['service_level']);
00806 
00807                 $_xmlShippingMethodRate = $_xmlShippingMethod->addChild('Rate');
00808                 
00809                 $_xmlShippingMethodRateItem = $_xmlShippingMethodRate->addChild('ShipmentBased');
00810                 $_xmlShippingMethodRateItem->addChild('Amount', $_carrier['price']);
00811                 $_xmlShippingMethodRateItem->addChild('CurrencyCode', $_carrier['currency']);
00812 
00813                 $_xmlShippingMethodIncludedRegions = $_xmlShippingMethod->addChild('IncludedRegions');
00814                 $_xmlShippingMethodIncludedRegions->addChild('PredefinedRegion', 'WorldAll');
00815             }
00816             $xml->addChild('CartPromotionId', 'cart-total-discount');
00817         }
00818 
00819         return $xml;
00820     }
00821 
00822     protected function _appendTaxTables($xml, $quote, $rules, $isShipping = false)
00823     {
00824         return $this->_getTaxTablesXml($quote, $rules, $isShipping, $xml);
00825     }
00826 
00827     protected function _appendDiscounts($xml, $quote)
00828     {
00829         $totalDiscount = $quote->getShippingAddress()->getBaseDiscountAmount() + $quote->getBillingAddress()->getBaseDiscountAmount();
00830         $discountAmount = ($totalDiscount ? $totalDiscount : 0);
00831 
00832         $_promotions = $xml->addChild('Promotions');
00833         $_promotion = $_promotions->addChild('Promotion');
00834         $_promotion->addChild('PromotionId', 'cart-total-discount');
00835         $_promotion->addChild('Description', 'Discount');
00836         $_benefit = $_promotion->addChild('Benefit');
00837         $_fad = $_benefit->addChild('FixedAmountDiscount');
00838         $_fad->addChild('Amount', $discountAmount);
00839         $_fad->addChild('CurrencyCode', $quote->getBaseCurrencyCode());
00840 
00841         return $xml;
00842     }
00843 
00844 
00845 
00846 
00847 
00848 
00849     public function callbackXmlError(Exception $e)
00850     {
00851         
00852         $xmlErrorString = '<?xml version="1.0" encoding="UTF-8"?>'."\n"
00853             .'<OrderCalculationsResponse xmlns="http://payments.amazon.com/checkout/2008-11-30/">'."\n"
00854             .' <Response>'."\n"
00855             .'   <Error>'."\n"
00856             .'     <Code>INTERNAL_SERVER_ERROR</Code>'."\n"
00857             .'     <Message>[MESSAGE]</Message>'."\n"
00858             .'   </Error>'."\n"
00859             .' </Response>'."\n"
00860             .'</OrderCalculationsResponse>';
00861         $_errorMsg = $e->getMessage();
00862         $_errorMessage = "{$_errorMsg}\n\n"
00863             ."code: {$e->getCode()}\n\n"
00864             ."file: {$e->getFile()}\n\n"
00865             ."line: {$e->getLine()}\n\n"
00866             ."trac: {$e->getTraceAsString()}\n\n";
00867         if ($this->getDebug()) {
00868          $debug = Mage::getModel('amazonpayments/api_debug')
00869             ->setResponseBody($_errorMessage)
00870             ->setRequestBody(time() .' - error callback response')
00871             ->save();
00872         }
00873 
00874         if ($_errorMsg = $e->getMessage() && 0) {
00875             $xmlErrorString = str_replace('[MESSAGE]', $_errorMsg, $xmlErrorString);
00876         } else {
00877             $xmlErrorString = str_replace('[MESSAGE]', 'Error', $xmlErrorString);
00878         }
00879         $xml = new SimpleXMLElement($xmlErrorString);
00880         return $xml;
00881     }
00882 
00883 
00884 
00885 
00886 
00887 
00888     public function getDocumentApi()
00889     {
00890         if (is_null($this->getData('document_api'))) {
00891             $_documentApi = Mage::getModel('amazonpayments/api_cba_document')
00892                 ->setWsdlUri('https://merchant-api.amazon.com/gateway/merchant-interface-mime/')
00893                 ->setMerchantInfo(array(
00894                     'merchantIdentifier' => Mage::getStoreConfig('payment/amazonpayments_cba/merchant_tocken'),
00895                     'merchantName' => Mage::getStoreConfig('payment/amazonpayments_cba/merchant_name'),
00896                 ))
00897                 ->init(
00898                     Mage::getStoreConfig('payment/amazonpayments_cba/merchant_login'),
00899                     Mage::getStoreConfig('payment/amazonpayments_cba/merchant_pass')
00900                 );
00901             $this->setData('document_api', $_documentApi);
00902         }
00903         return $this->getData('document_api');
00904     }
00905 
00906 
00907 
00908 
00909 
00910 
00911 
00912     public function syncOrder($order)
00913     {
00914         if ($order->getId()) {
00915             $this->getDocumentApi()->sendAcknowledgement($order);
00916         }
00917         return $this;
00918     }
00919 
00920 
00921 
00922 
00923 
00924 
00925 
00926     public function cancel($order)
00927     {
00928         $this->getDocumentApi()->cancel($order);
00929         return $this;
00930     }
00931 
00932 
00933 
00934 
00935 
00936 
00937 
00938 
00939     public function refund($payment, $amount)
00940     {
00941         $this->getDocumentApi()->refund($payment, $amount);
00942         return $this;
00943     }
00944 
00945 
00946 
00947 
00948 
00949 
00950 
00951     public function confirmShipment($shipment)
00952     {
00953         $items = array();
00954         foreach ($shipment->getAllItems() as $item) {
00955             
00956             if ($item->getOrderItem()->getParentItemId()) {
00957                 continue;
00958             }
00959             $items[] = array(
00960                 'id' => $item->getOrderItem()->getExtOrderItemId(),
00961                 'qty' => $item->getQty()
00962             );
00963         }
00964 
00965         $carrierName = '';
00966         $shippingMethod = '';
00967         $trackNumber = '';
00968 
00969 
00970 
00971 
00972         foreach ($shipment->getAllTracks() as $track) {
00973             $carrierName = $track->getTitle();
00974             $trackNumber = $track->getNumber();
00975             break;
00976         }
00977         if (preg_match("/\((.+)\)/", $shipment->getOrder()->getShippingDescription(), $_result)) {
00978             $shippingMethod = $_result[1];
00979         }
00980 
00981         $this->getDocumentApi()->confirmShipment(
00982             $shipment->getOrder()->getExtOrderId(),
00983             $carrierName,
00984             $shippingMethod,
00985             $items,
00986             $trackNumber
00987         );
00988         $shipment->addComment(
00989             Mage::helper('amazonpayments')->__('Shipment was created with Checkout by Amazon.')
00990         );
00991         return $this;
00992     }
00993 
00994 
00995 
00996 
00997 
00998 
00999 
01000 
01001     public function sendTrackingNumber($order, $track)
01002     {
01003 
01004         return $this;
01005     }
01006 
01007 }