package main import ( "mongo.games.com/game/common" "mongo.games.com/game/protocol/gamehall" "mongo.games.com/game/webapi" "mongo.games.com/goserver/core/basic" "mongo.games.com/goserver/core/logger" "mongo.games.com/goserver/core/netlib" "mongo.games.com/goserver/core/task" "mongo.games.com/goserver/core/utils" "strconv" "sync/atomic" "time" ) func init() { common.RegisterHandler(int(gamehall.GameHallPacketID_PACKET_CS_ENTERTHRIDGAME), &CSEnterThridGameHandler{}) netlib.RegisterFactory(int(gamehall.GameHallPacketID_PACKET_CS_ENTERTHRIDGAME), &CSEnterThridGamePacketFactory{}) common.RegisterHandler(int(gamehall.GameHallPacketID_PACKET_CS_LEAVETHRIDGAME), &CSLeaveThridGameHandler{}) netlib.RegisterFactory(int(gamehall.GameHallPacketID_PACKET_CS_LEAVETHRIDGAME), &CSLeaveThridGamePacketFactory{}) common.RegisterHandler(int(gamehall.GameHallPacketID_PACKET_CS_THRIDGAMEBALANCEUPDATE), &CSThridBalanceRefreshHandler{}) netlib.RegisterFactory(int(gamehall.GameHallPacketID_PACKET_CS_THRIDGAMEBALANCEUPDATE), &CSThridBalanceRefreshPacketFactory{}) } // 第三方-->系统 func _StartTransferThird2SystemTask(p *Player) { if p.scene == nil { logger.Logger.Tracef("player snid=%v TransferThird2SystemTask p.scene == nil return", p.SnId) return } if p.scene.sceneMode != int(common.SceneMode_Thr) { logger.Logger.Infof("player snid=%v TransferThird2SystemTask p.scene == thrID return", p.SnId) return } if p.thridBalanceRefreshReqing { logger.Logger.Tracef("player snid=%v TransferThird2SystemTask p.thridBalanceRefreshReqing == true return", p.SnId) return } gainway := common.GainWay_Transfer_Thrid2System plt := webapi.ThridPlatformMgrSington.FindPlatformByPlatformBaseGameId(p.scene.gameId) if plt == nil { logger.Logger.Tracef("player snid=%v TransferThird2SystemTask plt == nil return", p.SnId) return } oper := plt.GetPlatformBase().Name + "2System" thirdBalance := int64(0) timeStamp := time.Now().UnixNano() p.thridBalanceRefreshReqing = true timeout := false task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { for i := int32(0); i < model.GameParamData.ThirdPltTransferMaxTry; { var err error var coinLog *model.PayCoinLog var coinlogex *model.CoinLog var apiHasTransfer = false remark := plt.GetPlatformBase().Name + "转出到系统" allow := plt.ReqIsAllowTransfer(p.SnId, p.Platform, p.Channel) if !allow { goto Rollback } err, thirdBalance = plt.ReqUserBalance(p.SnId, p.Platform, p.Channel, p.Ip) if err != nil { goto Rollback } if thirdBalance <= 0 { return nil } if plt.GetPlatformBase().TransferInteger { thirdBalance = (thirdBalance / 100) * 100 if thirdBalance <= 0 { return nil } } timeStamp = time.Now().UnixNano() //如果請求超時的話資金就不能從三方出來,玩家的錢只會少 err, timeout = plt.ReqTransfer(p.SnId, -thirdBalance, strconv.FormatInt(timeStamp, 10), p.Platform, p.Channel, p.Ip) if err != nil || timeout { goto Rollback } apiHasTransfer = true coinLog = model.NewPayCoinLog(timeStamp, int32(p.SnId), thirdBalance, int32(gainway), oper, model.PayCoinLogType_Coin, 0) timeStamp = coinLog.TimeStamp err = model.InsertPayCoinLogs(p.Platform, coinLog) if err != nil { goto Rollback } coinlogex = model.NewCoinLogEx(p.SnId, thirdBalance, p.Coin+thirdBalance, p.SafeBoxCoin, 0, int32(gainway), 0, oper, remark, p.Platform, p.Channel, p.BeUnderAgentCode, 0, p.PackageID, int32(plt.GetPlatformBase().VultGameID)) err = model.InsertCoinLog(coinlogex) if err != nil { goto Rollback } return nil Rollback: if coinLog != nil { model.RemovePayCoinLog(p.Platform, coinLog.LogId) } if coinlogex != nil { model.RemoveCoinLogOne(coinlogex.Platform, coinlogex.LogId) } //如果發現有任何一個超時,則就不在往下執行,因為不知道數據是否正確 if timeout { logger.Logger.Errorf("player snid=%v third->system transfer %v timeout at try %v times,then stop try!", p.SnId, -thirdBalance, i+1) break } if apiHasTransfer { err, timeout = plt.ReqTransfer(p.SnId, thirdBalance, strconv.FormatInt(time.Now().UnixNano(), 10), p.Platform, p.Channel, p.Ip) if err != nil { logger.Logger.Errorf("player snid=%v third->system transfer rollback fail at try %v times", p.SnId, i+1) } } //如果发现有任何一個超时,則就不在往下执行,因为不知道数据是否在三方已经处理 if timeout { logger.Logger.Errorf("player snid=%v third->system rollback transfer %v timeout at try %v times,then stop try!", p.SnId, thirdBalance, i+1) break } logger.Logger.Tracef("player snid=%v third->system transfer rollback at try %v times", p.SnId, i+1) i++ if i < model.GameParamData.ThirdPltTransferMaxTry { time.Sleep(time.Duration(model.GameParamData.ThirdPltTransferInterval) * time.Duration(time.Second)) } } return errors.New("third->system transfer error >max try times!") }), task.CompleteNotifyWrapper(func(data interface{}, tt task.Task) { statePack := &gamehall.SCThridGameBalanceUpdateState{} if data != nil { p.thirdBalanceRefreshMark[plt.GetPlatformBase().Name] = false p.thridBalanceReqIsSucces = false statePack.OpRetCode = gamehall.OpResultCode_Game_OPRC_Error_Game logger.Logger.Trace("SCThridAccountTransferHandler third->system transfer error:", data) } else { p.thridBalanceReqIsSucces = true statePack.OpRetCode = gamehall.OpResultCode_Game_OPRC_Sucess_Game p.Coin += thirdBalance p.SetPayTs(timeStamp) p.thirdBalanceRefreshMark[plt.GetPlatformBase().Name] = true ThirdPlatformMgrSington.AddThirdPlatformCoin(p.Platform, plt.GetPlatformBase().Tag, thirdBalance) } p.SendToClient(int(gamehall.GameHallPacketID_PACKET_SC_THRIDGAMEBALANCEUPDATESTATE), statePack) p.dirty = true //这个地方虽然说拉取失败,但是为了不影响玩家玩其他的游戏,还是可以进入其它场景 //后面玩家自己通过手动刷新余额 if p.scene != nil { p.scene = nil } p.thridBalanceRefreshReqing = false p.diffData.Coin = -1 //强制更新金币 p.SendDiffData() return }), "ThridAccountTransfer").Start() } type CSEnterThridGamePacketFactory struct { } type CSEnterThridGameHandler struct { } func (this *CSEnterThridGamePacketFactory) CreatePacket() interface{} { pack := &gamehall.CSEnterThridGame{} return pack } func (this *CSEnterThridGameHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error { logger.Logger.Trace("CSEnterThridGameHandler Process recv ", data) p := PlayerMgrSington.GetPlayer(sid) if p == nil { logger.Logger.Warn("CSEnterThridGameHandler p == nil") return nil } if msg, ok := data.(*gamehall.CSEnterThridGame); ok { returnErrorCodeFunc := func(code gamehall.OpResultCode_Game) { pack := &gamehall.SCEnterThridGame{} pack.OpRetCode = code pack.ThridGameId = msg.ThridGameId p.SendToClient(int(gamehall.GameHallPacketID_PACKET_SC_ENTERTHRIDGAME), pack) logger.Trace(pack) } //正在请求刷新余额中不能进入三方 if p.thridBalanceRefreshReqing { logger.Logger.Warn("CSEnterThridGameHandler client req thridBalanceRefreshReqing", p.SnId) returnErrorCodeFunc(gamehall.OpResultCode_Game_OPRC_ThirdPltProcessing_Game) return nil } //msg.ThridGameId=proto.Int32(430010001) if p.scene != nil { logger.Logger.Infof("Player %v in game.", p.SnId) returnErrorCodeFunc(gamehall.OpResultCode_Game_OPRC_ThirdPltProcessing_Game) return nil } if p.isDelete { returnErrorCodeFunc(gamehall.OpResultCode_Game_OPRC_RoomHadClosed_Game) return nil } //pt := PlatformMgrSington.GetPackageTag(p.PackageID) //if pt != nil && pt.IsForceBind == 1 { // if p.BeUnderAgentCode == "" || p.BeUnderAgentCode == "0" { // returnErrorCodeFunc(gamehall.OpResultCode_Game_OPRC_MustBindPromoter_Game) // return nil // } //} ok, thridPltGameItem := ThirdPltGameMappingConfig.FindByGameID(msg.GetThridGameId()) if !ok { logger.Logger.Infof("Player %v thridgame id err.", p.SnId, msg.GetThridGameId()) returnErrorCodeFunc(gamehall.OpResultCode_Game_OPRC_Error_Game) return nil } thridGameId := thridPltGameItem.GetThirdGameID() //检测房间状态是否开启 gps := PlatformMgrSington.GetGameConfig(p.Platform, msg.GetThridGameId()) if gps == nil { logger.Logger.Infof("Player %v no cfg room close", p.SnId) returnErrorCodeFunc(gamehall.OpResultCode_Game_OPRC_RoomHadClosed_Game) return nil } dbGameFree := gps.DbGameFree if dbGameFree == nil { logger.Logger.Infof("Player %v no gamefree", p.SnId) returnErrorCodeFunc(gamehall.OpResultCode_Game_OPRC_RoomHadClosed_Game) return nil } //找到对应的平台 v, ok := webapi.ThridPlatformMgrSington.ThridPlatformMap.Load(thridPltGameItem.GetThirdPlatformName()) if !ok { logger.Logger.Infof("Player %v no platform", p.SnId) returnErrorCodeFunc(gamehall.OpResultCode_Game_OPRC_RoomHadClosed_Game) return nil } plt := v.(webapi.IThirdPlatform) pfConfig := PlatformMgrSington.GetPlatform(p.Platform) if pfConfig == nil || pfConfig.ThirdGameMerchant == nil || pfConfig.ThirdGameMerchant[int32(plt.GetPlatformBase().BaseGameID)] == 0 { logger.Logger.Infof("Player %v no pfcfg", p.SnId) returnErrorCodeFunc(gamehall.OpResultCode_Game_OPRC_RoomHadClosed_Game) return nil } //检查限额,金额不足 if dbGameFree.GetLimitCoin() != 0 && p.GetCoin() < int64(dbGameFree.GetLimitCoin()) { returnErrorCodeFunc(gamehall.OpResultCode_Game_OPRC_CoinNotEnough_Game) return nil } //三方不检查游戏次数限制 //todayData, _ := p.GetDaliyGameData(int(msg.GetThridGameId())) //if dbGameFree.GetPlayNumLimit() != 0 && // todayData != nil && // todayData.GameTimes >= int64(dbGameFree.GetPlayNumLimit()) { // logger.Logger.Infof("CSEnterThridGameHandler player snid:%v todayData.GameTimes:%v>PlayNumLimit:%v then kick", p.SnId, todayData.GameTimes, dbGameFree.GetPlayNumLimit()) // returnErrorCodeFunc(gamehall.OpResultCode_OPRC_RoomGameTimes) // return nil //} //检查平台配额是否足够 if plt.GetPlatformBase().IsNeedCheckQuota { dgQuota := ThirdPlatformMgrSington.GetThirdPlatformCoin(p.Platform, plt.GetPlatformBase().Tag) if dgQuota <= 0 || dgQuota <= p.GetCoin() { logger.Logger.Infof("Player snid %v %v platfrom Quota of game not enough.", p.SnId, plt.GetPlatformBase().Name) returnErrorCodeFunc(gamehall.OpResultCode_Game_OPRC_Dg_QuotaNotEnough_Game) return nil } } //检查场景是否开放或者存在,预设数据 scene := SceneMgrSington.GetThirdScene(plt) if scene != nil { p.scene = scene } else { logger.Logger.Infof("Player %v no scene", p.SnId) returnErrorCodeFunc(gamehall.OpResultCode_Game_OPRC_RoomHadClosed_Game) return nil } pack := &gamehall.SCEnterThridGame{} pack.ThridGameId = msg.ThridGameId amount := p.GetCoin() if plt.GetPlatformBase().TransferInteger { amount = (amount / 100) * 100 } p.Coin = p.GetCoin() - amount gainway := common.GainWay_Transfer_System2Thrid oper := "System2" + plt.GetPlatformBase().Name timeStamp := time.Now().UnixNano() p.thridBalanceRefreshReqing = true transferTimeOut := false task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { var err error var ok bool url := "" remark := "转入" + plt.GetPlatformBase().Name + thridPltGameItem.GetDesc() //thridPlatformCoin := int64(0) var coinLog *model.PayCoinLog var coinlogex *model.CoinLog err = ensureThridPltUserName(plt, p, s.RemoteAddr()) if err != nil && err != webapi.ErrNoCreated { goto Rollback } coinLog = model.NewPayCoinLog(timeStamp, int32(p.SnId), -amount, int32(gainway), oper, model.PayCoinLogType_Coin, 0) timeStamp = coinLog.TimeStamp err = model.InsertPayCoinLogs(p.Platform, coinLog) if err != nil { goto Rollback } coinlogex = model.NewCoinLogEx(p.SnId, -amount, p.Coin, p.SafeBoxCoin, 0, int32(gainway), 0, oper, remark, p.Platform, p.Channel, p.BeUnderAgentCode, 0, p.PackageID, int32(plt.GetPlatformBase().VultGameID)) err = model.InsertCoinLog(coinlogex) if err != nil { goto Rollback } ok = utils.RunPanicless(func() { err, url = plt.ReqEnterGame(p.SnId, thridGameId, s.RemoteAddr(), p.Platform, p.Channel, p.Ip) }) if err != nil || !ok { logger.Logger.Errorf("plt.ReqEnterGame() snid:%v error: %v", p.SnId, err) if thrErr, ok := err.(webapi.ThirdError); ok { if thrErr.IsClose() { pack.OpRetCode = gamehall.OpResultCode_Game_OPRC_Thr_GameClose_Game } else { pack.OpRetCode = gamehall.OpResultCode_Game_OPRC_Error_Game } } else { pack.OpRetCode = gamehall.OpResultCode_Game_OPRC_Error_Game } goto Rollback } err, transferTimeOut = plt.ReqTransfer(p.SnId, amount, strconv.FormatInt(timeStamp, 10), p.Platform, p.Channel, p.Ip) if err != nil || transferTimeOut { logger.Logger.Errorf("plt.ReqTransfer() snid:%v error:%v", p.SnId, err) pack.OpRetCode = gamehall.OpResultCode_Game_OPRC_Error_Game goto Rollback } pack.OpRetCode = gamehall.OpResultCode_Game_OPRC_Sucess_Game pack.ScreenOrientationType = proto.Int32(thridPltGameItem.GetScreenOrientationType()) pack.EnterUrl = proto.String(url) return nil Rollback: pack.OpRetCode = gamehall.OpResultCode_Game_OPRC_Error_Game if coinLog != nil { model.RemovePayCoinLog(p.Platform, coinLog.LogId) } if coinlogex != nil { if transferTimeOut { err2 := model.UpdateCoinLogRemark(coinlogex.Platform, coinlogex.LogId, plt.GetPlatformBase().Name+"需人工处理") if err2 != nil { logger.Logger.Errorf("thr UpdateCoinLogRemark(%v) error: %v", coinlogex.LogId, err2) } } else { model.RemoveCoinLogOne(coinlogex.Platform, coinlogex.LogId) } } return errors.New("system->third transfer rollback!") }), task.CompleteNotifyWrapper(func(data interface{}, tt task.Task) { if pack.GetOpRetCode() == gamehall.OpResultCode_Game_OPRC_Sucess_Game { ThirdPlatformMgrSington.AddThirdPlatformCoin(p.Platform, plt.GetPlatformBase().Tag, -amount) p.SetPayTs(timeStamp) } else { //如帐变出现问题,就在日志里面查下面的输出信息!!! //如果转账超时,三方的转账是否成功就是未知的,这时不能将金币再加到玩家身上。 //如果出现超时问题,就需要人工对账。 //注意:这个地方说的超时已经包含CG工程Check订单后的超时 if transferTimeOut { logger.Logger.Errorf("CSEnterThridGameHandler player snid:%v transfer %v to %v timeout:", p.SnId, amount, plt.GetPlatformBase().Name) } else { p.Coin += amount } p.scene = nil pack.OpRetCode = gamehall.OpResultCode_Game_OPRC_Error_Game logger.Logger.Trace("SCThridAccountTransferHandler system->third transfer error:", data) } p.dirty = true p.thirdBalanceRefreshMark[plt.GetPlatformBase().Name] = false p.SendDiffData() p.SendToClient(int(gamehall.GameHallPacketID_PACKET_SC_ENTERTHRIDGAME), pack) p.thridBalanceRefreshReqing = false logger.Logger.Trace("CSEnterThridGameHandler send client:", pack) return }), "CSEnterThridGameHandler").Start() } return nil } func ensureThridPltUserName(pltform webapi.IThirdPlatform, p *Player, ip string) error { var err error err = pltform.ReqCreateAccount(p.SnId, p.Platform, p.Channel, p.GetIP()) if err != nil { if err != webapi.ErrNoCreated { logger.Logger.Errorf("Snid=%v Plt=%v CreateAccountReq error:%v", p.SnId, pltform.GetPlatformBase().Name, err) } return err } return nil //switch pltform.GetPlatformBase().Name { //case "WWG平台": // if len(p.WwgPlatformName) == 0 { // err = pltform.ReqCreateAccount(p.SnId, p.Platform, p.Channel) // if err != nil { // logger.Logger.Error("WwgCreateAccountReq error:", err) // return err // } // p.WwgPlatformName = pltform.MappingGameName(p.SnId) // } //case "FG平台": // if len(p.FgPlatformName) == 0 { // err = pltform.ReqCreateAccount(p.SnId, p.Platform, p.Channel) // if err != nil { // logger.Logger.Error("FgCreateAccountReq error:", err) // return err // } // p.FgPlatformName = pltform.MappingGameName(p.SnId) // } //case "AMEBA平台": // if len(p.AmebaPlatformName) == 0 { // err = pltform.ReqCreateAccount(p.SnId, p.Platform, p.Channel) // if err != nil { // logger.Logger.Error("AmebaCreateAccountReq error:", err) // return err // } // p.AmebaPlatformName = pltform.MappingGameName(p.SnId) // } //case "VR彩票": // if len(p.VrPlatformName) == 0 { // err = pltform.ReqCreateAccount(p.SnId, p.Platform, p.Channel) // if err != nil { // logger.Logger.Error("VrCreateAccountReq error:", err) // return err // } // p.VrPlatformName = pltform.MappingGameName(p.SnId) // } //} //return nil } type CSLeaveThridGamePacketFactory struct { } type CSLeaveThridGameHandler struct { } func (this *CSLeaveThridGamePacketFactory) CreatePacket() interface{} { pack := &gamehall.CSLeaveThridGame{} return pack } func (this *CSLeaveThridGameHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error { logger.Logger.Trace("CSLeaveThridGameHandler Process recv ", data) if _, ok := data.(*gamehall.CSLeaveThridGame); ok { p := PlayerMgrSington.GetPlayer(sid) if p == nil { logger.Logger.Warn("CSLeaveThridGameHandler p == nil") return nil } _StartTransferThird2SystemTask(p) pack := &gamehall.SCLeaveThridGame{} pack.OpRetCode = gamehall.OpResultCode_Game_OPRC_Sucess_Game p.SendToClient(int(gamehall.GameHallPacketID_PACKET_SC_LEAVETHRIDGAME), pack) } return nil } type CSThridBalanceRefreshPacketFactory struct { } type CSThridBalanceRefreshHandler struct { } func (this *CSThridBalanceRefreshPacketFactory) CreatePacket() interface{} { pack := &gamehall.CSThridGameBalanceUpdate{} return pack } func (this *CSThridBalanceRefreshHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error { logger.Logger.Trace("CSThridBalanceRefreshHandler Process recv ", data) if _, ok := data.(*gamehall.CSThridGameBalanceUpdate); ok { p := PlayerMgrSington.GetPlayer(sid) if p == nil { logger.Logger.Warn("CSThridBalanceRefreshHandler p == nil") return nil } if p.scene != nil { logger.Logger.Tracef("player snid=%v CSThridBalanceRefreshHandler p.scene != nil return", p.SnId) return nil } //请求太快,不做处理,给API减轻一些压力 if p.thridBalanceRefreshReqing { logger.Logger.Warn("CSThridBalanceRefreshHandler client req too fast") return nil } p.thridBalanceRefreshReqing = true gainway := common.GainWay_Transfer_Thrid2System waitgroup := webapi.ThridPlatformMgrSington.AllPlatformCount() isSucces := true timeout := false webapi.ThridPlatformMgrSington.ThridPlatformMap.Range(func(key, value interface{}) bool { plt := value.(webapi.IThirdPlatform) if stateOk, exist := p.thirdBalanceRefreshMark[plt.GetPlatformBase().Name]; exist && stateOk { waitgroup-- if 0 == waitgroup { statePack := &gamehall.SCThridGameBalanceUpdateState{} pack := &gamehall.SCThridGameBalanceUpdate{} pack.OpRetCode = gamehall.OpResultCode_Game_OPRC_Sucess_Game p.thridBalanceReqIsSucces = true statePack.OpRetCode = gamehall.OpResultCode_Game_OPRC_Sucess_Game p.SendToClient(int(gamehall.GameHallPacketID_PACKET_SC_THRIDGAMEBALANCEUPDATESTATE), statePack) pack.Coin = proto.Int64(p.Coin) p.SendToClient(int(gamehall.GameHallPacketID_PACKET_SC_THRIDGAMEBALANCEUPDATE), pack) p.thridBalanceRefreshReqing = false } return true } var tsk task.Task tsk = task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { plt := tsk.GetEnv("plt").(webapi.IThirdPlatform) tsk.PutEnv("timeStamp", time.Now().UnixNano()) var err error var coinLog *model.PayCoinLog var coinlogex *model.CoinLog var apiHasTransfer = false remark := "刷新" + plt.GetPlatformBase().Name + "转出到系统" thirdBalance := int64(0) allow := false if plt == nil { logger.Logger.Tracef("player snid=%v CSThridBalanceRefreshHandler plt == nil return", p.SnId) return int64(-1) } pfConfig := PlatformMgrSington.GetPlatform(p.Platform) if pfConfig == nil { return int64(0) } if pfConfig.ThirdGameMerchant == nil || pfConfig.ThirdGameMerchant[int32(plt.GetPlatformBase().BaseGameID)] == 0 { return int64(0) } oper := plt.GetPlatformBase().Name + "2System" err = ensureThridPltUserName(plt, p, s.RemoteAddr()) if err != nil { if err == webapi.ErrNoCreated { return int64(0) } logger.Logger.Tracef("player snid=%v at %v ensureThridPltUserName() err: %v", p.SnId, plt.GetPlatformBase().Name, err) goto Rollback } allow = plt.ReqIsAllowTransfer(p.SnId, p.Platform, p.Channel) if !allow { logger.Logger.Tracef("player snid=%v at %v is not allow Transfer", p.SnId, plt.GetPlatformBase().Name) goto Rollback } err, thirdBalance = plt.ReqUserBalance(p.SnId, p.Platform, p.Channel, p.Ip) if err != nil { logger.Logger.Tracef("player snid=%v at %v plt.ReqUserBalance() err: %v", p.SnId, plt.GetPlatformBase().Name, err) goto Rollback } if thirdBalance <= 0 { return int64(0) } if plt.GetPlatformBase().TransferInteger { thirdBalance = (thirdBalance / 100) * 100 if thirdBalance <= 0 { return int64(0) } } err, timeout = plt.ReqTransfer(p.SnId, -thirdBalance, strconv.FormatInt(time.Now().UnixNano(), 10), p.Platform, p.Channel, p.Ip) if err != nil || timeout { logger.Logger.Tracef("player snid=%v at %v plt.ReqTransfer() err: %v", p.SnId, plt.GetPlatformBase().Name, err) goto Rollback } apiHasTransfer = true coinLog = model.NewPayCoinLog(time.Now().UnixNano(), int32(p.SnId), thirdBalance, int32(gainway), oper, model.PayCoinLogType_Coin, 0) tsk.PutEnv("timeStamp", coinLog.TimeStamp) err = model.InsertPayCoinLogs(p.Platform, coinLog) if err != nil { logger.Logger.Tracef("player snid=%v at %v model.InsertPayCoinLogs() err: %v", p.SnId, plt.GetPlatformBase().Name, err) goto Rollback } coinlogex = model.NewCoinLogEx(p.SnId, thirdBalance, p.Coin+thirdBalance, p.SafeBoxCoin, 0, int32(gainway), 0, oper, remark, p.Platform, p.Channel, p.BeUnderAgentCode, 0, p.PackageID, int32(plt.GetPlatformBase().VultGameID)) err = model.InsertCoinLog(coinlogex) if err != nil { logger.Logger.Tracef("player snid=%v at %v model.InsertCoinLogs() err: %v", p.SnId, plt.GetPlatformBase().Name, err) goto Rollback } tsk.PutEnv("plt", plt) return thirdBalance Rollback: if coinLog != nil { model.RemovePayCoinLog(p.Platform, coinLog.LogId) } if coinlogex != nil { model.RemoveCoinLogOne(coinlogex.Platform, coinlogex.LogId) } if timeout { logger.Logger.Errorf("player snid=%v CSThridBalanceRefreshHandler transfer %v to %v timeout!", p.SnId, -thirdBalance, plt.GetPlatformBase().Name) return int64(-1) } if apiHasTransfer { err, timeout = plt.ReqTransfer(p.SnId, thirdBalance, strconv.FormatInt(time.Now().UnixNano(), 10), p.Platform, p.Channel, p.Ip) if timeout { logger.Logger.Errorf("player snid=%v CSThridBalanceRefreshHandler transfer rollback %v to %v timeout!", p.SnId, thirdBalance, plt.GetPlatformBase().Name) } } return int64(-1) }), task.CompleteNotifyWrapper(func(data interface{}, tt task.Task) { thirdBalance := data.(int64) plt := tsk.GetEnv("plt").(webapi.IThirdPlatform) timeStamp := tsk.GetEnv("timeStamp").(int64) if thirdBalance < 0 { isSucces = false logger.Logger.Tracef("player snid=%v at platform=%v CSThridBalanceRefreshHandler third->system transfer fail", p.SnId, plt.GetPlatformBase().Name) } else if thirdBalance > 0 { p.thirdBalanceRefreshMark[plt.GetPlatformBase().Name] = true p.Coin += thirdBalance p.SetPayTs(timeStamp) ThirdPlatformMgrSington.AddThirdPlatformCoin(p.Platform, plt.GetPlatformBase().Tag, thirdBalance) p.dirty = true logger.Logger.Tracef("player snid=%v at platform=%v CSThridBalanceRefreshHandler third->system transfer succes", p.SnId, plt.GetPlatformBase().Name) } else { p.thirdBalanceRefreshMark[plt.GetPlatformBase().Name] = true } if atomic.AddInt32(&waitgroup, -1) == 0 { p.diffData.Coin = -1 p.SendDiffData() statePack := &gamehall.SCThridGameBalanceUpdateState{} pack := &gamehall.SCThridGameBalanceUpdate{} if isSucces { pack.OpRetCode = gamehall.OpResultCode_Game_OPRC_Sucess_Game p.thridBalanceReqIsSucces = true statePack.OpRetCode = gamehall.OpResultCode_Game_OPRC_Sucess_Game } else { pack.OpRetCode = gamehall.OpResultCode_Game_OPRC_Error_Game p.thridBalanceReqIsSucces = false statePack.OpRetCode = gamehall.OpResultCode_Game_OPRC_Error_Game } p.SendToClient(int(gamehall.GameHallPacketID_PACKET_SC_THRIDGAMEBALANCEUPDATESTATE), statePack) pack.Coin = proto.Int64(p.Coin) p.SendToClient(int(gamehall.GameHallPacketID_PACKET_SC_THRIDGAMEBALANCEUPDATE), pack) p.thridBalanceRefreshReqing = false logger.Logger.Tracef("SendToClient() player snid=%v at CSThridBalanceRefreshHandler() pack:%v", p.SnId, pack.String()) } }), "ThridAccount") tsk.PutEnv("plt", value) tsk.Start() return true }) } return nil }