修改WooCommerce REST API请求:将传入ID映射为SKU实现库存同步
WooCommerce REST API 按SKU匹配产品解决同步问题
问题背景
线下药店库存系统的产品ID为随机分配,线上WooCommerce使用独立的产品ID体系,双方ID不匹配且无法修改。计划将线上产品SKU设置为线下系统的产品ID,需要修改REST API逻辑:
- GET请求:用请求参数中的ID(线下产品ID)匹配线上SKU,返回对应产品数据
- PUT请求:用请求参数中的ID匹配线上SKU,更新对应产品库存/价格
当前请求直接返回404/400错误,因为请求中的ID不是线上产品ID,且无法修改客户端请求代码。之前尝试woocommerce_rest_pre_insert_product_object等钩子无效,因为请求在钩子触发前就被路由层拦截。
解决方案
核心思路是在REST API路由解析阶段,提前将请求中的ID(实际为SKU)替换为对应的线上产品ID,让WooCommerce默认的API流程能正常执行,无需修改后续逻辑。
实现代码
<?php add_action('rest_api_init', function() { // 拦截单个产品的GET和PUT请求 add_filter('rest_request_before_callbacks', 'replace_sku_with_product_id', 10, 3); }); function replace_sku_with_product_id($response, $handler, $request) { // 检查是否是产品的单个请求路由(GET /wp-json/wc/v3/products/{id} 或 PUT) $route = $request->get_route(); if (!preg_match('/^\/wc\/v\d+\/products\/(\d+)$/', $route, $matches)) { return $response; } $requested_id = $matches[1]; // 尝试通过SKU查找线上产品ID $product_id = wc_get_product_id_by_sku($requested_id); if (!$product_id) { // 没找到对应产品,返回404 return new WP_Error('rest_product_invalid', __('Invalid product ID/SKU.'), array('status' => 404)); } // 修改请求的路由参数,替换为实际产品ID $request->set_param('id', $product_id); // 同时修改请求的路由路径,确保后续逻辑正确识别 $new_route = preg_replace('/^(\/wc\/v\d+\/products\/)\d+$/', '$1' . $product_id, $route); $request->set_route($new_route); return $response; }
代码说明
- 钩子时机:使用
rest_request_before_callbacks钩子,这个钩子在路由匹配完成后、回调函数执行前触发,能在WooCommerce验证产品ID之前修改请求参数。 - 路由匹配:通过正则表达式判断是否是单个产品的GET/PUT请求,避免影响其他API接口。
- SKU转产品ID:用
wc_get_product_id_by_sku查找对应线上产品ID,找不到则返回404错误。 - 修改请求参数:替换请求中的
id参数和路由路径,让WooCommerce后续逻辑误以为请求的是真实产品ID,从而正常执行GET查询或PUT更新操作。
为什么之前的代码无效?
之前使用的woocommerce_rest_pre_insert_product_object钩子是在产品准备插入/更新时触发,但WooCommerce在进入这个钩子之前,会先验证请求中的ID是否对应存在的产品,所以当ID不存在时,直接返回404,钩子根本不会被触发。而rest_request_before_callbacks是更早的钩子,能在ID验证前修改参数。
内容的提问来源于stack exchange,提问作者MiddleMan
相关产品推荐
相关产品推荐

