From 46ddaca893da7df14b276e537c3c53e69f7ac371 Mon Sep 17 00:00:00 2001 From: hy001 Date: Thu, 16 Apr 2026 17:27:49 +0800 Subject: [PATCH] Fix baishun wallet payload and callback log sizing --- internal/integration/java.go | 48 +++++++----- internal/model/baishun_models.go | 124 +++++++++++++++---------------- internal/repo/repo.go | 9 ++- internal/service/baishun.go | 28 ++++++- migrations/002_baishun_game.sql | 2 +- 5 files changed, 126 insertions(+), 85 deletions(-) diff --git a/internal/integration/java.go b/internal/integration/java.go index 4315209..e0f2c93 100644 --- a/internal/integration/java.go +++ b/internal/integration/java.go @@ -36,16 +36,21 @@ type UserProfile struct { } type GoldReceiptCommand struct { - ReceiptType string `json:"receiptType"` - UserID int64 `json:"userId"` - SysOrigin string `json:"sysOrigin"` - EventID string `json:"eventId"` - Remark string `json:"remark,omitempty"` - Amount int64 `json:"amount"` - CloseDelayAsset bool `json:"closeDelayAsset"` - OpUserType string `json:"opUserType"` - CustomizeOrigin string `json:"customizeOrigin,omitempty"` - CustomizeOriginDesc string `json:"customizeOriginDesc,omitempty"` + ReceiptType string `json:"receiptType"` + UserID int64 `json:"userId"` + SysOrigin string `json:"sysOrigin"` + EventID string `json:"eventId"` + Remark string `json:"remark,omitempty"` + Amount PennyAmountPayload `json:"amount"` + CloseDelayAsset bool `json:"closeDelayAsset"` + OpUserType string `json:"opUserType"` + CustomizeOrigin string `json:"customizeOrigin,omitempty"` + CustomizeOriginDesc string `json:"customizeOriginDesc,omitempty"` +} + +type PennyAmountPayload struct { + PennyAmount int64 `json:"pennyAmount,string"` + DollarAmount int64 `json:"dollarAmount"` } type TestGoldReceiptCommand struct { @@ -62,8 +67,8 @@ type TestGoldReceiptCommand struct { type InviteCode struct { UserID Int64Value `json:"userId"` - InviteCode string `json:"inviteCode"` - HasBound bool `json:"hasBound"` + InviteCode string `json:"inviteCode"` + HasBound bool `json:"hasBound"` } type GrantGoldRequest struct { @@ -76,11 +81,11 @@ type GrantGoldRequest struct { } type GrantPropsRequest struct { - TrackID int64 `json:"trackId"` - AcceptUserID int64 `json:"acceptUserId"` - SysOrigin string `json:"sysOrigin"` - Origin string `json:"origin"` - SourceGroupID int64 `json:"sourceGroupId"` + TrackID int64 `json:"trackId"` + AcceptUserID int64 `json:"acceptUserId"` + SysOrigin string `json:"sysOrigin"` + Origin string `json:"origin"` + SourceGroupID int64 `json:"sourceGroupId"` } type resultResponse[T any] struct { @@ -299,12 +304,19 @@ func (c *Client) ChangeGoldBalance(ctx context.Context, cmd GoldReceiptCommand) EventID: cmd.EventID, SysOrigin: cmd.SysOrigin, Remark: cmd.Remark, - Amount: cmd.Amount, + Amount: cmd.Amount.DollarAmount, CloseDelayAsset: cmd.CloseDelayAsset, } return c.postJSON(ctx, c.cfg.JavaWalletBaseURL+"/wallet/gold/client/balance/change/test", testCmd, nil, nil) } +func NewPennyAmountPayloadFromDollar(amount int64) PennyAmountPayload { + return PennyAmountPayload{ + PennyAmount: amount * 100, + DollarAmount: amount, + } +} + func shouldFallbackToGoldTestEndpoint(err error) bool { if err == nil { return false diff --git a/internal/model/baishun_models.go b/internal/model/baishun_models.go index fe0f15a..beb664e 100644 --- a/internal/model/baishun_models.go +++ b/internal/model/baishun_models.go @@ -3,20 +3,20 @@ package model import "time" type SysGameListConfig struct { - ID int64 `gorm:"column:id;primaryKey"` - SysOrigin string `gorm:"column:sys_origin;size:32"` - GameOrigin string `gorm:"column:game_origin;size:32"` - GameID string `gorm:"column:game_id;size:64"` - Name string `gorm:"column:name;size:128"` - Category string `gorm:"column:category;size:64"` - GameCode string `gorm:"column:game_code;size:512"` - Cover string `gorm:"column:cover;size:1024"` - Showcase bool `gorm:"column:is_showcase"` - Sort int64 `gorm:"column:sort"` - FullScreen bool `gorm:"column:full_screen"` + ID int64 `gorm:"column:id;primaryKey"` + SysOrigin string `gorm:"column:sys_origin;size:32"` + GameOrigin string `gorm:"column:game_origin;size:32"` + GameID string `gorm:"column:game_id;size:64"` + Name string `gorm:"column:name;size:128"` + Category string `gorm:"column:category;size:64"` + GameCode string `gorm:"column:game_code;size:512"` + Cover string `gorm:"column:cover;size:1024"` + Showcase bool `gorm:"column:is_showcase"` + Sort int64 `gorm:"column:sort"` + FullScreen bool `gorm:"column:full_screen"` ClientOrigin string `gorm:"column:client_origin;size:32"` - Regions string `gorm:"column:regions;size:255"` - GameMode string `gorm:"column:game_mode;size:255"` + Regions string `gorm:"column:regions;size:255"` + GameMode string `gorm:"column:game_mode;size:255"` } func (SysGameListConfig) TableName() string { return "sys_game_list_config" } @@ -98,65 +98,65 @@ type BaishunLaunchSession struct { func (BaishunLaunchSession) TableName() string { return "baishun_launch_session" } type BaishunOrderIdempotency struct { - ID int64 `gorm:"column:id;primaryKey"` - SysOrigin string `gorm:"column:sys_origin;size:32;uniqueIndex:uk_baishun_order,priority:1;index:idx_baishun_order_user_time,priority:1"` - OrderID string `gorm:"column:order_id;size:128;uniqueIndex:uk_baishun_order,priority:2"` - GameRoundID string `gorm:"column:game_round_id;size:128;index:idx_baishun_round"` - RoomID string `gorm:"column:room_id;size:64"` - UserID int64 `gorm:"column:user_id;index:idx_baishun_order_user_time,priority:2"` - VendorGameID int `gorm:"column:vendor_game_id"` - CurrencyDiff int64 `gorm:"column:currency_diff"` - DiffMsg string `gorm:"column:diff_msg;size:32"` - MsgType string `gorm:"column:msg_type;size:64"` - CurrencyType *int `gorm:"column:currency_type"` - WalletEventID string `gorm:"column:wallet_event_id;size:160;uniqueIndex:uk_baishun_wallet_event"` - WalletAssetRecordID *int64 `gorm:"column:wallet_asset_record_id"` - Status string `gorm:"column:status;size:32"` - RequestJSON string `gorm:"column:request_json;type:longtext"` - ResponseJSON string `gorm:"column:response_json;type:longtext"` - CreateTime time.Time `gorm:"column:create_time;index:idx_baishun_order_user_time,priority:3"` - UpdateTime time.Time `gorm:"column:update_time"` + ID int64 `gorm:"column:id;primaryKey"` + SysOrigin string `gorm:"column:sys_origin;size:32;uniqueIndex:uk_baishun_order,priority:1;index:idx_baishun_order_user_time,priority:1"` + OrderID string `gorm:"column:order_id;size:128;uniqueIndex:uk_baishun_order,priority:2"` + GameRoundID string `gorm:"column:game_round_id;size:128;index:idx_baishun_round"` + RoomID string `gorm:"column:room_id;size:64"` + UserID int64 `gorm:"column:user_id;index:idx_baishun_order_user_time,priority:2"` + VendorGameID int `gorm:"column:vendor_game_id"` + CurrencyDiff int64 `gorm:"column:currency_diff"` + DiffMsg string `gorm:"column:diff_msg;size:32"` + MsgType string `gorm:"column:msg_type;size:64"` + CurrencyType *int `gorm:"column:currency_type"` + WalletEventID string `gorm:"column:wallet_event_id;size:160;uniqueIndex:uk_baishun_wallet_event"` + WalletAssetRecordID *int64 `gorm:"column:wallet_asset_record_id"` + Status string `gorm:"column:status;size:32"` + RequestJSON string `gorm:"column:request_json;type:longtext"` + ResponseJSON string `gorm:"column:response_json;type:longtext"` + CreateTime time.Time `gorm:"column:create_time;index:idx_baishun_order_user_time,priority:3"` + UpdateTime time.Time `gorm:"column:update_time"` } func (BaishunOrderIdempotency) TableName() string { return "baishun_order_idempotency" } type BaishunCallbackLog struct { - ID int64 `gorm:"column:id;primaryKey"` - SysOrigin string `gorm:"column:sys_origin;size:32"` - RequestType string `gorm:"column:request_type;size:32;index:idx_baishun_log_type_time,priority:1"` - OrderID string `gorm:"column:order_id;size:128;index:idx_baishun_log_order"` - GameRoundID string `gorm:"column:game_round_id;size:128"` - RoomID string `gorm:"column:room_id;size:64;index:idx_baishun_log_room_user,priority:1"` - UserID *int64 `gorm:"column:user_id;index:idx_baishun_log_room_user,priority:2"` - VendorGameID *int `gorm:"column:vendor_game_id"` - RequestJSON string `gorm:"column:request_json;type:longtext"` - ResponseJSON string `gorm:"column:response_json;type:longtext"` - BizCode string `gorm:"column:biz_code;size:32"` - BizMessage string `gorm:"column:biz_message;size:255"` - Status string `gorm:"column:status;size:32"` - CreateTime time.Time `gorm:"column:create_time;index:idx_baishun_log_type_time,priority:2"` - UpdateTime time.Time `gorm:"column:update_time"` + ID int64 `gorm:"column:id;primaryKey"` + SysOrigin string `gorm:"column:sys_origin;size:32"` + RequestType string `gorm:"column:request_type;size:32;index:idx_baishun_log_type_time,priority:1"` + OrderID string `gorm:"column:order_id;size:128;index:idx_baishun_log_order"` + GameRoundID string `gorm:"column:game_round_id;size:128"` + RoomID string `gorm:"column:room_id;size:64;index:idx_baishun_log_room_user,priority:1"` + UserID *int64 `gorm:"column:user_id;index:idx_baishun_log_room_user,priority:2"` + VendorGameID *int `gorm:"column:vendor_game_id"` + RequestJSON string `gorm:"column:request_json;type:longtext"` + ResponseJSON string `gorm:"column:response_json;type:longtext"` + BizCode string `gorm:"column:biz_code;size:32"` + BizMessage string `gorm:"column:biz_message;type:text"` + Status string `gorm:"column:status;size:32"` + CreateTime time.Time `gorm:"column:create_time;index:idx_baishun_log_type_time,priority:2"` + UpdateTime time.Time `gorm:"column:update_time"` } func (BaishunCallbackLog) TableName() string { return "baishun_callback_log" } type BaishunRoomState struct { - ID int64 `gorm:"column:id;primaryKey"` - SysOrigin string `gorm:"column:sys_origin;size:32;uniqueIndex:uk_baishun_room_state,priority:1"` - RoomID string `gorm:"column:room_id;size:64;uniqueIndex:uk_baishun_room_state,priority:2"` - HostUserID int64 `gorm:"column:host_user_id"` - CurrentGameID string `gorm:"column:current_game_id;size:64"` - CurrentVendorGameID *int `gorm:"column:current_vendor_game_id"` - CurrentGameName string `gorm:"column:current_game_name;size:128"` - CurrentGameCover string `gorm:"column:current_game_cover;size:1024"` - GameSessionID string `gorm:"column:game_session_id;size:64;index:idx_baishun_room_state_session"` - LaunchUserID *int64 `gorm:"column:launch_user_id"` - State string `gorm:"column:state;size:32"` - ExtraJSON string `gorm:"column:extra_json;type:text"` - StartTime *time.Time `gorm:"column:start_time"` - EndTime *time.Time `gorm:"column:end_time"` - CreateTime time.Time `gorm:"column:create_time"` - UpdateTime time.Time `gorm:"column:update_time"` + ID int64 `gorm:"column:id;primaryKey"` + SysOrigin string `gorm:"column:sys_origin;size:32;uniqueIndex:uk_baishun_room_state,priority:1"` + RoomID string `gorm:"column:room_id;size:64;uniqueIndex:uk_baishun_room_state,priority:2"` + HostUserID int64 `gorm:"column:host_user_id"` + CurrentGameID string `gorm:"column:current_game_id;size:64"` + CurrentVendorGameID *int `gorm:"column:current_vendor_game_id"` + CurrentGameName string `gorm:"column:current_game_name;size:128"` + CurrentGameCover string `gorm:"column:current_game_cover;size:1024"` + GameSessionID string `gorm:"column:game_session_id;size:64;index:idx_baishun_room_state_session"` + LaunchUserID *int64 `gorm:"column:launch_user_id"` + State string `gorm:"column:state;size:32"` + ExtraJSON string `gorm:"column:extra_json;type:text"` + StartTime *time.Time `gorm:"column:start_time"` + EndTime *time.Time `gorm:"column:end_time"` + CreateTime time.Time `gorm:"column:create_time"` + UpdateTime time.Time `gorm:"column:update_time"` } func (BaishunRoomState) TableName() string { return "baishun_room_state" } diff --git a/internal/repo/repo.go b/internal/repo/repo.go index 90c2871..e30950c 100644 --- a/internal/repo/repo.go +++ b/internal/repo/repo.go @@ -43,7 +43,7 @@ func (r *Repository) Ping(ctx context.Context) error { } func (r *Repository) AutoMigrate() error { - return r.DB.AutoMigrate( + if err := r.DB.AutoMigrate( &model.InviteCampaignConfig{}, &model.InviteCampaignRewardRule{}, &model.InviteCampaignRelation{}, @@ -58,5 +58,10 @@ func (r *Repository) AutoMigrate() error { &model.BaishunOrderIdempotency{}, &model.BaishunCallbackLog{}, &model.BaishunRoomState{}, - ) + ); err != nil { + return err + } + + // Keep callback error details queryable even when downstream returns a long body. + return r.DB.Exec("ALTER TABLE baishun_callback_log MODIFY COLUMN biz_message TEXT NULL").Error } diff --git a/internal/service/baishun.go b/internal/service/baishun.go index b518732..5397e44 100644 --- a/internal/service/baishun.go +++ b/internal/service/baishun.go @@ -48,6 +48,7 @@ const ( baishunCodeSignatureError = 1010 baishunCodeRepeatUnknown = 1011 baishunCodeServerError = 1999 + legacyBizMessageRuneLimit = 255 ) type BaishunService struct { @@ -789,7 +790,7 @@ func (s *BaishunService) HandleChangeBalance(ctx context.Context, req BaishunCha SysOrigin: session.SysOrigin, EventID: walletEventID, Remark: defaultIfBlank(req.DiffMsg, req.MsgType), - Amount: abs64(req.CurrencyDiff), + Amount: integration.NewPennyAmountPayloadFromDollar(abs64(req.CurrencyDiff)), CloseDelayAsset: false, OpUserType: "APP", CustomizeOrigin: fmt.Sprintf("BAISHUN_GAME_%d", req.GameID), @@ -1204,7 +1205,11 @@ func (s *BaishunService) saveCallbackLog(ctx context.Context, requestType, reque parsed := parseInt64Default(userID) logRecord.UserID = &parsed } - _ = s.repo.DB.WithContext(ctx).Create(&logRecord).Error + err = s.repo.DB.WithContext(ctx).Create(&logRecord).Error + if err != nil && isBizMessageTooLongError(err) { + logRecord.BizMessage = truncateRunes(logRecord.BizMessage, legacyBizMessageRuneLimit) + _ = s.repo.DB.WithContext(ctx).Create(&logRecord).Error + } } func (s *BaishunService) failStandard(code int, message string) baishunStandardResponse { @@ -1357,6 +1362,25 @@ func abs64(value int64) int64 { return value } +func isBizMessageTooLongError(err error) bool { + if err == nil { + return false + } + message := strings.ToLower(err.Error()) + return strings.Contains(message, "data too long") && strings.Contains(message, "biz_message") +} + +func truncateRunes(value string, limit int) string { + if limit <= 0 || value == "" { + return "" + } + runes := []rune(value) + if len(runes) <= limit { + return value + } + return string(runes[:limit]) +} + func parseInt64Default(value string) int64 { parsed, _ := strconv.ParseInt(strings.TrimSpace(value), 10, 64) return parsed diff --git a/migrations/002_baishun_game.sql b/migrations/002_baishun_game.sql index 8d4a7eb..9b2a89f 100644 --- a/migrations/002_baishun_game.sql +++ b/migrations/002_baishun_game.sql @@ -114,7 +114,7 @@ CREATE TABLE IF NOT EXISTS baishun_callback_log ( request_json LONGTEXT DEFAULT NULL, response_json LONGTEXT DEFAULT NULL, biz_code VARCHAR(32) DEFAULT NULL, - biz_message VARCHAR(255) DEFAULT NULL, + biz_message TEXT DEFAULT NULL, status VARCHAR(32) NOT NULL DEFAULT 'SUCCESS', create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,