@@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { CourierApiError } from '../courier.error';
|
||||
import { CourierConfigService } from '../courier.config';
|
||||
import { CourierConfigService, type XiaofeixiaConfig } from '../courier.config';
|
||||
import { PrismaService } from '../../../common/prisma/prisma.module';
|
||||
import {
|
||||
logCourierCall,
|
||||
@@ -21,12 +21,12 @@ export class XiaofeixiaClient {
|
||||
private readonly prisma: PrismaService,
|
||||
) {}
|
||||
|
||||
async request<T>(cmd: string, bizParams: RequestParams): Promise<T> {
|
||||
const cfg = this.courierConfig.load().xiaofeixia;
|
||||
async request<T>(cmd: string, bizParams: RequestParams, override?: XiaofeixiaConfig): Promise<T> {
|
||||
const cfg = override ?? this.courierConfig.load().xiaofeixia;
|
||||
const scene = sceneForXfxCmd(cmd);
|
||||
const externalNo = this.pickExternalNo(bizParams);
|
||||
|
||||
if (!cfg.mchId || !cfg.apiKey) {
|
||||
if (!cfg.mchId || !cfg.apiKey || !cfg.apiUrl) {
|
||||
await logCourierCall(this.prisma, {
|
||||
scene,
|
||||
requestUrl: cfg.apiUrl || '(未配置)',
|
||||
@@ -36,7 +36,7 @@ export class XiaofeixiaClient {
|
||||
externalNo,
|
||||
});
|
||||
throw new CourierApiError(
|
||||
'小飞侠商户配置不完整,请设置 XIAOFEIXIA_MCH_ID 与 XIAOFEIXIA_API_KEY',
|
||||
'小飞侠商户配置不完整,请在仓配管理中填写 API 地址、商户号与 API Key',
|
||||
'CONFIG_ERROR',
|
||||
'XIAOFEIXIA',
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@ import { CourierProviderCode } from '../courier.constants';
|
||||
import { CourierApiError } from '../courier.error';
|
||||
import type {
|
||||
BatchShipmentQuery,
|
||||
CourierCallOptions,
|
||||
CreateShipmentInput,
|
||||
CreateShipmentResult,
|
||||
DeliveryCoverageResult,
|
||||
@@ -29,28 +30,32 @@ export class XiaofeixiaProvider implements ICourierProvider {
|
||||
|
||||
constructor(private readonly client: XiaofeixiaClient) {}
|
||||
|
||||
async createShipment(input: CreateShipmentInput): Promise<CreateShipmentResult> {
|
||||
const data = await this.client.request<XiaofeixiaCreateOrderData>(XIAOFEIXIA_CMD.CREATE_ORDER, {
|
||||
customerId: input.customerId,
|
||||
outNumber: input.outNumber,
|
||||
fromAddress: input.from.address,
|
||||
fromAddressDetail: input.from.addressDetail,
|
||||
fromCoordinate: this.formatCoordinate(input.from.coordinate),
|
||||
fromMobile: input.from.mobile,
|
||||
fromName: input.from.name,
|
||||
toAddress: input.to.address,
|
||||
toAddressDetail: input.to.addressDetail,
|
||||
toCoordinate: this.formatCoordinate(input.to.coordinate),
|
||||
toMobile: input.to.mobile,
|
||||
toName: input.to.name,
|
||||
goodsName: input.goodsName,
|
||||
goodsNum: input.goodsNum,
|
||||
weight: input.weight,
|
||||
insuredSumPrice: input.insuredSumPrice,
|
||||
collectionPrice: input.collectionPrice,
|
||||
payMode: input.payMode,
|
||||
remark: input.remark,
|
||||
});
|
||||
async createShipment(input: CreateShipmentInput, options?: CourierCallOptions): Promise<CreateShipmentResult> {
|
||||
const data = await this.client.request<XiaofeixiaCreateOrderData>(
|
||||
XIAOFEIXIA_CMD.CREATE_ORDER,
|
||||
{
|
||||
customerId: input.customerId,
|
||||
outNumber: input.outNumber,
|
||||
fromAddress: input.from.address,
|
||||
fromAddressDetail: input.from.addressDetail,
|
||||
fromCoordinate: this.formatCoordinate(input.from.coordinate),
|
||||
fromMobile: input.from.mobile,
|
||||
fromName: input.from.name,
|
||||
toAddress: input.to.address,
|
||||
toAddressDetail: input.to.addressDetail,
|
||||
toCoordinate: this.formatCoordinate(input.to.coordinate),
|
||||
toMobile: input.to.mobile,
|
||||
toName: input.to.name,
|
||||
goodsName: input.goodsName,
|
||||
goodsNum: input.goodsNum,
|
||||
weight: input.weight,
|
||||
insuredSumPrice: input.insuredSumPrice,
|
||||
collectionPrice: input.collectionPrice,
|
||||
payMode: input.payMode,
|
||||
remark: input.remark,
|
||||
},
|
||||
options?.xiaofeixia,
|
||||
);
|
||||
|
||||
return {
|
||||
providerShipmentId: data.id,
|
||||
@@ -58,24 +63,32 @@ export class XiaofeixiaProvider implements ICourierProvider {
|
||||
};
|
||||
}
|
||||
|
||||
async cancelShipment(query: ShipmentQuery): Promise<void> {
|
||||
async cancelShipment(query: ShipmentQuery, options?: CourierCallOptions): Promise<void> {
|
||||
this.assertShipmentQuery(query);
|
||||
await this.client.request(XIAOFEIXIA_CMD.CANCEL_ORDER, {
|
||||
number: query.trackingNumber,
|
||||
outNumber: query.outNumber,
|
||||
});
|
||||
await this.client.request(
|
||||
XIAOFEIXIA_CMD.CANCEL_ORDER,
|
||||
{
|
||||
number: query.trackingNumber,
|
||||
outNumber: query.outNumber,
|
||||
},
|
||||
options?.xiaofeixia,
|
||||
);
|
||||
}
|
||||
|
||||
async getShipment(query: ShipmentQuery): Promise<ShipmentDetail> {
|
||||
async getShipment(query: ShipmentQuery, options?: CourierCallOptions): Promise<ShipmentDetail> {
|
||||
this.assertShipmentQuery(query);
|
||||
const data = await this.client.request<XiaofeixiaOrderDetail>(XIAOFEIXIA_CMD.GET_ORDER, {
|
||||
number: query.trackingNumber,
|
||||
outNumber: query.outNumber,
|
||||
});
|
||||
const data = await this.client.request<XiaofeixiaOrderDetail>(
|
||||
XIAOFEIXIA_CMD.GET_ORDER,
|
||||
{
|
||||
number: query.trackingNumber,
|
||||
outNumber: query.outNumber,
|
||||
},
|
||||
options?.xiaofeixia,
|
||||
);
|
||||
return this.mapOrderDetail(data);
|
||||
}
|
||||
|
||||
async batchGetShipments(query: BatchShipmentQuery): Promise<ShipmentDetail[]> {
|
||||
async batchGetShipments(query: BatchShipmentQuery, options?: CourierCallOptions): Promise<ShipmentDetail[]> {
|
||||
const number = query.trackingNumbers?.join(',');
|
||||
const outNumber = query.outNumbers?.join(',');
|
||||
|
||||
@@ -83,27 +96,36 @@ export class XiaofeixiaProvider implements ICourierProvider {
|
||||
throw new CourierApiError('运单号与商家单号至少传一个', '300000', this.code);
|
||||
}
|
||||
|
||||
const data = await this.client.request<XiaofeixiaOrderDetail[]>(XIAOFEIXIA_CMD.BATCH_GET_ORDER, {
|
||||
number,
|
||||
outNumber,
|
||||
});
|
||||
const data = await this.client.request<XiaofeixiaOrderDetail[]>(
|
||||
XIAOFEIXIA_CMD.BATCH_GET_ORDER,
|
||||
{
|
||||
number,
|
||||
outNumber,
|
||||
},
|
||||
options?.xiaofeixia,
|
||||
);
|
||||
|
||||
return (data ?? []).map((item) => this.mapOrderDetail(item));
|
||||
}
|
||||
|
||||
async getTrack(query: ShipmentQuery): Promise<TrackNode[]> {
|
||||
async getTrack(query: ShipmentQuery, options?: CourierCallOptions): Promise<TrackNode[]> {
|
||||
this.assertShipmentQuery(query);
|
||||
const data = await this.client.request<XiaofeixiaTrackNode[]>(XIAOFEIXIA_CMD.TRACK_ROUTE, {
|
||||
number: query.trackingNumber,
|
||||
outNumber: query.outNumber,
|
||||
});
|
||||
const data = await this.client.request<XiaofeixiaTrackNode[]>(
|
||||
XIAOFEIXIA_CMD.TRACK_ROUTE,
|
||||
{
|
||||
number: query.trackingNumber,
|
||||
outNumber: query.outNumber,
|
||||
},
|
||||
options?.xiaofeixia,
|
||||
);
|
||||
return data ?? [];
|
||||
}
|
||||
|
||||
async checkDeliveryCoverage(toAddress: string): Promise<DeliveryCoverageResult> {
|
||||
async checkDeliveryCoverage(toAddress: string, options?: CourierCallOptions): Promise<DeliveryCoverageResult> {
|
||||
const data = await this.client.request<XiaofeixiaDeliveryCoverageData>(
|
||||
XIAOFEIXIA_CMD.DELIVERY_COVERAGE,
|
||||
{ toAddress },
|
||||
options?.xiaofeixia,
|
||||
);
|
||||
|
||||
return {
|
||||
@@ -113,10 +135,11 @@ export class XiaofeixiaProvider implements ICourierProvider {
|
||||
};
|
||||
}
|
||||
|
||||
async estimateFreight(weight: number): Promise<FreightEstimateResult> {
|
||||
async estimateFreight(weight: number, options?: CourierCallOptions): Promise<FreightEstimateResult> {
|
||||
const data = await this.client.request<XiaofeixiaFreightEstimateData>(
|
||||
XIAOFEIXIA_CMD.ESTIMATE_FREIGHT,
|
||||
{ weight },
|
||||
options?.xiaofeixia,
|
||||
);
|
||||
|
||||
return { freightPrice: data.freightPrice };
|
||||
|
||||
Reference in New Issue
Block a user