删除无用字段
This commit is contained in:
@@ -25,4 +25,3 @@ ADMIN_DEFAULT_USERS_JSON=[{"username":"admin","password":"dev-admin-123456","rol
|
|||||||
|
|
||||||
AGISO_APP_SECRET=
|
AGISO_APP_SECRET=
|
||||||
AGISO_MESSAGING_ENABLED=false
|
AGISO_MESSAGING_ENABLED=false
|
||||||
AGISO_MESSAGE_APP_SECRET=
|
|
||||||
|
|||||||
@@ -22,4 +22,3 @@ ADMIN_DEFAULT_USERS_JSON=[{"username":"admin","password":"replace-with-strong-ad
|
|||||||
|
|
||||||
AGISO_APP_SECRET=
|
AGISO_APP_SECRET=
|
||||||
AGISO_MESSAGING_ENABLED=false
|
AGISO_MESSAGING_ENABLED=false
|
||||||
AGISO_MESSAGE_APP_SECRET=
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
APP_DOMAIN=order.khhao.com
|
||||||
|
APP_BASE_URL=https://order.khhao.com
|
||||||
|
|
||||||
|
TZ=Asia/Shanghai
|
||||||
|
BACKEND_PORT=3000
|
||||||
|
CLAIM_BASE_URL=https://order.khhao.com/#/claim
|
||||||
|
DATABASE_URL=postgres://postgres:FACCqheAzy51op0RFdbv@postgres:5432/order_site
|
||||||
|
DATABASE_SSL=false
|
||||||
|
DATABASE_MAX_CONNECTIONS=20
|
||||||
|
DATA_ROOT=/app/data
|
||||||
|
OCR_PROJECT_ROOT=/app/subservices/ocr-worker
|
||||||
|
TENCENT_REDEEM_PROOF_MODE=basic
|
||||||
|
TENCENT_BROWSER_HEADLESS=true
|
||||||
|
TENCENT_BROWSER_DEVTOOLS=false
|
||||||
|
TENCENT_BROWSER_PREWARM=true
|
||||||
|
TENCENT_BROWSER_KEEP_ALIVE=true
|
||||||
|
TENCENT_BROWSER_SLOW_MO=0
|
||||||
|
TENCENT_SESSION_DEBUG=false
|
||||||
|
|
||||||
|
ADMIN_SESSION_SECRET=xm4BDpbdHJvU4RIlpGqD0nvQTZtIidvQMk6LSP1d
|
||||||
|
ADMIN_DEFAULT_USERS_JSON=[{"username":"admin","password":"Mzl5iG6pkdrzLs73COiB","role":"admin"},{"username":"operator","password":"d9tvmbPPMRdLySEhORzk","role":"operator"}]
|
||||||
|
|
||||||
|
AGISO_APP_SECRET=9fcb0f688aab713f9af3e85d29ba8b15
|
||||||
|
AGISO_MESSAGING_ENABLED=false
|
||||||
@@ -76,7 +76,6 @@ npm run typecheck
|
|||||||
- 全局兜底配置仍走 `.env`:
|
- 全局兜底配置仍走 `.env`:
|
||||||
- `AGISO_APP_SECRET`
|
- `AGISO_APP_SECRET`
|
||||||
- `AGISO_MESSAGING_ENABLED`
|
- `AGISO_MESSAGING_ENABLED`
|
||||||
- `AGISO_MESSAGE_APP_SECRET`
|
|
||||||
- 默认消息模板与店铺级覆盖配置改为文件:
|
- 默认消息模板与店铺级覆盖配置改为文件:
|
||||||
- `apps/backend/data/agiso-shops.json`
|
- `apps/backend/data/agiso-shops.json`
|
||||||
- 后台维护入口:
|
- 后台维护入口:
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ module.exports = {
|
|||||||
enabled: false,
|
enabled: false,
|
||||||
sendMessageEndpoint: 'https://gw-api.agiso.com/aldsIdle/ImMsg/SendMsg',
|
sendMessageEndpoint: 'https://gw-api.agiso.com/aldsIdle/ImMsg/SendMsg',
|
||||||
apiVersion: '1',
|
apiVersion: '1',
|
||||||
appSecret: '',
|
|
||||||
messageTemplate: '您的订单 {platformOrderId} 已创建领取链接,请在 {expiredAt} 前完成领取:{claimUrl}',
|
messageTemplate: '您的订单 {platformOrderId} 已创建领取链接,请在 {expiredAt} 前完成领取:{claimUrl}',
|
||||||
autoDeliveryMessageTemplate: '您的订单 {platformOrderId} 已完成自动发货,请注意查收。',
|
autoDeliveryMessageTemplate: '您的订单 {platformOrderId} 已完成自动发货,请注意查收。',
|
||||||
shops: {},
|
shops: {},
|
||||||
|
|||||||
@@ -215,11 +215,6 @@ function applyEnvOverrides(baseConfig) {
|
|||||||
nextConfig.platforms.agiso.autoDelivery.apiVersion = agisoAutoDeliveryApiVersion
|
nextConfig.platforms.agiso.autoDelivery.apiVersion = agisoAutoDeliveryApiVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
const agisoMessageAppSecret = String(process.env.AGISO_MESSAGE_APP_SECRET || '').trim()
|
|
||||||
if (agisoMessageAppSecret) {
|
|
||||||
nextConfig.platforms.agiso.messaging.appSecret = agisoMessageAppSecret
|
|
||||||
}
|
|
||||||
|
|
||||||
const agisoMessageApiVersion = String(process.env.AGISO_MESSAGE_API_VERSION || '').trim()
|
const agisoMessageApiVersion = String(process.env.AGISO_MESSAGE_API_VERSION || '').trim()
|
||||||
if (agisoMessageApiVersion) {
|
if (agisoMessageApiVersion) {
|
||||||
nextConfig.platforms.agiso.messaging.apiVersion = agisoMessageApiVersion
|
nextConfig.platforms.agiso.messaging.apiVersion = agisoMessageApiVersion
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const CORE_BOOT_RETRY_DELAY_MS = 5_000
|
|||||||
|
|
||||||
const app = express()
|
const app = express()
|
||||||
const port = Number(runtimeConfig.server.port || 3000)
|
const port = Number(runtimeConfig.server.port || 3000)
|
||||||
|
const host = '0.0.0.0'
|
||||||
const startupState = createStartupState()
|
const startupState = createStartupState()
|
||||||
|
|
||||||
app.use((req, res, next) => {
|
app.use((req, res, next) => {
|
||||||
@@ -88,8 +89,8 @@ app.use('/api/v1/webhooks', webhooksRouter)
|
|||||||
app.use('/api/v1/claim', claimsRouter)
|
app.use('/api/v1/claim', claimsRouter)
|
||||||
app.use('/api/v1/admin', adminRouter)
|
app.use('/api/v1/admin', adminRouter)
|
||||||
|
|
||||||
const server = app.listen(port, () => {
|
const server = app.listen(port, host, () => {
|
||||||
logInfo('[startup]', `order-site-backend listening on http://127.0.0.1:${port}`)
|
logInfo('[startup]', `order-site-backend listening on http://${host}:${port}`)
|
||||||
void bootstrapCoreServices()
|
void bootstrapCoreServices()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ const ACTIVITY_URL = 'https://df.qq.com/cp/a20240812cdk/index.html'
|
|||||||
const CHROME_PATH = String(runtimeConfig.browser.chromePath || '').trim()
|
const CHROME_PATH = String(runtimeConfig.browser.chromePath || '').trim()
|
||||||
const DEFAULT_LOGIN_TYPE = 'qq'
|
const DEFAULT_LOGIN_TYPE = 'qq'
|
||||||
const SESSION_TTL_MS = 30 * 60 * 1000
|
const SESSION_TTL_MS = 30 * 60 * 1000
|
||||||
|
export const REDEEM_SUCCESS_AUTO_CLOSE_MS = 3 * 60 * 1000
|
||||||
const DEFAULT_VIEWPORT = resolveDefaultViewport()
|
const DEFAULT_VIEWPORT = resolveDefaultViewport()
|
||||||
const SESSION_DEBUG_ENABLED = Boolean(runtimeConfig.session.debug)
|
const SESSION_DEBUG_ENABLED = Boolean(runtimeConfig.session.debug)
|
||||||
|
|
||||||
@@ -103,6 +104,8 @@ export async function createTencentBrowserSession(payload = {}) {
|
|||||||
createdAt: new Date().toISOString(),
|
createdAt: new Date().toISOString(),
|
||||||
updatedAt: new Date().toISOString(),
|
updatedAt: new Date().toISOString(),
|
||||||
expiresAt: Date.now() + SESSION_TTL_MS,
|
expiresAt: Date.now() + SESSION_TTL_MS,
|
||||||
|
autoCloseAt: 0,
|
||||||
|
autoCloseTimer: null,
|
||||||
sessionDir,
|
sessionDir,
|
||||||
browserContext,
|
browserContext,
|
||||||
page,
|
page,
|
||||||
@@ -245,7 +248,7 @@ export async function refreshTencentBrowserSession(sessionId, { includeQrImage =
|
|||||||
}
|
}
|
||||||
|
|
||||||
session.updatedAt = new Date().toISOString()
|
session.updatedAt = new Date().toISOString()
|
||||||
session.expiresAt = Date.now() + SESSION_TTL_MS
|
session.expiresAt = resolveTencentSessionExpiresAt(session)
|
||||||
|
|
||||||
if (!session.qrImageBase64 || session.status === 'expired') {
|
if (!session.qrImageBase64 || session.status === 'expired') {
|
||||||
if (session.status === 'expired') {
|
if (session.status === 'expired') {
|
||||||
@@ -293,7 +296,9 @@ export async function redeemTencentBrowserSession(sessionId, payload = {}) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return runTencentBrowserRedeem({
|
resetTencentSessionAutoClose(session)
|
||||||
|
|
||||||
|
await runTencentBrowserRedeem({
|
||||||
session,
|
session,
|
||||||
code,
|
code,
|
||||||
maxAttempts,
|
maxAttempts,
|
||||||
@@ -312,6 +317,14 @@ export async function redeemTencentBrowserSession(sessionId, payload = {}) {
|
|||||||
saveRedeemArtifacts,
|
saveRedeemArtifacts,
|
||||||
activityUrl: ACTIVITY_URL,
|
activityUrl: ACTIVITY_URL,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
armRedeemedSessionAutoClose(session)
|
||||||
|
await persistSessionState(session)
|
||||||
|
|
||||||
|
return {
|
||||||
|
...buildSessionPayload(session),
|
||||||
|
redeem: session.lastRedeem,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function closeTencentBrowserSession(sessionId) {
|
export async function closeTencentBrowserSession(sessionId) {
|
||||||
@@ -611,12 +624,46 @@ async function ensureLoginTab(page, loginType) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function applyInitialQrSessionState(session) {
|
function applyInitialQrSessionState(session) {
|
||||||
|
resetTencentSessionAutoClose(session)
|
||||||
session.status = 'waiting_scan'
|
session.status = 'waiting_scan'
|
||||||
session.notice = `请使用${getLoginTypeLabel(session.loginType)}扫码登录`
|
session.notice = `请使用${getLoginTypeLabel(session.loginType)}扫码登录`
|
||||||
session.updatedAt = new Date().toISOString()
|
session.updatedAt = new Date().toISOString()
|
||||||
session.expiresAt = Date.now() + SESSION_TTL_MS
|
session.expiresAt = Date.now() + SESSION_TTL_MS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function resolveTencentSessionExpiresAt(session, nowMs = Date.now()) {
|
||||||
|
const autoCloseAt = Number(session?.autoCloseAt || 0)
|
||||||
|
if (autoCloseAt > 0) {
|
||||||
|
return autoCloseAt
|
||||||
|
}
|
||||||
|
|
||||||
|
return nowMs + SESSION_TTL_MS
|
||||||
|
}
|
||||||
|
|
||||||
|
function armRedeemedSessionAutoClose(session) {
|
||||||
|
resetTencentSessionAutoClose(session)
|
||||||
|
|
||||||
|
const autoCloseAt = Date.now() + REDEEM_SUCCESS_AUTO_CLOSE_MS
|
||||||
|
session.autoCloseAt = autoCloseAt
|
||||||
|
session.expiresAt = autoCloseAt
|
||||||
|
session.autoCloseTimer = setTimeout(() => {
|
||||||
|
void closeSession(session, { markClosed: true }).catch(() => {
|
||||||
|
// ignore delayed auto-close failures
|
||||||
|
})
|
||||||
|
}, REDEEM_SUCCESS_AUTO_CLOSE_MS)
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetTencentSessionAutoClose(session) {
|
||||||
|
if (session?.autoCloseTimer) {
|
||||||
|
clearTimeout(session.autoCloseTimer)
|
||||||
|
session.autoCloseTimer = null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (session) {
|
||||||
|
session.autoCloseAt = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function extractHostState(page) {
|
async function extractHostState(page) {
|
||||||
return page.evaluate(() => {
|
return page.evaluate(() => {
|
||||||
const isVisible = (element) => {
|
const isVisible = (element) => {
|
||||||
@@ -924,6 +971,7 @@ async function cleanupExpiredTencentBrowserSessions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function closeSession(session, { markClosed }) {
|
async function closeSession(session, { markClosed }) {
|
||||||
|
resetTencentSessionAutoClose(session)
|
||||||
sessions.delete(session.sessionId)
|
sessions.delete(session.sessionId)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import test from 'node:test'
|
||||||
|
import assert from 'node:assert/strict'
|
||||||
|
|
||||||
|
import {
|
||||||
|
REDEEM_SUCCESS_AUTO_CLOSE_MS,
|
||||||
|
resolveTencentSessionExpiresAt,
|
||||||
|
} from './session.js'
|
||||||
|
|
||||||
|
test('resolveTencentSessionExpiresAt uses normal ttl when no auto-close is armed', () => {
|
||||||
|
const nowMs = Date.UTC(2026, 3, 14, 9, 30, 0)
|
||||||
|
assert.equal(
|
||||||
|
resolveTencentSessionExpiresAt({ autoCloseAt: 0 }, nowMs),
|
||||||
|
nowMs + (30 * 60 * 1000),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('resolveTencentSessionExpiresAt keeps redeemed auto-close deadline once armed', () => {
|
||||||
|
const nowMs = Date.UTC(2026, 3, 14, 9, 30, 0)
|
||||||
|
const autoCloseAt = nowMs + REDEEM_SUCCESS_AUTO_CLOSE_MS
|
||||||
|
|
||||||
|
assert.equal(
|
||||||
|
resolveTencentSessionExpiresAt({ autoCloseAt }, nowMs + 60_000),
|
||||||
|
autoCloseAt,
|
||||||
|
)
|
||||||
|
})
|
||||||
@@ -79,7 +79,6 @@ export {}
|
|||||||
* }
|
* }
|
||||||
* messaging: {
|
* messaging: {
|
||||||
* enabled: boolean
|
* enabled: boolean
|
||||||
* appSecret: string
|
|
||||||
* apiVersion: string
|
* apiVersion: string
|
||||||
* sendMessageEndpoint: string
|
* sendMessageEndpoint: string
|
||||||
* messageTemplate: string
|
* messageTemplate: string
|
||||||
|
|||||||
Reference in New Issue
Block a user