Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions common/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,5 +211,6 @@ const (
const (
TopUpStatusPending = "pending"
TopUpStatusSuccess = "success"
TopUpStatusFailed = "failed"
TopUpStatusExpired = "expired"
Comment thread
coderabbitai[bot] marked this conversation as resolved.
)
16 changes: 16 additions & 0 deletions constant/waffo_pay_method.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package constant

// WaffoPayMethod defines the display and API parameter mapping for Waffo payment methods.
type WaffoPayMethod struct {
Name string `json:"name"` // Frontend display name
Icon string `json:"icon"` // Frontend icon identifier: credit-card, apple, google
PayMethodType string `json:"payMethodType"` // Waffo API PayMethodType, can be comma-separated
PayMethodName string `json:"payMethodName"` // Waffo API PayMethodName, empty means auto-select by Waffo checkout
}

// DefaultWaffoPayMethods is the default list of supported payment methods.
var DefaultWaffoPayMethods = []WaffoPayMethod{
{Name: "Card", Icon: "/pay-card.png", PayMethodType: "CREDITCARD,DEBITCARD", PayMethodName: ""},
{Name: "Apple Pay", Icon: "/pay-apple.png", PayMethodType: "APPLEPAY", PayMethodName: "APPLEPAY"},
{Name: "Google Pay", Icon: "/pay-google.png", PayMethodType: "GOOGLEPAY", PayMethodName: "GOOGLEPAY"},
}
82 changes: 68 additions & 14 deletions controller/topup.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,52 @@ func GetTopUpInfo(c *gin.Context) {
}
}

// 如果启用了 Waffo 支付,添加到支付方法列表
enableWaffo := setting.WaffoEnabled &&
((!setting.WaffoSandbox &&
setting.WaffoApiKey != "" &&
setting.WaffoPrivateKey != "" &&
setting.WaffoPublicCert != "") ||
(setting.WaffoSandbox &&
setting.WaffoSandboxApiKey != "" &&
setting.WaffoSandboxPrivateKey != "" &&
setting.WaffoSandboxPublicCert != ""))
if enableWaffo {
hasWaffo := false
for _, method := range payMethods {
if method["type"] == "waffo" {
hasWaffo = true
break
}
}

if !hasWaffo {
waffoMethod := map[string]string{
"name": "Waffo (Global Payment)",
"type": "waffo",
"color": "rgba(var(--semi-blue-5), 1)",
"min_topup": strconv.Itoa(setting.WaffoMinTopUp),
}
payMethods = append(payMethods, waffoMethod)
}
}

data := gin.H{
"enable_online_topup": operation_setting.PayAddress != "" && operation_setting.EpayId != "" && operation_setting.EpayKey != "",
"enable_stripe_topup": setting.StripeApiSecret != "" && setting.StripeWebhookSecret != "" && setting.StripePriceId != "",
"enable_creem_topup": setting.CreemApiKey != "" && setting.CreemProducts != "[]",
"creem_products": setting.CreemProducts,
"enable_waffo_topup": enableWaffo,
"waffo_pay_methods": func() interface{} {
if enableWaffo {
return setting.GetWaffoPayMethods()
}
return nil
}(),
"creem_products": setting.CreemProducts,
"pay_methods": payMethods,
"min_topup": operation_setting.MinTopUp,
"stripe_min_topup": setting.StripeMinTopUp,
"waffo_min_topup": setting.WaffoMinTopUp,
"amount_options": operation_setting.GetPaymentSetting().AmountOptions,
"discount": operation_setting.GetPaymentSetting().AmountDiscount,
}
Expand Down Expand Up @@ -204,27 +242,42 @@ func RequestEpay(c *gin.Context) {
var orderLocks sync.Map
var createLock sync.Mutex

// refCountedMutex 带引用计数的互斥锁,确保最后一个使用者才从 map 中删除
type refCountedMutex struct {
mu sync.Mutex
refCount int
}

// LockOrder 尝试对给定订单号加锁
func LockOrder(tradeNo string) {
lock, ok := orderLocks.Load(tradeNo)
if !ok {
createLock.Lock()
defer createLock.Unlock()
lock, ok = orderLocks.Load(tradeNo)
if !ok {
lock = new(sync.Mutex)
orderLocks.Store(tradeNo, lock)
}
createLock.Lock()
var rcm *refCountedMutex
if v, ok := orderLocks.Load(tradeNo); ok {
rcm = v.(*refCountedMutex)
} else {
rcm = &refCountedMutex{}
orderLocks.Store(tradeNo, rcm)
}
lock.(*sync.Mutex).Lock()
rcm.refCount++
createLock.Unlock()
rcm.mu.Lock()
}

// UnlockOrder 释放给定订单号的锁
func UnlockOrder(tradeNo string) {
lock, ok := orderLocks.Load(tradeNo)
if ok {
lock.(*sync.Mutex).Unlock()
v, ok := orderLocks.Load(tradeNo)
if !ok {
return
}
rcm := v.(*refCountedMutex)
rcm.mu.Unlock()

createLock.Lock()
rcm.refCount--
if rcm.refCount == 0 {
orderLocks.Delete(tradeNo)
}
createLock.Unlock()
}

func EpayNotify(c *gin.Context) {
Expand Down Expand Up @@ -410,3 +463,4 @@ func AdminCompleteTopUp(c *gin.Context) {
}
common.ApiSuccess(c, nil)
}

Loading