Orders: Calculate and Apply Tax Rates to REST API Orders
WooCommerce Tax Rates calculate and apply without any need to extend the code, but if you use a Tax plugin to modify WooCommerce Tax Rates and it does not yet support WooCommerce Orders created via the REST API, you may need a solution similar to these. Below we provide two examples (one for TaxJar and one for Avalara AvaTax) to help solve for this issue.
Important: Always test customizations to your site on a staging environment before making changes to your live / production site. If you are not experienced with testing changes on a staging site, here is a good article to review.
TaxJar
/** * Hook into the Order Save and Taxjar to calculate totals. * @param bool $and_taxes True if Taxes should be calculated. * @param WC_Abstract_Order $order The current order. */ function xx_taxjar_extension( $and_taxes, $order ){ if ( !( $order instanceof WC_Order ) || ( 'rest-api' != $order->get_created_via() ) ) return; if ( !class_exists('WC_Taxjar_Integration') ) return; $taxjar = new WC_Taxjar_Integration; $address = $taxjar->get_address_from_order( $order ); $line_items = array(); $taxjar->backend_tax_classes = array(); $order_items = $order->get_items(); foreach ( $order_items as $item_key => $item ) { if ( is_object( $item ) ) { // Woo 3.0+ $id = $item->get_product_id(); $quantity = $item->get_quantity(); $unit_price = wc_format_decimal( $item->get_subtotal() / $quantity ); $discount = wc_format_decimal( $item->get_subtotal() - $item->get_total() ); $tax_class_name = $item->get_tax_class(); $tax_status = $item->get_tax_status(); } else { // Woo 2.6 $id = $item['product_id']; $quantity = $item['qty']; $unit_price = wc_format_decimal( $item['line_subtotal'] / $quantity ); $discount = wc_format_decimal( $item['line_subtotal'] - $item['line_total'] ); $tax_class_name = $item['tax_class']; $product = $order->get_product_from_item( $item ); $tax_status = $product ? $product->get_tax_status() : 'taxable'; } $taxjar->backend_tax_classes[$id] = $tax_class_name; $tax_class = explode( '-', $tax_class_name ); $tax_code = ''; if ( isset( $tax_class ) && is_numeric( end( $tax_class ) ) ) { $tax_code = end( $tax_class ); } if ( 'taxable' !== $tax_status ) { $tax_code = '99999'; } if ( $unit_price ) { array_push($line_items, array( 'id' => $id . '-' . $item_key, 'quantity' => $quantity, 'product_tax_code' => $tax_code, 'unit_price' => $unit_price, 'discount' => $discount, )); } } if ( method_exists( $order, 'get_shipping_total' ) ) { $shipping = $order->get_shipping_total(); // Woo 3.0+ } else { $shipping = $order->get_total_shipping(); // Woo 2.6 } $taxes = $taxjar->calculate_tax( array( 'to_country' => $address[ 'to_country' ], 'to_state' => $address[ 'to_state' ], 'to_zip' => $address[ 'to_zip' ], 'to_city' => $address[ 'to_city' ], 'to_street' => $address[ 'to_street' ], 'shipping_amount' => $shipping, 'line_items' => $line_items, ) ); foreach ( $order_items as $item_key => $item ) { $product_id = $item->get_product_id(); $line_item_key = $product_id . '-' . $item_key; $item_taxes = $item->get_taxes(); $taxes_charged = 0; if( sizeof($item_taxes) > 0 ){ if( sizeof($item_taxes["total"]) > 0 ){ foreach( $item_taxes["total"] AS $tax_total ){ $taxes_charged = (float)$tax_total; } } } if( $taxes_charged == 0 ){ if ( isset( $taxes['rate_ids'][ $line_item_key ] ) ) { $rate_id = $taxes['rate_ids'][ $line_item_key ]; $item_tax = new WC_Order_Item_Tax(); $item_tax->set_rate( $rate_id ); $item_tax->set_order_id( $order->get_id() ); $item_tax->save(); } } } } add_action( 'woocommerce_order_before_calculate_totals', 'xx_taxjar_extension', 10, 2 );
Avalara AvaTax
/** * Hook into the Order Save and calculate Avatax totals. * @param bool $and_taxes True if Taxes should be calculated. * @param WC_Abstract_Order $order The current order. */ function xx_avatax_calc_tax( $and_taxes, $wc_order ){ if ( !( $wc_order instanceof WC_Order ) || ( 'rest-api' !== $wc_order->get_created_via() ) ) return; if ( !function_exists( 'wc_avatax' ) ) return; if( !$and_taxes ) return; wc_avatax()->get_order_handler()->calculate_order_tax( $wc_order ); } add_action( 'woocommerce_order_before_calculate_totals', 'xx_avatax_calc_tax', 10, 2 );