一般做进出口公司都会涉及到税收问题,最近公司在做出口电商时就需要计算税费,这里记录分享下,税收采用的是第三方TaxJar提供的服务。
TaxJar官网:https://www.taxjar.com/
TaxJar开发者网站:https://developers.taxjar.com/api/reference/
TaxJar GitHub网站:https://github.com/taxjar/taxjar-java
TaxJar测试Sanbox环境license key获取网站:https://sandbox.account.avalara.com/#/a/2000273400
1.准备环境
想要对接taxjar首先需要登录它的开发者网站申请一个开发者账号,这个账号是通用的即测试环境(后面简称"sanbox"环境)和正式环境(后面简称"live"环境)都可以登录。然后我们登录上面那个sanbox环境获取license key的网站获取taxjar sanbox环境的apiToken。
点进去后再点击Generate即可得到,是一串数字加字母的字符。
2.开发对接
开发环境是java的spring boot环境,首先把刚刚获取到的apiToken放到配置文件里
taxjar获取税率有多种方式,我知道的有根据收货地详细信息获取,还有一种是跟收货详细地址 + 商品来获取税率,我采用的是第二种。
新建一个TaxUtil类
package com.sunvalley.shop.order.util;
import com.sunvalley.shop.common.util.json.JacksonUtil;
import com.sunvalley.shop.order.constants.Constants;
import com.sunvalley.shop.order.modelEx.ShopOrderAddressEx;
import com.sunvalley.shop.order.modelEx.ShopOrderItemEx;
import com.taxjar.Taxjar;
import com.taxjar.exception.TaxjarException;
import com.taxjar.model.rates.RateResponse;
import com.taxjar.model.taxes.TaxResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 类或方法的功能描述 :税率计算
*
* @author: lockie.zou
* @date: 2018-03-30 15:59
*/
public class TaxUtil {
/**
* 税收token
*/
private static String apiToken = "";
@Value("${taxjar.apiToken}")
private String token;
@PostConstruct
public void getApiToken() {
apiToken = token;
}
/**
* 根据国家,城市,街道,邮编获取税率
* @param country
* @param city
* @param street
* @param zipCode
* @return
* @throws TaxjarException
*/
public static Float ratesForLocation(String country, String city, String street, String zipCode) throws TaxjarException {
Taxjar client = new Taxjar(apiToken);
Map params = new HashMap<>();
params.put("country", country);
params.put("city", city);
params.put("street", street);
RateResponse res = client.ratesForLocation(zipCode, params);
// 返回综合税
return res.rate.getCombinedRate();
}
/**
* 根据收货地址,商品获取税率
* @param address
* @param itemExList
* @return
*/
public static TaxResponse taxForOrder(ShopOrderAddressEx address, List itemExList) throws TaxjarException {
Taxjar client = new Taxjar(apiToken);
if (null == address || null == itemExList) {
return null;
}
BigDecimal orderTotal = BigDecimal.ZERO;
// 发货地址信息
Map params = new HashMap<>();
params.put("from_country", "US");
params.put("from_zip", "94538");
params.put("from_state", "CA");
params.put("from_city", "Fremont");
params.put("from_street", "46724 Lakeview Blvd");
// 收货地址信息
params.put("to_country", address.getCountry());
params.put("to_state", address.getRegion());
params.put("to_city", address.getCity());
params.put("to_street", address.getAddress1());
params.put("to_zip", address.getPostcode());
params.put("shipping", 0);
// 2018-8-16 lockie 联系地址传用户的收货地址
List
注意事项:
正常情况下只要输入订单的收货地址ShopOrderAddressEx和商品集合List
在使用了优惠时计算税费的时候就要注意了,商品单价和数量还是正常传,只是传discount折扣字段需要注意了。假如我们下了一个订单买了三个商品分别是A商品1个单价9.99,B商品2个单价19.99,C商品3个单价28.79,这个已经够复杂了覆盖了大多数场景,假如用户使用一个20%的优惠,即打个8折,这个时候discount的值就是
商品 | discount |
A | 9.99 * 1 * 0.2 |
B | 19.99 * 2 * 0.2 |
C | 28.79 * 3 *0.2 |
所以discount字段的意思是单个商品的优惠金额
正常情况下位使用优惠接口返回值:
如果使用了优惠码,打了8折后的税收返回值: