From 24d5f233d9dd9b47b7df057b770715f5aa1a22bf Mon Sep 17 00:00:00 2001 From: yml Date: Tue, 14 Apr 2026 23:02:45 +0800 Subject: [PATCH] =?UTF-8?q?=E9=BB=98=E8=AE=A4=E6=B6=88=E6=81=AF=E6=A8=A1?= =?UTF-8?q?=E6=9D=BF=E5=A2=9E=E5=8A=A0=E6=8D=A2=E8=A1=8C-=E5=BE=85?= =?UTF-8?q?=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/backend/data/agiso-shops.json | 2 +- .../admin/admin-platform-config-service.js | 11 +++---- .../platforms/agiso/xianyu/message-service.js | 15 ++++++++-- .../agiso/xianyu/message-service.test.js | 29 ++++++++++++++++++- 4 files changed, 47 insertions(+), 10 deletions(-) diff --git a/apps/backend/data/agiso-shops.json b/apps/backend/data/agiso-shops.json index 9b0a7196..e36a8b87 100644 --- a/apps/backend/data/agiso-shops.json +++ b/apps/backend/data/agiso-shops.json @@ -1,6 +1,6 @@ { "defaults": { - "messageTemplate": "您的订单 {platformOrderId} 已创建领取链接,请您复制链接到 浏览器 自动兑换, 请尽快打开并完成领取:\\n\\n{claimUrl}", + "messageTemplate": "您的订单 {platformOrderId} 已创建领取链接,请您复制链接到浏览器自动兑换,请尽快打开并完成领取:\n\n{claimUrl}", "autoDeliveryMessageTemplate": "亲亲,您购买的兑换码已自行兑换成功,请在游戏中邮件领取,感谢您的支持" }, "shops": { diff --git a/apps/backend/src/services/admin/admin-platform-config-service.js b/apps/backend/src/services/admin/admin-platform-config-service.js index e3320154..fc937119 100644 --- a/apps/backend/src/services/admin/admin-platform-config-service.js +++ b/apps/backend/src/services/admin/admin-platform-config-service.js @@ -9,6 +9,7 @@ import { saveAgisoMessagingConfig, } from '../platforms/agiso/shop-config-service.js' import { enrichAgisoXianyuTradeOrder } from '../platforms/agiso/xianyu/order-detail-service.js' +import { normalizeAgisoMessageTemplate } from '../platforms/agiso/xianyu/message-service.js' import { getOrderFulfillmentBindingConfigs, getOrderFulfillmentBindingsFilePath, @@ -141,8 +142,8 @@ export function updateAdminAgisoShopConfigs(payload = /** @type {AdminAgisoShopC function mapAdminAgisoMessagingDefaults(defaults = {}) { return { - messageTemplate: String(defaults.messageTemplate || '').trim(), - autoDeliveryMessageTemplate: String(defaults.autoDeliveryMessageTemplate || '').trim(), + messageTemplate: normalizeAgisoMessageTemplate(String(defaults.messageTemplate || '').trim()), + autoDeliveryMessageTemplate: normalizeAgisoMessageTemplate(String(defaults.autoDeliveryMessageTemplate || '').trim()), } } @@ -153,8 +154,8 @@ function mapAdminAgisoShopConfigItem(shopId, config = {}) { accessToken: String(config.accessToken || '').trim(), accessTokenMasked: maskSecret(config.accessToken), enabled: typeof config.enabled === 'boolean' ? config.enabled : null, - messageTemplate: String(config.messageTemplate || '').trim(), - autoDeliveryMessageTemplate: String(config.autoDeliveryMessageTemplate || '').trim(), + messageTemplate: normalizeAgisoMessageTemplate(String(config.messageTemplate || '').trim()), + autoDeliveryMessageTemplate: normalizeAgisoMessageTemplate(String(config.autoDeliveryMessageTemplate || '').trim()), appSecretConfigured: Boolean(String(config.appSecret || '').trim()), apiVersion: String(config.apiVersion || '').trim(), sendMessageEndpoint: String(config.sendMessageEndpoint || '').trim(), @@ -168,7 +169,7 @@ function applyOptionalStringField(target, key, source) { const value = String(source[key] || '').trim() if (value) { - target[key] = value + target[key] = normalizeAgisoMessageTemplate(value) return } diff --git a/apps/backend/src/services/platforms/agiso/xianyu/message-service.js b/apps/backend/src/services/platforms/agiso/xianyu/message-service.js index 39967ad3..a2f1560a 100644 --- a/apps/backend/src/services/platforms/agiso/xianyu/message-service.js +++ b/apps/backend/src/services/platforms/agiso/xianyu/message-service.js @@ -49,6 +49,13 @@ export async function ensureAgisoXianyuAutoDeliveryMessageDeliveredForTask({ ord }) } +export function normalizeAgisoMessageTemplate(value) { + return String(value || '') + .replaceAll('\\r\\n', '\n') + .replaceAll('\\n', '\n') + .replaceAll('\r\n', '\n') +} + async function deliverAgisoXianyuMessageForTask({ order, task, @@ -241,7 +248,8 @@ function generateSign(params, appSecret) { } function renderAgisoClaimMessage({ order, task, claimUrl, expiredAt, template, shopName = '' }) { - const source = String(template || '').trim() || '您的订单 {platformOrderId} 已创建领取链接,请在 {expiredAt} 前完成领取:{claimUrl}' + const source = normalizeAgisoMessageTemplate(String(template || '').trim()) + || '您的订单 {platformOrderId} 已创建领取链接,请在 {expiredAt} 前完成领取:{claimUrl}' return renderAgisoMessageTemplate({ order, @@ -254,7 +262,8 @@ function renderAgisoClaimMessage({ order, task, claimUrl, expiredAt, template, s } export function renderAgisoAutoDeliveryMessage({ order, task, template, shopName = '' }) { - const source = String(template || '').trim() || '您的订单 {platformOrderId} 已完成自动发货,请注意查收。' + const source = normalizeAgisoMessageTemplate(String(template || '').trim()) + || '您的订单 {platformOrderId} 已完成自动发货,请注意查收。' return renderAgisoMessageTemplate({ order, @@ -276,7 +285,7 @@ function renderAgisoMessageTemplate({ } = {}) { const resolvedShopName = String(shopName || order?.shop_name || order?.shop_id || '').trim() - return String(template || '') + return normalizeAgisoMessageTemplate(template) .replaceAll('{platformOrderId}', String(order?.platform_order_id || '')) .replaceAll('{taskNo}', String(task?.task_no || '')) .replaceAll('{shopName}', resolvedShopName) diff --git a/apps/backend/src/services/platforms/agiso/xianyu/message-service.test.js b/apps/backend/src/services/platforms/agiso/xianyu/message-service.test.js index 39d05b14..7d6395e1 100644 --- a/apps/backend/src/services/platforms/agiso/xianyu/message-service.test.js +++ b/apps/backend/src/services/platforms/agiso/xianyu/message-service.test.js @@ -2,7 +2,11 @@ import test from 'node:test' import assert from 'node:assert/strict' import { runtimeConfig } from '../../../../config/runtime.js' -import { deliverAgisoXianyuMessageForTaskWithDeps } from './message-service.js' +import { + deliverAgisoXianyuMessageForTaskWithDeps, + normalizeAgisoMessageTemplate, + renderAgisoAutoDeliveryMessage, +} from './message-service.js' test('deliverAgisoXianyuMessageForTaskWithDeps skips duplicate successful claim message by order scope', async () => { const originalMessaging = runtimeConfig.platforms.agiso.messaging @@ -74,3 +78,26 @@ test('deliverAgisoXianyuMessageForTaskWithDeps skips duplicate successful claim runtimeConfig.platforms.agiso.appSecret = originalAppSecret } }) + +test('normalizeAgisoMessageTemplate converts escaped newline sequences into real line breaks', () => { + assert.equal( + normalizeAgisoMessageTemplate('第一行\\n第二行\\r\\n第三行'), + '第一行\n第二行\n第三行', + ) +}) + +test('renderAgisoAutoDeliveryMessage supports escaped newlines in configured template', () => { + const message = renderAgisoAutoDeliveryMessage({ + order: { + platform_order_id: '4502280133178028841', + shop_id: '2209880145223', + shop_name: '大锤号商', + }, + task: { + task_no: 'DT7af76e9b2438', + }, + template: '订单 {platformOrderId}\\n结果:{resultMessage}', + }) + + assert.equal(message, '订单 4502280133178028841\n结果:自动发货成功') +})