function test_returns_false_if_not_shipping_to_nexus_area() { update_option('woocommerce_default_country', 'US:CO'); $tj = new WC_Taxjar_Integration(); $tj_nexus = new WC_Taxjar_Nexus($tj); $this->assertFalse($tj_nexus->has_nexus_check('US', 'XO')); }
/** * TaxJar API call * * @return void */ public function taxjar_api_call($options = array()) { global $woocommerce; $this->_log(':::: TaxJar Plugin requested ::::'); // Process $options array and turn them into varibables $options = is_array($options) ? $options : array(); extract(array_replace_recursive(array('to_country' => null, 'to_state' => null, 'to_zip' => null, 'to_city' => null, 'amount' => null, 'shipping_amount' => null), $options)); // Initalize some variables & properties $store_settings = $this->get_store_settings(); $customer = $woocommerce->customer; $this->tax_rate = 0; $this->amount_to_collect = 0; $this->item_collectable = 0; $this->shipping_collectable = 0; $this->freight_taxable = 1; $this->has_nexus = 0; $this->tax_source = 'origin'; $this->rate_id = null; // Strict conditions to be met before API call can be conducted if (empty($to_country) || empty($to_zip) || $customer->is_vat_exempt()) { return false; } $taxjar_nexus = new WC_Taxjar_Nexus($this); if (!$taxjar_nexus->has_nexus_check($to_country, $to_state)) { $this->_log(':::: Order not shipping to nexus area ::::'); return false; } // Setup Vars for API call $to_zip = explode(',', $to_zip); $to_zip = array_shift($to_zip); $from_country = $store_settings['store_country_setting']; $from_state = $store_settings['store_state_setting']; $from_zip = $store_settings['taxjar_zip_code_setting']; $from_city = $store_settings['taxjar_city_setting']; $shipping_amount = is_null($shipping_amount) ? 0.0 : $shipping_amount; $this->_log(':::: TaxJar API called ::::'); $url = $this->uri . 'taxes'; $body_string = sprintf('plugin=woo&to_state=%s&from_state=%s&amount=%s&shipping=%s&from_city=%s&from_zip=%s&to_city=%s&to_zip=%s&from_country=%s&to_country=%s&line_items[][quantity]=1&line_items[][unit_price]=%s', $to_state, $from_state, $amount, $shipping_amount, $from_city, $from_zip, $to_city, $to_zip, $from_country, $to_country, $amount); // Build the URL and Transient key $url = str_replace(' ', '%20', $url); $cache_key = hash('md5', $url . '/' . $body_string); // To check to see if we hit the API or not $taxjar_response = false; // Make sure we don't have a cached rate if (false === ($cache_value = wp_cache_get($cache_key, 'taxjar'))) { // Log this request $this->_log("Requesting: " . $url); // Make API call with API token in header $response = wp_remote_post($url, array('headers' => array('Authorization' => 'Token token="' . $this->settings['api_token'] . '"', 'Content-Type' => 'application/x-www-form-urlencoded'), 'user-agent' => $this->ua, 'body' => $body_string)); // Fail loudly if we get an error from wp_remote_post if (is_wp_error($response)) { new WP_Error('request', __("There was an error retrieving the tax rates. Please check your server configuration.")); } else { if (200 == $response['response']['code']) { // Log the response $this->_log("Received: " . $response['body']); // Decode Response $taxjar_response = json_decode($response['body']); $taxjar_response = $taxjar_response->tax; // Update Properties based on Response $this->has_nexus = (int) $taxjar_response->has_nexus; $this->tax_source = empty($taxjar_response->tax_source) ? 'origin' : $taxjar_response->tax_source; $this->amount_to_collect = $taxjar_response->amount_to_collect; if (!empty($taxjar_response->breakdown)) { if (!empty($taxjar_response->breakdown->shipping)) { $this->shipping_collectable = $taxjar_response->breakdown->shipping->tax_collectable; } } $this->item_collectable = $this->amount_to_collect - $this->shipping_collectable; $this->tax_rate = $taxjar_response->rate; $this->freight_taxable = (int) $taxjar_response->freight_taxable; // Create cache value $cache_value = $this->amount_to_collect . '::' . $this->tax_rate . '::' . $this->freight_taxable . '::' . $this->has_nexus . '::' . $this->tax_source . '::' . $this->item_collectable . '::' . $this->shipping_collectable; // Log the new cached value $this->_log("Cache Value: " . $cache_value); // Set Cache wp_cache_set($cache_key, $cache_value, 'taxjar', $this->cache_time); } else { // Log Response Error $this->_log("Received (" . $response['response']['code'] . "): " . $response['body']); } } } else { // Read the cached value based on our delimiter $cache_value = explode('::', $cache_value); // Set properties to the cached values $this->amount_to_collect = $cache_value[0]; $this->tax_rate = $cache_value[1]; $this->freight_taxable = $cache_value[2]; $this->has_nexus = $cache_value[3]; $this->tax_source = $cache_value[4]; $this->item_collectable = $cache_value[5]; $this->shipping_collectable = $cache_value[6]; // Log Cached Response $this->_log("Cached Amount: " . $this->amount_to_collect); $this->_log("Cached Nexus: " . $this->has_nexus); $this->_log("Cached Source: " . $this->tax_source); $this->_log("Cached Rate: " . $this->tax_rate); $this->_log("Shipping Taxable? " . $this->freight_taxable); $this->_log("Item Tax to Collect: " . $this->item_collectable); $this->_log("Shipping Tax to Collect: " . $this->shipping_collectable); } // Remove taxes if they are set somehow and customer is exempt if ($customer->is_vat_exempt()) { $wc_cart_object->remove_taxes(); } elseif ($this->has_nexus) { //} else { // Use Woo core to find matching rates for taxable address $source_zip = $this->tax_source == 'destination' ? $to_zip : $from_zip; $source_city = $this->tax_source == 'destination' ? $to_city : $from_city; if (strtoupper($to_city) == strtoupper($from_city)) { $source_city = $to_city; } // Setup Tax Rates $tax_rates = array("tax_rate_country" => $to_country, "tax_rate_state" => $to_state, "tax_rate_name" => sprintf("%s Tax", $to_state), "tax_rate_priority" => 1, "tax_rate_compound" => false, "tax_rate_shipping" => $this->freight_taxable, "tax_rate" => $this->tax_rate * 100, "tax_rate_class" => ''); // Clear the cached rates $this->clear_wc_tax_cache($to_country, $to_state, $source_city, $source_zip); $this->_log($source_city); $wc_rates = WC_Tax::find_rates(array('country' => $to_country, 'state' => $to_state, 'postcode' => $source_zip, 'city' => $source_city, 'tax_class' => '')); // If we have rates, use those, but if no rates returned create one to link with, or use the first rate returned. if (!empty($wc_rates)) { $this->_log('::: TAX RATES FOUND :::'); $this->_log($wc_rates); // Get the existing ID $rate_id = key($wc_rates); // Update Tax Rates with TaxJar rates ( rates might be coming from a cached taxjar rate ) $this->_log(':: UPDATING TAX RATES TO ::'); $this->_log($tax_rates); WC_TAX::_update_tax_rate($rate_id, $tax_rates); } else { // Insert a rate if we did not find one $this->_log(':: Adding New Tax Rate ::'); $rate_id = WC_Tax::_insert_tax_rate($tax_rates); WC_Tax::_update_tax_rate_postcodes($rate_id, wc_clean($source_zip)); WC_Tax::_update_tax_rate_cities($rate_id, wc_clean($source_city)); } $this->_log('Tax Rate ID Set: ' . $rate_id); $this->rate_id = $rate_id; } }