关于 woocommerce-rest-api
面向 WooCommerce 集成开发的技能指南,介绍如何通过 REST API 读写商品、订单、客户和库存,并使用 Node.js 客户端处理认证与请求。
主要功能
- 01访问商品、订单、客户和设置
- 02使用 Node.js 客户端认证
- 03筛选与分页查询商品
- 04创建订单并更新库存
- 05批量操作与增量同步建议
适用场景
- 01构建无头店铺或移动应用
- 02将 WooCommerce 接入 ERP、CRM 或履约系统
- 03同步仓库或 POS 库存
- 04批量导入商品或更新价格
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ finsilabs/ awesome-ecommerce-skills --skill woocommerce-rest-api安装后在 Claude Code 中输入/woocommerce-rest-api确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
tile.jsonevals/bulk-product-sync-with-concurrency-contr/criteria.jsontask.mdevals/order-creation-and-status-management-wit/criteria.jsontask.mdevals/paginated-product-catalog-with-increment/criteria.jsontask.md详细介绍
WooCommerce REST API
概述
WooCommerce 提供一个带版本号的 REST API(/wp-json/wc/v3/),可通过 HTTPS 访问产品、订单、客户、优惠券和商店设置。在非 HTTPS 环境中,它使用 OAuth 1.0a;在 HTTPS 环境中,则使用 Basic Auth(消费者密钥/密钥)。官方的 @woocommerce/woocommerce-rest-api Node.js 客户端会自动处理身份验证,并支持完整的 CRUD 操作。
何时使用此技能
- 构建无头店面,从 WooCommerce 读取产品和分类
- 将 WooCommerce 与 ERP、CRM 或履约系统集成
- 在 WordPress Admin 之外创建订单管理仪表板
- 在 WooCommerce 与仓库或 POS 系统之间同步库存
- 自动从外部目录批量导入产品或更新价格
- 构建需要访问 WooCommerce 商店数据的移动应用
核心说明
-
生成 API 凭据
在 WordPress Admin → WooCommerce → Settings → Advanced → REST API → Add Key 中:
- Description:
My Integration - User:(管理员用户)
- Permissions:Read/Write
这会生成一个 Consumer Key(
ck_xxx)和 Consumer Secret(cs_xxx)。请将它们存储在环境变量中,切勿写入源代码。WOOCOMMERCE_URL=https://mystore.com WOOCOMMERCE_CONSUMER_KEY=ck_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx WOOCOMMERCE_CONSUMER_SECRET=cs_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - Description:
-
设置 Node.js 客户端
npm install @woocommerce/woocommerce-rest-api// lib/woocommerce.ts import WooCommerceRestApi from "@woocommerce/woocommerce-rest-api"; export const woo = new WooCommerceRestApi({ url: process.env.WOOCOMMERCE_URL!, consumerKey: process.env.WOOCOMMERCE_CONSUMER_KEY!, consumerSecret: process.env.WOOCOMMERCE_CONSUMER_SECRET!, version: "wc/v3", axiosConfig: { timeout: 15000, }, }); -
使用筛选和分页查询产品
// lib/products.ts interface ProductQuery { page?: number; perPage?: number; category?: number; status?: "publish" | "draft" | "private"; stockStatus?: "instock" | "outofstock" | "onbackorder"; orderby?: "date" | "popularity" | "price" | "title"; } export async function getProducts(params: ProductQuery = {}) { const response = await woo.get("products", { page: params.page ?? 1, per_page: params.perPage ?? 20, status: params.status ?? "publish", stock_status: params.stockStatus, orderby: params.orderby ?? "date", category: params.category, }); return { products: response.data, totalPages: parseInt(response.headers["x-wp-totalpages"]), totalProducts: parseInt(response.headers["x-wp-total"]), }; } export async function getProductById(id: number) { const response = await woo.get(`products/${id}`); return response.data; } // Get product variations export async function getProductVariations(productId: number) { const response = await woo.get(`products/${productId}/variations`, { per_page: 100, }); return response.data; } -
创建和管理订单
// lib/orders.ts interface OrderLineItem { product_id: number; variation_id?: number; quantity: number; } interface CreateOrderParams { billing: { first_name: string; last_name: string; email: string; address_1: string; city: string; postcode: string; country: string; }; line_items: OrderLineItem[]; payment_method?: string; } export async function createOrder(params: CreateOrderParams) { const response = await woo.post("orders", { ...params, status: "pending", payment_method: params.payment_method ?? "stripe", payment_method_title: "Credit Card", set_paid: false, }); return response.data; } export async function updateOrderStatus( orderId: number, status: "pending" | "processing" | "on-hold" | "completed" | "cancelled" | "refunded", note?: string ) { const updateData: any = { status }; if (note) { // Add an order note await woo.post(`orders/${orderId}/notes`, { note }); } const response = await woo.put(`orders/${orderId}`, updateData); return response.data; } export async function getOrders(params: { status?: string; after?: string; // ISO 8601 date page?: number; } = {}) { const response = await woo.get("orders", { status: params.status ?? "processing", after: params.after, per_page: 50, page: params.page ?? 1, }); return { orders: response.data, totalPages: parseInt(response.headers["x-wp-totalpages"]), }; } -
管理库存和产品更新
// Update stock quantity for a product or variation export async function updateStock(productId: number, quantity: number, variationId?: number) { const endpoint = variationId ? `products/${productId}/variations/${variationId}` : `products/${productId}`; const response = await woo.put(endpoint, { stock_quantity: quantity, manage_stock: true, }); return response.data; } // Batch update products (up to 100 per request) export async function batchUpdateProducts( updates: Array<{ id: number; regular_price?: string; stock_quantity?: number; status?: string }> ) { const response = await woo.post("products/batch", { update: updates }); return response.data; }
示例
从外部目录完整同步产品
import pLimit from "p-limit";
export async function syncProductsFromCatalog(
externalProducts: Array<{ sku: string; price: number; stock: number }>
) {
const limit = pLimit(5); // Max 5 concurrent API calls
const results = await Promise.allSettled(
externalProducts.map((ext) =>
limit(async () => {
// Look up WooCommerce product by SKU
const searchResponse = await woo.get("products", { sku: ext.sku });
const existing = searchResponse.data[0];
if (existing) {
// Update existing product
return woo.put(`products/${existing.id}`, {
regular_price: ext.price.toFixed(2),
stock_quantity: ext.stock,
manage_stock: true,
});
} else {
console.warn(`SKU not found in WooCommerce: ${ext.sku}`);
return null;
}
})
)
);
const failed = results.filter((r) => r.status === "rejected");
if (failed.length > 0) {
console.error(`${failed.length} products failed to sync`);
}
return results;
}
客户管理
// Create or update customer
export async function upsertCustomer(email: string, data: Record<string, any>) {
const searchResponse = await woo.get("customers", { email });
const existing = searchResponse.data[0];
if (existing) {
const response = await woo.put(`customers/${existing.id}`, data);
return response.data;
} else {
const response = await woo.post("customers", { email, ...data });
return response.data;
}
}
// Get customer order history
export async function getCustomerOrders(customerId: number) {
const response = await woo.get("orders", {
customer: customerId,
per_page: 50,
orderby: "date",
order: "desc",
});
return response.data;
}
最佳实践
- 始终使用 HTTPS — OAuth 1.0a 可通过 HTTP 使用,但每次请求都会传输凭据;对于服务器间调用,HTTPS + Basic Auth 更简单、更安全
- 遵守速率限制 — WordPress 默认不会强制执行 API 速率限制,但大量请求可能导致 PHP-FPM 或 MySQL 资源耗尽;批量操作请使用
p-limit或队列 - 批量更新时使用批处理端点 —
/products/batch可在一个请求中接受最多 100 个创建/更新/删除操作,而不是发送 100 个独立请求 - 使用
_fields参数筛选字段 —?_fields=id,name,price,stock_quantity可大幅减少大型产品列表的响应负载 - 处理 WooCommerce 专属错误代码 — API 会在错误正文中返回
rest_invalid_param、woocommerce_rest_cannot_create等错误;请解析response.data.code,以进行针对性的错误处理 - 增量同步时使用
after和before日期筛选条件 — 使用 ISO 8601 时间戳筛选自上次同步以来修改的订单/产品,避免重新扫描整个目录 - 存储不带尾部斜杠的 API URL — WooCommerce 客户端会处理 URL 的构建;基础 URL 中的尾部斜杠会导致端点中出现双斜杠
常见问题
| 问题 | 解决方案 |
|---|---|
密钥正确但仍出现 401 Unauthorized | 确认站点使用 HTTPS;通过 HTTP 连接时,客户端必须使用 OAuth 1.0a,而不是 Basic Auth — 在客户端配置中设置 isHttps: false |
| 产品端点返回空数组 | 检查分配给 API 密钥的用户是否具有正确的权限;必须具备默认的 woocommerce_manage_products 权限 |
| 创建订单时出现产品 ID 错误 | 可变产品的 line_items 中必须包含 variation_id;对可变产品仅传入 product_id 会导致 invalid_variation 错误 |
| 缺少分页标头 | x-wp-total 和 x-wp-totalpages 标头仅存在于列表端点,不存在于单个资源端点 |
| 批处理操作部分失败 | 批处理响应会为每个项目返回单独的错误;请遍历 response.data.update 数组,并检查每个项目是否具有 error 属性 |
| 产品列表响应缓慢 | 添加 ?_fields=id,name,price 以减少负载;同时考虑在 WordPress 服务器上启用持久对象缓存(Redis) |
Related Skills
- @woocommerce-plugin-development
- @woocommerce-subscriptions
- @woocommerce-performance
- @headless-commerce-architecture
- @rest-api-design
评论
支持 Markdown