修复:goctl api 生成的代码没有在路由中加入Ipa模式
All checks were successful
Build docker and publish / build (20.15.1) (push) Successful in 7m48s

This commit is contained in:
shanshanzhong 2026-03-06 00:15:35 -08:00
parent 6e13e67dc8
commit b625dda4c9
9 changed files with 420 additions and 180 deletions

34
apis/public/iap.api Normal file
View File

@ -0,0 +1,34 @@
syntax = "v1"
info (
title: "IAP API"
desc: "API for ppanel"
author: "Tension"
email: "tension@ppanel.com"
version: "0.0.1"
)
import "../types.api"
@server (
prefix: v1/public/iap/apple
group: public/iap/apple
middleware: AuthMiddleware,DeviceMiddleware
)
service ppanel {
@doc "Attach Apple Transaction"
@handler AttachAppleTransaction
post /transactions/attach (AttachAppleTransactionRequest) returns (AttachAppleTransactionResponse)
@doc "Attach Apple Transaction By Id"
@handler AttachAppleTransactionById
post /transactions/attach/id (AttachAppleTransactionByIdRequest) returns (AttachAppleTransactionResponse)
@doc "Restore Apple Transactions"
@handler RestoreAppleTransactions
post /transactions/restore (RestoreAppleTransactionsRequest)
@doc "Get Apple IAP Status"
@handler GetAppleStatus
get /status returns (GetAppleStatusResponse)
}

View File

@ -19,6 +19,7 @@ func DeviceLoginHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
return
}
req.IP = c.ClientIP()
l := auth.NewDeviceLoginLogic(c.Request.Context(), svcCtx)
resp, err := l.DeviceLogin(&req)
result.HttpResult(c, resp, err)

View File

@ -25,6 +25,7 @@ func TelephoneLoginHandler(svcCtx *svc.ServiceContext) func(c *gin.Context) {
}
// get client ip
req.IP = c.ClientIP()
req.UserAgent = c.Request.UserAgent()
if svcCtx.Config.Verify.LoginVerify {
verifyTurns := turnstile.New(turnstile.Config{
Secret: svcCtx.Config.Verify.TurnstileSecret,

View File

@ -26,6 +26,7 @@ import (
auth "github.com/perfect-panel/server/internal/handler/auth"
authOauth "github.com/perfect-panel/server/internal/handler/auth/oauth"
common "github.com/perfect-panel/server/internal/handler/common"
publicIapApple "github.com/perfect-panel/server/internal/handler/public/iap/apple"
publicAnnouncement "github.com/perfect-panel/server/internal/handler/public/announcement"
publicDocument "github.com/perfect-panel/server/internal/handler/public/document"
publicOrder "github.com/perfect-panel/server/internal/handler/public/order"
@ -733,6 +734,23 @@ func RegisterHandlers(router *gin.Engine, serverCtx *svc.ServiceContext) {
publicAnnouncementGroupRouter.GET("/list", publicAnnouncement.QueryAnnouncementHandler(serverCtx))
}
publicIapAppleGroupRouter := router.Group("/v1/public/iap/apple")
publicIapAppleGroupRouter.Use(middleware.AuthMiddleware(serverCtx), middleware.DeviceMiddleware(serverCtx))
{
// Attach Apple Transaction
publicIapAppleGroupRouter.POST("/transactions/attach", publicIapApple.AttachAppleTransactionHandler(serverCtx))
// Attach Apple Transaction By Id
publicIapAppleGroupRouter.POST("/transactions/attach/id", publicIapApple.AttachAppleTransactionByIdHandler(serverCtx))
// Restore Apple Transactions
publicIapAppleGroupRouter.POST("/transactions/restore", publicIapApple.RestoreAppleTransactionsHandler(serverCtx))
// Get Apple IAP Status
publicIapAppleGroupRouter.GET("/status", publicIapApple.GetAppleStatusHandler(serverCtx))
}
publicDocumentGroupRouter := router.Group("/v1/public/document")
publicDocumentGroupRouter.Use(middleware.AuthMiddleware(serverCtx), middleware.DeviceMiddleware(serverCtx))

View File

@ -251,7 +251,7 @@ func (r *InviteLinkResolver) cacheShortLink(referCode, shortLink string) {
}
cacheKey := inviteShortLinkCachePrefix + referCode
_ = r.svcCtx.Redis.Set(r.ctx, cacheKey, shortLink, 0).Err()
_ = r.svcCtx.Redis.Set(r.ctx, cacheKey, shortLink, 7*24*time.Hour).Err()
}
func uniqueReferCodes(referCodes []string) []string {

View File

@ -121,10 +121,13 @@ func (l *GetInviteSalesLogic) GetInviteSales(req *types.GetInviteSalesRequest) (
hashVal := h.Sum64() % 10000000000
userHashStr := fmt.Sprintf("%010d", hashVal)
// Format product name as "{{ quantity }}天VPN服务"
productName := fmt.Sprintf("%d天VPN服务", order.Quantity)
if order.Quantity <= 0 {
productName = "1天VPN服务"
// Format product name: prefer subscribe name, fallback to quantity-based label
productName := order.ProductName
if productName == "" {
productName = fmt.Sprintf("%d天VPN服务", order.Quantity)
if order.Quantity <= 0 {
productName = "VPN服务"
}
}
list = append(list, types.InvitedUserSale{

View File

@ -37,14 +37,14 @@ func (l *GetUserInviteStatsLogic) GetUserInviteStats(req *types.GetUserInviteSta
}
userId := u.Id
// 2. 获取历史邀请佣金 (FriendlyCount): 所有被邀请用户产生订单的佣金总和
// 注意:这里复用了 friendly_count 字段名,实际含义是佣金总额
// 2. 获取历史邀请佣金总额 (FriendlyCount): 从佣金日志中统计邀请人收到的佣金
// type=33佣金日志object_id=userIdcontent JSON 中 type 为 331(购买) 或 332(续费) 时才是真实收入
var totalCommission sql.NullInt64
err = l.svcCtx.DB.WithContext(l.ctx).
Table("`order` o").
Select("COALESCE(SUM(o.commission), 0) as total").
Joins("JOIN user u ON o.user_id = u.id").
Where("u.referer_id = ? AND o.status IN (?, ?)", userId, 2, 5). // 只统计已支付和已完成的订单
Table("system_logs").
Select("COALESCE(SUM(JSON_EXTRACT(content, '$.amount')), 0) as total").
Where("type = ? AND object_id = ? AND JSON_EXTRACT(content, '$.type') IN (?, ?)",
33, userId, 331, 332).
Scan(&totalCommission).Error
if err != nil {

View File

@ -39,5 +39,6 @@ import (
"apis/public/payment.api"
"apis/public/document.api"
"apis/public/portal.api"
"apis/public/iap.api"
)

File diff suppressed because one or more lines are too long