修复订单重复推送走兑换逻辑bug, 修复任务关闭失败bug

This commit is contained in:
yml
2026-04-14 21:32:55 +08:00
parent 4d03b4ef8d
commit 52c190c575
8 changed files with 414 additions and 61 deletions
@@ -4,7 +4,7 @@ import { runtimeConfig } from '../../../../config/runtime.js'
import { getAgisoMessagingDefaults, getAgisoShopConfigMap } from '../shop-config-service.js'
import {
createMessageDelivery,
findLatestSuccessfulMessageDeliveryByTask,
findLatestSuccessfulMessageDelivery,
updateMessageDelivery,
} from '../../../../repositories/message-delivery-repo.js'
import { nowIso } from '../../../../utils/time.js'
@@ -56,6 +56,28 @@ async function deliverAgisoXianyuMessageForTask({
messageContent,
claimUrl = '',
} = {}) {
return deliverAgisoXianyuMessageForTaskWithDeps({
order,
task,
channel,
messageContent,
claimUrl,
})
}
export async function deliverAgisoXianyuMessageForTaskWithDeps({
order,
task,
channel,
messageContent,
claimUrl = '',
} = {}, deps = {}) {
const now = deps.nowIso || nowIso
const findSuccessfulDelivery = deps.findLatestSuccessfulMessageDelivery || findLatestSuccessfulMessageDelivery
const insertMessageDelivery = deps.createMessageDelivery || createMessageDelivery
const patchMessageDelivery = deps.updateMessageDelivery || updateMessageDelivery
const sendRequest = deps.fetch || fetch
if (!order || !task || !messageContent) {
return { sent: false, skipped: true, reason: 'missing_message_context' }
}
@@ -72,7 +94,14 @@ async function deliverAgisoXianyuMessageForTask({
return { sent: false, skipped: true, reason: 'missing_endpoint_or_access_token_or_app_secret' }
}
const successful = await findLatestSuccessfulMessageDeliveryByTask(task.id, channel)
const successful = await findSuccessfulDelivery({
provider: 'agiso',
platform: String(order.platform || '').trim() || 'unknown',
shopId: String(order.shop_id || '').trim(),
platformOrderId: String(order.platform_order_id || '').trim(),
channel,
claimUrl: String(claimUrl || ''),
})
if (successful) {
return { sent: false, skipped: true, reason: 'already_sent', deliveryId: successful.id }
}
@@ -87,8 +116,8 @@ async function deliverAgisoXianyuMessageForTask({
accessToken,
apiVersion: String(config.apiVersion || '1').trim() || '1',
})
const createdAt = nowIso()
const delivery = await createMessageDelivery({
const createdAt = now()
const delivery = await insertMessageDelivery({
provider: 'agiso',
platform: String(order.platform || '').trim() || 'unknown',
shopId: String(order.shop_id || '').trim(),
@@ -113,7 +142,7 @@ async function deliverAgisoXianyuMessageForTask({
})
try {
const response = await fetch(url, {
const response = await sendRequest(url, {
method: 'POST',
headers: requestHeaders,
body: new URLSearchParams(requestBody).toString(),
@@ -122,13 +151,13 @@ async function deliverAgisoXianyuMessageForTask({
const parsed = safeParseJson(rawText)
const success = isAgisoSendSuccess(response.status, parsed)
const errorMessage = success ? '' : resolveAgisoErrorMessage(parsed, rawText, response.status)
const updated = await updateMessageDelivery(delivery.id, {
const updated = await patchMessageDelivery(delivery.id, {
status: success ? 'success' : 'failed',
response_status: response.status,
response_json: JSON.stringify(parsed ?? { rawText }),
error_message: errorMessage,
sent_at: success ? nowIso() : null,
updated_at: nowIso(),
sent_at: success ? now() : null,
updated_at: now(),
})
return {
@@ -141,13 +170,13 @@ async function deliverAgisoXianyuMessageForTask({
}
} catch (error) {
const message = error instanceof Error ? error.message : String(error || '发送消息失败')
await updateMessageDelivery(delivery.id, {
await patchMessageDelivery(delivery.id, {
status: 'failed',
response_status: 0,
response_json: '{}',
error_message: message,
sent_at: null,
updated_at: nowIso(),
updated_at: now(),
})
return {
@@ -0,0 +1,76 @@
import test from 'node:test'
import assert from 'node:assert/strict'
import { runtimeConfig } from '../../../../config/runtime.js'
import { deliverAgisoXianyuMessageForTaskWithDeps } from './message-service.js'
test('deliverAgisoXianyuMessageForTaskWithDeps skips duplicate successful claim message by order scope', async () => {
const originalMessaging = runtimeConfig.platforms.agiso.messaging
const originalAppSecret = runtimeConfig.platforms.agiso.appSecret
runtimeConfig.platforms.agiso.messaging = {
...originalMessaging,
enabled: true,
sendMessageEndpoint: 'https://example.com/send',
apiVersion: '1',
accessToken: 'access-token',
}
runtimeConfig.platforms.agiso.appSecret = 'app-secret'
const calls = {
find: [],
create: 0,
fetch: 0,
}
try {
const result = await deliverAgisoXianyuMessageForTaskWithDeps({
order: {
id: 15,
platform: 'xianyu',
shop_id: '2209880145223',
platform_order_id: '4502280133178028841',
},
task: {
id: 36,
task_no: 'DT7af76e9b2438',
},
channel: 'agiso_im',
messageContent: '测试消息',
claimUrl: 'https://221329.cc.cd/#/claim/same-token',
}, {
findLatestSuccessfulMessageDelivery: async (input) => {
calls.find.push(input)
return { id: 16, task_id: null }
},
createMessageDelivery: async () => {
calls.create += 1
return { id: 999 }
},
fetch: async () => {
calls.fetch += 1
return { status: 200, text: async () => '{}' }
},
})
assert.deepEqual(calls.find, [
{
provider: 'agiso',
platform: 'xianyu',
shopId: '2209880145223',
platformOrderId: '4502280133178028841',
channel: 'agiso_im',
claimUrl: 'https://221329.cc.cd/#/claim/same-token',
},
])
assert.equal(calls.create, 0)
assert.equal(calls.fetch, 0)
assert.equal(result.sent, false)
assert.equal(result.skipped, true)
assert.equal(result.reason, 'already_sent')
assert.equal(result.deliveryId, 16)
} finally {
runtimeConfig.platforms.agiso.messaging = originalMessaging
runtimeConfig.platforms.agiso.appSecret = originalAppSecret
}
})