Files
order_site/apps/backend/src/repositories/webhook-event-repo.ts
T
yml2213 7fc3d60588 新增 affiliate_dash 回调路由与幂等去重(阶段 5)
- POST /api/v1/open/affiliate-dash:验签 → 查任务(404 重试) → webhook_events 幂等闸门 → 状态同步
- migration 013:webhook_events(provider+event_id 唯一)
- task-repo findAffiliateDashTaskByOrder(仿 feifei 同构 SQL)
- notify-service:去重闸门在找到任务之后,任务未匹配不被 eventId 永久拦截
- typecheck + 212 测试通过;前置错误分支脚本验证通过
2026-08-05 16:07:33 +08:00

44 lines
1.2 KiB
TypeScript

import { query } from '../db/client.js'
import type { JsonObject } from '../types/json.js'
import { nowIso } from '../utils/time.js'
/**
* 幂等写入一条 webhook 事件(provider + event_id 唯一)。
* 冲突时不做任何更新并返回 inserted=false —— 供回调去重闸门使用。
*/
export async function insertWebhookEventOnce(input: {
provider: string
eventId: string
eventType: string
taskId?: number | string | null
payload: JsonObject
processedAt?: string
}): Promise<{ inserted: boolean }> {
const processedAt = input.processedAt || nowIso()
const result = await query<{ id: number }>(
`
INSERT INTO webhook_events (
provider,
event_id,
event_type,
task_id,
payload,
processed_at,
created_at
) VALUES ($1, $2, $3, $4, $5::jsonb, $6, $6)
ON CONFLICT (provider, event_id) DO NOTHING
RETURNING id
`,
[
String(input.provider || '').trim(),
String(input.eventId || '').trim(),
String(input.eventType || '').trim(),
input.taskId == null ? null : Number(input.taskId),
JSON.stringify(input.payload || {}),
processedAt,
],
)
return { inserted: result.rows.length > 0 }
}