移除快手小店以及 api

This commit is contained in:
yml2213
2026-07-09 21:03:39 +08:00
parent a075b8acf7
commit ffbc19a9db
38 changed files with 110 additions and 2724 deletions
@@ -17,18 +17,12 @@ import {
backCloudtentaclesVirtualNumber,
getCloudtentaclesBindInfo,
} from '../../platforms/cloudtentacles/virtual-number-service.js'
import { consumeKuaishouEticket } from '../../platforms/kuaishou-eticket/consume-service.js'
import { isKuaishouEticketMockTicketCode } from '../../platforms/kuaishou-eticket/mock-ticket-service.js'
import { resendKuaishouIndustryVoucherSendCallback } from '../../platforms/kuaishou-industry/send-code-service.js'
import { consumeKuaishouIndustryVoucher } from '../../platforms/kuaishou-industry/voucher-service.js'
import {
attachKuaishouIndustryVoucherToTask,
bindKuaishouIndustryVouchersToOrderTasks,
} from '../../platforms/kuaishou-industry/voucher-binding-service.js'
import {
getKuaishouEticketSourceConfig,
resolveKuaishouEticketShopConfig,
} from '../../platforms/kuaishou-eticket/source-config-service.js'
import { createHttpError } from '../../../utils/http.js'
import { nowIso } from '../../../utils/time.js'
import { TASK_STATUS } from '../../../domain/task-status.js'
@@ -58,7 +52,6 @@ import type {
AdminViewerSessionInput,
} from '../../../types/admin/read-inputs.js'
import type {
AdminTaskKuaishouCloudDispatchInput,
AdminTaskKuaishouIndustryConsumeInput,
} from '../../../types/admin/write-inputs.js'
import type { AdminTaskActionResponse } from '../../../types/admin/write-models.js'
@@ -246,7 +239,6 @@ export async function prepareAdminTaskKuaishouCloudFulfillment(
export async function dispatchAdminTaskKuaishouCloudFulfillment(
taskId: AdminEntityIdInput,
payload: AdminTaskKuaishouCloudDispatchInput = {},
session: AdminViewerSessionInput | null = null,
): Promise<AdminTaskActionResponse> {
const task = await getRequiredTask(taskId)
@@ -281,11 +273,15 @@ export async function dispatchAdminTaskKuaishouCloudFulfillment(
})
}
const ticketCode = String(payload.ticketCode || '').trim()
const persistedTicketCode = String(flow.ticket.code || '').trim()
const voucherContext = normalizeAdminTaskIndustryVoucherContext(taskContext.kuaishouIndustryVoucher)
const industryVoucherCode = String(
voucherContext.voucherCode || voucherContext.eticketId || '',
).trim()
const resolvedTicketCode = persistedTicketCode || industryVoucherCode
if (!persistedTicketCode && !ticketCode) {
throw createHttpError('客户还没有在领取页提交核销码,暂时不能直接发货', {
if (!resolvedTicketCode) {
throw createHttpError('旧快手小店核销流程已停用,请改用行业电子凭证处理', {
statusCode: 409,
errorCode: 'admin_task_kuaishou_cloud_missing_ticket_code',
})
@@ -322,16 +318,9 @@ export async function dispatchAdminTaskKuaishouCloudFulfillment(
...syncedFlow,
ticket: {
...syncedFlow.ticket,
code: ticketCode || persistedTicketCode,
capturedAt: ticketCode ? now : syncedFlow.ticket.capturedAt,
capturedBy:
ticketCode && session
? {
userId: Number(session.userId || 0) || 0,
username: String(session.username || '').trim(),
role: String(session.role || '').trim(),
}
: syncedFlow.ticket.capturedBy,
code: resolvedTicketCode,
capturedAt: resolvedTicketCode ? (syncedFlow.ticket.capturedAt || now) : syncedFlow.ticket.capturedAt,
capturedBy: syncedFlow.ticket.capturedBy,
},
dispatch: {
...syncedFlow.dispatch,
@@ -366,7 +355,7 @@ export async function dispatchAdminTaskKuaishouCloudFulfillment(
task.id,
'kuaishou_cloud_dispatched',
{
ticketCodeMasked: maskCode(ticketCode || persistedTicketCode),
ticketCodeMasked: maskCode(resolvedTicketCode),
skuId: syncedFlow.binding.skuId,
vnId: syncedFlow.binding.vnId,
vnPhoneMasked: maskPhone(syncedFlow.binding.vnPhone),
@@ -548,77 +537,18 @@ export async function returnNumberAdminTaskKuaishouCloudFulfillment(
id: flow.binding.vnId,
})
const order = await getOrderById(task.order_id)
const ticketCode = String(flow.ticket.code || '').trim()
const shopId = String(flow.consume.shopId || order?.shop_id || '').trim()
const shopName = String(flow.consume.shopName || order?.shop_name || '').trim()
const mockTicketCode = isKuaishouEticketMockTicketCode(ticketCode)
const eticketSource = getKuaishouEticketSourceConfig()
const shopConfig = resolveKuaishouEticketShopConfig({
shopId,
shopName,
})
let consumeStatus = 'pending'
let consumeErrorMessage = ''
let consumedAt = null
let nextTaskStatus = 'completed'
let nextResultCode = 'kuaishou_cloud_completed'
let nextResultMessage = 'cloudtentacles 发货、退号并完成快手核销'
const consumeAlreadyCompleted = flow.consume.status === 'success'
if (consumeAlreadyCompleted) {
consumeStatus = 'success'
consumedAt = flow.consume.consumedAt || now
} else if (!order) {
consumeStatus = 'failed'
consumeErrorMessage = '任务关联订单不存在,无法执行快手核销'
} else if (!ticketCode) {
consumeStatus = 'failed'
consumeErrorMessage = '客户未提交有效核销码,无法执行快手核销'
} else if (mockTicketCode) {
const consumeResult = await consumeKuaishouEticket({
eTicketId: ticketCode,
oid: String(flow.ticket.oid || '').trim(),
formToken: String(flow.ticket.formToken || '').trim(),
})
consumeStatus = consumeResult.consumed ? 'success' : 'failed'
consumedAt = consumeResult.consumed ? now : null
consumeErrorMessage = String(consumeResult.errorMessage || '').trim()
} else if (
!shopConfig ||
shopConfig.enabled === false ||
!String(shopConfig.cookie || '').trim()
) {
consumeStatus = 'failed'
consumeErrorMessage = '订单对应快手小店缺少可用 Cookie,无法执行快手核销'
} else {
try {
const consumeResult = await consumeKuaishouEticket({
baseUrl: eticketSource.baseUrl,
cookie: shopConfig.cookie,
eTicketId: ticketCode,
oid: String(flow.ticket.oid || '').trim(),
formToken: String(flow.ticket.formToken || '').trim(),
})
if (consumeResult.consumed) {
consumeStatus = 'success'
consumedAt = now
} else {
consumeStatus = 'failed'
consumeErrorMessage = String(consumeResult.errorMessage || '快手核销失败').trim()
}
} catch (error) {
consumeStatus = 'failed'
consumeErrorMessage = error instanceof Error ? error.message : '快手核销失败'
}
}
if (consumeStatus !== 'success') {
nextTaskStatus = 'manual_review'
nextResultCode = 'kuaishou_cloud_consume_failed'
nextResultMessage = consumeErrorMessage || '号码已退还,但快手核销未完成,请人工处理'
}
const consumeStatus = consumeAlreadyCompleted ? 'success' : 'skipped'
let consumeErrorMessage = ''
const consumedAt = consumeAlreadyCompleted ? flow.consume.consumedAt || now : null
const nextTaskStatus = 'completed'
const nextResultCode = consumeAlreadyCompleted
? 'kuaishou_cloud_completed'
: 'kuaishou_cloud_completed_without_eticket_consume'
const nextResultMessage = consumeAlreadyCompleted
? 'cloudtentacles 发货、退号并完成电子凭证核销'
: 'cloudtentacles 发货、退号并收口'
const nextContext = {
...taskContext,
@@ -639,8 +569,8 @@ export async function returnNumberAdminTaskKuaishouCloudFulfillment(
consume: {
...flow.consume,
status: consumeStatus,
shopId: shopId || flow.consume.shopId,
shopName,
shopId: flow.consume.shopId,
shopName: flow.consume.shopName,
autoConsumeEnabled: flow.consume.autoConsumeEnabled === true,
consumedAt,
errorMessage: consumeErrorMessage,
@@ -653,7 +583,7 @@ export async function returnNumberAdminTaskKuaishouCloudFulfillment(
delivery_status: 'delivered',
result_code: nextResultCode,
result_message: nextResultMessage,
redeemed_at: consumeStatus === 'success' ? now : task.redeemed_at,
redeemed_at: now,
last_error: consumeErrorMessage,
context_json: JSON.stringify(nextContext),
updated_at: now,
@@ -669,18 +599,19 @@ export async function returnNumberAdminTaskKuaishouCloudFulfillment(
now,
)
const consumeEventType = consumeAlreadyCompleted
? 'kuaishou_cloud_consume_already_completed'
: 'kuaishou_cloud_consume_skipped'
await createTaskEvent(
task.id,
consumeAlreadyCompleted
? 'kuaishou_cloud_consume_already_completed'
: consumeStatus === 'success'
? 'kuaishou_cloud_consumed'
: 'kuaishou_cloud_consume_failed',
consumeEventType,
{
ticketCodeMasked: maskCode(ticketCode),
shopId,
shopName,
shopId: flow.consume.shopId,
shopName: flow.consume.shopName,
consumeStatus,
consumeMode: 'legacy_writeoff_disabled',
errorMessage: consumeErrorMessage,
},
now,
@@ -961,7 +892,7 @@ async function getRequiredIndustryVoucherForTask(task: TaskRow): Promise<Kuaisho
}
const taskContext = parseTaskContext(task)
const voucherContext = taskContext.kuaishouIndustryVoucher || {}
const voucherContext = normalizeAdminTaskIndustryVoucherContext(taskContext.kuaishouIndustryVoucher)
const voucherCode = String(voucherContext.voucherCode || voucherContext.eticketId || '').trim()
if (voucherCode) {
const voucher = await findKuaishouIndustryVoucherByCode(voucherCode, task.platform_order_id)
@@ -1000,6 +931,12 @@ async function getRequiredIndustryVoucherForTask(task: TaskRow): Promise<Kuaisho
})
}
function normalizeAdminTaskIndustryVoucherContext(value: unknown): Record<string, any> {
return value && typeof value === 'object' && !Array.isArray(value)
? value as Record<string, any>
: {}
}
async function resolveIndustryVouchersForOrder(platformOrderId: string): Promise<KuaishouIndustryVoucherRow[]> {
const normalizedOid = String(platformOrderId || '').trim()
if (!normalizedOid) {