package main import ( "bytes" "encoding/json" "fmt" "io" "log" "net/http" "time" "github.com/golang-jwt/jwt/v4" "gorm.io/driver/mysql" "gorm.io/gorm" ) // Configs from dev_configs.toml const ( DbDSN = "root:bindbox2025kdy@tcp(150.158.78.154:3306)/dev_game?charset=utf8mb4&parseTime=True&loc=Local" JwtSecret = "AppUserJwtSecret2025" ApiURL = "http://127.0.0.1:9991/api/app/lottery/join" ) type UserItemCards struct { ID int64 `gorm:"column:id"` Status int32 `gorm:"column:status"` UsedAt time.Time `gorm:"column:used_at"` UsedActivityID int64 `gorm:"column:used_activity_id"` UsedIssueID int64 `gorm:"column:used_issue_id"` UsedDrawLogID int64 `gorm:"column:used_draw_log_id"` } func (UserItemCards) TableName() string { return "user_item_cards" } func main() { // 1. Connect DB db, err := gorm.Open(mysql.Open(DbDSN), &gorm.Config{}) if err != nil { log.Fatalf("DB connection failed: %v", err) } // 2. Reset Item Card 836 cardID := int64(836) fmt.Printf("Restoring UserItemCard %d...\n", cardID) // We set status to 1 and clear used fields res := db.Model(&UserItemCards{}).Where("id = ?", cardID).Updates(map[string]interface{}{ "status": 1, "used_at": nil, "used_activity_id": 0, "used_issue_id": 0, "used_draw_log_id": 0, }) if res.Error != nil { log.Fatalf("Failed to restore card: %v", res.Error) } fmt.Println("Card restored to Status 1.") // 3. Generate JWT tokenString, err := generateToken(9090, JwtSecret) if err != nil { log.Fatalf("Failed to generate token: %v", err) } fmt.Printf("Generated Token for User 9090.\n") // 4. Send API Request targetSlot := int64(1) reqBody := map[string]interface{}{ "activity_id": 94, "issue_id": 105, "count": 1, "slot_index": []int64{targetSlot}, "item_card_id": cardID, "channel": "simulation", } jsonBody, _ := json.Marshal(reqBody) req, _ := http.NewRequest("POST", ApiURL, bytes.NewBuffer(jsonBody)) req.Header.Set("Content-Type", "application/json") // Backend seems to expect raw token string without Bearer prefix req.Header.Set("Authorization", tokenString) client := &http.Client{} fmt.Println("Sending JoinLottery request...") resp, err := client.Do(req) if err != nil { log.Fatalf("Request failed: %v", err) } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) fmt.Printf("Response Status: %s\n", resp.Status) fmt.Printf("Response Body: %s\n", string(body)) // If success (200 OK), parse order info, simulate payment, trigger draw if resp.StatusCode == 200 { var resMap map[string]interface{} json.Unmarshal(body, &resMap) // joinID := resMap["join_id"].(string) // Unused orderNo := resMap["order_no"].(string) fmt.Printf("Order Created: %s. Simulating Payment...\n", orderNo) // Simulate Payment in DB db.Table("orders").Where("order_no = ?", orderNo).Updates(map[string]interface{}{ "status": 2, "paid_at": time.Now(), }) fmt.Println("Order marked as PAID (Status 2).") // Trigger Draw via GetLotteryResult with order_no resultURL := fmt.Sprintf("http://127.0.0.1:9991/api/app/lottery/result?order_no=%s", orderNo) reqResult, _ := http.NewRequest("GET", resultURL, nil) reqResult.Header.Set("Authorization", tokenString) fmt.Println("Triggering Draw (GetLotteryResult)...") respResult, err := client.Do(reqResult) if err != nil { log.Fatalf("Result Request failed: %v", err) } defer respResult.Body.Close() bodyResult, _ := io.ReadAll(respResult.Body) fmt.Printf("Draw Response: %s\n", string(bodyResult)) time.Sleep(2 * time.Second) checkLogs(db, cardID) } } func generateToken(userID int64, secret string) (string, error) { // Claims mimicking bindbox-game/internal/pkg/jwtoken/jwtoken.go structure claims := jwt.MapClaims{ "id": int32(userID), "username": "simulation", "nickname": "simulation_user", "is_super": 0, "platform": "simulation", // Standard claims "exp": time.Now().Add(time.Hour).Unix(), "iat": time.Now().Unix(), "nbf": time.Now().Unix(), } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString([]byte(secret)) } func checkLogs(db *gorm.DB, cardID int64) { fmt.Println("\n--- Verification Results ---") // Check Card Status var card UserItemCards if err := db.First(&card, cardID).Error; err != nil { fmt.Printf("Error fetching card: %v\n", err) return } fmt.Printf("Card Status: %d (Expected 2 if success)\n", card.Status) if card.Status == 2 { fmt.Printf("Card Used At: %v\n", card.UsedAt) fmt.Printf("Used Draw Log ID: %d\n", card.UsedDrawLogID) if card.UsedDrawLogID > 0 { // Check Draw Log type ActivityDrawLogs struct { ID int64 `gorm:"column:id"` RewardID int64 `gorm:"column:reward_id"` OrderID int64 `gorm:"column:order_id"` } var dl ActivityDrawLogs db.Table("activity_draw_logs").First(&dl, card.UsedDrawLogID) fmt.Printf("Original Draw Reward ID: %d, Order ID: %d\n", dl.RewardID, dl.OrderID) // Check Inventory Count for this Order (Should be > 1 if doubled) var inventoryCount int64 db.Table("user_inventory").Where("order_id = ?", dl.OrderID).Count(&inventoryCount) fmt.Printf("Total Inventory Items for Order %d: %d\n", dl.OrderID, inventoryCount) if inventoryCount > 1 { fmt.Println("SUCCESS: Double reward applied (Inventory count > 1)") } else { fmt.Println("WARNING: Inventory count is 1. Double reward might NOT have been applied.") } } } else { fmt.Println("FAILURE: Card status is still 1 (Not Consumed).") } }