断开快手后端旧依赖

This commit is contained in:
yml
2026-05-25 21:12:03 +08:00
parent dc099ae6f8
commit 9aafddd624
19 changed files with 113 additions and 86 deletions
-2
View File
@@ -5,7 +5,6 @@ import process from "node:process";
import adminRouter from "./routes/admin-kuaishou.js"; import adminRouter from "./routes/admin-kuaishou.js";
import claimsRouter from "./routes/claims-kuaishou.js"; import claimsRouter from "./routes/claims-kuaishou.js";
import open91Router from "./routes/open-91.js"; import open91Router from "./routes/open-91.js";
import webhooksRouter from "./routes/webhooks.js";
import { accessLogMiddleware } from "./middleware/access-log.js"; import { accessLogMiddleware } from "./middleware/access-log.js";
import { createCorsMiddleware } from "./middleware/cors.js"; import { createCorsMiddleware } from "./middleware/cors.js";
import { buildHealthPayload, type StartupState } from "./startup/state.js"; import { buildHealthPayload, type StartupState } from "./startup/state.js";
@@ -91,7 +90,6 @@ export function createKuaishouApp({
}); });
app.use("/api/v1/open/91", open91Router); app.use("/api/v1/open/91", open91Router);
app.use("/api/v1/webhooks", webhooksRouter);
app.use("/api/v1/claim", claimsRouter); app.use("/api/v1/claim", claimsRouter);
app.use("/api/v1/admin", adminRouter); app.use("/api/v1/admin", adminRouter);
+1 -1
View File
@@ -6,7 +6,7 @@ import dashboardRouter from "./admin/dashboard.js";
import inventoryRouter from "./admin/inventory-kuaishou.js"; import inventoryRouter from "./admin/inventory-kuaishou.js";
import messageDeliveriesRouter from "./admin/message-deliveries.js"; import messageDeliveriesRouter from "./admin/message-deliveries.js";
import ordersRouter from "./admin/orders.js"; import ordersRouter from "./admin/orders.js";
import platformConfigRouter from "./admin/platform-config.js"; import platformConfigRouter from "./admin/platform-config-kuaishou.js";
import { requireAdminSession } from "./admin/shared.js"; import { requireAdminSession } from "./admin/shared.js";
import tasksRouter from "./admin/tasks-kuaishou.js"; import tasksRouter from "./admin/tasks-kuaishou.js";
import usersRouter from "./admin/users.js"; import usersRouter from "./admin/users.js";
@@ -0,0 +1,19 @@
import { Router } from "express";
import { requireAdminRoles } from "./shared.js";
import cloudtentaclesRouter from "./platform-config/cloudtentacles.js";
import kuaishouCloudFulfillmentRouter from "./platform-config/kuaishou-cloud-fulfillment.js";
import kuaishouEticketRouter from "./platform-config/kuaishou-eticket.js";
import ninetyoneRouter from "./platform-config/ninetyone.js";
import notificationsRouter from "./platform-config/notifications.js";
const router = Router();
router.use("/platform-config", requireAdminRoles(["admin"]));
router.use("/platform-config", notificationsRouter);
router.use("/platform-config", kuaishouEticketRouter);
router.use("/platform-config", ninetyoneRouter);
router.use("/platform-config", cloudtentaclesRouter);
router.use("/platform-config", kuaishouCloudFulfillmentRouter);
export default router;
@@ -21,7 +21,7 @@ import {
useAdminCloudtentaclesSku, useAdminCloudtentaclesSku,
validateAdminCloudtentaclesSession, validateAdminCloudtentaclesSession,
verifyAdminCloudtentaclesLoginCode, verifyAdminCloudtentaclesLoginCode,
} from "../../../services/admin/platform-config/service.js"; } from "../../../services/admin/platform-config/cloudtentacles-service.js";
import type { import type {
AdminCloudtentaclesCatalogQueryRouteBody, AdminCloudtentaclesCatalogQueryRouteBody,
AdminCloudtentaclesFullFlowRouteBody, AdminCloudtentaclesFullFlowRouteBody,
@@ -3,7 +3,7 @@ import { Router } from "express";
import { import {
getAdminKuaishouCloudFulfillmentConfig, getAdminKuaishouCloudFulfillmentConfig,
updateAdminKuaishouCloudFulfillmentConfig, updateAdminKuaishouCloudFulfillmentConfig,
} from "../../../services/admin/platform-config/service.js"; } from "../../../services/admin/platform-config/kuaishou-cloud-fulfillment-service.js";
import type { AdminKuaishouCloudFulfillmentConfigRouteBody } from "../../../types/admin-route-inputs.js"; import type { AdminKuaishouCloudFulfillmentConfigRouteBody } from "../../../types/admin-route-inputs.js";
import { createJsonHandler } from "../shared.js"; import { createJsonHandler } from "../shared.js";
import type { JsonRecord } from "./shared.js"; import type { JsonRecord } from "./shared.js";
@@ -6,7 +6,7 @@ import {
queryAdminKuaishouEticketDetail, queryAdminKuaishouEticketDetail,
queryAdminKuaishouEticketShopInfo, queryAdminKuaishouEticketShopInfo,
updateAdminKuaishouEticketSourceConfig, updateAdminKuaishouEticketSourceConfig,
} from "../../../services/admin/platform-config/service.js"; } from "../../../services/admin/platform-config/kuaishou-eticket-service.js";
import type { import type {
AdminKuaishouEticketConsumeRouteBody, AdminKuaishouEticketConsumeRouteBody,
AdminKuaishouEticketDetailQueryRouteBody, AdminKuaishouEticketDetailQueryRouteBody,
@@ -4,7 +4,7 @@ import {
failAdminNinetyoneOrder, failAdminNinetyoneOrder,
getAdminNinetyoneOrders, getAdminNinetyoneOrders,
retryAdminNinetyoneOrder, retryAdminNinetyoneOrder,
} from "../../../services/admin/platform-config/service.js"; } from "../../../services/admin/platform-config/ninetyone-service.js";
import type { AdminEntityRouteParams } from "../../../types/admin-route-inputs.js"; import type { AdminEntityRouteParams } from "../../../types/admin-route-inputs.js";
import { createJsonHandler } from "../shared.js"; import { createJsonHandler } from "../shared.js";
import type { JsonRecord } from "./shared.js"; import type { JsonRecord } from "./shared.js";
@@ -7,7 +7,7 @@ import {
testAdminNotification, testAdminNotification,
updateAdminNotificationConfig, updateAdminNotificationConfig,
updateAdminScheduledJobsConfig, updateAdminScheduledJobsConfig,
} from "../../../services/admin/platform-config/service.js"; } from "../../../services/admin/platform-config/notification-service.js";
import type { import type {
AdminEntityRouteParams, AdminEntityRouteParams,
AdminNotificationConfigRouteBody, AdminNotificationConfigRouteBody,
@@ -1,16 +1,15 @@
import { Router } from "express"; import { Router } from "express";
import { replayAdminWebhookEvent } from "../../services/admin/write/webhook-events.js";
import { import {
getAdminWebhookEventDetail, getAdminWebhookEventDetail,
getAdminWebhookEvents, getAdminWebhookEvents,
} from "../../services/admin/admin-read-service.js"; } from "../../services/admin/admin-read-service.js";
import { createHttpError } from "../../utils/http.js";
import { createJsonHandler, requireAdminRoles } from "./shared.js"; import { createJsonHandler, requireAdminRoles } from "./shared.js";
import type { import type {
AdminWebhookEventRouteParams, AdminWebhookEventRouteParams,
AdminWebhookEventRouteQuery, AdminWebhookEventRouteQuery,
} from "../../types/admin-route-inputs.js"; } from "../../types/admin-route-inputs.js";
import type { AdminWebhookReplayResponse } from "../../types/admin-write-models.js";
const router = Router(); const router = Router();
@@ -47,17 +46,17 @@ router.post(
"/webhook-events/:eventId/replay", "/webhook-events/:eventId/replay",
requireAdminRoles(["admin"]), requireAdminRoles(["admin"]),
createJsonHandler( createJsonHandler(
(req) => () => {
replayAdminWebhookEvent( throw createHttpError("快手轻量后端不支持重放旧 Webhook", {
(req.params as AdminWebhookEventRouteParams).eventId statusCode: 409,
), errorCode: "admin_webhook_replay_disabled",
});
},
{ {
successMessage: "Webhook 已重放", successMessage: "Webhook 已重放",
errorMessage: "重放 webhook 失败", errorMessage: "重放 webhook 失败",
scope: "[admin-kuaishou/webhook-events/:eventId/replay]", scope: "[admin-kuaishou/webhook-events/:eventId/replay]",
audit: (req, data) => { audit: (req, data) => {
const result = data as AdminWebhookReplayResponse;
return { return {
action: "webhook_replayed", action: "webhook_replayed",
targetType: "webhook_event", targetType: "webhook_event",
@@ -65,8 +64,8 @@ router.post(
(req.params as AdminWebhookEventRouteParams).eventId (req.params as AdminWebhookEventRouteParams).eventId
), ),
data: { data: {
eventId: result.eventId, disabled: true,
replayed: result.replayed, result: data,
}, },
}; };
}, },
@@ -1,4 +1,3 @@
import { getAgisoShopConfig } from '../platforms/agiso/shop-config-service.js'
import { safeParseJson } from './admin-query-utils.js' import { safeParseJson } from './admin-query-utils.js'
import { normalizeAdminRole } from './admin-auth-service.js' import { normalizeAdminRole } from './admin-auth-service.js'
import { import {
@@ -224,13 +223,6 @@ export function resolveDisplayShopName(provider: unknown, shopId: unknown, shopN
return '' return ''
} }
if (String(provider || '').trim().toLowerCase() === 'agiso') {
const configuredName = String(getAgisoShopConfig(normalizedShopId)?.shopName || '').trim()
if (configuredName) {
return configuredName
}
}
return normalizedShopId return normalizedShopId
} }
@@ -0,0 +1,6 @@
export function normalizeAgisoMessageTemplate(value: unknown): string {
return String(value || "")
.replaceAll("\\r\\n", "\n")
.replaceAll("\\n", "\n")
.replaceAll("\r\n", "\n");
}
@@ -49,7 +49,7 @@ import {
resolveAdminCloudtentaclesCredentialPayload, resolveAdminCloudtentaclesCredentialPayload,
resolveAdminCloudtentaclesSessionPayload, resolveAdminCloudtentaclesSessionPayload,
} from "./cloudtentacles.js"; } from "./cloudtentacles.js";
import { normalizeAdminCloudtentaclesSourceConfigPayload } from "./writes.js"; import { normalizeAdminCloudtentaclesSourceConfigPayload } from "./cloudtentacles-writes.js";
import { import {
mapAdminCloudtentaclesSession, mapAdminCloudtentaclesSession,
mapAdminCloudtentaclesSourceConfig, mapAdminCloudtentaclesSourceConfig,
@@ -0,0 +1,19 @@
type JsonObject = Record<string, any>;
export function normalizeAdminCloudtentaclesSourceConfigPayload(
payload: JsonObject = {}
) {
const sourceKey =
String(payload.sourceKey || payload.key || "").trim() || "default";
return {
key: sourceKey,
label: String(payload.label || "").trim(),
enabled: payload.enabled !== false,
baseUrl: String(payload.baseUrl || "").trim() || "https://123.207.217.176",
username: String(payload.username || "").trim(),
password: String(payload.password || "").trim(),
phone: String(payload.phone || "").trim(),
deviceId: String(payload.deviceId || "-").trim() || "-",
deviceType: Number(payload.deviceType || 0),
};
}
@@ -1,4 +1,4 @@
import { normalizeAgisoMessageTemplate } from '../../platforms/agiso/xianyu/message-service.js' import { normalizeAgisoMessageTemplate } from './agiso-template.js'
import { maskSecret } from './mappers.js' import { maskSecret } from './mappers.js'
type JsonObject = Record<string, any> type JsonObject = Record<string, any>
@@ -98,19 +98,3 @@ export function buildAdminAgisoMessagingSavePayload(
shops: nextMap, shops: nextMap,
}; };
} }
export function normalizeAdminCloudtentaclesSourceConfigPayload(payload: JsonObject = {}) {
const sourceKey =
String(payload.sourceKey || payload.key || "").trim() || "default";
return {
key: sourceKey,
label: String(payload.label || "").trim(),
enabled: payload.enabled !== false,
baseUrl: String(payload.baseUrl || "").trim() || "https://123.207.217.176",
username: String(payload.username || "").trim(),
password: String(payload.password || "").trim(),
phone: String(payload.phone || "").trim(),
deviceId: String(payload.deviceId || "-").trim() || "-",
deviceType: Number(payload.deviceType || 0),
};
}
@@ -5,10 +5,7 @@ import {
updateOrder, updateOrder,
} from '../../repositories/order-repo.js' } from '../../repositories/order-repo.js'
import { replaceOrderItems } from '../../repositories/order-item-repo.js' import { replaceOrderItems } from '../../repositories/order-item-repo.js'
import { getClaimTokenById } from '../../repositories/claim-token-repo.js'
import { buildClaimUrl } from '../claim/claim-service.js'
import { syncDeliveryTasksForOrder } from './delivery-task-service.js' import { syncDeliveryTasksForOrder } from './delivery-task-service.js'
import { ensureAgisoXianyuClaimMessageDeliveredForTask } from '../platforms/agiso/xianyu/message-service.js'
import { resolveOrderItemForFulfillment } from './product-match-service.js' import { resolveOrderItemForFulfillment } from './product-match-service.js'
import { nowIso } from '../../utils/time.js' import { nowIso } from '../../utils/time.js'
import { logWebhook } from '../../utils/logger.js' import { logWebhook } from '../../utils/logger.js'
@@ -51,6 +48,11 @@ type SourceOrderEvent = {
type UpsertOrderSourceOptions = { type UpsertOrderSourceOptions = {
sourceLabel?: string sourceLabel?: string
handleClaimLinkTask?: (input: {
event: SourceOrderEvent
order: OrderRow
task: TaskRow
}) => Promise<Record<string, unknown> | null | undefined>
} }
type MessageDeliveryResult = { type MessageDeliveryResult = {
@@ -99,7 +101,7 @@ export async function upsertOrderFromWebhook(event: SourceOrderEvent): Promise<U
export async function upsertOrderFromSource( export async function upsertOrderFromSource(
event: SourceOrderEvent, event: SourceOrderEvent,
{ sourceLabel = 'source' }: UpsertOrderSourceOptions = {}, { sourceLabel = 'source', handleClaimLinkTask }: UpsertOrderSourceOptions = {},
): Promise<UpsertOrderResult> { ): Promise<UpsertOrderResult> {
const now = nowIso() const now = nowIso()
const exactExisting = await findOrderByPlatformOrderId({ const exactExisting = await findOrderByPlatformOrderId({
@@ -219,37 +221,28 @@ export async function upsertOrderFromSource(
resolvedSkuCodes: configuredItems.map((item) => item.skuCode), resolvedSkuCodes: configuredItems.map((item) => item.skuCode),
}) })
for (const task of tasks) { if (handleClaimLinkTask) {
const isClaimLinkTask = String(task.task_status || '') === 'link_generated' for (const task of tasks) {
|| ( const isClaimLinkTask = String(task.task_status || '') === 'link_generated'
String(task.executor_key || '').trim() === 'kuaishou_ct_assisted' || (
&& ['pending_binding_prepare', 'waiting_binding', 'role_confirmed', 'dispatched_pending_return'].includes(String(task.task_status || '').trim()) String(task.executor_key || '').trim() === 'kuaishou_ct_assisted'
) && ['pending_binding_prepare', 'waiting_binding', 'role_confirmed', 'dispatched_pending_return'].includes(String(task.task_status || '').trim())
)
if ( if (!isClaimLinkTask || !task.primary_claim_token_id) {
event.provider !== 'agiso' continue
|| event.platform !== 'xianyu' }
|| !isClaimLinkTask
|| !task.primary_claim_token_id const result = await handleClaimLinkTask({ event, order, task })
) { if (!result) {
continue continue
}
messageDeliveries.push({
taskId: task.id,
...result,
})
} }
const claimToken = await getClaimTokenById(task.primary_claim_token_id)
if (!claimToken) {
continue
}
const result = await ensureAgisoXianyuClaimMessageDeliveredForTask({
order,
task,
claimUrl: buildClaimUrl(claimToken.token),
expiredAt: claimToken.expired_at,
})
messageDeliveries.push({
taskId: task.id,
...result,
})
} }
return { return {
@@ -1,14 +1,17 @@
import crypto from 'node:crypto' import crypto from 'node:crypto'
import { runtimeConfig } from '../../config/runtime.js' import { runtimeConfig } from '../../config/runtime.js'
import { getClaimTokenById } from '../../repositories/claim-token-repo.js'
import { createWebhookEvent, updateWebhookEvent } from '../../repositories/webhook-event-repo.js' import { createWebhookEvent, updateWebhookEvent } from '../../repositories/webhook-event-repo.js'
import { buildClaimUrl } from '../claim/claim-service.js'
import { ensureAgisoXianyuClaimMessageDeliveredForTask } from '../platforms/agiso/xianyu/message-service.js'
import { enrichAgisoXianyuTradeOrder } from '../platforms/agiso/xianyu/order-detail-service.js' import { enrichAgisoXianyuTradeOrder } from '../platforms/agiso/xianyu/order-detail-service.js'
import { import {
extractAgisoTradeOrderItemSources, extractAgisoTradeOrderItemSources,
extractAgisoTradePayload, extractAgisoTradePayload,
resolveAgisoTradePlatformOrderId, resolveAgisoTradePlatformOrderId,
} from './agiso-trade-parsing.js' } from './agiso-trade-parsing.js'
import { upsertOrderFromWebhook } from './order-service.js' import { upsertOrderFromSource, upsertOrderFromWebhook } from './order-service.js'
import { hasConfiguredOrderItems } from './product-match-service.js' import { hasConfiguredOrderItems } from './product-match-service.js'
import { createHttpError } from '../../utils/http.js' import { createHttpError } from '../../utils/http.js'
import { parseJsonObject } from '../../utils/json.js' import { parseJsonObject } from '../../utils/json.js'
@@ -98,7 +101,7 @@ export async function executeAgisoTradeWebhookWithDeps(
) { ) {
const updateEvent = deps.updateWebhookEvent || updateWebhookEvent const updateEvent = deps.updateWebhookEvent || updateWebhookEvent
const hasConfiguredItems = deps.hasConfiguredOrderItems || hasConfiguredOrderItems const hasConfiguredItems = deps.hasConfiguredOrderItems || hasConfiguredOrderItems
const upsertOrder = deps.upsertOrderFromWebhook || upsertOrderFromWebhook const upsertOrder = deps.upsertOrderFromWebhook || upsertAgisoOrderFromWebhook
try { try {
if (!parsed.signatureValid) { if (!parsed.signatureValid) {
@@ -287,6 +290,25 @@ export async function executeAgisoTradeWebhookWithDeps(
} }
} }
async function upsertAgisoOrderFromWebhook(event) {
return upsertOrderFromSource(event, {
sourceLabel: 'webhook',
handleClaimLinkTask: async ({ order, task }) => {
const claimToken = await getClaimTokenById(task.primary_claim_token_id)
if (!claimToken) {
return null
}
return ensureAgisoXianyuClaimMessageDeliveredForTask({
order,
task,
claimUrl: buildClaimUrl(claimToken.token),
expiredAt: claimToken.expired_at,
})
},
})
}
async function enrichTradeBeforeUpsert( async function enrichTradeBeforeUpsert(
parsed, parsed,
{ requestId = '', webhookEventId = null } = {}, { requestId = '', webhookEventId = null } = {},
@@ -1,6 +1,7 @@
import crypto from 'node:crypto' import crypto from 'node:crypto'
import { runtimeConfig } from '../../../../config/runtime.js' import { runtimeConfig } from '../../../../config/runtime.js'
import { normalizeAgisoMessageTemplate } from '../../../admin/platform-config/agiso-template.js'
import { getAgisoMessagingDefaults, getAgisoShopConfigMap } from '../shop-config-service.js' import { getAgisoMessagingDefaults, getAgisoShopConfigMap } from '../shop-config-service.js'
import { import {
createMessageDelivery, createMessageDelivery,
@@ -193,13 +194,6 @@ export async function ensureAgisoXianyuAutoDeliveryMessageDeliveredForTask({
}) })
} }
export function normalizeAgisoMessageTemplate(value: unknown): string {
return String(value || '')
.replaceAll('\\r\\n', '\n')
.replaceAll('\\n', '\n')
.replaceAll('\r\n', '\n')
}
async function deliverAgisoXianyuMessageForTask({ async function deliverAgisoXianyuMessageForTask({
order, order,
task, task,
+1
View File
@@ -3,6 +3,7 @@
"files": [ "files": [
"src/index-kuaishou.ts" "src/index-kuaishou.ts"
], ],
"include": [],
"exclude": [ "exclude": [
"node_modules", "node_modules",
"data", "data",