优化电子凭证接口日志和结果展示

This commit is contained in:
yml2213
2026-07-09 19:00:47 +08:00
parent 32eb442b72
commit f8a1b992af
2 changed files with 83 additions and 8 deletions
@@ -33,11 +33,12 @@ export async function requestKuaishouIndustryOpenApi(
input: KuaishouIndustryOpenApiCallInput, input: KuaishouIndustryOpenApiCallInput,
): Promise<KuaishouIndustryOpenApiCallResult> { ): Promise<KuaishouIndustryOpenApiCallResult> {
let config = getKuaishouIndustryConfig() let config = getKuaishouIndustryConfig()
const apiLabel = formatKuaishouOpenApiLabel(input.apiMethod)
if (!config.enabled) { if (!config.enabled) {
logKuaishouOpenApi( logKuaishouOpenApi(
input, input,
`快手 OpenAPI 未启用,跳过 ${input.apiMethod}`, `快手 OpenAPI 未启用,跳过 ${apiLabel}`,
undefined, undefined,
) )
return { success: true, skippedReason: 'disabled' } return { success: true, skippedReason: 'disabled' }
@@ -56,7 +57,7 @@ export async function requestKuaishouIndustryOpenApi(
} catch (error) { } catch (error) {
logKuaishouOpenApi( logKuaishouOpenApi(
input, input,
`快手 OpenAPI token 准备失败 ${input.apiMethod}`, `快手 OpenAPI token 准备失败 ${apiLabel}`,
resolveKuaishouOpenApiErrorDetail(error), resolveKuaishouOpenApiErrorDetail(error),
'warn', 'warn',
) )
@@ -71,7 +72,7 @@ export async function requestKuaishouIndustryOpenApi(
if (!config.accessToken) { if (!config.accessToken) {
logKuaishouOpenApi( logKuaishouOpenApi(
input, input,
`快手 OpenAPI accessToken 缺失 ${input.apiMethod}`, `快手 OpenAPI accessToken 缺失 ${apiLabel}`,
undefined, undefined,
'warn', 'warn',
) )
@@ -110,7 +111,7 @@ export async function requestKuaishouIndustryOpenApi(
}) })
input.onRequest?.(requestLog) input.onRequest?.(requestLog)
logKuaishouOpenApi(input, `发起快手 OpenAPI ${input.apiMethod}`, requestLog) logKuaishouOpenApi(input, `发起快手 OpenAPI ${apiLabel}`, requestLog)
try { try {
const startedAt = Date.now() const startedAt = Date.now()
@@ -134,8 +135,8 @@ export async function requestKuaishouIndustryOpenApi(
logKuaishouOpenApi( logKuaishouOpenApi(
input, input,
success success
? `快手 OpenAPI 调用成功 ${input.apiMethod}` ? `快手 OpenAPI 调用成功 ${apiLabel}`
: `快手 OpenAPI 调用失败 ${input.apiMethod}`, : `快手 OpenAPI 调用失败 ${apiLabel}`,
{ {
durationMs, durationMs,
httpStatus: res.status, httpStatus: res.status,
@@ -156,7 +157,7 @@ export async function requestKuaishouIndustryOpenApi(
const errorDetail = resolveKuaishouOpenApiErrorDetail(error) const errorDetail = resolveKuaishouOpenApiErrorDetail(error)
logKuaishouOpenApi( logKuaishouOpenApi(
input, input,
`快手 OpenAPI 调用异常 ${input.apiMethod}`, `快手 OpenAPI 调用异常 ${apiLabel}`,
{ {
...errorDetail, ...errorDetail,
request: requestLog, request: requestLog,
@@ -187,6 +188,7 @@ export function buildKuaishouOpenApiRequestLog({
url, url,
method: httpMethod || 'POST', method: httpMethod || 'POST',
contentType: 'application/x-www-form-urlencoded', contentType: 'application/x-www-form-urlencoded',
apiName: resolveKuaishouOpenApiName(signParams.method),
apiMethod: signParams.method, apiMethod: signParams.method,
appkey: signParams.appkey, appkey: signParams.appkey,
access_token: signParams.access_token, access_token: signParams.access_token,
@@ -251,3 +253,25 @@ function logKuaishouOpenApi(
logIntegration('[kuaishou-industry/openapi]', message, detail, { level }) logIntegration('[kuaishou-industry/openapi]', message, detail, { level })
} }
function formatKuaishouOpenApiLabel(method: unknown): string {
const apiMethod = String(method || '').trim()
const apiName = resolveKuaishouOpenApiName(apiMethod)
return apiName ? `${apiName}(${apiMethod})` : apiMethod
}
function resolveKuaishouOpenApiName(method: unknown): string {
const apiMethod = String(method || '').trim()
const names: Record<string, string> = {
'integration.callback.virtual.eticket.send': '电子凭证发货回调',
'integration.callback.virtual.eticket.consume': '电子凭证核销回调',
'integration.callback.virtual.eticket.destroy': '电子凭证销毁回调',
'integration.callback.virtual.eticket.reverse': '电子凭证冲正回调',
'open.virtual.eticket.checkavailable': '检查电子凭证有效性',
'open.seller.order.refund.pcursor.list': '售后单列表',
'open.seller.order.refund.approve': '商家同意退款',
'open.seller.order.refund.disagree.refund': '商家不同意退款',
}
return names[apiMethod] || ''
}
@@ -49,6 +49,7 @@ import { formatAdminDateTime } from '@/utils/admin-time'
import { stringifyDisplayJson } from '@/utils/date-time' import { stringifyDisplayJson } from '@/utils/date-time'
type DateRangeValue = [Dayjs | null, Dayjs | null] | null type DateRangeValue = [Dayjs | null, Dayjs | null] | null
type IndustryTab = 'vouchers' | 'refunds' | 'result'
type VoucherFilterState = { type VoucherFilterState = {
oid: string oid: string
@@ -74,6 +75,7 @@ type RefundListState = {
const DEFAULT_ETICKET_TYPE = 'DINING_OPEN_TICKET' const DEFAULT_ETICKET_TYPE = 'DINING_OPEN_TICKET'
export default function AdminKuaishouIndustryPage() { export default function AdminKuaishouIndustryPage() {
const [activeTab, setActiveTab] = useState<IndustryTab>('vouchers')
const [voucherLoading, setVoucherLoading] = useState(false) const [voucherLoading, setVoucherLoading] = useState(false)
const [actionLoading, setActionLoading] = useState('') const [actionLoading, setActionLoading] = useState('')
const [vouchers, setVouchers] = useState<AdminKuaishouIndustryVoucher[]>([]) const [vouchers, setVouchers] = useState<AdminKuaishouIndustryVoucher[]>([])
@@ -289,6 +291,7 @@ export default function AdminKuaishouIndustryPage() {
const response = await consumeAdminKuaishouIndustryVoucher(buildVoucherToolPayload()) const response = await consumeAdminKuaishouIndustryVoucher(buildVoucherToolPayload())
setLastResultTitle('手动核销') setLastResultTitle('手动核销')
setLastResult(response.data) setLastResult(response.data)
setActiveTab('result')
showSuccess('手动核销已完成') showSuccess('手动核销已完成')
await loadVouchers() await loadVouchers()
} catch (error) { } catch (error) {
@@ -304,6 +307,7 @@ export default function AdminKuaishouIndustryPage() {
const response = await resendAdminKuaishouIndustryVoucherCode(buildVoucherToolPayload()) const response = await resendAdminKuaishouIndustryVoucherCode(buildVoucherToolPayload())
setLastResultTitle('重发发码回调') setLastResultTitle('重发发码回调')
setLastResult(response.data) setLastResult(response.data)
setActiveTab('result')
if (response.data.success) { if (response.data.success) {
showSuccess('发码回调已重发') showSuccess('发码回调已重发')
} else { } else {
@@ -361,6 +365,7 @@ export default function AdminKuaishouIndustryPage() {
const response = await action() const response = await action()
setLastResultTitle(title) setLastResultTitle(title)
setLastResult(response.data) setLastResult(response.data)
setActiveTab('result')
afterSuccess?.(response.data) afterSuccess?.(response.data)
if (response.data.success) { if (response.data.success) {
showSuccess(`${title}已执行`) showSuccess(`${title}已执行`)
@@ -407,6 +412,8 @@ export default function AdminKuaishouIndustryPage() {
<PageHeader title="快手电子凭证" description="行业电子凭证接口工具与售后处理" /> <PageHeader title="快手电子凭证" description="行业电子凭证接口工具与售后处理" />
<Tabs <Tabs
activeKey={activeTab}
onChange={(key) => setActiveTab(key as IndustryTab)}
items={[ items={[
{ {
key: 'vouchers', key: 'vouchers',
@@ -768,6 +775,8 @@ export default function AdminKuaishouIndustryPage() {
} }
function renderResultTab() { function renderResultTab() {
const summary = resolveOpenApiResultSummary(lastResult)
return ( return (
<Card <Card
title={lastResultTitle} title={lastResultTitle}
@@ -778,7 +787,15 @@ export default function AdminKuaishouIndustryPage() {
} }
> >
{lastResult ? ( {lastResult ? (
<pre className="json-preview">{stringifyDisplayJson(lastResult)}</pre> <Space direction="vertical" size={12} className="full-width">
<Alert
type={summary.success ? 'success' : 'error'}
showIcon
message={summary.title}
description={summary.description}
/>
<pre className="json-preview">{stringifyDisplayJson(lastResult)}</pre>
</Space>
) : ( ) : (
<Alert type="info" showIcon message="暂无接口结果" /> <Alert type="info" showIcon message="暂无接口结果" />
)} )}
@@ -809,6 +826,40 @@ function extractRefundRows(response: Record<string, unknown> | null): Array<Reco
: [] : []
} }
function resolveOpenApiResultSummary(value: unknown) {
const result = value && typeof value === 'object' && !Array.isArray(value)
? value as Record<string, unknown>
: {}
const response = result.response && typeof result.response === 'object' && !Array.isArray(result.response)
? result.response as Record<string, unknown>
: null
const success = Boolean(result.success)
const code = String(response?.code || response?.sub_code || '').trim()
const resultCode = String(response?.result || '').trim()
const message = String(
response?.error_msg ||
response?.msg ||
response?.sub_msg ||
response?.message ||
result.error ||
'',
).trim()
const status = Number(result.httpStatus || 0) || 0
const durationMs = Number(result.durationMs || 0) || 0
const markers = [
status ? `HTTP ${status}` : '',
resultCode ? `result=${resultCode}` : '',
code ? `code=${code}` : '',
durationMs ? `${durationMs}ms` : '',
].filter(Boolean)
return {
success,
title: success ? '接口返回成功' : '接口返回失败',
description: [markers.join(' / '), message].filter(Boolean).join('') || '请查看下方原始响应。',
}
}
function getVoucherStatusColor(status: string) { function getVoucherStatusColor(status: string) {
const normalized = String(status || '').toUpperCase() const normalized = String(status || '').toUpperCase()
if (normalized === 'CONSUMED') return 'green' if (normalized === 'CONSUMED') return 'green'