优化电子凭证接口日志和结果展示
This commit is contained in:
@@ -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'
|
||||||
|
|||||||
Reference in New Issue
Block a user