Fix baishun wallet payload and callback log sizing

This commit is contained in:
hy001 2026-04-16 17:27:49 +08:00
parent 39e70ad0a3
commit 46ddaca893
5 changed files with 126 additions and 85 deletions

View File

@ -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

View File

@ -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" }

View File

@ -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
}

View File

@ -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

View File

@ -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,