在Ky中实现OAuth 1.0结合React Query时数据始终为undefined的问题排查
从你的描述来看,Postman能正常拿到数据、WooCommerce返回200状态码和产品数组,但React Query里数据始终是undefined,说明问题大概率出在客户端的响应解析、Schema校验或者错误处理环节,而非OAuth签名逻辑本身(毕竟签名成功才会得到200和数据)。咱们一步步来排查:
1. 先排查Schema解析的问题(最可能的原因)
你的fetchAll方法直接用productSchema.parse(response),如果Schema定义和WooCommerce返回的产品结构不匹配(比如某个必填字段缺失、类型不匹配),parse会直接抛出异常。而如果你的代码没有捕获这个异常,React Query会把请求标记为失败,data字段就会是undefined,但错误信息会被存在error属性里(你可能没注意到)。
临时修改代码排查:
给fetchAll加上错误捕获和日志,用safeParse代替parse来直观看到解析问题:
export const ProductServices = { fetchAll: async () => { try { const response = await wooApiV3.get(`products`).json(); // 先打印原始响应,确认和Postman返回的结构一致 console.log('Raw WooCommerce Response:', response); // 用safeParse避免直接抛出异常,查看解析结果 const parseResult = productSchema.safeParse(response); if (!parseResult.success) { console.error('Schema解析失败:', parseResult.error); throw new Error('产品数据格式校验失败'); } return parseResult.data; } catch (err) { console.error('获取产品列表出错:', err); throw err; // 抛出错误让React Query捕获 } }, };
运行后看控制台日志:
- 如果
Raw WooCommerce Response和Postman里的一致,那就是Schema的问题,需要调整productSchema让它匹配WooCommerce的产品结构(比如允许可选字段、调整字段类型)。 - 如果控制台有Schema解析错误,根据错误信息修改Schema即可。
2. 检查Ky的请求配置是否存在冲突
你的Ky实例在beforeRequest钩子中修改了extendedOptions.searchParams,有可能和Ky的内置参数处理逻辑冲突。可以试试直接修改request.url而非设置searchParams:
修改beforeRequest钩子的最后部分:
// 替换原来的 extendedOptions.searchParams = existingParams; url.search = existingParams.toString(); request.url = url.toString();
这样更直接地修改请求URL的查询参数,避免Ky的参数合并逻辑可能带来的问题。
另外,确认你的ExtendedOptions类型是否正确包含了searchParams字段,避免类型错误导致参数没有被正确传递。
3. 确认React Query的使用逻辑
检查你调用ProductServices.fetchAll的React Query代码,确保没有忽略错误:
const { data, error, isLoading } = useQuery({ queryKey: ['products'], queryFn: ProductServices.fetchAll, }); // 渲染时检查错误 if (isLoading) return <div>加载中...</div>; if (error) return <div>出错了: {(error as Error).message}</div>; // 再渲染data
如果之前没有处理error状态,可能会忽略掉Schema解析或请求抛出的错误,误以为数据是undefined。
4. 验证OAuth签名的边缘情况(可选)
虽然Postman能拿到数据,但可以临时在generateOAuthSignature里打印baseString和signingKey,和Postman生成的对比,确保签名逻辑完全一致:
export const generateOAuthSignature = ( method: string, url: string, params: Record<string, string>, consumerSecret: string ): string => { const sortedParams = Object.keys(params) .sort() .map( key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}` ) .join('&'); const baseString = [ method.toUpperCase(), encodeURIComponent(url), encodeURIComponent(sortedParams), ].join('&'); console.log('OAuth Base String:', baseString); // 和Postman对比 console.log('Signing Key:', `${encodeURIComponent(consumerSecret)}&`); const signingKey = `${encodeURIComponent(consumerSecret)}&`; const hash = CryptoJS.HmacSHA1(baseString, signingKey); return CryptoJS.enc.Base64.stringify(hash); };
如果和Postman生成的base string一致,说明签名逻辑没问题,可以排除这部分原因。
总结
最可能的根源是Schema解析失败,因为你已经确认WooCommerce返回了有效数据,只要解决Schema和返回结构不匹配的问题,或者捕获解析错误,就能解决数据undefined的问题。
备注:内容来源于stack exchange,提问作者Milos N.

