feat: 基本实现拆单收货--

This commit is contained in:
2026-07-29 18:22:21 +08:00
parent 1b45f9dac6
commit 63ff3edb11
46 changed files with 4402 additions and 1892 deletions
@@ -0,0 +1,145 @@
import { supplierDao } from '../dao/supplier.dao.js'
import { bridgeFetchWithAuth, findSupplierByIdentification, getBridgeApiBase, getBridgeToken, warmBridgeToken } from '../utils/bridge-auth.js'
import { sha256 } from '../utils/crypto.js'
import { logger } from '../utils/logger.js'
import { createSupplierOpenSignature } from '../utils/supplier-open-crypto.js'
import { serviceFail, serviceOk } from '../types/service-result.js'
type BridgePointsResponse = {
resultCode?: number
message?: string
userPoints?: number | string
}
export const supplierService = {
async getSupplierInfo(supplierIdentification: string) {
logger.info('supplier info query', { supplierIdentification })
if (!supplierIdentification) {
return serviceFail('供应商唯一标识不能为空')
}
const supplier = await supplierDao.findActiveByIdentification(supplierIdentification)
if (!supplier) {
return serviceFail('供应商信息未配置或已停用', 404, 'SUPPLIER_NOT_CONFIGURED')
}
return serviceOk({
id: supplier.id,
supplierIdentification: supplier.supplierIdentification,
supplierId: supplier.supplierId,
supplierName: supplier.supplierName
})
},
async warmSupplierToken(userId: string, supplierIdentification: string) {
logger.info('supplier token warmup', { userId, supplierIdentification })
if (!userId || !supplierIdentification) {
return serviceFail('用户信息和供应商唯一标识不能为空')
}
const supplier = await findSupplierByIdentification(supplierIdentification).catch(error => error)
if (supplier instanceof Error) {
return serviceFail(supplier.message || '供应商信息未配置或已停用', 404, 'SUPPLIER_NOT_CONFIGURED')
}
try {
await warmBridgeToken(supplier)
} catch (error) {
return serviceFail(error instanceof Error ? error.message : '获取平台授权令牌失败', 502, 'BRIDGE_TOKEN_FAILED')
}
return serviceOk({
supplierIdentification,
supplierId: supplier.supplierId,
supplierName: supplier.supplierName,
userId
})
},
async getUserPoints(supplierId: string, userId: string) {
logger.info('supplier points query', { supplierId, userId })
if (!supplierId || !userId) {
return serviceFail('供应商或用户信息不能为空')
}
const { response, payload: pointsPayload } = await bridgeFetchWithAuth<BridgePointsResponse>(
supplierId,
'/pointOrder/queryPoints',
{ userId }
)
if (!response.ok || pointsPayload.resultCode !== 0) {
return serviceFail(pointsPayload.message || '查询用户积分失败', 502, 'BRIDGE_POINTS_FAILED')
}
return serviceOk({
userPoints: Number(pointsPayload.userPoints || 0)
})
},
async getDebugTokens(supplierIdentification: string, forceRefreshZhghToken: boolean) {
logger.info('supplier debug tokens query', { supplierIdentification, forceRefreshZhghToken })
if (!supplierIdentification) {
return serviceFail('供应商唯一标识不能为空')
}
const supplier = await findSupplierByIdentification(supplierIdentification).catch(error => error)
if (supplier instanceof Error) {
return serviceFail(supplier.message || '供应商信息未配置或已停用', 404, 'SUPPLIER_NOT_CONFIGURED')
}
const timestamp = Date.now()
const orderType = 2
const orderId = 'SUB_ORDER_ID_1,SUB_ORDER_ID_2'
const mainOrderId = 'MAIN_ORDER_ID'
const userId = 'USER_ID'
const supplierOpenToken = createSupplierOpenSignature(supplier.supplierId, supplier.clientId, timestamp)
const zhghBridgeToken = await getBridgeToken(supplier.supplierId, forceRefreshZhghToken)
return serviceOk({
supplierOpen: {
name: 'supplierOpenToken',
usage: '调用供应商开放接口 /supplierOpenApi/pointOrder/queryOrderInfo',
supplierId: supplier.supplierId,
clientId: supplier.clientId,
timestamp,
token: supplierOpenToken,
orderType,
orderId,
queryOrderInfoBody: {
supplierId: supplier.supplierId,
token: supplierOpenToken,
orderType,
orderId,
timestamp
}
},
zhghBridge: {
name: 'zhghBridgeToken',
usage: '调用 zhgh /open/pointOrder/* 桥接接口',
apiBase: getBridgeApiBase(),
supplierId: supplier.supplierId,
clientId: supplier.clientId,
timestamp,
sendSha256: sha256(`${supplier.clientId}${supplier.clientSecret}${timestamp}`),
token: zhghBridgeToken,
splitOrderBody: {
supplierId: supplier.supplierId,
token: zhghBridgeToken,
orderType,
orderId,
mainOrderId,
userId,
time: timestamp
}
}
})
}
}