对接淘宝平台实现订单数据到本地数据库

发布于:2025-07-16 ⋅ 阅读:(17) ⋅ 点赞:(0)

项目背景

公司电商平台需要江订单数据下载到本地数据库,让后将对订单进行拆分转化为公司内部的产品组合。实现电商平台订单转移到公司内部平台进行处理。由于淘宝API依赖于网络,存在着网络不稳定和同步时间长的问题,所以应用必须把淘宝的订单数据同步到本地。如何才能 快速、完整的把订单同步到本地是本方案将要讨论的问题。

要点

同步订单:同步最近三个月的订单
增量同步:对于已经同步的订单,发生修改或者新增的订单就是增量订单

淘宝API

taobao.trades.sold.get
获取当前商家已经卖出的商品订单数据(最近三个月),返回的顺序是订单创建时间的倒序排列,包含了订单的部分数据,详细叙述需要taobao.trade.fullinfo.get获取订单详情
taobao.trades.sold.increment.get
查询卖家已卖出的增量交易数据(根据修改时间),一次请求只能查询时间跨度为一天的增量交易记录,即end_modified - start_modified <= 1天。 返回的数据结果是以订单的修改时间倒序排列的,通过从后往前翻页的方式可以避免漏单问题。返回的数据结果只包含了订单的部分数据,可通过taobao.trade.fullinfo.get获取订单详情。
taobao.trade.fullinfo.get
获取单笔交易的详细信息

解决方案

全量同步:同步最近三个月的订单数据
增量同步:同步时间段内修改的数据
初始化:通过taobao.trades.sold.get获取最近三个月的订单数据,再通过taobao.trade.fullinfo.get获取详细的订单数据,保存到本地
增量:通过定时轮询(10min)taobao.trades.sold.increment.get获取修改过的数据,再通过taobao.trade.fullinfo.get获取详细的订单数据保存到本地数据库

初步代码构建

1、创建配置类,配置APPKey和secert以及链接淘宝API的Client

import com.taobao.api.DefaultTaobaoClient;
import com.taobao.api.TaobaoClient;
 
public class TaobaoApiConfig {
    public static final String APP_KEY = "your_app_key";
    public static final String APP_SECRET = "your_app_secret";
 
    public static TaobaoClient getTaobaoClient() {
        return new DefaultTaobaoClient("https://eco.taobao.com/router/rest", APP_KEY, APP_SECRET);
    }
}

2、获取Token

@Component
public class TaobaoAuthService {
    public String getAccessToken(String code) throws ApiException {
        TaobaoClient client = new DefaultTaobaoClient(URL, APP_KEY, APP_SECRET);
        TopAuthTokenCreateRequest req = new TopAuthTokenCreateRequest();
        req.setCode(code);
        req.setGrantType("authorization_code");
        TopAuthTokenCreateResponse rsp = client.execute(req);
        return rsp.getToken().getAccessToken(); // 返回有效期为3小时的Token
    }
}

3、记录每次增量的时间

public String getLastTime(){

}

4、增量同步

@Service
public class OrderSyncService {
    @Autowired private RedisTemplate<String, String> redisTemplate;
    @Autowired private TaobaoClient taobaoClient;
    
    // 每10分钟执行增量同步
    @Scheduled(fixedDelay = 10 * 60 * 1000)
    public void syncIncrementalOrders() throws ApiException {
        String shopId = "SHOP_123";
        String sessionKey = getSessionKey(shopId); // 从DB获取店铺授权
        
        // 1. 获取时间窗口(防漏单关键)
        Date endModified = getTaobaoTime(); // 必须用淘宝服务器时间[1,2](@ref)
        Date startModified = getLastSyncTime(shopId); // 从Redis读取上次同步时间
        startModified = DateUtils.addMinutes(startModified, -5); // 时间前移5分钟,避免边界漏单[2](@ref)

        // 2. 构建增量请求(仅拉取订单ID提升性能)
        TradesSoldIncrementGetRequest req = new TradesSoldIncrementGetRequest();
        req.setStartModified(startModified);
        req.setEndModified(endModified);
        req.setUseHasNext(true); // 禁用COUNT(*)优化性能[1](@ref)
        req.setPageSize(100L);
        req.setFields("tid"); // 只获取订单ID
        
        // 3. 倒序分页处理(从最后一页向前翻)
        boolean hasNext = true;
        long pageNo = 1L;
        List<String> orderIds = new ArrayList<>();
        
        while (hasNext) {
            req.setPageNo(pageNo);
            TradesSoldIncrementGetResponse rsp = taobaoClient.execute(req, sessionKey);
            
            // 收集当前页订单ID
            orderIds.addAll(rsp.getTrades().stream()
                .map(Trade::getTid)
                .collect(Collectors.toList())
            );
            
            // 关键:计算下一页页码(倒序)
            long totalPages = rsp.getTotalPages();
            hasNext = rsp.getHasNext();
            pageNo = totalPages - pageNo + 1; // 例:总5页时,第1页→第5页,第5页→第1页[1](@ref)
        }
        
        // 4. 批量获取订单详情(减少API调用)
        batchFetchOrderDetails(orderIds, sessionKey);
        
        // 5. 更新检查点(Redis记录本次同步结束时间)
        redisTemplate.opsForValue().set("sync:taobao:" + shopId, endModified.toString());
    }
    
    // 批量获取订单详情(异步提升吞吐)
    @Async("orderTaskExecutor")
    public void batchFetchOrderDetails(List<String> orderIds, String sessionKey) {
        for (String tid : orderIds) {
            TradeFullinfoGetRequest detailReq = new TradeFullinfoGetRequest();
            detailReq.setTid(Long.parseLong(tid));
            TradeFullinfoGetResponse detailRsp = taobaoClient.execute(detailReq, sessionKey);
            saveOrderToDB(detailRsp.getTrade()); // 存储到数据库
        }
    }
    
    // 获取淘宝服务器时间(避免时差导致漏单)
    private Date getTaobaoTime() throws ApiException {
        TimeGetRequest req = new TimeGetRequest();
        TimeGetResponse rsp = taobaoClient.execute(req);
        return rsp.getTime();
    }
}

注意

1、使用全量同步时,一次性同步三个月的订单数据可能会出现超时,可以通过按天来同步或者按照小时段来同步。
2、使用增量同步时,是按照修改时间倒序返回数据,所以分页时必须从最后一页开始翻页,否则有可能出现丢单。这是因为如果从第一页开始翻页,则翻页过程中发生变更的订单就会减少订单总数,使翻页出现误差。
3、记录上次的同步时间,防止重复劳动。


网站公告

今日签到

点亮在社区的每一天
去签到