mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-09-24 16:05:44 +08:00
feat(payment): Stripe multi-method support + card type + hide single-type selector
- Add TypeCard payment type for bank card payments - Stripe provider now supports card/alipay/wxpay payment methods - Map payment types to Stripe payment_method_types (card, alipay, wechat_pay) - Hide supported types selector for single-type providers (alipay/wxpay official) - Add card i18n labels and PaymentMethodSelector styles
This commit is contained in:
@@ -1 +1 @@
|
||||
0.1.108.36
|
||||
0.1.108.37
|
||||
|
||||
@@ -59,7 +59,7 @@ func (s *Stripe) GetPublishableKey() string {
|
||||
func (s *Stripe) Name() string { return "Stripe" }
|
||||
func (s *Stripe) ProviderKey() string { return "stripe" }
|
||||
func (s *Stripe) SupportedTypes() []payment.PaymentType {
|
||||
return []payment.PaymentType{payment.TypeStripe}
|
||||
return []payment.PaymentType{payment.TypeCard, payment.TypeAlipay, payment.TypeWxpay}
|
||||
}
|
||||
|
||||
// centsToYuan converts an amount in cents (int64) to yuan (float64).
|
||||
@@ -76,6 +76,13 @@ func yuanToCents(amountStr string) (int64, error) {
|
||||
return int64(math.Round(amount * 100)), nil
|
||||
}
|
||||
|
||||
// stripePaymentMethodTypes maps our PaymentType to Stripe payment_method_types.
|
||||
var stripePaymentMethodTypes = map[string][]string{
|
||||
payment.TypeCard: {"card"},
|
||||
payment.TypeAlipay: {"alipay"},
|
||||
payment.TypeWxpay: {"wechat_pay"},
|
||||
}
|
||||
|
||||
// CreatePayment creates a Stripe PaymentIntent.
|
||||
func (s *Stripe) CreatePayment(ctx context.Context, req payment.CreatePaymentRequest) (*payment.CreatePaymentResponse, error) {
|
||||
s.ensureInit()
|
||||
@@ -85,15 +92,33 @@ func (s *Stripe) CreatePayment(ctx context.Context, req payment.CreatePaymentReq
|
||||
return nil, fmt.Errorf("stripe create payment: %w", err)
|
||||
}
|
||||
|
||||
params := &stripe.PaymentIntentCreateParams{
|
||||
Amount: stripe.Int64(amountInCents),
|
||||
Currency: stripe.String(stripeCurrency),
|
||||
AutomaticPaymentMethods: &stripe.PaymentIntentCreateAutomaticPaymentMethodsParams{
|
||||
Enabled: stripe.Bool(true),
|
||||
},
|
||||
Description: stripe.String(req.Subject),
|
||||
Metadata: map[string]string{"orderId": req.OrderID},
|
||||
methods, ok := stripePaymentMethodTypes[req.PaymentType]
|
||||
if !ok {
|
||||
methods = []string{"card"}
|
||||
}
|
||||
|
||||
pmTypes := make([]*string, len(methods))
|
||||
for i, m := range methods {
|
||||
pmTypes[i] = stripe.String(m)
|
||||
}
|
||||
|
||||
params := &stripe.PaymentIntentCreateParams{
|
||||
Amount: stripe.Int64(amountInCents),
|
||||
Currency: stripe.String(stripeCurrency),
|
||||
PaymentMethodTypes: pmTypes,
|
||||
Description: stripe.String(req.Subject),
|
||||
Metadata: map[string]string{"orderId": req.OrderID},
|
||||
}
|
||||
|
||||
// WeChat Pay requires payment_method_options with client type
|
||||
if req.PaymentType == payment.TypeWxpay {
|
||||
params.PaymentMethodOptions = &stripe.PaymentIntentCreatePaymentMethodOptionsParams{
|
||||
WeChatPay: &stripe.PaymentIntentCreatePaymentMethodOptionsWeChatPayParams{
|
||||
Client: stripe.String("web"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
params.SetIdempotencyKey(fmt.Sprintf("pi-%s", req.OrderID))
|
||||
params.Context = ctx
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ const (
|
||||
TypeAlipayDirect PaymentType = "alipay_direct"
|
||||
TypeWxpayDirect PaymentType = "wxpay_direct"
|
||||
TypeStripe PaymentType = "stripe"
|
||||
TypeCard PaymentType = "card"
|
||||
TypeEasyPay PaymentType = "easypay"
|
||||
)
|
||||
|
||||
@@ -39,6 +40,8 @@ func GetBasePaymentType(t string) string {
|
||||
switch {
|
||||
case t == "easypay":
|
||||
return "easypay"
|
||||
case t == "card":
|
||||
return "card"
|
||||
case len(t) >= 6 && t[:6] == "alipay":
|
||||
return "alipay"
|
||||
case len(t) >= 5 && t[:5] == "wxpay":
|
||||
|
||||
@@ -63,14 +63,14 @@ const emit = defineEmits<{
|
||||
const { t } = useI18n()
|
||||
|
||||
function isStripe(type: string) {
|
||||
return type === 'stripe'
|
||||
return type === 'stripe' || type === 'card'
|
||||
}
|
||||
|
||||
function iconBgClass(type: string): string {
|
||||
if (type === 'easypay') return 'bg-[#FF6B35]'
|
||||
if (type.includes('alipay')) return 'bg-[#00AEEF]'
|
||||
if (type.includes('wxpay')) return 'bg-[#07C160]'
|
||||
if (type === 'stripe') return 'bg-[#635bff]'
|
||||
if (type === 'stripe' || type === 'card') return 'bg-[#635bff]'
|
||||
return 'bg-gray-500'
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ function methodSelectedClass(type: string): string {
|
||||
if (type === 'easypay') return 'border-[#FF6B35] bg-orange-50 text-gray-900 shadow-sm dark:bg-orange-950 dark:text-gray-100'
|
||||
if (type.includes('alipay')) return 'border-[#00AEEF] bg-blue-50 text-gray-900 shadow-sm dark:bg-blue-950 dark:text-gray-100'
|
||||
if (type.includes('wxpay')) return 'border-[#07C160] bg-green-50 text-gray-900 shadow-sm dark:bg-green-950 dark:text-gray-100'
|
||||
if (type === 'stripe') return 'border-[#635bff] bg-indigo-50 text-gray-900 shadow-sm dark:bg-indigo-950 dark:text-gray-100'
|
||||
if (type === 'stripe' || type === 'card') return 'border-[#635bff] bg-indigo-50 text-gray-900 shadow-sm dark:bg-indigo-950 dark:text-gray-100'
|
||||
return 'border-primary-500 bg-primary-50 text-gray-900 shadow-sm dark:bg-primary-950 dark:text-gray-100'
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Supported types -->
|
||||
<div>
|
||||
<!-- Supported types (hide for single-type providers) -->
|
||||
<div v-if="availableTypes.length > 1">
|
||||
<label class="input-label">
|
||||
{{ t('admin.settings.payment.supportedTypes') }}
|
||||
<span class="text-red-500">*</span>
|
||||
|
||||
@@ -30,7 +30,7 @@ export const PROVIDER_SUPPORTED_TYPES: Record<string, string[]> = {
|
||||
easypay: ['easypay', 'alipay', 'wxpay'],
|
||||
alipay: ['alipay'],
|
||||
wxpay: ['wxpay'],
|
||||
stripe: ['stripe'],
|
||||
stripe: ['card', 'alipay', 'wxpay'],
|
||||
}
|
||||
|
||||
/** Webhook paths for each provider (relative to origin). */
|
||||
|
||||
@@ -5059,6 +5059,7 @@ export default {
|
||||
alipay: 'Alipay',
|
||||
wxpay: 'WeChat Pay',
|
||||
stripe: 'Stripe',
|
||||
card: 'Card',
|
||||
alipay_direct: 'Alipay (Direct)',
|
||||
wxpay_direct: 'WeChat Pay (Direct)',
|
||||
},
|
||||
|
||||
@@ -5256,6 +5256,7 @@ export default {
|
||||
alipay: '支付宝',
|
||||
wxpay: '微信支付',
|
||||
stripe: 'Stripe',
|
||||
card: '银行卡',
|
||||
alipay_direct: '支付宝(直连)',
|
||||
wxpay_direct: '微信支付(直连)',
|
||||
},
|
||||
|
||||
@@ -18,7 +18,7 @@ export type OrderStatus =
|
||||
| 'REFUNDED'
|
||||
| 'REFUND_FAILED'
|
||||
|
||||
export type PaymentType = 'alipay' | 'wxpay' | 'alipay_direct' | 'wxpay_direct' | 'stripe'
|
||||
export type PaymentType = 'alipay' | 'wxpay' | 'alipay_direct' | 'wxpay_direct' | 'stripe' | 'card'
|
||||
|
||||
export type OrderType = 'balance' | 'subscription'
|
||||
|
||||
|
||||
@@ -2841,6 +2841,7 @@ const allPaymentTypes = computed(() => [
|
||||
{ value: 'easypay', label: t('payment.methods.easypay') },
|
||||
{ value: 'alipay', label: t('payment.methods.alipay') },
|
||||
{ value: 'wxpay', label: t('payment.methods.wxpay') },
|
||||
{ value: 'card', label: t('payment.methods.card') },
|
||||
{ value: 'stripe', label: t('payment.methods.stripe') },
|
||||
])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user