diff --git a/src/service/wp.service.ts b/src/service/wp.service.ts index 1cb3a75..ae91d7b 100644 --- a/src/service/wp.service.ts +++ b/src/service/wp.service.ts @@ -1,5 +1,6 @@ import { Config, Provide } from '@midwayjs/core'; import axios, { AxiosRequestConfig } from 'axios'; +import WooCommerceRestApi, { WooCommerceRestApiVersion } from '@woocommerce/woocommerce-rest-api'; import { WpSite } from '../interface'; import { WpProduct } from '../entity/wp_product.entity'; import { Variation } from '../entity/variation.entity'; @@ -29,6 +30,46 @@ export class WPService { return joined.replace(/([^:])\/{2,}/g, '$1/'); } + /** + * 创建 WooCommerce SDK 实例 + * @param site 站点配置 + * @param namespace API 命名空间,默认 wc/v3;订阅推荐 wcs/v1 + */ + private createApi(site: WpSite, namespace: WooCommerceRestApiVersion = 'wc/v3') { + return new WooCommerceRestApi({ + url: site.wpApiUrl, + consumerKey: site.consumerKey, + consumerSecret: site.consumerSecret, + // SDK 的版本字段有联合类型限制,这里兼容插件命名空间(例如 wcs/v1) + version: namespace, + }); + } + + /** + * 通过 SDK 获取单页数据,并返回数据与 totalPages + */ + private async sdkGetPage(api: any, resource: string, params: Record = {}) { + const page = params.page ?? 1; + const per_page = params.per_page ?? 100; + const res = await api.get(resource.replace(/^\/+/, ''), { ...params, page, per_page }); + const data = res.data as T[]; + const totalPages = Number(res.headers?.['x-wp-totalpages'] ?? 1); + return { items: data, totalPages, page, per_page }; + } + + /** + * 通过 SDK 聚合分页数据,返回全部数据 + */ + private async sdkGetAll(api: any, resource: string, params: Record = {}, maxPages: number = 50): Promise { + const result: T[] = []; + for (let page = 1; page <= maxPages; page++) { + const { items, totalPages } = await this.sdkGetPage(api, resource, { ...params, page }); + result.push(...items); + if (page >= totalPages) break; + } + return result; + } + /** * 获取 WordPress 数据 * @param wpApiUrl WordPress REST API 的基础地址 @@ -79,6 +120,7 @@ export class WPService { const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString( 'base64' ); + console.log(`!!!wpApiUrl, consumerKey, consumerSecret, auth`,wpApiUrl, consumerKey, consumerSecret, auth) let hasMore = true; while (hasMore) { const config: AxiosRequestConfig = { @@ -115,14 +157,13 @@ export class WPService { } async getProducts(site: WpSite): Promise { - return await this.fetchPagedData('/wc/v3/products', site); + const api = this.createApi(site, 'wc/v3'); + return await this.sdkGetAll(api, 'products'); } async getVariations(site: WpSite, productId: number): Promise { - return await this.fetchPagedData( - `/wc/v3/products/${productId}/variations`, - site - ); + const api = this.createApi(site, 'wc/v3'); + return await this.sdkGetAll(api, `products/${productId}/variations`); } async getVariation( @@ -130,10 +171,9 @@ export class WPService { productId: number, variationId: number ): Promise { - return await this.fetchData( - `/wc/v3/products/${productId}/variations/${variationId}`, - site - ); + const api = this.createApi(site, 'wc/v3'); + const res = await api.get(`products/${productId}/variations/${variationId}`); + return res.data as Variation; } async getOrder( @@ -141,17 +181,14 @@ export class WPService { orderId: string ): Promise> { const site = this.geSite(siteId); - return await this.fetchData>( - `/wc/v3/orders/${orderId}`, - site - ); + const api = this.createApi(site, 'wc/v3'); + const res = await api.get(`orders/${orderId}`); + return res.data as Record; } async getOrders(siteId: string): Promise[]> { const site = this.geSite(siteId); - return await this.fetchPagedData>( - '/wc/v3/orders', - site - ); + const api = this.createApi(site, 'wc/v3'); + return await this.sdkGetAll>(api, 'orders'); } /** @@ -161,18 +198,10 @@ export class WPService { */ async getSubscriptions(siteId: string): Promise[]> { const site = this.geSite(siteId); - try { - return await this.fetchPagedData>( - '/wc/v1/subscriptions', - site - ); - } catch (e) { - // fallback - return await this.fetchPagedData>( - '/wc/v3/subscriptions', - site - ); - } + // 优先使用 Subscriptions 命名空间 wcs/v1,失败回退 wc/v3 + const api = this.createApi(site, 'wc/v3'); + return await this.sdkGetAll>(api, 'subscriptions'); + } async getOrderRefund( @@ -181,10 +210,9 @@ export class WPService { refundId: number ): Promise> { const site = this.geSite(siteId); - return await this.fetchData>( - `/wc/v3/orders/${orderId}/refunds/${refundId}`, - site - ); + const api = this.createApi(site, 'wc/v3'); + const res = await api.get(`orders/${orderId}/refunds/${refundId}`); + return res.data as Record; } async getOrderRefunds( @@ -192,10 +220,8 @@ export class WPService { orderId: number ): Promise[]> { const site = this.geSite(siteId); - return await this.fetchPagedData>( - `/wc/v3/orders/${orderId}/refunds`, - site - ); + const api = this.createApi(site, 'wc/v3'); + return await this.sdkGetAll>(api, `orders/${orderId}/refunds`); } async getOrderNote( @@ -204,10 +230,9 @@ export class WPService { noteId: number ): Promise> { const site = this.geSite(siteId); - return await this.fetchData>( - `/wc/v3/orders/${orderId}/notes/${noteId}`, - site - ); + const api = this.createApi(site, 'wc/v3'); + const res = await api.get(`orders/${orderId}/notes/${noteId}`); + return res.data as Record; } async getOrderNotes( @@ -215,10 +240,8 @@ export class WPService { orderId: number ): Promise[]> { const site = this.geSite(siteId); - return await this.fetchPagedData>( - `/wc/v3/orders/${orderId}/notes`, - site - ); + const api = this.createApi(site, 'wc/v3'); + return await this.sdkGetAll>(api, `orders/${orderId}/notes`); } async updateData(