修复接单注册审核与拼单状态校验

This commit is contained in:
yml2213
2026-08-18 18:16:48 +08:00
parent ee79195f47
commit b2eaf3b6c7
8 changed files with 94 additions and 19 deletions
@@ -134,8 +134,10 @@ export async function verifyAdminSessionToken(token: unknown): Promise<AdminSess
})
}
const [encodedPayload, signature] = normalizedToken.split('.')
if (!encodedPayload || !signature) {
const parts = normalizedToken.split('.')
const encodedPayload = parts[0]
const signature = parts[1]
if (parts.length !== 2 || !encodedPayload || !signature) {
throw createHttpError('后台登录态无效', {
statusCode: 401,
errorCode: 'admin_auth_invalid',
@@ -2057,7 +2057,11 @@ export async function acceptAdminWorkOrders(payload: JsonObject = {}, actorName
const workOrders = await Promise.all(
workOrderIds.map((workOrderId) => getRequiredWorkOrder(workOrderId)),
)
if (workOrders.some((workOrder) => workOrder.status !== WORK_ORDER_STATUS.PENDING_ACCEPTANCE)) {
if (
workOrders.some(
(workOrder) => mapWorkOrderAdmin(workOrder).status !== WORK_ORDER_STATUS.PENDING_ACCEPTANCE,
)
) {
throw createHttpError('选中的订单包含非待验收状态,请刷新后重试', {
statusCode: 409,
errorCode: 'work_order_batch_accept_status_invalid',
@@ -2204,7 +2208,12 @@ export async function getAdminWorkerPlatformSummary() {
statuses: [WORK_ORDER_STATUS.OPEN],
excludeFilledSharing: true,
}),
listWorkOrders({ page: 1, pageSize: 1, statuses: [WORK_ORDER_STATUS.IN_PROGRESS], useOperationalStatus: true }),
listWorkOrders({
page: 1,
pageSize: 1,
statuses: [WORK_ORDER_STATUS.IN_PROGRESS],
useOperationalStatus: true,
}),
])
return {
pendingWorkerCount: pendingWorkers.total,
@@ -20,6 +20,7 @@ import {
getWorkCategoryByKey,
getWorkerLevelByKey,
getLatestWorkerSmsCode,
recordWorkerSmsCodeFailure,
getWorkerUserByInviteCode,
getWorkerUserById,
getWorkerWithdrawalAccount,
@@ -141,6 +142,7 @@ import {
const WORKER_DAILY_WITHDRAW_LIMIT = 3
const VIP_AUTO_ACCEPT_EVIDENCE_WINDOW_HOURS = 24
const WORKER_SMS_MAX_VERIFY_ATTEMPTS = 5
export type WorkerSession = {
sessionId: string
@@ -198,7 +200,11 @@ export async function sendWorkerSmsCode(payload: JsonObject = {}) {
}
const latest = await getLatestWorkerSmsCode(phone, 'register')
if (latest && new Date(latest.created_at).getTime() > Date.now() - cooldownMs) {
if (
latest &&
!latest.consumed_at &&
new Date(latest.created_at).getTime() > Date.now() - cooldownMs
) {
throw createHttpError('验证码发送过于频繁,请稍后再试', {
statusCode: 429,
errorCode: 'worker_sms_cooldown',
@@ -262,13 +268,24 @@ export async function registerWorker(payload: JsonObject = {}) {
latest.code_hash === hashSmsCode(code),
)
if (!codeValid) {
if (latest && !latest.consumed_at) {
const failed = await recordWorkerSmsCodeFailure(
latest.id,
nowIso(),
WORKER_SMS_MAX_VERIFY_ATTEMPTS,
)
if (failed && failed.consumed_at) {
throw createHttpError('验证码错误次数过多,请重新获取验证码', {
statusCode: 400,
errorCode: 'worker_sms_code_locked',
})
}
}
throw createHttpError('短信验证码错误或已过期', {
statusCode: 400,
errorCode: 'worker_sms_code_invalid',
})
}
await consumeWorkerSmsCode(latest!.id, nowIso())
if (await getWorkerUserByUsername(phone)) {
throw createHttpError('该手机号已注册,请直接登录', {
statusCode: 409,
@@ -311,7 +328,7 @@ export async function registerWorker(payload: JsonObject = {}) {
displayName,
phone,
levelId: defaults.level?.id || null,
status: 'active',
status: 'pending_review',
inviterId: inviter ? Number(inviter.id) : null,
inviteCode: await generateInviteCode(now),
now,
@@ -324,9 +341,12 @@ export async function registerWorker(payload: JsonObject = {}) {
})
}
// 账号创建成功后再消费验证码,避免邀请码、昵称或数据库异常导致验证码提前失效。
await consumeWorkerSmsCode(latest!.id, nowIso())
return {
worker: mapWorkerUser(created),
reviewRequired: false,
reviewRequired: true,
}
}
@@ -534,8 +554,15 @@ export async function verifyWorkerSessionToken(token: unknown): Promise<WorkerSe
})
}
const [encodedPayload, signature] = normalizedToken.split('.')
if (!encodedPayload || !signature || !safeCompare(signature, signWorkerPayload(encodedPayload))) {
const parts = normalizedToken.split('.')
const encodedPayload = parts[0]
const signature = parts[1]
if (
parts.length !== 2 ||
!encodedPayload ||
!signature ||
!safeCompare(signature, signWorkerPayload(encodedPayload))
) {
throw createHttpError('接单登录态无效', {
statusCode: 401,
errorCode: 'worker_auth_invalid',