统一领取流:Step1 填 UID,按平台分叉履约
领取页改为统一 UID 入口;lewan 强制角色 ID 匹配后才发货核销,feifei 将 uid 拼入 H5 并去掉 claim 短链,对外仍返回本站 claimUrl。
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { createTaskEvent } from '../../repositories/task-event-repo.js'
|
||||
import { getTaskById, updateTask, updateTaskStatusIfCurrent } from '../../repositories/task-repo.js'
|
||||
import { createHttpError } from '../../utils/http.js'
|
||||
import { parseTaskContext as parseTaskContextValue } from '../../utils/task-json.js'
|
||||
import { addHours, nowIso } from '../../utils/time.js'
|
||||
import {
|
||||
TASK_STATUS,
|
||||
@@ -11,14 +12,19 @@ import {
|
||||
} from '../../domain/task-status.js'
|
||||
import {
|
||||
dispatchKuaishouCloudFulfillmentTask,
|
||||
hasKuaishouCloudCustomerRole,
|
||||
hasKuaishouCloudDefaultRoleSnapshot,
|
||||
normalizeKuaishouCloudFlow,
|
||||
prepareKuaishouCloudFulfillmentTask,
|
||||
rebindKuaishouCloudTaskRole,
|
||||
refreshKuaishouCloudTaskRoleInfo,
|
||||
} from '../fulfillment/kuaishou-cloud/index.js'
|
||||
import { syncKuaishouFeifeiTaskStatus } from '../fulfillment/kuaishou-feifei/index.js'
|
||||
import {
|
||||
assertBoundUidMatchesExpected,
|
||||
assertClaimExpectedUidReady,
|
||||
assertValidClaimUid,
|
||||
canUpdateClaimUid,
|
||||
getClaimIdentityFromTask,
|
||||
} from './claim-identity.js'
|
||||
import { buildClaimDetailPayload, getClaimContext } from './kuaishou-cloud-claim-context.js'
|
||||
import { syncKuaishouCloudRoleInfo } from './kuaishou-cloud-sync-service.js'
|
||||
import type { TaskRow } from '../../types/repository/rows.js'
|
||||
@@ -179,9 +185,11 @@ export async function getKuaishouCloudClaimDetail(token: unknown): Promise<Claim
|
||||
}
|
||||
}
|
||||
|
||||
// 已提交 UID 的 lewan 任务:详情查询时顺带刷新角色,便于前端轮询匹配状态
|
||||
if (
|
||||
executorKey === 'kuaishou_ct_assisted' &&
|
||||
!isKuaishouCloudMockTask(task)
|
||||
!isKuaishouCloudMockTask(task) &&
|
||||
getClaimIdentityFromTask(task).expectedUid
|
||||
) {
|
||||
task = (await syncKuaishouCloudRoleInfo(task)) || task
|
||||
}
|
||||
@@ -194,6 +202,81 @@ export async function getKuaishouCloudClaimDetail(token: unknown): Promise<Claim
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一领取 Step1:提交游戏 UID。
|
||||
*/
|
||||
export async function submitClaimUid(
|
||||
token: unknown,
|
||||
payload: { uid?: unknown } = {},
|
||||
): Promise<ClaimDetailPayload> {
|
||||
const context = await getClaimContext(token)
|
||||
const expectedUid = assertValidClaimUid(payload.uid)
|
||||
const now = nowIso()
|
||||
|
||||
if (!canUpdateClaimUid(context.task)) {
|
||||
throw createHttpError('当前任务状态不可修改 UID', {
|
||||
statusCode: 409,
|
||||
errorCode: 'claim_uid_locked',
|
||||
})
|
||||
}
|
||||
|
||||
const taskContext = parseTaskContext(context.task)
|
||||
const previous = getClaimIdentityFromTask(context.task)
|
||||
const nextContext = {
|
||||
...taskContext,
|
||||
claimIdentity: {
|
||||
expectedUid,
|
||||
submittedAt: previous.expectedUid === expectedUid && previous.submittedAt
|
||||
? previous.submittedAt
|
||||
: now,
|
||||
source: 'claim_page',
|
||||
},
|
||||
}
|
||||
|
||||
let updatedTask =
|
||||
(await updateTask(context.task.id, {
|
||||
context_json: JSON.stringify(nextContext),
|
||||
claimed_at: context.task.claimed_at || now,
|
||||
last_error: '',
|
||||
updated_at: now,
|
||||
})) || {
|
||||
...context.task,
|
||||
context_json: JSON.stringify(nextContext),
|
||||
claimed_at: context.task.claimed_at || now,
|
||||
updated_at: now,
|
||||
}
|
||||
|
||||
if (previous.expectedUid !== expectedUid) {
|
||||
await createTaskEvent(
|
||||
context.task.id,
|
||||
'claim_uid_submitted',
|
||||
{
|
||||
expectedUid,
|
||||
previousUid: previous.expectedUid || '',
|
||||
source: 'claim_page',
|
||||
},
|
||||
now,
|
||||
)
|
||||
}
|
||||
|
||||
const executorKey = String(updatedTask.executor_key || '').trim()
|
||||
if (executorKey === 'kuaishou_ct_assisted' && !isKuaishouCloudMockTask(updatedTask)) {
|
||||
try {
|
||||
const prepared = await prepareKuaishouCloudFulfillmentTask(updatedTask, {
|
||||
source: 'claim_page_submit_uid',
|
||||
actor: { source: 'claim_page' },
|
||||
})
|
||||
if (prepared?.task) {
|
||||
updatedTask = prepared.task
|
||||
}
|
||||
} catch {
|
||||
// 绑定资源准备失败时仍保留 UID,详情页可继续重试/轮询
|
||||
}
|
||||
}
|
||||
|
||||
return getKuaishouCloudClaimDetail(token)
|
||||
}
|
||||
|
||||
export async function rebindKuaishouCloudClaimRole(token: unknown) {
|
||||
const context = await getClaimContext(token)
|
||||
|
||||
@@ -213,20 +296,7 @@ export async function rebindKuaishouCloudClaimRole(token: unknown) {
|
||||
}
|
||||
|
||||
function parseTaskContext(task: Partial<TaskRow> | null | undefined): JsonObject {
|
||||
const rawValue = task?.context_json
|
||||
if (!rawValue) {
|
||||
return {}
|
||||
}
|
||||
|
||||
if (typeof rawValue === 'object') {
|
||||
return rawValue
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(String(rawValue || '{}'))
|
||||
} catch {
|
||||
return {}
|
||||
}
|
||||
return parseTaskContextValue(task)
|
||||
}
|
||||
|
||||
function hasUsableIndustryVoucher(context: JsonObject = {}) {
|
||||
@@ -273,6 +343,7 @@ export async function confirmKuaishouCloudClaimRole(token: unknown) {
|
||||
return getKuaishouCloudClaimDetail(token)
|
||||
}
|
||||
|
||||
const expectedUid = assertClaimExpectedUidReady(context.task)
|
||||
const contextSource = parseTaskContext(context.task)
|
||||
const mockMode = isKuaishouCloudMockContext(contextSource)
|
||||
const refreshed = mockMode
|
||||
@@ -285,13 +356,6 @@ export async function confirmKuaishouCloudClaimRole(token: unknown) {
|
||||
})
|
||||
const flow = normalizeKuaishouCloudFlow(parseTaskContext(refreshed.task).kuaishouCloudFulfillment)
|
||||
|
||||
if (flow.ticket.status !== 'verified') {
|
||||
throw createHttpError('请先完成电子凭证确认', {
|
||||
statusCode: 409,
|
||||
errorCode: 'claim_kuaishou_cloud_ticket_not_verified',
|
||||
})
|
||||
}
|
||||
|
||||
if (!flow.binding.vnPhone || !flow.binding.roleName || !flow.binding.roleId) {
|
||||
throw createHttpError('角色信息还未刷新到系统,请完成绑定后稍等片刻再试', {
|
||||
statusCode: 409,
|
||||
@@ -299,16 +363,9 @@ export async function confirmKuaishouCloudClaimRole(token: unknown) {
|
||||
})
|
||||
}
|
||||
|
||||
const hasDefaultRoleSnapshot = hasKuaishouCloudDefaultRoleSnapshot(flow)
|
||||
if (!mockMode && !hasKuaishouCloudCustomerRole(flow)) {
|
||||
const message = hasDefaultRoleSnapshot
|
||||
? '当前仍是虚拟机默认角色,请先重新绑定自己的角色信息'
|
||||
: '系统还未获取到虚拟机默认角色信息,请稍后刷新角色信息后再试'
|
||||
throw createHttpError(message, {
|
||||
statusCode: 409,
|
||||
errorCode: hasDefaultRoleSnapshot
|
||||
? 'claim_kuaishou_cloud_default_role_not_rebound'
|
||||
: 'claim_kuaishou_cloud_default_role_not_ready',
|
||||
if (!mockMode) {
|
||||
assertBoundUidMatchesExpected(refreshed.task, flow, {
|
||||
errorCodePrefix: 'claim_kuaishou_cloud',
|
||||
})
|
||||
}
|
||||
|
||||
@@ -326,6 +383,7 @@ export async function confirmKuaishouCloudClaimRole(token: unknown) {
|
||||
context.task.id,
|
||||
'kuaishou_cloud_role_confirmed',
|
||||
{
|
||||
expectedUid,
|
||||
vnPhone: flow.binding.vnPhone,
|
||||
roleName: flow.binding.roleName,
|
||||
roleId: flow.binding.roleId,
|
||||
@@ -359,6 +417,15 @@ export async function redeemKuaishouCloudClaim(token: unknown) {
|
||||
})
|
||||
}
|
||||
|
||||
const flowBeforeRedeem = normalizeKuaishouCloudFlow(
|
||||
parseTaskContext(context.task).kuaishouCloudFulfillment,
|
||||
)
|
||||
if (!isKuaishouCloudMockTask(context.task)) {
|
||||
assertBoundUidMatchesExpected(context.task, flowBeforeRedeem, {
|
||||
errorCodePrefix: 'claim_kuaishou_cloud_redeem',
|
||||
})
|
||||
}
|
||||
|
||||
const lockedTask = await updateTaskStatusIfCurrent(context.task.id, TASK_STATUS.ROLE_CONFIRMED, {
|
||||
task_status: TASK_STATUS.REDEEMING,
|
||||
user_action_status: 'not_required',
|
||||
|
||||
Reference in New Issue
Block a user