×

api开发 电商平台 数据挖掘

技术开发一步步教你接入 1688 商品 API:实现商品信息实时同步

admin admin 发表于2025-10-31 15:51:38 浏览23 评论0

抢沙发发表评论

在电商系统开发中,对接 1688 开放平台的商品 API 实现信息实时同步是常见需求。本文将详细介绍接入流程,并提供完整代码示例,帮助开发者快速实现商品数据的实时获取与同步功能。

一、准备工作:1688 接入前置条件

1. 注册与认证

  • 登录注册开发账号

  • 完成认证(个人开发者部分 API 权限受限)

  • 获取apiKeyapiSecret(应用密钥)

2. 了解 API 基础信息

  • 接口文档地址:

  • 核心接口:alibaba.product.get(获取商品详情)、alibaba.product.list(商品列表)

  • 调用方式:HTTP/HTTPS POST,支持 JSON 格式

  • 签名机制:基于 HMAC-SHA1 的签名算法

二、核心技术实现:签名生成与 API 调用

1. 签名生成工具类

1688 API 要求所有请求必须包含合法签名,以下是签名生成的 Java 实现:

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;

public class SignUtils {
    private static final String SIGN_METHOD = "HMAC-SHA1";
    private static final String FORMAT = "json";
    private static final String VERSION = "1.0";

    /**
     * 生成API请求参数(包含签名)
     */
    public static Map<String, String> generateParams(String appKey, String appSecret, 
                                                  String method, Map<String, String> bizParams) {
        Map<String, String> params = new TreeMap<>();
        
        // 系统参数
        params.put("app_key", appKey);
        params.put("method", method);
        params.put("format", FORMAT);
        params.put("v", VERSION);
        params.put("sign_method", SIGN_METHOD);
        params.put("timestamp", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        
        // 业务参数
        if (bizParams != null) {
            params.putAll(bizParams);
        }
        
        // 生成签名
        String sign = generateSign(params, appSecret);
        params.put("sign", sign);
        
        return params;
    }

    /**
     * 生成签名
     */
    private static String generateSign(Map<String, String> params, String appSecret) {
        try {
            // 1. 拼接待签名字符串
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, String> entry : params.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                if (key != null && value != null && !key.equals("sign")) {
                    sb.append(key).append("=").append(URLEncoder.encode(value, StandardCharsets.UTF_8.name()))
                      .append("&");
                }
            }
            String signSource = sb.substring(0, sb.length() - 1);
            
            // 2. HMAC-SHA1加密
            Mac mac = Mac.getInstance("HmacSHA1");
            SecretKeySpec keySpec = new SecretKeySpec(appSecret.getBytes(StandardCharsets.UTF_8), "HmacSHA1");
            mac.init(keySpec);
            byte[] signBytes = mac.doFinal(signSource.getBytes(StandardCharsets.UTF_8));
            
            // 3. Base64编码
            return Base64.getEncoder().encodeToString(signBytes);
        } catch (Exception e) {
            throw new RuntimeException("生成签名失败", e);
        }
    }
}

三、商品信息同步服务实现

1. 数据模型定义

定义商品实体类,映射 1688 返回的核心字段:

import lombok.Data;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

@Data
public class Product {
    private String productId;         // 商品ID
    private String title;             // 商品标题
    private String description;       // 商品描述
    private BigDecimal price;         // 价格
    private String currency;          // 货币单位
    private List<String> imageUrls;   // 商品图片
    private String categoryId;        // 类目ID
    private int stock;                // 库存
    private Date gmtCreate;           // 创建时间
    private Date gmtModified;         // 修改时间
}

2. 同步服务实现

实现商品信息的拉取与本地存储同步:

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;

@Service
public class ProductSyncService {
    private final Ali1688Client ali1688Client;
    private final ProductRepository productRepository;  // 本地数据库操作接口

    @Autowired
    public ProductSyncService(Ali1688Client ali1688Client, ProductRepository productRepository) {
        this.ali1688Client = ali1688Client;
        this.productRepository = productRepository;
    }

