Files
order_site/apps/backend/src/services/open-91/response.ts
T
yml2213 8bcd9bbd81 收紧后端 TypeScript:统一 Json 类型与 TaskContext 契约
关闭 allowJs;集中 JsonObject 定义并替换分散 any 别名;parseTaskContext 返回 TaskContext;任务详情 API 标注 AdminTaskDetailView;测试减少 as any。
2026-07-10 15:52:05 +08:00

116 lines
3.2 KiB
TypeScript

import type { JsonObject } from '../../types/json.js'
import {
OPEN_91_DEFAULT_FAIL_CODE,
OPEN_91_SUCCESS_MESSAGE,
} from './config.js'
import { isOpen91FailedTaskStatus } from '../../domain/task-status.js'
import { normalizeOpen91String } from './payload.js'
export function buildOpen91SuccessResponse(data: unknown, message = OPEN_91_SUCCESS_MESSAGE) {
return {
code: 200,
message,
data,
}
}
export function buildOpen91ErrorResponse(message: unknown, code = 500) {
return {
code,
message: normalizeOpen91String(message) || '系统错误',
data: null as null,
}
}
export function buildOpen91OutTradeNo(order: JsonObject) {
const orderId = Number(order?.id || 0)
return orderId > 0 ? `OS${String(orderId).padStart(10, '0')}` : ''
}
export function buildOpen91OrderCost(value = 0) {
const amount = Number(value)
return Number.isFinite(amount) ? amount.toFixed(4) : '0.0000'
}
export function buildOpen91CardItem({ claimUrl = '', expireTime = '' }: { claimUrl?: unknown, expireTime?: unknown } = {}) {
const normalizedClaimUrl = normalizeOpen91String(claimUrl)
return {
cardNo: normalizedClaimUrl,
cardPwd: '',
expireTime: formatOpen91ExpireTime(expireTime),
jumpLink: normalizedClaimUrl,
}
}
export function formatOpen91ExpireTime(value: unknown = '') {
const normalized = normalizeOpen91String(value)
if (!normalized) {
return ''
}
if (/^\d{10}$/.test(normalized) || /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/.test(normalized)) {
return normalized
}
const date = value instanceof Date ? value : new Date(normalized)
if (Number.isNaN(date.getTime())) {
return normalized
}
const parts = new Intl.DateTimeFormat('zh-CN', {
timeZone: 'Asia/Shanghai',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hourCycle: 'h23',
}).formatToParts(date)
const byType = Object.fromEntries(parts.map((part) => [part.type, part.value]))
return `${byType.year}-${byType.month}-${byType.day} ${byType.hour}:${byType.minute}:${byType.second}`
}
export function resolveOpen91QueryState(
{ tasks = [], readyTaskIds = [] }: { tasks?: JsonObject[], readyTaskIds?: unknown[] } = {},
) {
const normalizedTasks = Array.isArray(tasks) ? tasks : []
const readyTaskIdSet = new Set((Array.isArray(readyTaskIds) ? readyTaskIds : []).map((item) => Number(item)))
if (normalizedTasks.length === 0) {
return {
orderStatus: 30,
failCode: OPEN_91_DEFAULT_FAIL_CODE,
failReason: '订单未生成履约任务',
}
}
const failedTask = normalizedTasks.find((task) => {
const status = normalizeOpen91String(task?.task_status)
return isOpen91FailedTaskStatus(status) && !readyTaskIdSet.has(Number(task?.id || 0))
})
if (failedTask) {
return {
orderStatus: 30,
failCode: OPEN_91_DEFAULT_FAIL_CODE,
failReason: normalizeOpen91String(failedTask.last_error) || '订单无法履约',
}
}
if (readyTaskIdSet.size < normalizedTasks.length) {
return {
orderStatus: 10,
failCode: 0,
failReason: '',
}
}
return {
orderStatus: 20,
failCode: 0,
failReason: '',
}
}