修复feifei领取链接直返
This commit is contained in:
@@ -5,6 +5,7 @@ import { getOrderById, listOrders } from '../../repositories/order-repo.js'
|
||||
import { getTaskById, listTasks, listTasksByOrderId } from '../../repositories/task-repo.js'
|
||||
import { listTaskEventsByTaskId } from '../../repositories/task-event-repo.js'
|
||||
import { listCloudtentaclesSources } from '../platforms/cloudtentacles/source-config-service.js'
|
||||
import { resolveKuaishouFeifeiClaimUrl } from '../fulfillment/kuaishou-feifei/index.js'
|
||||
import { createHttpError } from '../../utils/http.js'
|
||||
import { formatFenToAmount, normalizeFen } from '../../utils/money.js'
|
||||
import {
|
||||
@@ -189,7 +190,10 @@ export async function getAdminTaskDetail(
|
||||
const taskContext = parseTaskContext(task)
|
||||
const taskState = parseTaskState(task)
|
||||
const viewerContext = createAdminViewerContext(session)
|
||||
const claimUrl = claimToken ? buildClaimUrl(claimToken.token) : ''
|
||||
const directClaimUrl = String(task.executor_key || '').trim() === 'kuaishou_feifei'
|
||||
? resolveKuaishouFeifeiClaimUrl(taskContext.kuaishouFeifei)
|
||||
: ''
|
||||
const claimUrl = directClaimUrl || (claimToken ? buildClaimUrl(claimToken.token) : '')
|
||||
const screenshotUrl = await resolveAdminTaskScreenshotUrl(task, viewerContext)
|
||||
const cloudSourceLabelMap = buildCloudSourceLabelMap()
|
||||
const kuaishouCloudFulfillment =
|
||||
@@ -227,12 +231,12 @@ export async function getAdminTaskDetail(
|
||||
quantity: orderItem.quantity,
|
||||
}
|
||||
: null,
|
||||
claimToken: claimToken
|
||||
claimToken: claimToken || directClaimUrl
|
||||
? {
|
||||
primaryClaimTokenId: claimToken.id,
|
||||
token: viewerContext.canViewSensitiveTaskData ? claimToken.token : '',
|
||||
status: claimToken.status,
|
||||
expiredAt: claimToken.expired_at,
|
||||
primaryClaimTokenId: claimToken?.id || 0,
|
||||
token: viewerContext.canViewSensitiveTaskData ? (claimToken?.token || '') : '',
|
||||
status: claimToken?.status || 'external',
|
||||
expiredAt: claimToken?.expired_at || '',
|
||||
claimUrl,
|
||||
}
|
||||
: null,
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
import test from 'node:test'
|
||||
import assert from 'node:assert/strict'
|
||||
|
||||
import { resolveKuaishouFeifeiClaimUrl } from './index.js'
|
||||
|
||||
test('resolveKuaishouFeifeiClaimUrl prefers feifei h5 url over local claim url', () => {
|
||||
assert.equal(
|
||||
resolveKuaishouFeifeiClaimUrl({
|
||||
claimUrl: 'https://ks.khhao.com/#/claim/local-token',
|
||||
h5: {
|
||||
entryUrl: 'https://feifei.example.com/h5/exchange',
|
||||
rechargeUrl: 'https://feifei.example.com/h5/bind?code=abc',
|
||||
},
|
||||
}),
|
||||
'https://feifei.example.com/h5/bind?code=abc',
|
||||
)
|
||||
})
|
||||
|
||||
test('resolveKuaishouFeifeiClaimUrl does not expose local claim token fallback', () => {
|
||||
assert.equal(
|
||||
resolveKuaishouFeifeiClaimUrl({
|
||||
claimUrl: 'local-token',
|
||||
h5: {},
|
||||
}),
|
||||
'',
|
||||
)
|
||||
})
|
||||
@@ -4,7 +4,6 @@ import { createHttpError } from '../../../utils/http.js'
|
||||
import { parseTaskContext } from '../../../utils/task-json.js'
|
||||
import { nowIso } from '../../../utils/time.js'
|
||||
import { TASK_STATUS } from '../../../domain/task-status.js'
|
||||
import { buildClaimUrl, createTaskClaimToken } from '../../claim/claim-service.js'
|
||||
import {
|
||||
createKuaishouFeifeiOrder,
|
||||
queryKuaishouFeifeiOrder,
|
||||
@@ -29,20 +28,18 @@ export async function prepareKuaishouFeifeiTask(task: TaskRow) {
|
||||
const now = nowIso()
|
||||
const taskContext = parseTaskContext(task)
|
||||
const flow = normalizeKuaishouFeifeiFlow(taskContext.kuaishouFeifei)
|
||||
const claimLinkState = await ensureTaskClaimLink(task)
|
||||
|
||||
if (flow.orderNo && flow.h5.rechargeUrl) {
|
||||
const existingClaimUrl = resolveKuaishouFeifeiClaimUrl(flow)
|
||||
if (flow.orderNo && existingClaimUrl) {
|
||||
const nextContext = {
|
||||
...taskContext,
|
||||
kuaishouFeifei: {
|
||||
...flow,
|
||||
claimUrl: claimLinkState.claimUrl,
|
||||
claimUrl: existingClaimUrl,
|
||||
},
|
||||
}
|
||||
return updateTask(task.id, {
|
||||
task_status: TASK_STATUS.LINK_GENERATED,
|
||||
claim_token: claimLinkState.token || task.claim_token || '',
|
||||
claim_expires_at: claimLinkState.expiredAt || task.claim_expires_at || null,
|
||||
user_action_status: 'pending_claim',
|
||||
context_json: JSON.stringify(nextContext),
|
||||
updated_at: now,
|
||||
@@ -62,15 +59,21 @@ export async function prepareKuaishouFeifeiTask(task: TaskRow) {
|
||||
productCode: flow.productCode,
|
||||
platformBuyNum: 1,
|
||||
})
|
||||
const feifeiClaimUrl = resolveKuaishouFeifeiOrderClaimUrl(order)
|
||||
if (!feifeiClaimUrl) {
|
||||
throw createHttpError('kuaishou-feifei 未返回领取链接', {
|
||||
statusCode: 502,
|
||||
errorCode: 'kuaishou_feifei_missing_claim_url',
|
||||
})
|
||||
}
|
||||
|
||||
const nextFlow = mergeKuaishouFeifeiOrder(flow, order, {
|
||||
platformOrderNo,
|
||||
claimUrl: claimLinkState.claimUrl,
|
||||
claimUrl: feifeiClaimUrl,
|
||||
syncedAt: now,
|
||||
})
|
||||
const updatedTask = await updateTask(task.id, {
|
||||
task_status: TASK_STATUS.LINK_GENERATED,
|
||||
claim_token: claimLinkState.token || task.claim_token || '',
|
||||
claim_expires_at: claimLinkState.expiredAt || task.claim_expires_at || null,
|
||||
user_action_status: 'pending_claim',
|
||||
result_code: 'kuaishou_feifei_order_created',
|
||||
result_message: order.rechargeStatusLabel || 'kuaishou-feifei 订单已创建',
|
||||
@@ -122,7 +125,7 @@ export async function syncKuaishouFeifeiTaskStatus(task: TaskRow) {
|
||||
let lastError = task.last_error
|
||||
const nextFlow = mergeKuaishouFeifeiOrder(flow, order, {
|
||||
syncedAt: now,
|
||||
claimUrl: flow.claimUrl,
|
||||
claimUrl: resolveKuaishouFeifeiOrderClaimUrl(order) || resolveKuaishouFeifeiClaimUrl(flow),
|
||||
})
|
||||
|
||||
if (order.rechargeStatus === 30) {
|
||||
@@ -197,6 +200,16 @@ export function normalizeKuaishouFeifeiFlow(value: unknown) {
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveKuaishouFeifeiClaimUrl(value: unknown) {
|
||||
const flow = normalizeKuaishouFeifeiFlow(value)
|
||||
const h5ClaimUrl = flow.h5.rechargeUrl || flow.h5.entryUrl
|
||||
if (h5ClaimUrl) {
|
||||
return h5ClaimUrl
|
||||
}
|
||||
|
||||
return isLocalClaimUrl(flow.claimUrl) ? '' : flow.claimUrl
|
||||
}
|
||||
|
||||
function mergeKuaishouFeifeiOrder(
|
||||
flow: ReturnType<typeof normalizeKuaishouFeifeiFlow>,
|
||||
order: Awaited<ReturnType<typeof createKuaishouFeifeiOrder>>,
|
||||
@@ -225,25 +238,13 @@ function mergeKuaishouFeifeiOrder(
|
||||
}
|
||||
}
|
||||
|
||||
async function ensureTaskClaimLink(task: TaskRow) {
|
||||
const tokenStatus = String(task?.primary_claim_token_status || '').trim()
|
||||
const token = String(task?.primary_claim_token || task?.claim_token || '').trim()
|
||||
const expiredAt = task?.primary_claim_expires_at || task?.claim_expires_at || null
|
||||
function resolveKuaishouFeifeiOrderClaimUrl(order: Awaited<ReturnType<typeof createKuaishouFeifeiOrder>>) {
|
||||
return String(order.h5.rechargeUrl || order.h5.entryUrl || '').trim()
|
||||
}
|
||||
|
||||
if (tokenStatus === 'active' && token && expiredAt && new Date(expiredAt).getTime() > Date.now()) {
|
||||
return {
|
||||
token,
|
||||
expiredAt,
|
||||
claimUrl: buildClaimUrl(token),
|
||||
}
|
||||
}
|
||||
|
||||
const claimToken = await createTaskClaimToken(task.id)
|
||||
return {
|
||||
token: claimToken.token,
|
||||
expiredAt: claimToken.expired_at,
|
||||
claimUrl: claimToken.claimUrl,
|
||||
}
|
||||
function isLocalClaimUrl(value: unknown) {
|
||||
const url = String(value || '').trim()
|
||||
return !/^https?:\/\//i.test(url) || url.includes('/#/claim/')
|
||||
}
|
||||
|
||||
function buildFeifeiPlatformOrderNo(task: TaskRow) {
|
||||
|
||||
@@ -2,6 +2,7 @@ import { findLatestOrderByPlatformOrderId } from '../../repositories/order-repo.
|
||||
import { listTasksByOrderId } from '../../repositories/task-repo.js'
|
||||
import { buildClaimUrl } from '../claim/claim-service.js'
|
||||
import { ensureTaskClaimLink } from '../fulfillment/kuaishou-cloud/index.js'
|
||||
import { resolveKuaishouFeifeiClaimUrl } from '../fulfillment/kuaishou-feifei/index.js'
|
||||
import { logIntegration } from '../../utils/logger.js'
|
||||
import {
|
||||
OPEN_91_MANUAL_FAILED_STATUS,
|
||||
@@ -88,7 +89,11 @@ export async function queryOpen91Order(payload: JsonObject = {}, { requestId = '
|
||||
let expireTime: unknown = task.primary_claim_expires_at || task.claim_expires_at || ''
|
||||
const primaryToken = String(task.primary_claim_token || task.claim_token || '').trim()
|
||||
|
||||
if (primaryToken) {
|
||||
if (String(task.executor_key || '').trim() === 'kuaishou_feifei') {
|
||||
const context = parseJsonObject(task.context_json)
|
||||
claimUrl = resolveKuaishouFeifeiClaimUrl(context.kuaishouFeifei)
|
||||
expireTime = ''
|
||||
} else if (primaryToken) {
|
||||
claimUrl = buildClaimUrl(primaryToken)
|
||||
} else if (String(task.executor_key || '').trim() === 'kuaishou_ct_assisted') {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user