fix(claim): 透出 affiliate_dash 上游错误,便于排查提交 UID 失败

上游 4xx 不再一律打成 502 兜底文案;affiliate_dash 依赖错误优先展示真实 message。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
yml2213
2026-09-15 11:51:32 +08:00
co-authored by Cursor
parent 868e8a740e
commit 2e197f93e0
3 changed files with 42 additions and 17 deletions
@@ -95,18 +95,20 @@ export async function affiliateDashRequest(input: {
logExternalHttpPacket('[affiliate-dash/http]', 'HTTP 响应失败', responsePacket, {
level: 'warn',
})
throw createHttpError(
summarizeAffiliateDashMessage(json) || `affiliate-dash 请求失败: HTTP ${response.status}`,
{
statusCode: 502,
errorCode: 'affiliate_dash_http_failed',
context: {
status: response.status,
message: summarizeAffiliateDashMessage(json),
body: text,
},
const upstreamMessage =
summarizeAffiliateDashMessage(json) || `affiliate-dash 请求失败: HTTP ${response.status}`
// 上游 4xx 透传状态码,便于领取页展示真实原因;5xx 仍归一为 502。
const statusCode =
response.status >= 400 && response.status < 500 ? response.status : 502
throw createHttpError(upstreamMessage, {
statusCode,
errorCode: 'affiliate_dash_http_failed',
context: {
status: response.status,
message: summarizeAffiliateDashMessage(json),
body: text,
},
)
})
}
if (!isAffiliateDashSuccessResponse(json)) {
+20 -1
View File
@@ -1,7 +1,7 @@
import assert from 'node:assert/strict'
import test from 'node:test'
import { resolveRouteErrorLogLevel } from './http.js'
import { buildErrorPayload, createHttpError, resolveRouteErrorLogLevel } from './http.js'
test('expected worker session expiry is debug-level', () => {
assert.equal(
@@ -14,3 +14,22 @@ test('expected worker session expiry is debug-level', () => {
)
assert.equal(resolveRouteErrorLogLevel({ statusCode: 500, errorCode: 'internal_error' }), 'error')
})
test('affiliate_dash errors surface upstream message even when mapped to 502', () => {
const error = createHttpError('乐玩开放平台 AccessKey 或 SecretKey 未配置', {
statusCode: 502,
errorCode: 'affiliate_dash_http_failed',
})
const payload = buildErrorPayload(error, '提交 UID 失败')
assert.equal(payload.msg, '乐玩开放平台 AccessKey 或 SecretKey 未配置')
assert.equal(payload.errorCode, 'affiliate_dash_http_failed')
})
test('generic 5xx still uses fallback message', () => {
const error = createHttpError('secret internal boom', {
statusCode: 500,
errorCode: 'internal_error',
})
const payload = buildErrorPayload(error, '服务内部错误')
assert.equal(payload.msg, '服务内部错误')
})
+9 -5
View File
@@ -29,12 +29,16 @@ export function buildSuccessPayload(data: unknown, msg: string = 'ok') {
export function buildErrorPayload(error: unknown, fallbackMessage: string) {
const classification = classifyRouteError(error)
const message =
classification.statusCode >= 500
const errorMessage = error instanceof Error ? String(error.message || '').trim() : ''
// 依赖方错误(如 affiliate_dash)即使映射为 5xx,也优先透出上游可读原因。
const preferUpstreamMessage =
errorMessage &&
(classification.statusCode < 500 || classification.errorCode.startsWith('affiliate_dash'))
const message = preferUpstreamMessage
? errorMessage
: classification.statusCode >= 500
? fallbackMessage || '服务内部错误'
: error instanceof Error
? error.message
: fallbackMessage
: errorMessage || fallbackMessage
return {
code: 1,