getClient()->setOptions($options); return $this; } /** * @param \Qs\Service\TaxCloud\Client $client * @return $this */ public function setClient(TaxCloudClient $client) { $this->client = $client; return $this; } /** * @return \Qs\Service\TaxCloud\Client */ public function getClient() { if (null === $this->client) { $this->client = new TaxCloudClient(); } return $this->client; } /** * @param array $request * @return bool|\Qs\Service\TaxCloud\Response\LookupRsp */ public function lookup(array $request) { $this->clearErrors(); try { return $this->getClient()->lookup($request); } catch (Exception $e) { $this->addError($e->getMessage()); return false; } } public function updateCartTaxes($cartId, array $destinationAddress) { if (false === ($cart = $this->getTable('Cart')->search($cartId))) { throw new Exception('Can\'t find cart'); } $transaction = null; if (empty($destinationAddress)) { throw new Exception('Destination address is undefined'); } if ($destinationAddress['state'] != Settings::get('taxCloudState')) { $this->clearCartTaxes($cart['id']); return true; } $destinationAddressHash = $this->calculateDestinationAddressHash($destinationAddress); if ('n' == $cart['taxExpired'] && $cart['destinationAddressHash'] == $destinationAddressHash) { return true; } $items = $this->getTaxableCartItems($cart['id']); if (empty($items)) { $taxExpired = 'n'; $this->getTable('Cart')->updateByKey(compact('taxExpired', 'destinationAddressHash'), $cart['id']); return !$this->hasErrors(); } $request = [ 'customerId' => (int) $cart['userId'], 'cartId' => $cart['id'], 'cartItems' => $items, 'origin' => [ 'address' => Settings::get('taxCloudAddress'), 'address2' => Settings::get('taxCloudAddress2'), 'city' => Settings::get('taxCloudCity'), 'state' => Settings::get('taxCloudState'), 'zip' => Settings::get('taxCloudZip'), ], 'destination' => [ 'address' => $destinationAddress['address'], 'address2' => $destinationAddress['address2'], 'city' => $destinationAddress['city'], 'state' => $destinationAddress['state'], 'zip' => $destinationAddress['zip'], ], 'deliveredBySeller' => true, ]; if (false === ($result = $this->lookup($request))) { $this->getTable('CartItem')->update( ['rowTax' => 0], '`cartId` = ' . Qs_Db::getInstance()->quote($cart['id']) ); $this->getTable('Cart')->updateByKey(['taxExpired' => 'y', 'destinationAddressHash' => null], $cart['id']); } else { /** @var CartItemResponse $cartItem */ foreach ($result->getCartItems() as $cartItem) { $this->getTable('CartItem')->updateByKey( ['rowTax' => $cartItem->getTaxAmount()], $cartItem->getCartItemIndex() ); } $taxExpired = 'n'; $this->getTable('Cart')->updateByKey(compact('taxExpired', 'destinationAddressHash'), $cart['id']); } return $this->hasErrors(); } protected function clearCartTaxes($cartId) { $this->getTable('CartItem')->updateByKey(['rowTax' => 0], $cartId); $this->getTable('Cart')->updateByKey(['taxExpired' => 'n', 'destinationAddressHash' => null], $cartId); return $this; } protected function getTaxableCartItems($cartId) { $items = []; /** @var \Zend_Db_Table_Row $row */ foreach ($this->getTable('CartItem')->fetchAll('`cartId` = ' . Qs_Db::getInstance()->quote($cartId)) as $row) { if ('n' == $row->applyTax) { continue; } $items[] = Qs_Array::map($row->toArray(), ['index' => 'id', 'itemId' => 'title', 'price', 'quantity', 'tic']); } return $items; } /** * @param $alias * @return Qs_Db_Table */ protected function getTable($alias) { static $tables; if (empty($tables[$alias])) { $tables[$alias] = new Qs_Db_Table($alias); } return $tables[$alias]; } public function calculateDestinationAddressHash(array $address) { $address = Qs_Array::map($address, ['address', 'address2', 'city', 'state', 'zip']); return md5(serialize($address)); } public function authorizeWithCapture(array $transaction) { $request = [ 'customerId' => (int)$transaction['userId'], 'cartId' => $transaction['cartId'], 'orderId' => $transaction['id'], 'dateAuthorized' => $transaction['added'], 'dateCaptured' => $transaction['added'], ]; $this->clearErrors(); try { $this->getClient()->authorizeWithCapture($request); return true; } catch (Exception $e) { $this->addError($e->getMessage()); return false; } } public function returnOrder($orderId) { $request = [ 'orderId' => $orderId, 'returnedDate' => date('Y-m-d H:i:s') ]; $this->clearErrors(); try { $this->getClient()->returned($request); return true; } catch (Exception $e) { if ($this->isAlreadyReturned($e->getMessage())) { return true; } $this->addError($e->getMessage()); return false; } } protected function isAlreadyReturned($error) { return false !== strpos($error, 'Cannot return the entire order because some items have already been returned'); } protected function clearErrors() { $this->errors = []; return $this; } protected function addError($error) { $this->errors[] = $error; return $this; } public function getErrors() { return $this->errors; } public function hasErrors() { return !empty($this->errors); } }