修复feifei领取链接直返
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user