合并 internal → main: 退款/提现/激活/CI 全面优化 #4
@@ -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"),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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").
|
||||
|
||||
Reference in New Issue
Block a user