feat: publish sanitized custom.97 source

This commit is contained in:
cneicy committed 2026-10-27 20:43:39 +08:00
1 parent 8e6ed0317b
commit 86c0276156
1022 files changed
+69903 -19207

No files matched your search

+46 -46
View File
@@ -45,17 +45,17 @@ type StripeAdaptor struct {
func (*StripeAdaptor) RequestAmount(c *gin.Context, req *StripePayRequest) {
if req.Amount < getStripeMinTopup() {
c.JSON(http.StatusOK, gin.H{"message": "error", "data": fmt.Sprintf("充值数量不能小于 %d", getStripeMinTopup())})
paymentError(c, common.NewMessage("Top-up amount cannot be less than {{min}}", map[string]any{"min": getStripeMinTopup()}))
return
}
if req.Amount > 10000 {
c.JSON(http.StatusOK, gin.H{"message": "error", "data": "充值数量不能大于 10000"})
paymentError(c, common.NewMessage("Top-up amount cannot exceed {{max}}", map[string]any{"max": 10000}))
return
}
id := c.GetInt("id")
group, err := model.GetUserGroup(id, true)
if err != nil {
c.JSON(http.StatusOK, gin.H{"message": "error", "data": "获取用户分组失败"})
paymentError(c, common.NewMessage("Failed to get the user group"))
return
}
if rejectInvalidCreditedQuota(c, id, getStripeCreditedQuota(req.Amount, group)) {
@@ -63,7 +63,7 @@ func (*StripeAdaptor) RequestAmount(c *gin.Context, req *StripePayRequest) {
}
payMoney := getStripePayMoney(float64(req.Amount), group)
if payMoney <= 0.01 {
c.JSON(http.StatusOK, gin.H{"message": "error", "data": "充值金额过低"})
paymentError(c, common.NewMessage("Payment amount is too low"))
return
}
c.JSON(http.StatusOK, gin.H{"message": "success", "data": strconv.FormatFloat(payMoney, 'f', 2, 64)})
@@ -71,32 +71,32 @@ func (*StripeAdaptor) RequestAmount(c *gin.Context, req *StripePayRequest) {
func (*StripeAdaptor) RequestPay(c *gin.Context, req *StripePayRequest) {
if req.PaymentMethod != model.PaymentMethodStripe {
c.JSON(http.StatusOK, gin.H{"message": "error", "data": "不支持的支付渠道"})
paymentError(c, common.NewMessage("Unsupported payment channel"))
return
}
if req.Amount < getStripeMinTopup() {
c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("充值数量不能小于 %d", getStripeMinTopup()), "data": 10})
common.ApiErrorStatus(c, http.StatusOK, common.NewMessage("Top-up amount cannot be less than {{min}}", map[string]any{"min": getStripeMinTopup()}), gin.H{"data": 10})
return
}
if req.Amount > 10000 {
c.JSON(http.StatusOK, gin.H{"message": "充值数量不能大于 10000", "data": 10})
common.ApiErrorStatus(c, http.StatusOK, common.NewMessage("Top-up amount cannot exceed {{max}}", map[string]any{"max": 10000}), gin.H{"data": 10})
return
}
if req.SuccessURL != "" && common.ValidateRedirectURL(req.SuccessURL) != nil {
c.JSON(http.StatusBadRequest, gin.H{"message": "支付成功重定向URL不在可信任域名列表中", "data": ""})
common.ApiErrorStatus(c, http.StatusBadRequest, common.NewMessage("Payment success redirect URL is not in the trusted domain list"), gin.H{"data": ""})
return
}
if req.CancelURL != "" && common.ValidateRedirectURL(req.CancelURL) != nil {
c.JSON(http.StatusBadRequest, gin.H{"message": "支付取消重定向URL不在可信任域名列表中", "data": ""})
common.ApiErrorStatus(c, http.StatusBadRequest, common.NewMessage("Payment cancel redirect URL is not in the trusted domain list"), gin.H{"data": ""})
return
}
id := c.GetInt("id")
user, err := model.GetUserById(id, false)
if err != nil || user == nil {
c.JSON(http.StatusOK, gin.H{"message": "error", "data": "用户不存在"})
paymentError(c, common.NewMessage("User does not exist"))
return
}
chargedMoney := GetChargedAmount(float64(req.Amount), *user)
@@ -111,8 +111,8 @@ func (*StripeAdaptor) RequestPay(c *gin.Context, req *StripePayRequest) {
payLink, err := genStripeLink(referenceId, user.StripeCustomer, user.Email, req.Amount, req.SuccessURL, req.CancelURL)
if err != nil {
logger.LogError(c.Request.Context(), fmt.Sprintf("Stripe 创建 Checkout Session 失败 user_id=%d trade_no=%s amount=%d error=%q", id, referenceId, req.Amount, err.Error()))
c.JSON(http.StatusOK, gin.H{"message": "error", "data": "拉起支付失败"})
logger.LogError(c.Request.Context(), common.LogText("Stripe failed to create Checkout Session user_id=%d trade_no=%s amount=%d error=%q", id, referenceId, req.Amount, err.Error()))
paymentError(c, common.NewMessage("Failed to start payment"))
return
}
@@ -128,11 +128,11 @@ func (*StripeAdaptor) RequestPay(c *gin.Context, req *StripePayRequest) {
}
err = topUp.Insert()
if err != nil {
logger.LogError(c.Request.Context(), fmt.Sprintf("Stripe 创建充值订单失败 user_id=%d trade_no=%s amount=%d error=%q", id, referenceId, req.Amount, err.Error()))
c.JSON(http.StatusOK, gin.H{"message": "error", "data": "创建订单失败"})
logger.LogError(c.Request.Context(), common.LogText("Stripe failed to create top-up order user_id=%d trade_no=%s amount=%d error=%q", id, referenceId, req.Amount, err.Error()))
paymentError(c, common.NewMessage("Failed to create order"))
return
}
logger.LogInfo(c.Request.Context(), fmt.Sprintf("Stripe 充值订单创建成功 user_id=%d trade_no=%s amount=%d money=%.2f", id, referenceId, req.Amount, chargedMoney))
logger.LogInfo(c.Request.Context(), common.LogText("Stripe top-up order created user_id=%d trade_no=%s amount=%d money=%.2f", id, referenceId, req.Amount, chargedMoney))
c.JSON(http.StatusOK, gin.H{
"message": "success",
"data": gin.H{
@@ -145,7 +145,7 @@ func RequestStripeAmount(c *gin.Context) {
var req StripePayRequest
err := c.ShouldBindJSON(&req)
if err != nil {
c.JSON(http.StatusOK, gin.H{"message": "error", "data": "参数错误"})
paymentError(c, common.NewMessage("Invalid parameters"))
return
}
stripeAdaptor.RequestAmount(c, &req)
@@ -155,7 +155,7 @@ func RequestStripePay(c *gin.Context) {
var req StripePayRequest
err := c.ShouldBindJSON(&req)
if err != nil {
c.JSON(http.StatusOK, gin.H{"message": "error", "data": "参数错误"})
paymentError(c, common.NewMessage("Invalid parameters"))
return
}
stripeAdaptor.RequestPay(c, &req)
@@ -164,32 +164,32 @@ func RequestStripePay(c *gin.Context) {
func StripeWebhook(c *gin.Context) {
ctx := c.Request.Context()
if !isStripeWebhookEnabled() {
logger.LogWarn(ctx, fmt.Sprintf("Stripe webhook 被拒绝 reason=webhook_disabled path=%q client_ip=%s", c.Request.RequestURI, c.ClientIP()))
logger.LogWarn(ctx, common.LogText("Stripe webhook rejected reason=webhook_disabled path=%q client_ip=%s", c.Request.RequestURI, c.ClientIP()))
c.AbortWithStatus(http.StatusForbidden)
return
}
payload, err := io.ReadAll(c.Request.Body)
if err != nil {
logger.LogError(ctx, fmt.Sprintf("Stripe webhook 读取请求体失败 path=%q client_ip=%s error=%q", c.Request.RequestURI, c.ClientIP(), err.Error()))
logger.LogError(ctx, common.LogText("Stripe webhook failed to read request body path=%q client_ip=%s error=%q", c.Request.RequestURI, c.ClientIP(), err.Error()))
c.AbortWithStatus(http.StatusServiceUnavailable)
return
}
signature := c.GetHeader("Stripe-Signature")
logger.LogInfo(ctx, fmt.Sprintf("Stripe webhook 收到请求 path=%q client_ip=%s signature=%q body=%q", c.Request.RequestURI, c.ClientIP(), signature, string(payload)))
logger.LogInfo(ctx, common.LogText("Stripe webhook received request path=%q client_ip=%s signature=%q body=%q", c.Request.RequestURI, c.ClientIP(), signature, string(payload)))
event, err := webhook.ConstructEventWithOptions(payload, signature, setting.StripeWebhookSecret, webhook.ConstructEventOptions{
IgnoreAPIVersionMismatch: true,
})
if err != nil {
logger.LogWarn(ctx, fmt.Sprintf("Stripe webhook 验签失败 path=%q client_ip=%s error=%q", c.Request.RequestURI, c.ClientIP(), err.Error()))
logger.LogWarn(ctx, common.LogText("Stripe webhook signature verification failed path=%q client_ip=%s error=%q", c.Request.RequestURI, c.ClientIP(), err.Error()))
c.AbortWithStatus(http.StatusBadRequest)
return
}
callerIp := c.ClientIP()
logger.LogInfo(ctx, fmt.Sprintf("Stripe webhook 验签成功 event_type=%s client_ip=%s path=%q", string(event.Type), callerIp, c.Request.RequestURI))
logger.LogInfo(ctx, common.LogText("Stripe webhook signature verified event_type=%s client_ip=%s path=%q", string(event.Type), callerIp, c.Request.RequestURI))
switch event.Type {
case stripe.EventTypeCheckoutSessionCompleted:
sessionCompleted(ctx, event, callerIp)
@@ -200,7 +200,7 @@ func StripeWebhook(c *gin.Context) {
case stripe.EventTypeCheckoutSessionAsyncPaymentFailed:
sessionAsyncPaymentFailed(ctx, event, callerIp)
default:
logger.LogInfo(ctx, fmt.Sprintf("Stripe webhook 忽略事件 event_type=%s client_ip=%s", string(event.Type), callerIp))
logger.LogInfo(ctx, common.LogText("Stripe webhook ignored event event_type=%s client_ip=%s", string(event.Type), callerIp))
}
c.Status(http.StatusOK)
@@ -211,13 +211,13 @@ func sessionCompleted(ctx context.Context, event stripe.Event, callerIp string)
referenceId := event.GetObjectValue("client_reference_id")
status := event.GetObjectValue("status")
if "complete" != status {
logger.LogWarn(ctx, fmt.Sprintf("Stripe checkout.completed 状态异常,忽略处理 trade_no=%s status=%s client_ip=%s", referenceId, status, callerIp))
logger.LogWarn(ctx, common.LogText("Stripe checkout.completed has unexpected status, ignored trade_no=%s status=%s client_ip=%s", referenceId, status, callerIp))
return
}
paymentStatus := event.GetObjectValue("payment_status")
if paymentStatus != "paid" {
logger.LogInfo(ctx, fmt.Sprintf("Stripe Checkout 支付未完成,等待异步结果 trade_no=%s payment_status=%s client_ip=%s", referenceId, paymentStatus, callerIp))
logger.LogInfo(ctx, common.LogText("Stripe Checkout payment not completed, waiting for async result trade_no=%s payment_status=%s client_ip=%s", referenceId, paymentStatus, callerIp))
return
}
@@ -229,7 +229,7 @@ func sessionCompleted(ctx context.Context, event stripe.Event, callerIp string)
func sessionAsyncPaymentSucceeded(ctx context.Context, event stripe.Event, callerIp string) {
customerId := event.GetObjectValue("customer")
referenceId := event.GetObjectValue("client_reference_id")
logger.LogInfo(ctx, fmt.Sprintf("Stripe 异步支付成功 trade_no=%s client_ip=%s", referenceId, callerIp))
logger.LogInfo(ctx, common.LogText("Stripe async payment succeeded trade_no=%s client_ip=%s", referenceId, callerIp))
fulfillOrder(ctx, event, referenceId, customerId, callerIp)
}
@@ -238,10 +238,10 @@ func sessionAsyncPaymentSucceeded(ctx context.Context, event stripe.Event, calle
// ultimately fail (e.g. bank transfer not received, SEPA rejected).
func sessionAsyncPaymentFailed(ctx context.Context, event stripe.Event, callerIp string) {
referenceId := event.GetObjectValue("client_reference_id")
logger.LogWarn(ctx, fmt.Sprintf("Stripe 异步支付失败 trade_no=%s client_ip=%s", referenceId, callerIp))
logger.LogWarn(ctx, common.LogText("Stripe async payment failed trade_no=%s client_ip=%s", referenceId, callerIp))
if len(referenceId) == 0 {
logger.LogWarn(ctx, fmt.Sprintf("Stripe 异步支付失败事件缺少订单号 client_ip=%s", callerIp))
logger.LogWarn(ctx, common.LogText("Stripe async payment failed event missing order number client_ip=%s", callerIp))
return
}
@@ -250,32 +250,32 @@ func sessionAsyncPaymentFailed(ctx context.Context, event stripe.Event, callerIp
topUp := model.GetTopUpByTradeNo(referenceId)
if topUp == nil {
logger.LogWarn(ctx, fmt.Sprintf("Stripe 异步支付失败但本地订单不存在 trade_no=%s client_ip=%s", referenceId, callerIp))
logger.LogWarn(ctx, common.LogText("Stripe async payment failed but local order not found trade_no=%s client_ip=%s", referenceId, callerIp))
return
}
if topUp.PaymentProvider != model.PaymentProviderStripe {
logger.LogWarn(ctx, fmt.Sprintf("Stripe 异步支付失败但订单支付网关不匹配 trade_no=%s payment_provider=%s client_ip=%s", referenceId, topUp.PaymentProvider, callerIp))
logger.LogWarn(ctx, common.LogText("Stripe async payment failed but order payment gateway mismatch trade_no=%s payment_provider=%s client_ip=%s", referenceId, topUp.PaymentProvider, callerIp))
return
}
if topUp.Status != common.TopUpStatusPending {
logger.LogInfo(ctx, fmt.Sprintf("Stripe 异步支付失败但订单状态非 pending,忽略处理 trade_no=%s status=%s client_ip=%s", referenceId, topUp.Status, callerIp))
logger.LogInfo(ctx, common.LogText("Stripe async payment failed but order not pending, ignored trade_no=%s status=%s client_ip=%s", referenceId, topUp.Status, callerIp))
return
}
topUp.Status = common.TopUpStatusFailed
if err := topUp.Update(); err != nil {
logger.LogError(ctx, fmt.Sprintf("Stripe 标记充值订单失败状态失败 trade_no=%s client_ip=%s error=%q", referenceId, callerIp, err.Error()))
logger.LogError(ctx, common.LogText("Stripe failed to mark top-up order as failed trade_no=%s client_ip=%s error=%q", referenceId, callerIp, err.Error()))
return
}
logger.LogInfo(ctx, fmt.Sprintf("Stripe 充值订单已标记为失败 trade_no=%s client_ip=%s", referenceId, callerIp))
logger.LogInfo(ctx, common.LogText("Stripe top-up order marked as failed trade_no=%s client_ip=%s", referenceId, callerIp))
}
// fulfillOrder is the shared logic for crediting quota after payment is confirmed.
func fulfillOrder(ctx context.Context, event stripe.Event, referenceId string, customerId string, callerIp string) {
if len(referenceId) == 0 {
logger.LogWarn(ctx, fmt.Sprintf("Stripe 完成订单时缺少订单号 client_ip=%s", callerIp))
logger.LogWarn(ctx, common.LogText("Stripe order completion missing order number client_ip=%s", callerIp))
return
}
@@ -288,34 +288,34 @@ func fulfillOrder(ctx context.Context, event stripe.Event, referenceId string, c
"event_type": string(event.Type),
}
if err := model.CompleteSubscriptionOrder(referenceId, common.GetJsonString(payload), model.PaymentProviderStripe, ""); err == nil {
logger.LogInfo(ctx, fmt.Sprintf("Stripe 订阅订单处理成功 trade_no=%s event_type=%s client_ip=%s", referenceId, string(event.Type), callerIp))
logger.LogInfo(ctx, common.LogText("Stripe subscription order processed trade_no=%s event_type=%s client_ip=%s", referenceId, string(event.Type), callerIp))
return
} else if err != nil && !errors.Is(err, model.ErrSubscriptionOrderNotFound) {
logger.LogError(ctx, fmt.Sprintf("Stripe 订阅订单处理失败 trade_no=%s event_type=%s client_ip=%s error=%q", referenceId, string(event.Type), callerIp, err.Error()))
logger.LogError(ctx, common.LogText("Stripe subscription order processing failed trade_no=%s event_type=%s client_ip=%s error=%q", referenceId, string(event.Type), callerIp, err.Error()))
return
}
err := model.Recharge(referenceId, customerId, callerIp)
if err != nil {
logger.LogError(ctx, fmt.Sprintf("Stripe 充值处理失败 trade_no=%s event_type=%s client_ip=%s error=%q", referenceId, string(event.Type), callerIp, err.Error()))
logger.LogError(ctx, common.LogText("Stripe top-up processing failed trade_no=%s event_type=%s client_ip=%s error=%q", referenceId, string(event.Type), callerIp, err.Error()))
return
}
total, _ := strconv.ParseFloat(event.GetObjectValue("amount_total"), 64)
currency := strings.ToUpper(event.GetObjectValue("currency"))
logger.LogInfo(ctx, fmt.Sprintf("Stripe 充值成功 trade_no=%s amount_total=%.2f currency=%s event_type=%s client_ip=%s", referenceId, total/100, currency, string(event.Type), callerIp))
logger.LogInfo(ctx, common.LogText("Stripe top-up succeeded trade_no=%s amount_total=%.2f currency=%s event_type=%s client_ip=%s", referenceId, total/100, currency, string(event.Type), callerIp))
}
func sessionExpired(ctx context.Context, event stripe.Event) {
referenceId := event.GetObjectValue("client_reference_id")
status := event.GetObjectValue("status")
if "expired" != status {
logger.LogWarn(ctx, fmt.Sprintf("Stripe checkout.expired 状态异常,忽略处理 trade_no=%s status=%s", referenceId, status))
logger.LogWarn(ctx, common.LogText("Stripe checkout.expired has unexpected status, ignored trade_no=%s status=%s", referenceId, status))
return
}
if len(referenceId) == 0 {
logger.LogWarn(ctx, "Stripe checkout.expired 缺少订单号")
logger.LogWarn(ctx, common.LogText("Stripe checkout.expired missing order number"))
return
}
@@ -323,24 +323,24 @@ func sessionExpired(ctx context.Context, event stripe.Event) {
LockOrder(referenceId)
defer UnlockOrder(referenceId)
if err := model.ExpireSubscriptionOrder(referenceId, model.PaymentProviderStripe); err == nil {
logger.LogInfo(ctx, fmt.Sprintf("Stripe 订阅订单已过期 trade_no=%s", referenceId))
logger.LogInfo(ctx, common.LogText("Stripe subscription order expired trade_no=%s", referenceId))
return
} else if err != nil && !errors.Is(err, model.ErrSubscriptionOrderNotFound) {
logger.LogError(ctx, fmt.Sprintf("Stripe 订阅订单过期处理失败 trade_no=%s error=%q", referenceId, err.Error()))
logger.LogError(ctx, common.LogText("Stripe subscription order expiry processing failed trade_no=%s error=%q", referenceId, err.Error()))
return
}
err := model.UpdatePendingTopUpStatus(referenceId, model.PaymentProviderStripe, common.TopUpStatusExpired)
if errors.Is(err, model.ErrTopUpNotFound) {
logger.LogWarn(ctx, fmt.Sprintf("Stripe 充值订单不存在,无法标记过期 trade_no=%s", referenceId))
logger.LogWarn(ctx, common.LogText("Stripe top-up order not found, cannot mark as expired trade_no=%s", referenceId))
return
}
if err != nil {
logger.LogError(ctx, fmt.Sprintf("Stripe 充值订单过期处理失败 trade_no=%s error=%q", referenceId, err.Error()))
logger.LogError(ctx, common.LogText("Stripe top-up order expiry processing failed trade_no=%s error=%q", referenceId, err.Error()))
return
}
logger.LogInfo(ctx, fmt.Sprintf("Stripe 充值订单已过期 trade_no=%s", referenceId))
logger.LogInfo(ctx, common.LogText("Stripe top-up order expired trade_no=%s", referenceId))
}
// genStripeLink generates a Stripe Checkout session URL for payment.
@@ -357,7 +357,7 @@ func sessionExpired(ctx context.Context, event stripe.Event) {
// Returns the checkout session URL or an error if the session creation fails.
func genStripeLink(referenceId string, customerId string, email string, amount int64, successURL string, cancelURL string) (string, error) {
if !strings.HasPrefix(setting.StripeApiSecret, "sk_") && !strings.HasPrefix(setting.StripeApiSecret, "rk_") {
return "", fmt.Errorf("无效的Stripe API密钥")
return "", errors.New("invalid Stripe API key")
}
stripe.Key = setting.StripeApiSecret