优化电子凭证操作与测试数据
This commit is contained in:
@@ -7,6 +7,7 @@ import crypto from 'node:crypto'
|
||||
import { createOrder, findOrderByPlatformOrderId } from '../../repositories/order-repo.js'
|
||||
import { replaceOrderItems } from '../../repositories/order-item-repo.js'
|
||||
import { createTask, updateTask } from '../../repositories/task-repo.js'
|
||||
import { upsertKuaishouIndustryVoucher } from '../../repositories/kuaishou-industry-voucher-repo.js'
|
||||
import {
|
||||
getFulfillmentProfileByKey,
|
||||
upsertFulfillmentProfile,
|
||||
@@ -15,6 +16,10 @@ import { buildClaimUrl, createTaskClaimToken } from '../claim/claim-service.js'
|
||||
import { assertValidClaimUid, normalizeClaimUid } from '../claim/claim-identity.js'
|
||||
import { OPEN_91_PLATFORM, OPEN_91_PROVIDER, assertOpen91Config } from '../open-91/config.js'
|
||||
import { parseOpen91ProductNo } from '../platforms/ninetyone/order-service.js'
|
||||
import {
|
||||
getKuaishouIndustrySourceConfig,
|
||||
listKuaishouIndustryShopConfigs,
|
||||
} from '../platforms/kuaishou-industry/source-config-service.js'
|
||||
import { isProductionLike } from '../../config/runtime-validation.js'
|
||||
import { createHttpError } from '../../utils/http.js'
|
||||
import { addHours, nowIso } from '../../utils/time.js'
|
||||
@@ -40,6 +45,16 @@ export type DevMockCreateResult = {
|
||||
open91QueryHint: string
|
||||
}
|
||||
|
||||
export type DevMockKuaishouIndustryVoucherResult = {
|
||||
createdCount: number
|
||||
sellerId: string
|
||||
vouchers: Array<{
|
||||
voucherCode: string
|
||||
oid: string
|
||||
status: string
|
||||
}>
|
||||
}
|
||||
|
||||
type DeliveryItem = {
|
||||
cloudSkuId: number
|
||||
cloudSkuName: string
|
||||
@@ -554,6 +569,102 @@ export async function createAffiliateDashMockClaim(input: {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成电子凭证列表测试数据,不调用快手接口。
|
||||
* 覆盖未使用、已核销、已销毁和发码失败等运营页面常见状态。
|
||||
*/
|
||||
export async function createKuaishouIndustryVoucherMockData(input: {
|
||||
sellerId?: unknown
|
||||
} = {}): Promise<DevMockKuaishouIndustryVoucherResult> {
|
||||
assertDevMockEnabled()
|
||||
|
||||
const now = nowIso()
|
||||
const timestamp = Date.now()
|
||||
const sellerId = resolveMockIndustrySellerId(input.sellerId)
|
||||
const specimens = [
|
||||
{ status: 'UNUSED', callbackStatus: 'success', productName: '周卡 VIP 尊享礼包' },
|
||||
{
|
||||
status: 'UNUSED',
|
||||
callbackStatus: 'failed',
|
||||
callbackError: '开发 Mock 模拟发码回调失败',
|
||||
productName: '幸运盲盒 限定款',
|
||||
},
|
||||
{
|
||||
status: 'CONSUMED',
|
||||
callbackStatus: 'success',
|
||||
consumeSerialNum: `CONSUME-MOCK-${timestamp}-3`,
|
||||
consumedAt: now,
|
||||
productName: '星轨通行证月卡',
|
||||
},
|
||||
{ status: 'UNUSED', callbackStatus: 'success', productName: '精英荣耀专属礼盒' },
|
||||
{
|
||||
status: 'DESTROYED',
|
||||
callbackStatus: 'success',
|
||||
destroyedAt: now,
|
||||
productName: '退款销毁测试券',
|
||||
},
|
||||
{
|
||||
status: 'CONSUMED',
|
||||
callbackStatus: 'success',
|
||||
consumeSerialNum: `CONSUME-MOCK-${timestamp}-6`,
|
||||
consumedAt: now,
|
||||
productName: '浪漫天命皮肤礼包',
|
||||
},
|
||||
]
|
||||
|
||||
const vouchers: DevMockKuaishouIndustryVoucherResult['vouchers'] = []
|
||||
for (const [index, specimen] of specimens.entries()) {
|
||||
const oid = `MOCK-KS-${timestamp}-${index + 1}`
|
||||
const voucher = await upsertKuaishouIndustryVoucher({
|
||||
oid,
|
||||
unitIndex: 1,
|
||||
sellerId,
|
||||
token: `mock-token-${timestamp}-${index + 1}`,
|
||||
eticketType: 'GAME_OPEN_TICKET_CONSUME',
|
||||
status: specimen.status,
|
||||
validStartTime: timestamp - 60 * 60 * 1000,
|
||||
validEndTime: timestamp + 7 * 24 * 60 * 60 * 1000,
|
||||
consumeSerialNum: specimen.consumeSerialNum || '',
|
||||
consumedAt: specimen.consumedAt || null,
|
||||
destroyedAt: specimen.destroyedAt || null,
|
||||
sendCallbackStatus: specimen.callbackStatus,
|
||||
sendCallbackAttemptCount: specimen.callbackStatus === 'failed' ? 1 : 0,
|
||||
sendCallbackLastError: specimen.callbackError || '',
|
||||
sendCallbackResponseJson: {
|
||||
mock: true,
|
||||
success: specimen.callbackStatus === 'success',
|
||||
},
|
||||
sendCallbackSentAt: now,
|
||||
rawPayloadJson: {
|
||||
source: 'dev_mock',
|
||||
mock: true,
|
||||
productName: specimen.productName,
|
||||
},
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
})
|
||||
|
||||
if (!voucher) {
|
||||
throw createHttpError('电子凭证 Mock 创建失败', {
|
||||
statusCode: 500,
|
||||
errorCode: 'dev_mock_kuaishou_industry_voucher_failed',
|
||||
})
|
||||
}
|
||||
|
||||
vouchers.push({
|
||||
voucherCode: voucher.voucher_code,
|
||||
oid: voucher.oid,
|
||||
status: voucher.status,
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
createdCount: vouchers.length,
|
||||
sellerId,
|
||||
vouchers,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 91 查询请求体(带签名),可选对本机发起查询。
|
||||
*/
|
||||
@@ -951,6 +1062,18 @@ function resolveMockUid(value: unknown, fallback: string) {
|
||||
return assertValidClaimUid(raw)
|
||||
}
|
||||
|
||||
function resolveMockIndustrySellerId(value: unknown): string {
|
||||
const sellerId = String(value || '').trim()
|
||||
if (sellerId) {
|
||||
return sellerId
|
||||
}
|
||||
|
||||
const shop = listKuaishouIndustryShopConfigs(getKuaishouIndustrySourceConfig()).find(
|
||||
(item) => item.enabled !== false && (item.sellerId || item.shopId),
|
||||
)
|
||||
return String(shop?.sellerId || shop?.shopId || '141242642').trim()
|
||||
}
|
||||
|
||||
function parseDeliveryItems(value: unknown): DeliveryItem[] {
|
||||
if (!value) {
|
||||
return [
|
||||
|
||||
Reference in New Issue
Block a user