feat(payment): i18n payment error codes and label localization
Pairs with the backend structured payment errors (reason + metadata). The
frontend now maps reason codes to localized messages with metadata as
interpolation variables, and automatically localizes raw config-field names
(e.g. "certSerial" → "证书序列号") using the existing UI-label i18n
namespace.
- frontend/src/utils/apiError.ts
- extractApiErrorCode now prefers the string `reason` over the numeric HTTP
`code`; reason is granular enough to drive i18n lookup, HTTP code is not.
- New extractApiErrorMetadata to pull interpolation params off the error.
- New extractI18nErrorMessage(err, t, namespace, fallback): looks up
`<namespace>.<REASON>` in i18n and substitutes metadata. Before
substitution, `metadata.key` and `metadata.keys` (slash-joined) are
re-translated through `admin.settings.payment.field_<key>` so users see
"缺少必填项:证书序列号" instead of "缺少必填项:certSerial".
- frontend/src/i18n/locales/{zh,en}.ts
- Add payment.errors entries for every structured reason code returned by
the backend (PAYMENT_DISABLED, INVALID_AMOUNT, TOO_MANY_PENDING,
DAILY_LIMIT_EXCEEDED, NO_AVAILABLE_INSTANCE, PAYMENT_PROVIDER_MISCONFIGURED,
WXPAY_CONFIG_MISSING_KEY / INVALID_KEY_LENGTH / INVALID_KEY, NOT_FOUND,
FORBIDDEN, CONFLICT, INVALID_ORDER_TYPE, INVALID_STATUS,
BALANCE_NOT_ENOUGH, REFUND_AMOUNT_EXCEEDED, REFUND_FAILED, and more),
with placeholders for template variables.
- 13 payment-related Vue files
- Migrate catch-block error reporting from extractApiErrorMessage to
extractI18nErrorMessage(err, t, 'payment.errors', fallback).
- Remove the ad-hoc paymentErrorMap computed in SettingsView.vue, which the
new helper supersedes (it reads i18n directly via t).
- frontend/src/components/payment/providerConfig.ts
- wxpay: publicKey and publicKeyId are now required (was optional), matching
the pubkey-only verifier direction; certSerial is already required.
This PR is drop-in safe: reason-preferring extractApiErrorCode is backward
compatible with callers that pass their own i18nMap, and error codes missing
from i18n fall back to the existing message-based path.
This commit is contained in:
@@ -5620,7 +5620,33 @@ export default {
|
||||
errors: {
|
||||
tooManyPending: '待支付订单过多(最多 {max} 个),请先完成或取消现有订单',
|
||||
cancelRateLimited: '取消订单过于频繁,请稍后再试',
|
||||
// Structured error codes (reason strings from backend ApplicationError)
|
||||
PAYMENT_DISABLED: '支付系统已关闭',
|
||||
USER_INACTIVE: '账号已被禁用',
|
||||
BALANCE_PAYMENT_DISABLED: '余额充值功能已关闭',
|
||||
INVALID_AMOUNT: '金额无效',
|
||||
INVALID_INPUT: '参数有误',
|
||||
PLAN_NOT_AVAILABLE: '套餐不存在或已下架',
|
||||
GROUP_NOT_FOUND: '订阅分组不可用',
|
||||
GROUP_TYPE_MISMATCH: '分组类型不是订阅类型',
|
||||
TOO_MANY_PENDING: '待支付订单过多(最多 {max} 个),请先完成或取消现有订单',
|
||||
DAILY_LIMIT_EXCEEDED: '今日充值已达上限,剩余额度 {remaining}',
|
||||
PAYMENT_GATEWAY_ERROR: '支付方式不可用',
|
||||
NO_AVAILABLE_INSTANCE: '暂无可用的支付通道',
|
||||
PAYMENT_PROVIDER_MISCONFIGURED: '支付通道配置错误,请联系管理员',
|
||||
WXPAY_CONFIG_MISSING_KEY: '微信支付配置缺少必填项:{key}',
|
||||
WXPAY_CONFIG_INVALID_KEY_LENGTH: '微信支付 {key} 长度错误,应为 {expected} 字节(实际 {actual})',
|
||||
WXPAY_CONFIG_INVALID_KEY: '微信支付 {key} 格式错误,请确认复制了完整的 PEM 内容',
|
||||
PENDING_ORDERS: '该服务商有未完成的订单,请等待订单完成后再操作',
|
||||
CANCEL_RATE_LIMITED: '取消订单过于频繁,请稍后再试',
|
||||
NOT_FOUND: '订单不存在',
|
||||
FORBIDDEN: '无权限操作此订单',
|
||||
CONFLICT: '订单状态已变更,请刷新',
|
||||
INVALID_ORDER_TYPE: '仅余额订单可申请退款',
|
||||
INVALID_STATUS: '当前订单状态不允许此操作',
|
||||
BALANCE_NOT_ENOUGH: '退款金额超过余额',
|
||||
REFUND_AMOUNT_EXCEEDED: '退款金额超过充值金额',
|
||||
REFUND_FAILED: '退款失败',
|
||||
},
|
||||
stripePay: '立即支付',
|
||||
stripeSuccessProcessing: '支付成功,正在处理订单...',
|
||||
|
||||
Reference in New Issue
Block a user