You can calculate tax using Avalara and add your own tax engines using either API Extensions or tax calculator capability. If a user needs a service other than Avalara then the following approaches help to integrate your own tax calculator.
Approach 1: Using estimateTaxes API Extension
This approach is used after creating a new API extension application.
The following steps set a tax response using the estimateTaxes API Extension:
- Create a new API Extension Application. Refer to the API Extension document.
- Use the API Extension function.
- The Estimate Taxes (Before) file is shown in the following code block:
module.exports = function(context, callback) { var responseBody = { "itemTaxContexts" : [], "shippingTax" : 0.00, "handlingFeeTax" : 0.00, "orderTax" : 0.00, "taxData": { "taxPercent": 0.00 } }; needle.get('https://example.com/taxService', (res) => { var taxResponse = JSON.parse(data); responseBody.orderTax = taxResponse.data.taxAmount responseBody.taxData = { "taxPercent": taxResponse.data.taxPercentage }; var lineItem = taxOrderInfo.lineItems[0]; // assume there is at least 1 item in the order responseBody.itemTaxContexts.push({ "id" : lineItem.id, "productCode" : lineItem.productCode, "quantity" : lineItem.quantity, "tax" : taxResponse.data.taxAmount, "shippingTax" : 0.0, "feeTotal": taxOrderInfo.handlingFee }); context.response.body = responseBody; context.response.end(); callback(); }); };
The sum of the item.itemTaxContexts elements must equal to orderTax in all the examples given below. This is a requirement for any tax integration in KCCP to be able to correctly calculate the prorated taxes when items are split across shipments.
Approach 2: Using Tax Calculator Capability
This approach helps you to add tax calculator capability through the Kibo commerce application.
The following steps add a tax calculator capability:
- In Dev Center, navigate to Develop > Applications > Packages > Capabilities.
- Click Add Capability.
- Search for Tax Calculator in the Add Capability modal and click Ok.
- Enter the external URL that receives the tax request and responds with the tax response. It will post to the URL directly and does not add any path.
- Select the country you want to enable it for. Press the “Enabled” toggle to enable the calculator. It might take a minute to start working.
Rest API Responses
This is what your endpoint will receive:
{ "OrderDate": "0001-01-01T00:00:00Z", "TaxContext": { "TaxContextId": "13", "CustomerId": "", "TaxExemptId": null, "TaxShipping": true, "OriginAddress": { "Address1": "1835 Kramer Lane", "Address2": "#100", "Address3": null, "Address4": null, "CityOrTown": "Austin", "StateOrProvince": "TX", "PostalOrZipCode": "78758", "CountryCode": "US", "AddressType": null, "IsValidated": false }, "DestinationAddress": { "Address1": "1234 Fake St", "Address2": "", "Address3": null, "Address4": null, "CityOrTown": "Houston", "StateOrProvince": "TX", "PostalOrZipCode": "12345", "CountryCode": "US", "AddressType": "Residential", "IsValidated": null } }, "LineItems": [ { "Id": "dbc98455f06d47359d47ae230119e28f", "ProductCode": "blz-1001", "VariantProductCode": null, "ProductName": "Wool Blazer", "ProductProperties": [ { "AttributeFQN": "tenant~availability", "Values": [ { "Value": "24-48hrs", "StringValue": "Usually Ships in 24 to 48 Hours" } ], "AttributeDetail": { "InputType": null, "ValueType": null, "DataType": null, "Name": "Availability", "Description": null }, "IsHidden": null, "IsMultiValue": false } ], "Quantity": 1, "LineItemPrice": 199.0, "DiscountTotal": 0.0, "DiscountedTotal": 199.0, "ShippingAmount": 0.0, "HandlingAmount": null, "FeeTotal": 0.0, "IsTaxable": true, "Reason": null, "Data": null, "ProductDiscount": null, "ShippingDiscount": null, "ProductDiscounts": [], "ShippingDiscounts": [], "OriginAddress": null, "DestinationAddress": null } ], "ShippingAmount": 0.0, "CurrencyCode": "USD", "HandlingFee": 0.0, "OriginalDocumentCode": "13", "OrderId": "12e9f48b2405bf00012c953200007729", "OrderNumber": 13, "OriginalOrderDate": "2022-01-20T17:06:35.0750575Z", "TaxRequestType": "Order", "Attributes": [], "ShippingDiscounts": null, "ShippingDiscount": null, "OrderDiscounts": null, "OrderDiscount": null, "HandlingDiscounts": null, "HandlingDiscount": null, "ShippingMethodCode": null, "ShippingMethodName": null }
Example: OrderTaxContext Response
This is what your endpoint should respond with:
{ "ItemTaxContexts": [ { "Id": "dbc98455f06d47359d47ae230119e28f", "ProductCode": "blz-1001", "Quantity": 1, "Tax": 1.0, "ShippingTax": 1.0, "TaxData": { } } ], "ShippingTax": 1.0, "HandlingFeeTax": 3.0, "OrderTax": 1.0 }
Example: Application
This just sends back dummy data for the specific order above, but it does work.
from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/', methods=['GET', 'POST']) def hello_world(): print(request.get_data(as_text=True)) return jsonify({ "ItemTaxContexts": [ { "Id": "dbc98455f06d47359d47ae230119e28f", "ProductCode": "blz-1001", "Quantity": 1, "Tax": 1.0, "ShippingTax": 1.0, "TaxData": { } } ], "ShippingTax": 1.0, "HandlingFeeTax": 3.0, "OrderTax": 1.0 }) app.run(host='0.0.0.0', port=8000)
And then in your terminal:
# In one terminal tab python3 app.py # In another terminal tab ngrok http 8000
Use the URL that ngrok gives you as your application URL.