添加快手 Cloud 换绑角色功能
This commit is contained in:
@@ -26,6 +26,7 @@ import {
|
||||
maskCode,
|
||||
normalizeKuaishouCloudFlow,
|
||||
prepareKuaishouCloudFulfillmentTask,
|
||||
rebindKuaishouCloudTaskRole,
|
||||
refreshKuaishouCloudTaskRoleInfo,
|
||||
} from '../fulfillment/kuaishou-cloud/index.js'
|
||||
import { buildClaimDetailPayload, getClaimContext } from './kuaishou-cloud-claim-context.js'
|
||||
@@ -59,7 +60,9 @@ export async function verifyKuaishouCloudClaimTicket(token: unknown, payload: Js
|
||||
}
|
||||
|
||||
const mockTicketCode = isKuaishouEticketMockTicketCode(ticketCode)
|
||||
let shopId = String(flow.consume.shopId || context.order.shop_id || (mockTicketCode ? 'mock' : '')).trim()
|
||||
let shopId = String(
|
||||
flow.consume.shopId || context.order.shop_id || (mockTicketCode ? 'mock' : ''),
|
||||
).trim()
|
||||
let shopName = String(flow.consume.shopName || context.order.shop_name || '').trim()
|
||||
let detailResult
|
||||
|
||||
@@ -134,13 +137,16 @@ export async function verifyKuaishouCloudClaimTicket(token: unknown, payload: Js
|
||||
} else {
|
||||
const preparedFlow = normalizeKuaishouCloudFlow(nextContext.kuaishouCloudFulfillment)
|
||||
if (preparedFlow.binding.prepareStatus !== 'ready' || !preparedFlow.binding.bindUrl) {
|
||||
await prepareKuaishouCloudFulfillmentTask({
|
||||
...context.task,
|
||||
context_json: JSON.stringify(nextContext),
|
||||
}, {
|
||||
source: 'claim_page_ticket_verified',
|
||||
actor: { source: 'claim_page' },
|
||||
})
|
||||
await prepareKuaishouCloudFulfillmentTask(
|
||||
{
|
||||
...context.task,
|
||||
context_json: JSON.stringify(nextContext),
|
||||
},
|
||||
{
|
||||
source: 'claim_page_ticket_verified',
|
||||
actor: { source: 'claim_page' },
|
||||
},
|
||||
)
|
||||
} else {
|
||||
await updateTask(context.task.id, {
|
||||
claim_token: context.claimToken.token,
|
||||
@@ -159,13 +165,18 @@ export async function verifyKuaishouCloudClaimTicket(token: unknown, payload: Js
|
||||
}
|
||||
}
|
||||
|
||||
await createTaskEvent(context.task.id, 'kuaishou_cloud_ticket_verified', {
|
||||
ticketCodeMasked: maskCode(detailResult.eTicketId || ticketCode),
|
||||
shopId,
|
||||
shopName,
|
||||
goodsTitle: String(detailResult.goods?.itemTitle || '').trim(),
|
||||
mock: mockTicketCode,
|
||||
}, now)
|
||||
await createTaskEvent(
|
||||
context.task.id,
|
||||
'kuaishou_cloud_ticket_verified',
|
||||
{
|
||||
ticketCodeMasked: maskCode(detailResult.eTicketId || ticketCode),
|
||||
shopId,
|
||||
shopName,
|
||||
goodsTitle: String(detailResult.goods?.itemTitle || '').trim(),
|
||||
mock: mockTicketCode,
|
||||
},
|
||||
now,
|
||||
)
|
||||
|
||||
return getKuaishouCloudClaimDetail(token)
|
||||
}
|
||||
@@ -195,10 +206,10 @@ export async function getKuaishouCloudClaimDetail(token: unknown) {
|
||||
let task = context.task
|
||||
|
||||
if (
|
||||
String(task.executor_key || '').trim() === 'kuaishou_ct_assisted'
|
||||
&& !isKuaishouCloudMockTask(task)
|
||||
String(task.executor_key || '').trim() === 'kuaishou_ct_assisted' &&
|
||||
!isKuaishouCloudMockTask(task)
|
||||
) {
|
||||
task = await syncKuaishouCloudRoleInfo(task) || task
|
||||
task = (await syncKuaishouCloudRoleInfo(task)) || task
|
||||
}
|
||||
|
||||
return buildClaimDetailPayload({
|
||||
@@ -209,6 +220,24 @@ export async function getKuaishouCloudClaimDetail(token: unknown) {
|
||||
})
|
||||
}
|
||||
|
||||
export async function rebindKuaishouCloudClaimRole(token: unknown) {
|
||||
const context = await getClaimContext(token)
|
||||
|
||||
if (String(context.task.executor_key || '').trim() !== 'kuaishou_ct_assisted') {
|
||||
throw createHttpError('当前领取链接不是快手 Cloud 客户领取流程', {
|
||||
statusCode: 409,
|
||||
errorCode: 'claim_not_kuaishou_cloud',
|
||||
})
|
||||
}
|
||||
|
||||
await rebindKuaishouCloudTaskRole(context.task, {
|
||||
source: 'claim_page_rebind_role',
|
||||
actor: { source: 'claim_page' },
|
||||
})
|
||||
|
||||
return getKuaishouCloudClaimDetail(token)
|
||||
}
|
||||
|
||||
function parseTaskContext(task: Partial<TaskRow> | null | undefined): JsonObject {
|
||||
const rawValue = task?.context_json
|
||||
if (!rawValue) {
|
||||
@@ -289,10 +318,13 @@ async function queryKuaishouEticketConsumeDetailWithShopFallback({
|
||||
}
|
||||
}
|
||||
|
||||
throw createHttpError(lastError instanceof Error ? lastError.message : '核销码校验失败,请确认是否复制完整', {
|
||||
statusCode: 409,
|
||||
errorCode: 'claim_kuaishou_cloud_ticket_invalid',
|
||||
})
|
||||
throw createHttpError(
|
||||
lastError instanceof Error ? lastError.message : '核销码校验失败,请确认是否复制完整',
|
||||
{
|
||||
statusCode: 409,
|
||||
errorCode: 'claim_kuaishou_cloud_ticket_invalid',
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
function resolveKuaishouEticketDetailCandidateShops({
|
||||
@@ -333,9 +365,7 @@ function isUsableKuaishouEticketShopConfig(
|
||||
shopConfig: KuaishouEticketShopConfig | null | undefined,
|
||||
): shopConfig is KuaishouEticketShopConfig {
|
||||
return Boolean(
|
||||
shopConfig &&
|
||||
shopConfig.enabled !== false &&
|
||||
String(shopConfig.cookie || '').trim(),
|
||||
shopConfig && shopConfig.enabled !== false && String(shopConfig.cookie || '').trim(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -373,11 +403,11 @@ export async function confirmKuaishouCloudClaimRole(token: unknown) {
|
||||
const refreshed = mockMode
|
||||
? { task: context.task }
|
||||
: await refreshKuaishouCloudTaskRoleInfo(context.task, {
|
||||
source: 'claim_page_role_confirm',
|
||||
actor: { source: 'claim_page' },
|
||||
recordEvent: false,
|
||||
forceProbe: true,
|
||||
})
|
||||
source: 'claim_page_role_confirm',
|
||||
actor: { source: 'claim_page' },
|
||||
recordEvent: false,
|
||||
forceProbe: true,
|
||||
})
|
||||
const flow = normalizeKuaishouCloudFlow(parseTaskContext(refreshed.task).kuaishouCloudFulfillment)
|
||||
|
||||
if (flow.ticket.status !== 'verified') {
|
||||
@@ -404,11 +434,16 @@ export async function confirmKuaishouCloudClaimRole(token: unknown) {
|
||||
updated_at: now,
|
||||
})
|
||||
|
||||
await createTaskEvent(context.task.id, 'kuaishou_cloud_role_confirmed', {
|
||||
vnPhone: flow.binding.vnPhone,
|
||||
roleName: flow.binding.roleName,
|
||||
roleId: flow.binding.roleId,
|
||||
}, now)
|
||||
await createTaskEvent(
|
||||
context.task.id,
|
||||
'kuaishou_cloud_role_confirmed',
|
||||
{
|
||||
vnPhone: flow.binding.vnPhone,
|
||||
roleName: flow.binding.roleName,
|
||||
roleId: flow.binding.roleId,
|
||||
},
|
||||
now,
|
||||
)
|
||||
|
||||
return getKuaishouCloudClaimDetail(token)
|
||||
}
|
||||
@@ -474,10 +509,15 @@ export async function redeemKuaishouCloudClaim(token: unknown) {
|
||||
updated_at: nowIso(),
|
||||
})
|
||||
|
||||
await createTaskEvent(lockedTask.id, 'kuaishou_cloud_redeem_failed', {
|
||||
source: 'claim_page_redeem',
|
||||
errorMessage: message,
|
||||
}, nowIso())
|
||||
await createTaskEvent(
|
||||
lockedTask.id,
|
||||
'kuaishou_cloud_redeem_failed',
|
||||
{
|
||||
source: 'claim_page_redeem',
|
||||
errorMessage: message,
|
||||
},
|
||||
nowIso(),
|
||||
)
|
||||
|
||||
throw error
|
||||
}
|
||||
@@ -490,10 +530,10 @@ function isKuaishouCloudMockTask(task: Partial<TaskRow> | null | undefined) {
|
||||
}
|
||||
|
||||
function isKuaishouCloudMockContext(context: JsonObject = {}) {
|
||||
const flow = context.kuaishouCloudFulfillment
|
||||
&& typeof context.kuaishouCloudFulfillment === 'object'
|
||||
? context.kuaishouCloudFulfillment
|
||||
: {}
|
||||
const flow =
|
||||
context.kuaishouCloudFulfillment && typeof context.kuaishouCloudFulfillment === 'object'
|
||||
? context.kuaishouCloudFulfillment
|
||||
: {}
|
||||
const mock = flow.mock && typeof flow.mock === 'object' ? flow.mock : context.mock
|
||||
|
||||
return Boolean(mock && typeof mock === 'object' && mock.enabled === true)
|
||||
@@ -502,8 +542,9 @@ function isKuaishouCloudMockContext(context: JsonObject = {}) {
|
||||
function buildMockVerifiedKuaishouCloudFlow(value: unknown, timestamp: string) {
|
||||
const flow = normalizeKuaishouCloudFlow(value)
|
||||
const source = flow as JsonObject
|
||||
const bindUrl = flow.binding.bindUrl
|
||||
|| `https://example.com/mock-kuaishou-cloud-bind?task=mock&ts=${encodeURIComponent(timestamp)}`
|
||||
const bindUrl =
|
||||
flow.binding.bindUrl ||
|
||||
`https://example.com/mock-kuaishou-cloud-bind?task=mock&ts=${encodeURIComponent(timestamp)}`
|
||||
const vnPhone = flow.binding.vnPhone || '13800000000'
|
||||
const roleName = flow.binding.roleName || flow.role.name || '测试角色'
|
||||
const roleId = flow.binding.roleId || flow.role.rid || '10001'
|
||||
@@ -590,8 +631,13 @@ async function completeMockKuaishouCloudClaimTask(task: TaskRow, timestamp: stri
|
||||
updated_at: timestamp,
|
||||
})
|
||||
|
||||
await createTaskEvent(task.id, 'kuaishou_cloud_mock_redeemed', {
|
||||
source: 'claim_page_mock',
|
||||
deliveryItems: flow.deliveryItems,
|
||||
}, timestamp)
|
||||
await createTaskEvent(
|
||||
task.id,
|
||||
'kuaishou_cloud_mock_redeemed',
|
||||
{
|
||||
source: 'claim_page_mock',
|
||||
deliveryItems: flow.deliveryItems,
|
||||
},
|
||||
timestamp,
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user