Compare commits
No commits in common. "408ec8f42419164778dc57cd6f54994f00bf920c" and "7d1671a513e87e3fcb063ee8cf2d36417bbc0d46" have entirely different histories.
408ec8f424
...
7d1671a513
|
|
@ -23,7 +23,7 @@ import {
|
||||||
UpdateReviewDTO,
|
UpdateReviewDTO,
|
||||||
OrderPaymentStatus,
|
OrderPaymentStatus,
|
||||||
} from '../dto/site-api.dto';
|
} from '../dto/site-api.dto';
|
||||||
import { UnifiedPaginationDTO, UnifiedSearchParamsDTO, ShopyyGetAllOrdersParams } from '../dto/api.dto';
|
import { UnifiedPaginationDTO, UnifiedSearchParamsDTO, } from '../dto/api.dto';
|
||||||
import {
|
import {
|
||||||
ShopyyAllProductQuery,
|
ShopyyAllProductQuery,
|
||||||
ShopyyCustomer,
|
ShopyyCustomer,
|
||||||
|
|
@ -40,7 +40,6 @@ import {
|
||||||
OrderStatus,
|
OrderStatus,
|
||||||
} from '../enums/base.enum';
|
} from '../enums/base.enum';
|
||||||
import { BatchOperationDTO, BatchOperationResultDTO } from '../dto/batch.dto';
|
import { BatchOperationDTO, BatchOperationResultDTO } from '../dto/batch.dto';
|
||||||
import dayjs = require('dayjs');
|
|
||||||
export class ShopyyAdapter implements ISiteAdapter {
|
export class ShopyyAdapter implements ISiteAdapter {
|
||||||
shopyyFinancialStatusMap = {
|
shopyyFinancialStatusMap = {
|
||||||
'200': '待支付',
|
'200': '待支付',
|
||||||
|
|
@ -571,21 +570,9 @@ export class ShopyyAdapter implements ISiteAdapter {
|
||||||
per_page,
|
per_page,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
mapGetAllOrdersParams(params: UnifiedSearchParamsDTO) :ShopyyGetAllOrdersParams{
|
|
||||||
|
|
||||||
const pay_at_min = dayjs(params.after || '').valueOf().toString();
|
|
||||||
const pay_at_max = dayjs(params.before || '').valueOf().toString();
|
|
||||||
|
|
||||||
return {
|
|
||||||
page: params.page || 1,
|
|
||||||
per_page: params.per_page || 20,
|
|
||||||
pay_at_min: pay_at_min,
|
|
||||||
pay_at_max: pay_at_max,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async getAllOrders(params?: UnifiedSearchParamsDTO): Promise<UnifiedOrderDTO[]> {
|
async getAllOrders(params?: UnifiedSearchParamsDTO): Promise<UnifiedOrderDTO[]> {
|
||||||
const normalizedParams = this.mapGetAllOrdersParams(params);
|
const data = await this.shopyyService.getAllOrders(this.site.id, params);
|
||||||
const data = await this.shopyyService.getAllOrders(this.site.id, normalizedParams);
|
|
||||||
return data.map(this.mapPlatformToUnifiedOrder.bind(this));
|
return data.map(this.mapPlatformToUnifiedOrder.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,23 +52,6 @@ export class UnifiedSearchParamsDTO<Where=Record<string, any>> {
|
||||||
orderBy?: Record<string, 'asc' | 'desc'> | string;
|
orderBy?: Record<string, 'asc' | 'desc'> | string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Shopyy获取所有订单参数DTO
|
|
||||||
*/
|
|
||||||
export class ShopyyGetAllOrdersParams {
|
|
||||||
@ApiProperty({ description: '页码', example: 1, required: false })
|
|
||||||
page?: number;
|
|
||||||
|
|
||||||
@ApiProperty({ description: '每页数量', example: 20, required: false })
|
|
||||||
per_page?: number;
|
|
||||||
|
|
||||||
@ApiProperty({ description: '支付时间范围开始', example: '2023-01-01T00:00:00Z', required: false })
|
|
||||||
pay_at_min?: string;
|
|
||||||
|
|
||||||
@ApiProperty({ description: '支付时间范围结束', example: '2023-01-01T23:59:59Z', required: false })
|
|
||||||
pay_at_max?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量操作错误项
|
* 批量操作错误项
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,486 +0,0 @@
|
||||||
import { Inject, Provide } from '@midwayjs/core';
|
|
||||||
import axios from 'axios';
|
|
||||||
import * as crypto from 'crypto';
|
|
||||||
import dayjs = require('dayjs');
|
|
||||||
import utc = require('dayjs/plugin/utc');
|
|
||||||
import timezone = require('dayjs/plugin/timezone');
|
|
||||||
|
|
||||||
// 扩展dayjs功能
|
|
||||||
dayjs.extend(utc);
|
|
||||||
dayjs.extend(timezone);
|
|
||||||
|
|
||||||
// 全局参数配置接口
|
|
||||||
interface FreightwavesConfig {
|
|
||||||
appSecret: string;
|
|
||||||
apiBaseUrl: string;
|
|
||||||
partner: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 地址信息接口
|
|
||||||
interface Address {
|
|
||||||
name: string;
|
|
||||||
phone: string;
|
|
||||||
company: string;
|
|
||||||
countryCode: string;
|
|
||||||
city: string;
|
|
||||||
state: string;
|
|
||||||
address1: string;
|
|
||||||
address2: string;
|
|
||||||
postCode: string;
|
|
||||||
zoneCode?: string;
|
|
||||||
countryName: string;
|
|
||||||
cityName: string;
|
|
||||||
stateName: string;
|
|
||||||
companyName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 包裹尺寸接口
|
|
||||||
interface Dimensions {
|
|
||||||
length: number;
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
lengthUnit: 'IN' | 'CM';
|
|
||||||
weight: number;
|
|
||||||
weightUnit: 'LB' | 'KG';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 包裹信息接口
|
|
||||||
interface Package {
|
|
||||||
dimensions: Dimensions;
|
|
||||||
currency: string;
|
|
||||||
description: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 申报信息接口
|
|
||||||
interface Declaration {
|
|
||||||
boxNo: string;
|
|
||||||
sku: string;
|
|
||||||
cnname: string;
|
|
||||||
enname: string;
|
|
||||||
declaredPrice: number;
|
|
||||||
declaredQty: number;
|
|
||||||
material: string;
|
|
||||||
intendedUse: string;
|
|
||||||
cweight: number;
|
|
||||||
hsCode: string;
|
|
||||||
battery: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 费用试算请求接口
|
|
||||||
interface RateTryRequest {
|
|
||||||
shipCompany: string;
|
|
||||||
partnerOrderNumber: string;
|
|
||||||
warehouseId?: string;
|
|
||||||
shipper: Address;
|
|
||||||
reciver: Address;
|
|
||||||
packages: Package[];
|
|
||||||
partner: string;
|
|
||||||
signService?: 0 | 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建订单请求接口
|
|
||||||
interface CreateOrderRequest extends RateTryRequest {
|
|
||||||
declaration: Declaration;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询订单请求接口
|
|
||||||
interface QueryOrderRequest {
|
|
||||||
partnerOrderNumber?: string;
|
|
||||||
shipOrderId?: string;
|
|
||||||
partner: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改订单请求接口
|
|
||||||
interface ModifyOrderRequest extends CreateOrderRequest {
|
|
||||||
shipOrderId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 订单退款请求接口
|
|
||||||
interface RefundOrderRequest {
|
|
||||||
shipOrderId: string;
|
|
||||||
partner: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 通用响应接口
|
|
||||||
interface FreightwavesResponse<T> {
|
|
||||||
code: string;
|
|
||||||
msg: string;
|
|
||||||
data: T;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 费用试算响应数据接口
|
|
||||||
interface RateTryResponseData {
|
|
||||||
shipCompany: string;
|
|
||||||
channelCode: string;
|
|
||||||
totalAmount: number;
|
|
||||||
currency: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建订单响应数据接口
|
|
||||||
interface CreateOrderResponseData {
|
|
||||||
partnerOrderNumber: string;
|
|
||||||
shipOrderId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查询订单响应数据接口
|
|
||||||
interface QueryOrderResponseData {
|
|
||||||
thirdOrderId: string;
|
|
||||||
shipCompany: string;
|
|
||||||
expressFinish: 0 | 1 | 2;
|
|
||||||
expressFailMsg: string;
|
|
||||||
expressOrder: {
|
|
||||||
mainTrackingNumber: string;
|
|
||||||
labelPath: string[];
|
|
||||||
totalAmount: number;
|
|
||||||
currency: string;
|
|
||||||
balance: number;
|
|
||||||
};
|
|
||||||
partnerOrderNumber: string;
|
|
||||||
shipOrderId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 修改订单响应数据接口
|
|
||||||
interface ModifyOrderResponseData extends CreateOrderResponseData {}
|
|
||||||
|
|
||||||
// 订单退款响应数据接口
|
|
||||||
interface RefundOrderResponseData {}
|
|
||||||
|
|
||||||
@Provide()
|
|
||||||
export class FreightwavesService {
|
|
||||||
@Inject() logger;
|
|
||||||
|
|
||||||
// 默认配置
|
|
||||||
private config: FreightwavesConfig = {
|
|
||||||
appSecret: 'gELCHguGmdTLo!zfihfM91hae8G@9Sz23Mh6pHrt',
|
|
||||||
apiBaseUrl: 'https://tms.freightwaves.ca',
|
|
||||||
partner: '25072621035200000060',
|
|
||||||
};
|
|
||||||
|
|
||||||
// 初始化配置
|
|
||||||
setConfig(config: Partial<FreightwavesConfig>): void {
|
|
||||||
this.config = { ...this.config, ...config };
|
|
||||||
}
|
|
||||||
|
|
||||||
// 生成签名
|
|
||||||
private generateSignature(body: any, date: string): string {
|
|
||||||
const bodyString = JSON.stringify(body);
|
|
||||||
const signatureStr = `${bodyString}${this.config.appSecret}${date}`;
|
|
||||||
return crypto.createHash('md5').update(signatureStr).digest('hex');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 发送请求
|
|
||||||
private async sendRequest<T>(url: string, data: any): Promise<FreightwavesResponse<T>> {
|
|
||||||
try {
|
|
||||||
// 设置请求头 - 使用太平洋时间 (America/Los_Angeles)
|
|
||||||
const date = dayjs().tz('America/Los_Angeles').format('YYYY-mm-dd HH:mm:ss');
|
|
||||||
const headers = {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'requestDate': date,
|
|
||||||
'signature': this.generateSignature(data, date),
|
|
||||||
};
|
|
||||||
|
|
||||||
// 记录请求前的详细信息
|
|
||||||
this.log(`Sending request to: ${this.config.apiBaseUrl}${url}`, {
|
|
||||||
headers,
|
|
||||||
data
|
|
||||||
});
|
|
||||||
|
|
||||||
// 发送请求 - 临时禁用SSL证书验证以解决UNABLE_TO_VERIFY_LEAF_SIGNATURE错误
|
|
||||||
const response = await axios.post<FreightwavesResponse<T>>(
|
|
||||||
`${this.config.apiBaseUrl}${url}`,
|
|
||||||
data,
|
|
||||||
{
|
|
||||||
headers,
|
|
||||||
httpsAgent: new (require('https').Agent)({
|
|
||||||
rejectUnauthorized: false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// 记录响应信息
|
|
||||||
this.log(`Received response from: ${this.config.apiBaseUrl}${url}`, {
|
|
||||||
status: response.status,
|
|
||||||
statusText: response.statusText,
|
|
||||||
data: response.data
|
|
||||||
});
|
|
||||||
|
|
||||||
// 处理响应
|
|
||||||
if (response.data.code !== '00000200') {
|
|
||||||
this.log(`Freightwaves API error: ${response.data.msg}`, { url, data, response: response.data });
|
|
||||||
throw new Error(response.data.msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return response.data;
|
|
||||||
} catch (error) {
|
|
||||||
// 更详细的错误记录
|
|
||||||
if (error.response) {
|
|
||||||
// 请求已发送,服务器返回错误状态码
|
|
||||||
this.log(`Freightwaves API request failed with status: ${error.response.status}`, {
|
|
||||||
url,
|
|
||||||
data,
|
|
||||||
response: error.response.data,
|
|
||||||
status: error.response.status,
|
|
||||||
headers: error.response.headers
|
|
||||||
});
|
|
||||||
} else if (error.request) {
|
|
||||||
// 请求已发送,但没有收到响应
|
|
||||||
this.log(`Freightwaves API request no response received`, {
|
|
||||||
url,
|
|
||||||
data,
|
|
||||||
request: error.request
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// 请求配置时发生错误
|
|
||||||
this.log(`Freightwaves API request configuration error: ${error.message}`, {
|
|
||||||
url,
|
|
||||||
data,
|
|
||||||
error: error.message
|
|
||||||
});
|
|
||||||
}
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 费用试算
|
|
||||||
* @param params 费用试算参数
|
|
||||||
* @returns 费用试算结果
|
|
||||||
*/
|
|
||||||
async rateTry(params: Omit<RateTryRequest, 'partner'>): Promise<RateTryResponseData> {
|
|
||||||
const requestData: RateTryRequest = {
|
|
||||||
...params,
|
|
||||||
partner: this.config.partner,
|
|
||||||
};
|
|
||||||
|
|
||||||
const response = await this.sendRequest<RateTryResponseData>('/shipService/order/rateTry', requestData);
|
|
||||||
return response.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建订单
|
|
||||||
* @param params 创建订单参数
|
|
||||||
* @returns 创建订单结果
|
|
||||||
*/
|
|
||||||
async createOrder(params: Omit<CreateOrderRequest, 'partner'>): Promise<CreateOrderResponseData> {
|
|
||||||
const requestData: CreateOrderRequest = {
|
|
||||||
...params,
|
|
||||||
partner: this.config.partner,
|
|
||||||
};
|
|
||||||
|
|
||||||
const response = await this.sendRequest<CreateOrderResponseData>('/shipService/order/createOrder?apipost_id=0422aa', requestData);
|
|
||||||
return response.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询订单
|
|
||||||
* @param params 查询订单参数
|
|
||||||
* @returns 查询订单结果
|
|
||||||
*/
|
|
||||||
async queryOrder(params: Omit<QueryOrderRequest, 'partner'>): Promise<QueryOrderResponseData> {
|
|
||||||
const requestData: QueryOrderRequest = {
|
|
||||||
...params,
|
|
||||||
partner: this.config.partner,
|
|
||||||
};
|
|
||||||
|
|
||||||
const response = await this.sendRequest<QueryOrderResponseData>('/shipService/order/queryOrder', requestData);
|
|
||||||
return response.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 修改订单
|
|
||||||
* @param params 修改订单参数
|
|
||||||
* @returns 修改订单结果
|
|
||||||
*/
|
|
||||||
async modifyOrder(params: Omit<ModifyOrderRequest, 'partner'>): Promise<ModifyOrderResponseData> {
|
|
||||||
const requestData: ModifyOrderRequest = {
|
|
||||||
...params,
|
|
||||||
partner: this.config.partner,
|
|
||||||
};
|
|
||||||
|
|
||||||
const response = await this.sendRequest<ModifyOrderResponseData>('/shipService/order/modifyOrder', requestData);
|
|
||||||
return response.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 订单退款
|
|
||||||
* @param params 订单退款参数
|
|
||||||
* @returns 订单退款结果
|
|
||||||
*/
|
|
||||||
async refundOrder(params: Omit<RefundOrderRequest, 'partner'>): Promise<RefundOrderResponseData> {
|
|
||||||
const requestData: RefundOrderRequest = {
|
|
||||||
...params,
|
|
||||||
partner: this.config.partner,
|
|
||||||
};
|
|
||||||
|
|
||||||
const response = await this.sendRequest<RefundOrderResponseData>('/shipService/order/refundOrder', requestData);
|
|
||||||
return response.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测试创建订单方法
|
|
||||||
* 用于演示如何使用createOrder方法
|
|
||||||
*/
|
|
||||||
async testCreateOrder() {
|
|
||||||
try {
|
|
||||||
// 设置必要的配置
|
|
||||||
this.setConfig({
|
|
||||||
appSecret: 'gELCHguGmdTLo!zfihfM91hae8G@9Sz23Mh6pHrt',
|
|
||||||
apiBaseUrl: 'https://tms.freightwaves.ca',
|
|
||||||
partner: '25072621035200000060'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 准备测试数据
|
|
||||||
const testParams: Omit<CreateOrderRequest, 'partner'> = {
|
|
||||||
shipCompany: 'DHL',
|
|
||||||
partnerOrderNumber: `test-order-${Date.now()}`,
|
|
||||||
warehouseId: '25072621035200000060',
|
|
||||||
shipper: {
|
|
||||||
name: 'John Doe',
|
|
||||||
phone: '123-456-7890',
|
|
||||||
company: 'Test Company',
|
|
||||||
countryCode: 'CA',
|
|
||||||
city: 'Toronto',
|
|
||||||
state: 'ON',
|
|
||||||
address1: '123 Main St',
|
|
||||||
address2: 'Suite 400',
|
|
||||||
postCode: 'M5V 2T6',
|
|
||||||
countryName: 'Canada',
|
|
||||||
cityName: 'Toronto',
|
|
||||||
stateName: 'Ontario',
|
|
||||||
companyName: 'Test Company Inc.'
|
|
||||||
},
|
|
||||||
reciver: {
|
|
||||||
name: 'Jane Smith',
|
|
||||||
phone: '987-654-3210',
|
|
||||||
company: 'Receiver Company',
|
|
||||||
countryCode: 'CA',
|
|
||||||
city: 'Vancouver',
|
|
||||||
state: 'BC',
|
|
||||||
address1: '456 Oak St',
|
|
||||||
address2: '',
|
|
||||||
postCode: 'V6J 2A9',
|
|
||||||
countryName: 'Canada',
|
|
||||||
cityName: 'Vancouver',
|
|
||||||
stateName: 'British Columbia',
|
|
||||||
companyName: 'Receiver Company Ltd.'
|
|
||||||
},
|
|
||||||
packages: [
|
|
||||||
{
|
|
||||||
dimensions: {
|
|
||||||
length: 10,
|
|
||||||
width: 8,
|
|
||||||
height: 6,
|
|
||||||
lengthUnit: 'IN',
|
|
||||||
weight: 5,
|
|
||||||
weightUnit: 'LB'
|
|
||||||
},
|
|
||||||
currency: 'CAD',
|
|
||||||
description: 'Test Package'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
declaration: {
|
|
||||||
boxNo: 'BOX-001',
|
|
||||||
sku: 'TEST-SKU-001',
|
|
||||||
cnname: '测试产品',
|
|
||||||
enname: 'Test Product',
|
|
||||||
declaredPrice: 100,
|
|
||||||
declaredQty: 1,
|
|
||||||
material: 'Plastic',
|
|
||||||
intendedUse: 'General use',
|
|
||||||
cweight: 5,
|
|
||||||
hsCode: '39269090',
|
|
||||||
battery: 'No'
|
|
||||||
},
|
|
||||||
signService: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
// 调用创建订单方法
|
|
||||||
this.log('开始测试创建订单...');
|
|
||||||
this.log('测试参数:', testParams);
|
|
||||||
|
|
||||||
// 注意:在实际环境中取消注释以下行来执行真实请求
|
|
||||||
const result = await this.createOrder(testParams);
|
|
||||||
this.log('创建订单成功:', result);
|
|
||||||
|
|
||||||
|
|
||||||
// 返回模拟结果
|
|
||||||
return {
|
|
||||||
partnerOrderNumber: testParams.partnerOrderNumber,
|
|
||||||
shipOrderId: `simulated-shipOrderId-${Date.now()}`
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
this.log('测试创建订单失败:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 测试查询订单方法
|
|
||||||
* @returns 查询订单结果
|
|
||||||
*/
|
|
||||||
async testQueryOrder() {
|
|
||||||
try {
|
|
||||||
// 设置必要的配置
|
|
||||||
this.setConfig({
|
|
||||||
appSecret: 'gELCHguGmdTLo!zfihfM91hae8G@9Sz23Mh6pHrt',
|
|
||||||
apiBaseUrl: 'https://console-mock.apipost.cn/mock/0',
|
|
||||||
partner: '25072621035200000060'
|
|
||||||
});
|
|
||||||
|
|
||||||
// 准备测试数据 - 可以通过partnerOrderNumber或shipOrderId查询
|
|
||||||
const testParams: Omit<QueryOrderRequest, 'partner'> = {
|
|
||||||
// 选择其中一个参数进行测试
|
|
||||||
partnerOrderNumber: 'test-order-123456789', // 示例订单号
|
|
||||||
// shipOrderId: 'simulated-shipOrderId-123456789' // 或者使用运单号
|
|
||||||
};
|
|
||||||
|
|
||||||
// 调用查询订单方法
|
|
||||||
this.log('开始测试查询订单...');
|
|
||||||
this.log('测试参数:', testParams);
|
|
||||||
|
|
||||||
// 注意:在实际环境中取消注释以下行来执行真实请求
|
|
||||||
const result = await this.queryOrder(testParams);
|
|
||||||
this.log('查询订单成功:', result);
|
|
||||||
|
|
||||||
this.log('测试完成:查询订单方法调用成功(模拟)');
|
|
||||||
|
|
||||||
// 返回模拟结果
|
|
||||||
return {
|
|
||||||
thirdOrderId: 'thirdOrder-123456789',
|
|
||||||
shipCompany: 'DHL',
|
|
||||||
expressFinish: 0,
|
|
||||||
expressFailMsg: '',
|
|
||||||
expressOrder: {
|
|
||||||
mainTrackingNumber: '1234567890',
|
|
||||||
labelPath: ['https://example.com/label.pdf'],
|
|
||||||
totalAmount: 100,
|
|
||||||
currency: 'CAD',
|
|
||||||
balance: 50
|
|
||||||
},
|
|
||||||
partnerOrderNumber: testParams.partnerOrderNumber,
|
|
||||||
shipOrderId: 'simulated-shipOrderId-123456789'
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
this.log('测试查询订单失败:', error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 辅助日志方法,处理logger可能未定义的情况
|
|
||||||
* @param message 日志消息
|
|
||||||
* @param data 附加数据
|
|
||||||
*/
|
|
||||||
private log(message: string, data?: any) {
|
|
||||||
if (this.logger) {
|
|
||||||
this.logger.info(message, data);
|
|
||||||
} else {
|
|
||||||
// 如果logger未定义,使用console输出
|
|
||||||
if (data) {
|
|
||||||
console.log(message, data);
|
|
||||||
} else {
|
|
||||||
console.log(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -141,7 +141,7 @@ export class OrderService {
|
||||||
updated: 0,
|
updated: 0,
|
||||||
errors: []
|
errors: []
|
||||||
};
|
};
|
||||||
console.log('开始进入循环同步订单', result.length, '个订单')
|
|
||||||
// 遍历每个订单进行同步
|
// 遍历每个订单进行同步
|
||||||
for (const order of result) {
|
for (const order of result) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -165,7 +165,6 @@ export class OrderService {
|
||||||
} else {
|
} else {
|
||||||
syncResult.created++;
|
syncResult.created++;
|
||||||
}
|
}
|
||||||
// console.log('updated', syncResult.updated, 'created:', syncResult.created)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// 记录错误但不中断整个同步过程
|
// 记录错误但不中断整个同步过程
|
||||||
syncResult.errors.push({
|
syncResult.errors.push({
|
||||||
|
|
@ -175,8 +174,6 @@ export class OrderService {
|
||||||
syncResult.processed++;
|
syncResult.processed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log('同步完成', syncResult.updated, 'created:', syncResult.created)
|
|
||||||
|
|
||||||
this.logger.debug('syncOrders result', syncResult)
|
this.logger.debug('syncOrders result', syncResult)
|
||||||
return syncResult;
|
return syncResult;
|
||||||
}
|
}
|
||||||
|
|
@ -353,7 +350,7 @@ export class OrderService {
|
||||||
await this.saveOrderItems({
|
await this.saveOrderItems({
|
||||||
siteId,
|
siteId,
|
||||||
orderId,
|
orderId,
|
||||||
externalOrderId: String(externalOrderId),
|
externalOrderId,
|
||||||
orderItems: line_items,
|
orderItems: line_items,
|
||||||
});
|
});
|
||||||
// 保存退款信息
|
// 保存退款信息
|
||||||
|
|
@ -1232,13 +1229,13 @@ export class OrderService {
|
||||||
parameters.push(siteId);
|
parameters.push(siteId);
|
||||||
}
|
}
|
||||||
if (startDate) {
|
if (startDate) {
|
||||||
sqlQuery += ` AND o.date_paid >= ?`;
|
sqlQuery += ` AND o.date_created >= ?`;
|
||||||
totalQuery += ` AND o.date_paid >= ?`;
|
totalQuery += ` AND o.date_created >= ?`;
|
||||||
parameters.push(startDate);
|
parameters.push(startDate);
|
||||||
}
|
}
|
||||||
if (endDate) {
|
if (endDate) {
|
||||||
sqlQuery += ` AND o.date_paid <= ?`;
|
sqlQuery += ` AND o.date_created <= ?`;
|
||||||
totalQuery += ` AND o.date_paid <= ?`;
|
totalQuery += ` AND o.date_created <= ?`;
|
||||||
parameters.push(endDate);
|
parameters.push(endDate);
|
||||||
}
|
}
|
||||||
// 支付方式筛选(使用参数化,避免SQL注入)
|
// 支付方式筛选(使用参数化,避免SQL注入)
|
||||||
|
|
@ -1326,7 +1323,7 @@ export class OrderService {
|
||||||
// 添加分页到主查询
|
// 添加分页到主查询
|
||||||
sqlQuery += `
|
sqlQuery += `
|
||||||
GROUP BY o.id
|
GROUP BY o.id
|
||||||
ORDER BY o.date_paid DESC
|
ORDER BY o.date_created DESC
|
||||||
LIMIT ? OFFSET ?
|
LIMIT ? OFFSET ?
|
||||||
`;
|
`;
|
||||||
parameters.push(pageSize, (current - 1) * pageSize);
|
parameters.push(pageSize, (current - 1) * pageSize);
|
||||||
|
|
@ -2544,7 +2541,7 @@ export class OrderService {
|
||||||
'姓名地址': nameAddress,
|
'姓名地址': nameAddress,
|
||||||
'邮箱': order.customer_email || '',
|
'邮箱': order.customer_email || '',
|
||||||
'号码': phone,
|
'号码': phone,
|
||||||
'订单内容': this.removeLastParenthesesContent(orderContent),
|
'订单内容': orderContent,
|
||||||
'盒数': boxCount,
|
'盒数': boxCount,
|
||||||
'换盒数': exchangeBoxCount,
|
'换盒数': exchangeBoxCount,
|
||||||
'换货内容': exchangeContent,
|
'换货内容': exchangeContent,
|
||||||
|
|
@ -2644,80 +2641,4 @@ export class OrderService {
|
||||||
throw new Error(`导出CSV文件失败: ${error.message}`);
|
throw new Error(`导出CSV文件失败: ${error.message}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 删除每个分号前面一个左右括号和最后一个左右括号包含的内容(包括括号本身)
|
|
||||||
* @param str 输入字符串
|
|
||||||
* @returns 删除后的字符串
|
|
||||||
*/
|
|
||||||
removeLastParenthesesContent(str: string): string {
|
|
||||||
if (!str || typeof str !== 'string') {
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 辅助函数:删除指定位置的括号对及其内容
|
|
||||||
const removeParenthesesAt = (s: string, leftIndex: number): string => {
|
|
||||||
if (leftIndex === -1) return s;
|
|
||||||
|
|
||||||
let rightIndex = -1;
|
|
||||||
let parenCount = 0;
|
|
||||||
|
|
||||||
for (let i = leftIndex; i < s.length; i++) {
|
|
||||||
const char = s[i];
|
|
||||||
if (char === '(') {
|
|
||||||
parenCount++;
|
|
||||||
} else if (char === ')') {
|
|
||||||
parenCount--;
|
|
||||||
if (parenCount === 0) {
|
|
||||||
rightIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rightIndex !== -1) {
|
|
||||||
return s.substring(0, leftIndex) + s.substring(rightIndex + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return s;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 1. 处理每个分号前面的括号对
|
|
||||||
let result = str;
|
|
||||||
|
|
||||||
// 找出所有分号的位置
|
|
||||||
const semicolonIndices: number[] = [];
|
|
||||||
for (let i = 0; i < result.length; i++) {
|
|
||||||
if (result[i] === ';') {
|
|
||||||
semicolonIndices.push(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 从后向前处理每个分号,避免位置变化影响后续处理
|
|
||||||
for (let i = semicolonIndices.length - 1; i >= 0; i--) {
|
|
||||||
const semicolonIndex = semicolonIndices[i];
|
|
||||||
|
|
||||||
// 从分号位置向前查找最近的左括号
|
|
||||||
let lastLeftParenIndex = -1;
|
|
||||||
for (let j = semicolonIndex - 1; j >= 0; j--) {
|
|
||||||
if (result[j] === '(') {
|
|
||||||
lastLeftParenIndex = j;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果找到左括号,删除该括号对及其内容
|
|
||||||
if (lastLeftParenIndex !== -1) {
|
|
||||||
result = removeParenthesesAt(result, lastLeftParenIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 处理整个字符串的最后一个括号对
|
|
||||||
let lastLeftParenIndex = result.lastIndexOf('(');
|
|
||||||
if (lastLeftParenIndex !== -1) {
|
|
||||||
result = removeParenthesesAt(result, lastLeftParenIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -313,6 +313,7 @@ export class ShopyyService {
|
||||||
|
|
||||||
const { items: firstPageItems, totalPages} = firstPage;
|
const { items: firstPageItems, totalPages} = firstPage;
|
||||||
|
|
||||||
|
// const { page = 1, per_page = 100 } = params;
|
||||||
// 如果只有一页数据,直接返回
|
// 如果只有一页数据,直接返回
|
||||||
if (totalPages <= 1) {
|
if (totalPages <= 1) {
|
||||||
return firstPageItems;
|
return firstPageItems;
|
||||||
|
|
@ -333,7 +334,7 @@ export class ShopyyService {
|
||||||
// 创建当前批次的并发请求
|
// 创建当前批次的并发请求
|
||||||
for (let i = 0; i < batchSize; i++) {
|
for (let i = 0; i < batchSize; i++) {
|
||||||
const page = currentPage + i;
|
const page = currentPage + i;
|
||||||
const pagePromise = this.getOrders(site, page, 100, params)
|
const pagePromise = this.getOrders(site, page, 100)
|
||||||
.then(pageResult => pageResult.items)
|
.then(pageResult => pageResult.items)
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.error(`获取第 ${page} 页数据失败:`, error);
|
console.error(`获取第 ${page} 页数据失败:`, error);
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
// Test script for FreightwavesService createOrder method
|
|
||||||
|
|
||||||
const { FreightwavesService } = require('./dist/service/test-freightwaves.service');
|
|
||||||
|
|
||||||
async function testFreightwavesService() {
|
|
||||||
try {
|
|
||||||
// Create an instance of the FreightwavesService
|
|
||||||
const service = new FreightwavesService();
|
|
||||||
|
|
||||||
// Call the test method
|
|
||||||
console.log('Starting test for createOrder method...');
|
|
||||||
const result = await service.testQueryOrder();
|
|
||||||
|
|
||||||
console.log('Test completed successfully!');
|
|
||||||
console.log('Result:', result);
|
|
||||||
console.log('\nTo run the actual createOrder request:');
|
|
||||||
console.log('1. Uncomment the createOrder call in the testCreateOrder method');
|
|
||||||
console.log('2. Update the test-secret, test-partner-id with real credentials');
|
|
||||||
console.log('3. Run this script again');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Test failed:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the test
|
|
||||||
testFreightwavesService();
|
|
||||||
Loading…
Reference in New Issue