fix(payment): Stripe instance polluting alipay/wxpay limits groups

Root cause: Stripe instance had supported_types="card,alipay,link,wxpay"
but only card/link were mapped to "stripe" group. Stripe's alipay/wxpay
leaked into independent groups, and since Stripe had no limits configured,
it triggered the "any unlimited → all zeros" early return, making ALL
method limits show as zero.

Fix: pcGroupByPaymentType now routes ALL types from Stripe provider
instances to the "stripe" group (by checking ProviderKey, not sub-type).
Frontend: Stripe provider dialog shows single "Stripe" limits entry
instead of per-sub-type entries.
This commit is contained in:
erio
2026-04-08 02:35:22 +08:00
parent 0bb1bfea3e
commit 36b14b0584
2 changed files with 14 additions and 12 deletions
@@ -10,9 +10,6 @@ import (
"github.com/Wei-Shaw/sub2api/internal/payment"
)
// stripeSubTypes are types that should be aggregated under TypeStripe for user-facing display.
var stripeSubTypes = map[string]bool{string(payment.TypeCard): true, string(payment.TypeLink): true}
// GetAvailableMethodLimits collects all payment types from enabled provider
// instances and returns limits for each, plus the global widest range.
// Stripe sub-types (card, link) are aggregated under "stripe".
@@ -55,7 +52,8 @@ func (s *PaymentConfigService) GetMethodLimits(ctx context.Context, types []stri
}
// pcGroupByPaymentType groups instances by user-facing payment type.
// Stripe sub-types (card, link) are merged under "stripe".
// For Stripe providers, ALL sub-types (card, link, alipay, wxpay) map to "stripe"
// because the user sees a single "Stripe" button, not individual sub-methods.
// Uses a seen set to avoid counting one instance twice.
func pcGroupByPaymentType(instances []*dbent.PaymentProviderInstance) map[string][]*dbent.PaymentProviderInstance {
typeInstances := make(map[string][]*dbent.PaymentProviderInstance)
@@ -70,15 +68,13 @@ func pcGroupByPaymentType(instances []*dbent.PaymentProviderInstance) map[string
}
}
for _, inst := range instances {
for _, t := range splitTypes(inst.SupportedTypes) {
if stripeSubTypes[t] || t == payment.TypeStripe {
add(payment.TypeStripe, inst)
} else {
add(t, inst)
}
}
// Stripe provider: all sub-types → single "stripe" group
if inst.ProviderKey == payment.TypeStripe {
add(payment.TypeStripe, inst)
continue
}
for _, t := range splitTypes(inst.SupportedTypes) {
add(t, inst)
}
}
return typeInstances
@@ -86,6 +82,7 @@ func pcGroupByPaymentType(instances []*dbent.PaymentProviderInstance) map[string
// pcInstanceTypeLimits extracts per-type limits from a provider instance.
// Returns (limits, true) if configured; (zero, false) if unlimited.
// For Stripe instances, limits are stored under "stripe" key regardless of sub-types.
func pcInstanceTypeLimits(inst *dbent.PaymentProviderInstance, pt string) (payment.ChannelLimits, bool) {
if inst.Limits == "" {
return payment.ChannelLimits{}, false
@@ -22,7 +22,7 @@
</label>
<Select
v-model="form.provider_key"
:options="(!!editing ? allKeyOptions : enabledKeyOptions) as any"
:options="(!!editing ? allKeyOptions : enabledKeyOptions) as SelectOption[]"
:disabled="!!editing"
@change="onKeyChange"
/>
@@ -219,6 +219,7 @@ import { reactive, computed, ref } from 'vue'
import { useI18n } from 'vue-i18n'
import BaseDialog from '@/components/common/BaseDialog.vue'
import Select from '@/components/common/Select.vue'
import type { SelectOption } from '@/components/common/Select.vue'
import ToggleSwitch from './ToggleSwitch.vue'
import type { ProviderInstance } from '@/types/payment'
import type { TypeOption } from './providerConfig'
@@ -308,6 +309,10 @@ const resolvedFields = computed(() => {
})
const limitableTypes = computed(() => {
// Stripe: single "stripe" entry (one set of shared limits)
if (form.provider_key === 'stripe') {
return [{ value: 'stripe', label: 'Stripe' }]
}
const selected = form.supported_types.filter(t => t !== 'easypay')
return selected.map(v => {
const found = props.allPaymentTypes.find(pt => pt.value === v)