合并 internal → main: 退款/提现/激活/CI 全面优化 #4

Open
shanshanzhong147 wants to merge 76 commits from internal into main
5 changed files with 54 additions and 15 deletions
Showing only changes of commit ae126296e3 - Show all commits
@@ -0,0 +1,17 @@
package order
import (
"context"
"github.com/perfect-panel/server/internal/model/user"
"gorm.io/gorm"
)
func paidSubscriptionQuery(ctx context.Context, db *gorm.DB, userID int64) *gorm.DB {
return db.WithContext(ctx).
Model(&user.Subscribe{}).
Where("user_id = ? AND (order_id > 0 OR token LIKE 'iap:%')", userID).
Order("expire_time DESC").
Order("updated_at DESC").
Order("id DESC")
}
@@ -0,0 +1,32 @@
package order
import (
"context"
"strings"
"testing"
"github.com/perfect-panel/server/internal/model/user"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func TestPaidSubscriptionQueryIncludesOrderBackedSubscriptionWithoutToken(t *testing.T) {
db, err := gorm.Open(mysql.New(mysql.Config{
DSN: "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local",
SkipInitializeWithVersion: true,
}), &gorm.Config{DryRun: true, DisableAutomaticPing: true})
if err != nil {
t.Fatalf("open dry-run db: %v", err)
}
var sub user.Subscribe
tx := paidSubscriptionQuery(context.Background(), db, 510).First(&sub)
sql := tx.Statement.SQL.String()
if strings.Contains(sql, "token != ''") {
t.Fatalf("paid subscription query should not require non-empty token: %s", sql)
}
if !strings.Contains(sql, "order_id > 0 OR token LIKE 'iap:%'") {
t.Fatalf("paid subscription query should include order-backed or iap-backed subscriptions: %s", sql)
}
}
@@ -88,13 +88,8 @@ func (l *PreCreateOrderLogic) PreCreateOrder(req *types.PurchaseOrderRequest) (r
// routes the request to renewal semantics, where first-purchase promos are disabled.
if !l.svcCtx.Config.Subscribe.SingleModel && orderType == 1 {
var existSub user.Subscribe
if e := l.svcCtx.DB.WithContext(l.ctx).
Model(&user.Subscribe{}).
Where("user_id = ? AND token != '' AND (order_id > 0 OR token LIKE 'iap:%')", entitlement.EffectiveUserID).
Order("expire_time DESC").
Order("updated_at DESC").
Order("id DESC").
First(&existSub).Error; e == nil && existSub.Id > 0 && existSub.Token != "" {
if e := paidSubscriptionQuery(l.ctx, l.svcCtx.DB, entitlement.EffectiveUserID).
First(&existSub).Error; e == nil && existSub.Id > 0 {
orderType = 2
l.Infow("[PreCreateOrder] purchase preview routed to renewal because an existing subscription was found",
logger.Field("route_mode", "global_single_subscription"),
+2 -7
View File
@@ -129,13 +129,8 @@ func (l *PurchaseLogic) Purchase(req *types.PurchaseOrderRequest) (resp *types.P
// 防止不同套餐购买创建第二条订阅。
if !l.svcCtx.Config.Subscribe.SingleModel && orderType == 1 {
var existSub user.Subscribe
if e := l.svcCtx.DB.WithContext(l.ctx).
Model(&user.Subscribe{}).
Where("user_id = ? AND token != '' AND (order_id > 0 OR token LIKE 'iap:%')", entitlement.EffectiveUserID).
Order("expire_time DESC").
Order("updated_at DESC").
Order("id DESC").
First(&existSub).Error; e == nil && existSub.Id > 0 && existSub.Token != "" {
if e := paidSubscriptionQuery(l.ctx, l.svcCtx.DB, entitlement.EffectiveUserID).
First(&existSub).Error; e == nil && existSub.Id > 0 {
orderType = 2
parentOrderID = existSub.OrderId
subscribeToken = existSub.Token
+1 -1
View File
@@ -67,7 +67,7 @@ func (m *defaultUserModel) FindSingleModeAnchorSubscribe(ctx context.Context, us
var data Subscribe
err := m.QueryNoCacheCtx(ctx, &data, func(conn *gorm.DB, _ interface{}) error {
return conn.Model(&Subscribe{}).
Where("user_id = ? AND token != '' AND (order_id > 0 OR token LIKE 'iap:%') AND `status` IN ?", userId, []int64{0, 1, 2, 3, 4, 5}).
Where("user_id = ? AND (order_id > 0 OR token LIKE 'iap:%') AND `status` IN ?", userId, []int64{0, 1, 2, 3, 4, 5}).
Order("expire_time DESC").
Order("updated_at DESC").
Order("id DESC").