You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用WooCommerce API获取Node.js产品数据返回重复项求助

WooCommerce API分页返回重复产品的解决思路

1. 修复URL参数的转义错误

你的代码中请求URL错误使用了HTML实体&分隔参数,这会导致WooCommerce API无法正确解析page参数,实际每次请求都在拉取第一页数据,这是重复产品的核心诱因。

将代码中的URL模板字符串里的&替换为&:

const result = await WooCommerce.getAsync(`products?per_page=100&page=${page}&orderby=id&order=asc`);

2. 用ID范围分页替代页码分页

页码分页在产品数据动态变化(比如同步时产品被修改、新增)时极易出现重复或遗漏,改用ID范围查询可彻底规避这个问题:

async function fetchAllProducts() {
    let lastId = 0;
    let allProducts = [];
    let productSKUs = new Set();
    let productIDs = new Set();

    while (true) {
        try {
            // 筛选ID大于lastId的产品,确保每次拉取未获取过的数据
            const result = await WooCommerce.getAsync(`products?per_page=100&orderby=id&order=asc&after=${lastId}`);
            await delay(1500);
            const data = JSON.parse(result.toJSON().body);

            if (data.length === 0) {
                break;
            }

            console.log(`Fetched ${data.length} products starting from ID ${lastId + 1}`);
            let uniqueCount = 0;

            data.forEach(product => {
                if (!productIDs.has(product.id)) {
                    productIDs.add(product.id);
                    productSKUs.add(product.sku);
                    allProducts.push(product);
                    displayProductDetails(product);
                    uniqueCount++;
                    // 更新lastId为当前批次最大的产品ID
                    lastId = Math.max(lastId, product.id);
                } else {
                    console.log(`Duplicate found: ID = ${product.id}`);
                }
            });

            console.log(`Unique products added: ${uniqueCount}`);
            await delay(3000);
        } catch (error) {
            console.error('Error fetching products:', error);
            break;
        }
    }

    console.log('Fetched products count:', allProducts.length);
    console.log('Unique SKUs count:', productSKUs.size);
    console.log('Unique IDs count:', productIDs.size);

    return allProducts;
}

注:after参数在WooCommerce REST API v3中用于筛选ID大于指定值的产品,确保请求数据无重叠。

3. 验证分页元数据的正确性

每次请求后打印返回头中的x-wp-total(总产品数)和x-wp-totalpages(总页数),确认分页逻辑是否正常:

console.log(`Total pages: ${result.headers['x-wp-totalpages']}`);
console.log(`Current page: ${page}`);

如果总页数计算异常,需排查服务器端问题:

  • 是否有自定义woocommerce_rest_product_query钩子修改了产品查询条件?
  • 是否拉取了草稿、回收站状态的产品?可添加status=publish参数明确获取已发布产品:products?per_page=100&page=${page}&orderby=id&order=asc&status=publish

4. 排除客户端库的问题

尝试用axios等原生HTTP库发起请求,绕过woocommerce-api库,确认是否是库的参数处理或签名问题:

const axios = require('axios');
const crypto = require('crypto');

// 生成WooCommerce API所需的OAuth1.0认证头
function generateAuthHeader(url, method) {
    const params = {
        oauth_consumer_key: 'ck_1234',
        oauth_nonce: crypto.randomBytes(16).toString('hex'),
        oauth_signature_method: 'HMAC-SHA256',
        oauth_timestamp: Math.floor(Date.now() / 1000).toString(),
        oauth_version: '1.0'
    };

    const sortedParams = Object.keys(params).sort().map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`).join('&');
    const baseString = `${method.toUpperCase()}&${encodeURIComponent(url)}&${encodeURIComponent(sortedParams)}`;
    const signingKey = `${encodeURIComponent('cs_1234')}&`;
    const signature = crypto.createHmac('sha256', signingKey).update(baseString).digest('base64');

    params.oauth_signature = signature;
    return `OAuth ${Object.keys(params).map(key => `${key}="${encodeURIComponent(params[key])}"`).join(', ')}`;
}

async function fetchWithAxios(page) {
    const url = `https://my-website.com/wp-json/wc/v3/products?per_page=100&page=${page}&orderby=id&order=asc`;
    const headers = {
        'Authorization': generateAuthHeader(url, 'GET')
    };
    const response = await axios.get(url, { headers });
    return response.data;
}

如果用axios请求无重复,说明woocommerce-api库存在缺陷,可考虑更换库。

5. 排查服务器端缓存与性能问题

即便你已禁用缓存,仍需确认:

  • 服务器反向代理(如Nginx)是否缓存了API请求?可添加Cache-Control: no-cache头强制跳过缓存:
const result = await WooCommerce.getAsync(`products?per_page=100&page=${page}&orderby=id&order=asc`, {
    headers: { 'Cache-Control': 'no-cache' }
});
  • 服务器负载过高是否导致数据库分页查询返回错误结果?检查服务器CPU、内存使用率,以及数据库慢查询日志,确认分页查询是否正常执行。

内容的提问来源于stack exchange,提问作者newbie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 22:04:59