diff --git a/frontend/src/i18n/locales/en.ts b/frontend/src/i18n/locales/en.ts
index 144ed116c1..e9979a9d2a 100644
--- a/frontend/src/i18n/locales/en.ts
+++ b/frontend/src/i18n/locales/en.ts
@@ -4372,6 +4372,10 @@ export default {
field_secretKey: 'Secret Key',
field_publishableKey: 'Publishable Key',
field_webhookSecret: 'Webhook Secret',
+ field_cid: 'Channel ID',
+ field_cidAlipay: 'Alipay Channel ID',
+ field_cidWxpay: 'WeChat Channel ID',
+ stripeWebhookHint: 'Configure the following URL as a Webhook endpoint in Stripe Dashboard:',
productNamePrefix: 'Product Name Prefix',
productNameSuffix: 'Product Name Suffix',
preview: 'Preview',
diff --git a/frontend/src/i18n/locales/zh.ts b/frontend/src/i18n/locales/zh.ts
index 1252669722..e4b47ca6a8 100644
--- a/frontend/src/i18n/locales/zh.ts
+++ b/frontend/src/i18n/locales/zh.ts
@@ -4545,6 +4545,10 @@ export default {
field_secretKey: '密钥',
field_publishableKey: '公开密钥',
field_webhookSecret: 'Webhook 密钥',
+ field_cid: '支付渠道 ID',
+ field_cidAlipay: '支付宝渠道 ID',
+ field_cidWxpay: '微信渠道 ID',
+ stripeWebhookHint: '请在 Stripe Dashboard 中将以下地址配置为 Webhook 端点:',
productNamePrefix: '商品名前缀',
productNameSuffix: '商品名后缀',
preview: '预览',
diff --git a/frontend/src/views/admin/SettingsView.vue b/frontend/src/views/admin/SettingsView.vue
index 5ea5723c2e..074aecf11d 100644
--- a/frontend/src/views/admin/SettingsView.vue
+++ b/frontend/src/views/admin/SettingsView.vue
@@ -1830,9 +1830,16 @@
-
+
+
+
+
+ {{ t('admin.settings.payment.stripeWebhookHint') }}
+
+
{{ stripeWebhookHint }}
+
{{ t('admin.settings.payment.selectProviderKey') }}
@@ -2979,22 +2986,36 @@ interface ConfigFieldDef {
label: string
sensitive: boolean
optional?: boolean
+ defaultValue?: string // auto-fill value for new providers
+ hint?: string // hint text shown below the field
}
+const baseURL = window.location.origin
+const WEBHOOK_PATHS: Record = {
+ easypay: '/api/v1/payment/webhook/easypay',
+ alipay: '/api/v1/payment/webhook/alipay',
+ wxpay: '/api/v1/payment/webhook/wxpay',
+ stripe: '/api/v1/payment/webhook/stripe',
+}
+const RETURN_PATH = '/payment/result'
+
const PROVIDER_CONFIG_FIELDS: Record = {
easypay: [
{ key: 'pid', label: 'PID', sensitive: false },
{ key: 'pkey', label: 'PKey', sensitive: true },
{ key: 'apiBase', label: '', sensitive: false },
- { key: 'notifyUrl', label: '', sensitive: false },
- { key: 'returnUrl', label: '', sensitive: false },
+ { key: 'notifyUrl', label: '', sensitive: false, defaultValue: baseURL + WEBHOOK_PATHS.easypay },
+ { key: 'returnUrl', label: '', sensitive: false, defaultValue: baseURL + RETURN_PATH },
+ { key: 'cid', label: '', sensitive: false, optional: true },
+ { key: 'cidAlipay', label: '', sensitive: false, optional: true },
+ { key: 'cidWxpay', label: '', sensitive: false, optional: true },
],
alipay: [
{ key: 'appId', label: 'App ID', sensitive: false },
{ key: 'privateKey', label: '', sensitive: true },
{ key: 'publicKey', label: '', sensitive: true },
- { key: 'notifyUrl', label: '', sensitive: false },
- { key: 'returnUrl', label: '', sensitive: false },
+ { key: 'notifyUrl', label: '', sensitive: false, defaultValue: baseURL + WEBHOOK_PATHS.alipay },
+ { key: 'returnUrl', label: '', sensitive: false, defaultValue: baseURL + RETURN_PATH },
],
wxpay: [
{ key: 'appId', label: 'App ID', sensitive: false },
@@ -3004,7 +3025,7 @@ const PROVIDER_CONFIG_FIELDS: Record = {
{ key: 'publicKey', label: '', sensitive: true },
{ key: 'publicKeyId', label: '', sensitive: false, optional: true },
{ key: 'certSerial', label: '', sensitive: false, optional: true },
- { key: 'notifyUrl', label: '', sensitive: false },
+ { key: 'notifyUrl', label: '', sensitive: false, defaultValue: baseURL + WEBHOOK_PATHS.wxpay },
],
stripe: [
{ key: 'secretKey', label: '', sensitive: true },
@@ -3013,6 +3034,13 @@ const PROVIDER_CONFIG_FIELDS: Record = {
],
}
+// Stripe webhook URL hint (shown below the config section)
+const stripeWebhookHint = computed(() =>
+ providerForm.provider_key === 'stripe'
+ ? baseURL + WEBHOOK_PATHS.stripe
+ : ''
+)
+
const currentProviderFields = computed(() => {
const fields = PROVIDER_CONFIG_FIELDS[providerForm.provider_key] || []
return fields.map(f => ({
@@ -3081,6 +3109,9 @@ function toggleProviderSupportedType(type: string) {
function onProviderKeyChange() {
// Auto-select all supported types for the new provider key
providerForm.supported_types = (PROVIDER_SUPPORTED_TYPES[providerForm.provider_key] || []).join(',')
+ // Clear config and re-apply defaults
+ Object.keys(providerConfig).forEach(k => delete providerConfig[k])
+ applyConfigDefaults(providerForm.provider_key)
}
function providerKeyLabel(key: string): string {
@@ -3137,6 +3168,17 @@ function resetProviderForm() {
providerForm.supported_types = (PROVIDER_SUPPORTED_TYPES[defaultKey] || []).join(',')
providerForm.enabled = true; providerForm.refund_enabled = false
Object.keys(providerConfig).forEach(k => delete providerConfig[k])
+ // Auto-fill default values for new providers
+ applyConfigDefaults(defaultKey)
+}
+
+function applyConfigDefaults(providerKey: string) {
+ const fields = PROVIDER_CONFIG_FIELDS[providerKey] || []
+ for (const f of fields) {
+ if (f.defaultValue && !providerConfig[f.key]) {
+ providerConfig[f.key] = f.defaultValue
+ }
+ }
}
function openCreateProvider() { editingProvider.value = null; resetProviderForm(); showProviderDialog.value = true }
function openEditProvider(provider: ProviderInstance) {