mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-09-24 16:05:44 +08:00
feat(i18n): add error code mapping for payment API errors
This commit is contained in:
@@ -5144,6 +5144,7 @@ export default {
|
||||
errors: {
|
||||
tooManyPending: 'Too many pending orders (max {max}). Please complete or cancel existing orders first.',
|
||||
cancelRateLimited: 'Too many cancellations. Please try again later.',
|
||||
PENDING_ORDERS: 'This provider has pending orders. Please wait for them to complete before making changes.',
|
||||
},
|
||||
stripePay: 'Pay Now',
|
||||
stripeSuccessProcessing: 'Payment successful, processing your order...',
|
||||
|
||||
@@ -5341,6 +5341,7 @@ export default {
|
||||
errors: {
|
||||
tooManyPending: '待支付订单过多(最多 {max} 个),请先完成或取消现有订单',
|
||||
cancelRateLimited: '取消订单过于频繁,请稍后再试',
|
||||
PENDING_ORDERS: '该服务商有未完成的订单,请等待订单完成后再操作',
|
||||
},
|
||||
stripePay: '立即支付',
|
||||
stripeSuccessProcessing: '支付成功,正在处理订单...',
|
||||
|
||||
@@ -10,6 +10,8 @@ interface ApiErrorLike {
|
||||
code?: number | string
|
||||
message?: string
|
||||
error?: string
|
||||
reason?: string
|
||||
metadata?: Record<string, unknown>
|
||||
response?: {
|
||||
data?: {
|
||||
detail?: string
|
||||
@@ -19,21 +21,36 @@ interface ApiErrorLike {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the error code from an API error object.
|
||||
*/
|
||||
export function extractApiErrorCode(err: unknown): string | undefined {
|
||||
if (!err || typeof err !== 'object') return undefined
|
||||
const e = err as ApiErrorLike
|
||||
const code = e.code ?? e.reason ?? e.response?.data?.code
|
||||
return code != null ? String(code) : undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract a displayable error message from an API error.
|
||||
*
|
||||
* Handles:
|
||||
* - Plain objects from API client interceptor: { status, code, message }
|
||||
* - Axios errors with response.data
|
||||
* - Standard Error instances
|
||||
* - Unknown types (stringified)
|
||||
*
|
||||
* @param err - The caught error (unknown type)
|
||||
* @param fallback - Fallback message if none can be extracted (use t('common.error') or similar)
|
||||
* @param i18nMap - Optional map of error codes to i18n translated strings
|
||||
*/
|
||||
export function extractApiErrorMessage(err: unknown, fallback = 'Unknown error'): string {
|
||||
export function extractApiErrorMessage(
|
||||
err: unknown,
|
||||
fallback = 'Unknown error',
|
||||
i18nMap?: Record<string, string>,
|
||||
): string {
|
||||
if (!err) return fallback
|
||||
|
||||
// Try i18n mapping by error code first
|
||||
if (i18nMap) {
|
||||
const code = extractApiErrorCode(err)
|
||||
if (code && i18nMap[code]) return i18nMap[code]
|
||||
}
|
||||
|
||||
// Plain object from API client interceptor (most common case)
|
||||
if (typeof err === 'object' && err !== null) {
|
||||
const e = err as ApiErrorLike
|
||||
|
||||
@@ -2888,6 +2888,10 @@ const cancelRateLimitModeOptions = computed(() => [
|
||||
{ value: 'fixed', label: t('admin.settings.payment.cancelRateLimitWindowModeFixed') },
|
||||
])
|
||||
|
||||
const paymentErrorMap = computed(() => ({
|
||||
PENDING_ORDERS: t('payment.errors.PENDING_ORDERS'),
|
||||
}))
|
||||
|
||||
async function loadProviders() {
|
||||
providersLoading.value = true
|
||||
try { const res = await adminAPI.payment.getProviders(); providers.value = res.data || [] }
|
||||
@@ -2920,7 +2924,7 @@ async function handleSaveProvider(payload: any) {
|
||||
// Also save the overall settings so payment config changes are persisted together
|
||||
await saveSettings()
|
||||
} catch (err: unknown) {
|
||||
appStore.showError(extractApiErrorMessage(err, t('common.error')))
|
||||
appStore.showError(extractApiErrorMessage(err, t('common.error'), paymentErrorMap.value))
|
||||
} finally {
|
||||
providerSaving.value = false
|
||||
}
|
||||
@@ -2932,7 +2936,7 @@ async function handleToggleField(provider: ProviderInstance, field: 'enabled' |
|
||||
await adminAPI.payment.updateProvider(provider.id, { [field]: newValue })
|
||||
if (field === 'enabled') provider.enabled = newValue
|
||||
else provider.refund_enabled = newValue
|
||||
} catch (err: unknown) { appStore.showError(extractApiErrorMessage(err, t('common.error'))) }
|
||||
} catch (err: unknown) { appStore.showError(extractApiErrorMessage(err, t('common.error'), paymentErrorMap.value)) }
|
||||
}
|
||||
|
||||
async function handleToggleType(provider: ProviderInstance, type: string) {
|
||||
@@ -2946,7 +2950,7 @@ async function handleToggleType(provider: ProviderInstance, type: string) {
|
||||
try {
|
||||
await adminAPI.payment.updateProvider(provider.id, { supported_types: updated } as any)
|
||||
provider.supported_types = updated
|
||||
} catch (err: unknown) { appStore.showError(extractApiErrorMessage(err, t('common.error'))) }
|
||||
} catch (err: unknown) { appStore.showError(extractApiErrorMessage(err, t('common.error'), paymentErrorMap.value)) }
|
||||
}
|
||||
|
||||
function confirmDeleteProvider(provider: ProviderInstance) {
|
||||
@@ -2961,7 +2965,7 @@ async function handleDeleteProvider() {
|
||||
appStore.showSuccess(t('common.deleted'))
|
||||
showDeleteProviderDialog.value = false
|
||||
loadProviders()
|
||||
} catch (err: unknown) { appStore.showError(extractApiErrorMessage(err, t('common.error'))) }
|
||||
} catch (err: unknown) { appStore.showError(extractApiErrorMessage(err, t('common.error'), paymentErrorMap.value)) }
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
|
||||
Reference in New Issue
Block a user