    /**
     * 同步单个商品信息
     */
    public Product syncSingleProduct(String productId) {
        JSONObject result = ali1688Client.getProductDetail(productId);
        
        // 验证API返回是否成功
        if (!"0".equals(result.getString("code"))) {
            throw new RuntimeException("获取商品信息失败: " + result.getString("msg"));
        }
        
        // 解析商品数据
        Product product = parseProduct(result.getJSONObject("data"));
        
        // 保存到本地数据库
        return productRepository.save(product);
    }

    /**
     * 批量同步商品列表
     */
    public int batchSyncProducts(int page, int pageSize) {
        JSONObject result = ali1688Client.getProductList(page, pageSize);
        
        if (!"0".equals(result.getString("code"))) {
            throw new RuntimeException("获取商品列表失败: " + result.getString("msg"));
        }
        
        // 解析商品列表
        JSONArray productArray = result.getJSONObject("data").getJSONArray("products");
        List<Product> products = new ArrayList<>();
        for (int i = 0; i < productArray.size(); i++) {
            products.add(parseProduct(productArray.getJSONObject(i)));
        }
        
        // 批量保存
        productRepository.saveAll(products);
        return products.size();
    }

    /**
     * 解析API返回的商品数据
     */
    private Product parseProduct(JSONObject productJson) {
        Product product = new Product();
        product.setProductId(productJson.getString("productId"));
        product.setTitle(productJson.getString("title"));
        product.setDescription(productJson.getString("description"));
        product.setPrice(productJson.getBigDecimal("price"));
        product.setCurrency(productJson.getString("currency"));
        product.setImageUrls(productJson.getJSONArray("imageUrls").toJavaList(String.class));
        product.setCategoryId(productJson.getString("categoryId"));
        product.setStock(productJson.getIntValue("stock"));
        // 更多字段映射...
        return product;
    }
}

四、定时同步与异常处理

1. 定时任务配置

使用 Spring Scheduler 实现定时同步:

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ProductSyncTask {
    private final ProductSyncService syncService;

    public ProductSyncTask(ProductSyncService syncService) {
        this.syncService = syncService;
    }

    /**
     * 每小时同步一次商品数据
     */
    @Scheduled(cron = "0 0 * * * ?")
    public void scheduledSyncProducts() {
        // 分页同步所有商品
        int page = 1;
        int pageSize = 50;
        while (true) {
            int syncCount = syncService.batchSyncProducts(page, pageSize);
            if (syncCount < pageSize) {
                break;  // 没有更多数据
            }
            page++;
        }
    }
}

2. 异常处理与重试机制

import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;

@Component
public class RetryableProductSync {
    private final ProductSyncService syncService;

    public RetryableProductSync(ProductSyncService syncService) {
        this.syncService = syncService;
    }

    /**
     * 带重试机制的商品同步
     */
    @Retryable(
        value = {Exception.class},
        maxAttempts = 3,
        backoff = @Backoff(delay = 1000, multiplier = 2)
    )
    public void syncWithRetry(String productId) {
        syncService.syncSingleProduct(productId);
    }
}

五、接入注意事项

  1. 接口权限:部分高级接口需要单独申请权限,需在开放平台完成权限开通

  2. 调用频率限制:1688 API 有严格的限流策略,需合理控制调用频率(默认 100 次 / 分钟)

  3. 数据缓存:建议对商品数据进行本地缓存,减少 API 调用次数

  4. 签名有效期:timestamp 参数需使用当前时间,且请求需在 15 分钟内发送

  5. 错误处理:针对不同错误码(如 401、429)进行专门处理,实现优雅降级

通过以上步骤,即可完成 1688 商品 API 的接入与商品信息实时同步功能。实际开发中可根据业务需求扩展字段映射和同步策略,建议结合消息队列实现异步处理,提升系统稳定性和响应速度。


少长咸集

群贤毕至

访客