行业电子凭证接入
- 新增 4 个回调接口:send-code/destroy-code/query-code/consume-code - 支持快手开放平台 MD5/HMAC_SHA256 签名验签 - send-code 回调自动创建 order/order_items/fulfillment_tasks/profiles - consume-code 回调与既有 flow.consume 结构兼容 - isKuaishouCloudTask 同时匹配 kuaishou-industry executor_key - claim 页面自动验证行业凭证 task,跳过核销码输入 - 退回时行业 task 跳过快手核销 API - 新增 KUASHOU_INDUSTRY_* 环境变量配置
This commit is contained in:
@@ -47,7 +47,13 @@ export async function verifyKuaishouCloudClaimTicket(token: unknown, payload: Js
|
||||
const context = await getClaimContext(token)
|
||||
const now = nowIso()
|
||||
|
||||
if (String(context.task.executor_key || '').trim() !== 'kuaishou_ct_assisted') {
|
||||
const executorKey = String(context.task.executor_key || '').trim()
|
||||
|
||||
if (executorKey === 'kuaishou-industry') {
|
||||
return verifyIndustryeVoucherTicket(context, now)
|
||||
}
|
||||
|
||||
if (executorKey !== 'kuaishou_ct_assisted') {
|
||||
throw createHttpError('当前领取链接不是快手 Cloud 客户领取流程', {
|
||||
statusCode: 409,
|
||||
errorCode: 'claim_not_kuaishou_cloud',
|
||||
@@ -237,6 +243,96 @@ export async function verifyKuaishouCloudClaimTicket(token: unknown, payload: Js
|
||||
return getKuaishouCloudClaimDetail(token)
|
||||
}
|
||||
|
||||
async function verifyIndustryeVoucherTicket(
|
||||
context: Awaited<ReturnType<typeof getClaimContext>>,
|
||||
now: string,
|
||||
) {
|
||||
const taskContext = parseTaskContext(context.task)
|
||||
const flow = normalizeKuaishouCloudFlow(taskContext.kuaishouCloudFulfillment)
|
||||
|
||||
if (flow.consume.status === 'success') {
|
||||
return getKuaishouCloudClaimDetail(context.claimToken.token)
|
||||
}
|
||||
|
||||
const industryContext = typeof taskContext === 'object' ? taskContext : {}
|
||||
const token = String(industryContext.token || '').trim()
|
||||
const certExpireType = Number(industryContext.certExpireType || 0)
|
||||
const certActualStartTime = Number(industryContext.certActualStartTime || 0)
|
||||
const certActualEndTime = Number(industryContext.certActualEndTime || 0)
|
||||
|
||||
const nextContext = {
|
||||
...taskContext,
|
||||
kuaishouCloudFulfillment: {
|
||||
...flow,
|
||||
ticket: {
|
||||
...flow.ticket,
|
||||
code: '',
|
||||
status: 'verified',
|
||||
capturedAt: flow.ticket.capturedAt || now,
|
||||
capturedBy: flow.ticket.capturedBy || { source: 'send_code_callback' },
|
||||
verifiedAt: now,
|
||||
oid: context.order.platform_order_id,
|
||||
formToken: token,
|
||||
leftCount: 0,
|
||||
goodsTitle: context.orderItem.sku_name || context.orderItem.sku_code || '',
|
||||
},
|
||||
consume: {
|
||||
...flow.consume,
|
||||
status: 'pending',
|
||||
shopId: context.order.shop_id,
|
||||
shopName: context.order.shop_name,
|
||||
autoConsumeEnabled: true,
|
||||
},
|
||||
certInfo: {
|
||||
certExpireType,
|
||||
certActualStartTime,
|
||||
certActualEndTime,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const taskWithTicket = (await updateTask(context.task.id, {
|
||||
claim_token: context.claimToken.token,
|
||||
claim_expires_at: context.claimToken.expired_at,
|
||||
context_json: JSON.stringify(nextContext),
|
||||
claimed_at: context.task.claimed_at || now,
|
||||
task_status: TASK_STATUS.WAITING_BINDING,
|
||||
user_action_status: 'pending_claim',
|
||||
last_error: '',
|
||||
updated_at: now,
|
||||
})) || {
|
||||
...context.task,
|
||||
context_json: JSON.stringify(nextContext),
|
||||
claimed_at: context.task.claimed_at || now,
|
||||
task_status: TASK_STATUS.WAITING_BINDING,
|
||||
user_action_status: 'pending_claim',
|
||||
last_error: '',
|
||||
updated_at: now,
|
||||
}
|
||||
|
||||
const preparedFlow = normalizeKuaishouCloudFlow(nextContext.kuaishouCloudFulfillment)
|
||||
if (preparedFlow.binding.prepareStatus !== 'ready' || !preparedFlow.binding.bindUrl) {
|
||||
await prepareKuaishouCloudFulfillmentTask(taskWithTicket, {
|
||||
source: 'send_code_callback',
|
||||
actor: { source: 'send_code_callback' },
|
||||
})
|
||||
}
|
||||
|
||||
await createTaskEvent(
|
||||
context.task.id,
|
||||
'kuaishou_cloud_ticket_verified',
|
||||
{
|
||||
ticketCodeMasked: '',
|
||||
source: 'send_code_callback',
|
||||
industryVoucher: true,
|
||||
verifiedAt: now,
|
||||
},
|
||||
now,
|
||||
)
|
||||
|
||||
return getKuaishouCloudClaimDetail(context.claimToken.token)
|
||||
}
|
||||
|
||||
export async function getKuaishouCloudClaimGuideAssetPath(filename: unknown) {
|
||||
const normalized = String(filename || '').trim()
|
||||
if (!ALLOWED_GUIDE_FILES.has(normalized)) {
|
||||
@@ -261,8 +357,18 @@ export async function getKuaishouCloudClaimDetail(token: unknown) {
|
||||
const context = await getClaimContext(token)
|
||||
let task = context.task
|
||||
|
||||
const executorKey = String(task.executor_key || '').trim()
|
||||
|
||||
if (executorKey === 'kuaishou-industry') {
|
||||
const flow = normalizeKuaishouCloudFlow(parseTaskContext(task).kuaishouCloudFulfillment)
|
||||
if (flow.consume.status !== 'success') {
|
||||
const now = nowIso()
|
||||
await verifyIndustryeVoucherTicket(context, now).catch(() => null)
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
String(task.executor_key || '').trim() === 'kuaishou_ct_assisted' &&
|
||||
executorKey === 'kuaishou_ct_assisted' &&
|
||||
!isKuaishouCloudMockTask(task)
|
||||
) {
|
||||
task = (await syncKuaishouCloudRoleInfo(task)) || task
|
||||
|
||||
Reference in New Issue
Block a user