Post by mkuttnig » Wed Dec 10, 2014 3:13 am


I have created a rather easy solution with

Based on suggestions listed in this post, I have created a GEO-Zone for New York State (USA--> NY)
Then I created a Tax Rate of 4% called "Sales Tax" (rate doesn't matter since it will be overridden) for that zone

In the tax.php I changed the getRates method like this:

Code: Select all

	public function getRates($value, $tax_class_id) {
		$tax_rate_data = array();

		/* NYS Sales tax specific code */
		$sales_tax_name = "Sales Tax";
		$postcode = 0; //Fallback value

		if (isset($_SESSION['shipping_address']))
			$shipping_address = $_SESSION['shipping_address'];
		if (isset($shipping_address )) {
			$postcode = @$shipping_address['postcode'];

		if (isset($this->tax_rates[$tax_class_id])) {
			foreach ($this->tax_rates[$tax_class_id] as $tax_rate) {
				$amount = 0;
				if ($tax_rate['name']==$sales_tax_name) {
					$amount += ($value / 100 * $this->getSalesTaxRateByPostCode($postcode));
				} else /* Do whatever opencart would do normally */
					if (isset($tax_rate_data[$tax_rate['tax_rate_id']])) {
						$amount = $tax_rate_data[$tax_rate['tax_rate_id']]['amount'];
					} else {
						$amount = 0;

					if ($tax_rate['type'] == 'F') {
						$amount += $tax_rate['rate'];
					} elseif ($tax_rate['type'] == 'P') {
						$amount += ($value / 100 * $tax_rate['rate']);

				$tax_rate_data[$tax_rate['tax_rate_id']] = array(
					'tax_rate_id' => $tax_rate['tax_rate_id'],
					'name'        => $tax_rate['name'],
					'rate'        => $tax_rate['rate'],
					'type'        => $tax_rate['type'],
					'amount'      => $amount

		return $tax_rate_data;

	public function getSalesTaxRateByPostCode($postcode) {
		$getnewtaxrate=$this->db->query("select zip_tax_rate from ziptax where zip_code = '$postcode'");
      	if (isset($newtaxrate)) return $newtaxrate;
      	else return 0;

getSalesTaxRateByPostCode() reads the rate from a database table based on the SQL script provided above.

I'm still in the testing process, but so far it looks good...

Let me know what you think, and if I'm missing something (other than the fact, that various zip codes are in multiple counties...



Wed Dec 10, 2014 3:06 am

Post by MrPhil » Thu May 11, 2017 11:49 pm

I am getting close to starting up a store using OC, and will need NYS zip->tax jurisdiction mapping. I need the TJ number anyway, for reporting purposes, and I will need several tax classes, so I will have the lookup routine return the TJ number, and look up the list of tax rates from that. Yes, it's true that NY warns against using ZIP Codes because they often overlap several TJs, but what else can I do? Don't forget that there are some 19 cities authorized to collect their own sales tax (in addition to 62 counties), and a number of ZIPs overlapping the state line in both directions. I see several zip->county and zip->city online references, including an official one from NYS Open Data. I figure that periodically I can download several lists and run a program to cross check them. All of these sources list only one city and county per ZIP, but we'll just have to live with that potential error condition. I have an older manually-maintained list with all the counties covered by a ZIP, but that's not terribly useful unless I want to allocate an arbitrary percentage of the sale to each county (TJ). I've considered picking the lowest total tax bill for multi-TJ ZIPs -- the losing counties won't be very happy, but what else can be done? I want to avoid complaints from customers that I'm charging too high of tax for them. With a fairly stagnant state population, I figure NY ZIPs won't change all that often.

Actually, I think the first step would be to take the given address and georeference it through Google Maps API to get the county and city, and then look up the TJ from that. So long as the volume is low, the service is free (or was, last time I checked). The problem is that people may misspell, misabbreviate, use an unofficial or obsolete name, or otherwise give an invalid address that Google can't find. I figure I can ask the customer once to check their address, and if they don't make a change (or it's still invalid), go to ZIP Code lookup. If it's an unknown ZIP, I'll tell them and charge the statewide average (say, 8.25%) and look it up manually later for the sales tax remit. I don't want to spend a lot of money on a service like Avalera, because my volumes will be far too low to justify that kind of expense. If NYS wants better tax compliance, they should make it easier to figure the TJ (e.g., a single statewide TJ for online and other remote sales, or base it on the seller's location).

Did you come up with something successful here, or use some extension?

User avatar
Active Member


Wed May 10, 2017 11:52 pm
Who is online

Users browsing this forum: No registered users and 10 guests