拆分feifei配置并修复商品查询

This commit is contained in:
yml2213
2026-07-07 14:59:22 +08:00
parent 83d501dc2d
commit 6af2fe2e23
13 changed files with 1317 additions and 221 deletions
@@ -2,7 +2,10 @@ import crypto from 'node:crypto'
import test from 'node:test'
import assert from 'node:assert/strict'
import { signKuaishouFeifeiPayload } from './http-client.js'
import {
isKuaishouFeifeiSuccessResponse,
signKuaishouFeifeiPayload,
} from './http-client.js'
test('signKuaishouFeifeiPayload signs app key, timestamp and raw body with HMAC SHA256', () => {
const input = {
@@ -19,3 +22,10 @@ test('signKuaishouFeifeiPayload signs app key, timestamp and raw body with HMAC
assert.equal(signKuaishouFeifeiPayload(input), expected)
})
test('isKuaishouFeifeiSuccessResponse accepts documented and actual success codes', () => {
assert.equal(isKuaishouFeifeiSuccessResponse({ code: 0, message: 'success' }), true)
assert.equal(isKuaishouFeifeiSuccessResponse({ code: 10000, message: 'success' }), true)
assert.equal(isKuaishouFeifeiSuccessResponse({ code: 10000, message: '商品不存在' }), false)
assert.equal(isKuaishouFeifeiSuccessResponse({ code: 1, message: 'success' }), false)
})
@@ -44,7 +44,7 @@ export async function kuaishouFeifeiRequest(pathname: string, payload: JsonObjec
})
}
if (Number(json.code || 0) !== 0) {
if (!isKuaishouFeifeiSuccessResponse(json)) {
throw createHttpError(String(json.message || 'kuaishou-feifei 业务失败'), {
statusCode: 502,
errorCode: 'kuaishou_feifei_business_failed',
@@ -85,6 +85,13 @@ export function signKuaishouFeifeiPayload({
.toLowerCase()
}
export function isKuaishouFeifeiSuccessResponse(json: JsonObject) {
const code = Number(json.code ?? 0)
const message = String(json.message || json.msg || '').trim().toLowerCase()
return code === 0 || (code === 10000 && message === 'success')
}
function parseJsonObject(text: string): JsonObject {
try {
const parsed = JSON.parse(text || '{}')
@@ -3,6 +3,30 @@ import { kuaishouFeifeiRequest } from './http-client.js'
type JsonObject = Record<string, any>
export async function listKuaishouFeifeiProducts(input: {
page?: number
perPage?: number
status?: string
supplyProductName?: string
} = {}) {
const page = Math.max(1, Number(input.page || 1) || 1)
const perPage = Math.min(100, Math.max(1, Number(input.perPage || 20) || 20))
const filters: JsonObject = {}
const status = String(input.status || 'on_sale').trim()
const supplyProductName = String(input.supplyProductName || '').trim()
if (status) filters.status = status
if (supplyProductName) filters.supply_product_name = supplyProductName
const response = await kuaishouFeifeiRequest('/api/open/v1/products/index', {
page,
per_page: perPage,
filters,
})
return mapKuaishouFeifeiProductList(response.data)
}
export async function createKuaishouFeifeiOrder(input: {
platformOrderNo: string
productCode: string
@@ -73,3 +97,40 @@ export function mapKuaishouFeifeiOrder(value: unknown) {
raw: source,
}
}
export function mapKuaishouFeifeiProductList(value: unknown) {
const source = value && typeof value === 'object' && !Array.isArray(value)
? value as JsonObject
: {}
const list = Array.isArray(source.list) ? source.list : []
return {
items: list.map((item) => mapKuaishouFeifeiProduct(item)),
total: Number(source.total || list.length) || 0,
page: Number(source.page || 1) || 1,
perPage: Number(source.per_page || source.perPage || list.length || 20) || 20,
raw: source,
}
}
export function mapKuaishouFeifeiProduct(value: unknown) {
const source = value && typeof value === 'object' && !Array.isArray(value)
? value as JsonObject
: {}
return {
productCode: String(source.product_code || '').trim(),
name: String(source.name || '').trim(),
channel: String(source.channel || '').trim(),
externalProductId: String(source.external_product_id || '').trim(),
imageUrl: String(source.image_url || '').trim(),
status: String(source.status || '').trim(),
supplyStatus: String(source.supply_status || '').trim(),
supplyPricePoints: Number(source.supply_price_points || 0) || 0,
feePoints: Number(source.fee_points || 0) || 0,
unitCostPoints: Number(source.unit_cost_points || 0) || 0,
maxOrderQuantity: Number(source.max_order_quantity || 0) || 0,
salePricePoints: source.sale_price_points == null ? null : Number(source.sale_price_points || 0) || 0,
raw: source,
}
}