301 lines
7.6 KiB
TypeScript
301 lines
7.6 KiB
TypeScript
import { Config, Provide } from '@midwayjs/core';
|
||
import axios, { AxiosRequestConfig } from 'axios';
|
||
import { WpSite } from '../interface';
|
||
import { WpProduct } from '../entity/wp_product.entity';
|
||
import { Variation } from '../entity/variation.entity';
|
||
import { UpdateVariationDTO, UpdateWpProductDTO } from '../dto/wp_product.dto';
|
||
|
||
@Provide()
|
||
export class WPService {
|
||
@Config('wpSite')
|
||
sites: WpSite[];
|
||
|
||
/**
|
||
* 获取 WordPress 数据
|
||
* @param wpApiUrl WordPress REST API 的基础地址
|
||
* @param endpoint API 端点路径(例如 wc/v3/products)
|
||
* @param consumerKey WooCommerce 的消费者密钥
|
||
* @param consumerSecret WooCommerce 的消费者密钥
|
||
*/
|
||
|
||
geSite(id: string): WpSite {
|
||
let idx = this.sites.findIndex(item => item.id === id);
|
||
return this.sites[idx];
|
||
}
|
||
|
||
async fetchData<T>(
|
||
endpoint: string,
|
||
site: WpSite,
|
||
param: Record<string, any> = {}
|
||
): Promise<T> {
|
||
try {
|
||
const { wpApiUrl, consumerKey, consumerSecret } = site;
|
||
const url = `${wpApiUrl}/wp-json${endpoint}`;
|
||
const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString(
|
||
'base64'
|
||
);
|
||
const response = await axios.request({
|
||
url,
|
||
headers: {
|
||
Authorization: `Basic ${auth}`,
|
||
},
|
||
method: 'GET',
|
||
...param,
|
||
});
|
||
return response.data;
|
||
} catch (error) {
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
async fetchPagedData<T>(
|
||
endpoint: string,
|
||
site: WpSite,
|
||
page: number = 1,
|
||
perPage: number = 100
|
||
): Promise<T[]> {
|
||
const allData: T[] = [];
|
||
const { wpApiUrl, consumerKey, consumerSecret } = site;
|
||
const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString(
|
||
'base64'
|
||
);
|
||
let hasMore = true;
|
||
while (hasMore) {
|
||
const config: AxiosRequestConfig = {
|
||
method: 'GET',
|
||
url: `${wpApiUrl}/wp-json${endpoint}`,
|
||
headers: {
|
||
Authorization: `Basic ${auth}`,
|
||
},
|
||
params: {
|
||
page,
|
||
per_page: perPage,
|
||
},
|
||
};
|
||
try {
|
||
const response = await axios.request(config);
|
||
|
||
// Append the current page data
|
||
allData.push(...response.data);
|
||
|
||
// Check for more pages
|
||
const totalPages = parseInt(
|
||
response.headers['x-wp-totalpages'] || '1',
|
||
10
|
||
);
|
||
hasMore = page < totalPages;
|
||
page += 1;
|
||
} catch (error) {
|
||
throw error;
|
||
}
|
||
}
|
||
|
||
return allData;
|
||
}
|
||
|
||
async getProducts(site: WpSite): Promise<WpProduct[]> {
|
||
return await this.fetchPagedData<WpProduct>('/wc/v3/products', site);
|
||
}
|
||
|
||
async getVariations(site: WpSite, productId: number): Promise<Variation[]> {
|
||
return await this.fetchPagedData<Variation>(
|
||
`/wc/v3/products/${productId}/variations`,
|
||
site
|
||
);
|
||
}
|
||
|
||
async getVariation(
|
||
site: WpSite,
|
||
productId: number,
|
||
variationId: number
|
||
): Promise<Variation> {
|
||
return await this.fetchData<Variation>(
|
||
`/wc/v3/products/${productId}/variations/${variationId}`,
|
||
site
|
||
);
|
||
}
|
||
|
||
async getOrder(
|
||
siteId: string,
|
||
orderId: string
|
||
): Promise<Record<string, any>> {
|
||
const site = this.geSite(siteId);
|
||
return await this.fetchData<Record<string, any>>(
|
||
`/wc/v3/orders/${orderId}`,
|
||
site
|
||
);
|
||
}
|
||
async getOrders(siteId: string): Promise<Record<string, any>[]> {
|
||
const site = this.geSite(siteId);
|
||
return await this.fetchPagedData<Record<string, any>>(
|
||
'/wc/v3/orders',
|
||
site
|
||
);
|
||
}
|
||
|
||
async getOrderRefund(
|
||
siteId: string,
|
||
orderId: string,
|
||
refundId: number
|
||
): Promise<Record<string, any>> {
|
||
const site = this.geSite(siteId);
|
||
return await this.fetchData<Record<string, any>>(
|
||
`/wc/v3/orders/${orderId}/refunds/${refundId}`,
|
||
site
|
||
);
|
||
}
|
||
|
||
async getOrderRefunds(
|
||
siteId: string,
|
||
orderId: number
|
||
): Promise<Record<string, any>[]> {
|
||
const site = this.geSite(siteId);
|
||
return await this.fetchPagedData<Record<string, any>>(
|
||
`/wc/v3/orders/${orderId}/refunds`,
|
||
site
|
||
);
|
||
}
|
||
|
||
async getOrderNote(
|
||
siteId: string,
|
||
orderId: number,
|
||
noteId: number
|
||
): Promise<Record<string, any>> {
|
||
const site = this.geSite(siteId);
|
||
return await this.fetchData<Record<string, any>>(
|
||
`/wc/v3/orders/${orderId}/notes/${noteId}`,
|
||
site
|
||
);
|
||
}
|
||
|
||
async getOrderNotes(
|
||
siteId: string,
|
||
orderId: number
|
||
): Promise<Record<string, any>[]> {
|
||
const site = this.geSite(siteId);
|
||
return await this.fetchPagedData<Record<string, any>>(
|
||
`/wc/v3/orders/${orderId}/notes`,
|
||
site
|
||
);
|
||
}
|
||
|
||
async updateData<T>(
|
||
endpoint: string,
|
||
site: WpSite,
|
||
data: Record<string, any>
|
||
): Promise<Boolean> {
|
||
const { wpApiUrl, consumerKey, consumerSecret } = site;
|
||
const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString(
|
||
'base64'
|
||
);
|
||
const config: AxiosRequestConfig = {
|
||
method: 'PUT',
|
||
url: `${wpApiUrl}/wp-json${endpoint}`,
|
||
headers: {
|
||
Authorization: `Basic ${auth}`,
|
||
},
|
||
data,
|
||
};
|
||
try {
|
||
await axios.request(config);
|
||
return true;
|
||
} catch (error) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 更新 WooCommerce 产品
|
||
* @param productId 产品 ID
|
||
* @param data 更新的数据
|
||
*/
|
||
async updateProduct(
|
||
site: WpSite,
|
||
productId: string,
|
||
data: UpdateWpProductDTO
|
||
): Promise<Boolean> {
|
||
const { regular_price, sale_price, ...params } = data;
|
||
return await this.updateData(`/wc/v3/products/${productId}`, site, {
|
||
...params,
|
||
regular_price: regular_price ? regular_price.toString() : null,
|
||
sale_price: sale_price ? sale_price.toString() : null,
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 更新 WooCommerce 产品变体
|
||
* @param productId 产品 ID
|
||
* @param variationId 变体 ID
|
||
* @param data 更新的数据
|
||
*/
|
||
async updateVariation(
|
||
site: WpSite,
|
||
productId: string,
|
||
variationId: string,
|
||
data: UpdateVariationDTO
|
||
): Promise<Boolean> {
|
||
const { regular_price, sale_price, ...params } = data;
|
||
return await this.updateData(
|
||
`/wc/v3/products/${productId}/variations/${variationId}`,
|
||
site,
|
||
{
|
||
...params,
|
||
regular_price: regular_price ? regular_price.toString() : null,
|
||
sale_price: sale_price ? sale_price.toString() : null,
|
||
}
|
||
);
|
||
}
|
||
|
||
/**
|
||
* 更新 Order
|
||
*/
|
||
async updateOrder(
|
||
site: WpSite,
|
||
orderId: string,
|
||
data: Record<string, any>
|
||
): Promise<Boolean> {
|
||
return await this.updateData(`/wc/v3/orders/${orderId}`, site, data);
|
||
}
|
||
|
||
async createShipment(
|
||
site: WpSite,
|
||
orderId: string,
|
||
data: Record<string, any>
|
||
) {
|
||
const { wpApiUrl, consumerKey, consumerSecret } = site;
|
||
const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString(
|
||
'base64'
|
||
);
|
||
const config: AxiosRequestConfig = {
|
||
method: 'POST',
|
||
url: `${wpApiUrl}/wp-json/wc-ast/v3/orders/${orderId}/shipment-trackings`,
|
||
headers: {
|
||
Authorization: `Basic ${auth}`,
|
||
},
|
||
data,
|
||
};
|
||
return await axios.request(config);
|
||
}
|
||
|
||
async deleteShipment(
|
||
site: WpSite,
|
||
orderId: string,
|
||
trackingId: string,
|
||
): Promise<Boolean> {
|
||
const { wpApiUrl, consumerKey, consumerSecret } = site;
|
||
const auth = Buffer.from(`${consumerKey}:${consumerSecret}`).toString(
|
||
'base64'
|
||
);
|
||
|
||
console.log('del', orderId, trackingId);
|
||
// 删除接口: DELETE /wp-json/wc-shipment-tracking/v3/orders/<order_id>/shipment-trackings/<tracking_id>
|
||
const config: AxiosRequestConfig = {
|
||
method: 'DELETE',
|
||
url: `${wpApiUrl}/wp-json/wc-ast/v3/orders/${orderId}/shipment-trackings/${trackingId}`,
|
||
headers: {
|
||
Authorization: `Basic ${auth}`,
|
||
},
|
||
};
|
||
return await axios.request(config);
|
||
}
|
||
} |