diff --git a/webapi/thridplatformmgr.go b/webapi/thridplatformmgr.go index 797d3a6..e78526a 100644 --- a/webapi/thridplatformmgr.go +++ b/webapi/thridplatformmgr.go @@ -58,6 +58,7 @@ func (this *ThridPlatformMgr) FindPlatformByPlatformBaseGameId(baseGameId int) ( }) return } + func (this *ThridPlatformMgr) PlatformIsExist(id int32) (isExist bool) { isExist = false this.ThridPlatformMap.Range(func(key, value interface{}) bool { diff --git a/webapi/xhj.go b/webapi/xhj.go index 292e0ae..283a02c 100644 --- a/webapi/xhj.go +++ b/webapi/xhj.go @@ -59,10 +59,12 @@ func (this *XHJThridPlatform) ThirdGameInfo2GamefreeId(thirdInfo *WebAPI_ThirdPl func (this *XHJThridPlatform) GetPlatformBase() ThirdPlatformBase { return this.ThirdPlatformBase } + func (this *XHJThridPlatform) ReqCreateAccount(Snid int32, Platform, Channel, ip string) error { return nil } + func (this *XHJThridPlatform) ReqUserBalance(Snid int32, Platform, Channel, ip string) (err error, balance int64) { pack := &webapi_proto.SARocketLoginOut{ Snid: int64(Snid), @@ -88,10 +90,12 @@ func (this *XHJThridPlatform) ReqIsAllowTransfer(Snid int32, Platform, Channel s return true } + func (this *XHJThridPlatform) ReqCheckTransferIsSuccess(Snid int32, TransferId string, Platform, Channel string) error { return nil } + func (this *XHJThridPlatform) ReqTransfer(Snid int32, Amount int64, TransferId string, Platform, Channel, ip string) (e error, timeout bool) { return nil, false @@ -118,6 +122,7 @@ func (this *XHJThridPlatform) ReqEnterGame(Snid int32, gameid string, clientIP s logger.Trace("XHJReqEnterGame Return:", Snid, ar.Url) return err, ar.Url } + func (this *XHJThridPlatform) ReqLeaveGame(Snid int32, gameid string, clientIP string, Platform, Channel string) (err error, amount int64) { pack := &webapi_proto.SARocketLoginOut{ Snid: int64(Snid), @@ -140,6 +145,7 @@ func (this *XHJThridPlatform) ReqLeaveGame(Snid int32, gameid string, clientIP s logger.Trace("XHJReqLeaveGame Return:", Snid, ar.Amount) return err, int64(ar.Amount) } + func (this *XHJThridPlatform) MappingGameName(snid int32) string { return strconv.Itoa(int(snid)) + "_XHJ" diff --git a/worldsrv/action_third.go b/worldsrv/action_third.go new file mode 100644 index 0000000..f0e7afa --- /dev/null +++ b/worldsrv/action_third.go @@ -0,0 +1,662 @@ +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 +} diff --git a/worldsrv/thirdPlatformGameMapping.go b/worldsrv/thirdPlatformGameMapping.go new file mode 100644 index 0000000..1597f9a --- /dev/null +++ b/worldsrv/thirdPlatformGameMapping.go @@ -0,0 +1,76 @@ +package main + +import ( + "games.yol.com/win88/protocol/server" + "games.yol.com/win88/srvdata" + "games.yol.com/win88/webapi" +) + +var ( + ThirdPltGameMappingConfig = &ThirdPlatformGameMappingConfiguration{ + DB_ThirdPlatformGameMappingMgr: srvdata.PBDB_ThirdPlatformGameMappingMgr, + GamefreeIdMappingMap: make(map[int32]*server.DB_ThirdPlatformGameMapping), + } +) + +type ThirdPlatformGameMappingConfiguration struct { + *srvdata.DB_ThirdPlatformGameMappingMgr + GamefreeIdMappingMap map[int32]*server.DB_ThirdPlatformGameMapping +} + +func (this *ThirdPlatformGameMappingConfiguration) Reload() { + //todo 缓存数据加快查找 + //logger.Logger.Info("=== 缓存三方平台游戏id映射关系数据加快查找===") + this.GamefreeIdMappingMap = make(map[int32]*server.DB_ThirdPlatformGameMapping) + var rawMappingInfo = make(map[int32]*webapi.WebAPI_ThirdPlatformGameMapping) + for _, v := range this.Datas.Arr { + this.GamefreeIdMappingMap[v.GetSystemGameID()] = v + rawMappingInfo[v.GetSystemGameID()] = &webapi.WebAPI_ThirdPlatformGameMapping{ + GameFreeID: v.GetSystemGameID(), + ThirdPlatformName: v.GetThirdPlatformName(), + ThirdGameID: v.GetThirdGameID(), + Desc: v.GetDesc(), + ScreenOrientationType: v.GetScreenOrientationType(), + ThirdID: v.GetThirdID(), + } + } + webapi.ThridPlatformMgrSington.ThridPlatformMap.Range(func(key, value interface{}) bool { + value.(webapi.IThirdPlatform).InitMappingRelation(rawMappingInfo) + return true + }) +} + +func (this *ThirdPlatformGameMappingConfiguration) FindByGameID(gamefreeId int32) (ok bool, item *server.DB_ThirdPlatformGameMapping) { + item, ok = this.GamefreeIdMappingMap[gamefreeId] + return +} + +//包含dg的查询 +func (this *ThirdPlatformGameMappingConfiguration) FindSystemGamefreeidByThirdGameInfo(thirdPlt string, inThirdGameId, inThirdGameName string) (gamefreeid int32) { + if v, exist := webapi.ThridPlatformMgrSington.ThridPlatformMap.Load(thirdPlt); exist { + return v.(webapi.IThirdPlatform).ThirdGameInfo2GamefreeId(&webapi.WebAPI_ThirdPlatformGameMapping{ + ThirdPlatformName: thirdPlt, + ThirdGameID: inThirdGameId, + Desc: inThirdGameName, + }) + } + return 0 +} +func (this *ThirdPlatformGameMappingConfiguration) FindThirdIdByThird(thirdName string) (thirdId int32) { + if v, exist := webapi.ThridPlatformMgrSington.ThridPlatformMap.Load(thirdName); exist { + if plt, ok := v.(webapi.IThirdPlatform); ok { + return int32(plt.GetPlatformBase().BaseGameID) + } + } + return 0 +} + +//gamefreeid与DG视讯gameid映射关系 +var g_GamefreeidMappingDGgameid = map[int32]int32{ + 280010001: 1, //视讯百家乐 + 280020001: 3, //视讯龙虎斗 + 280030001: 7, //视讯牛牛 + 280040001: 4, //视讯轮盘 + 280050001: 5, //视讯骰宝 + 280060001: 11, //视讯炸金花 +} diff --git a/worldsrv/thirdplatformmgr.go b/worldsrv/thirdplatformmgr.go new file mode 100644 index 0000000..a622ab2 --- /dev/null +++ b/worldsrv/thirdplatformmgr.go @@ -0,0 +1,252 @@ +package main + +import ( + "encoding/json" + "games.yol.com/win88/model" + "github.com/idealeak/goserver/core/basic" + "github.com/idealeak/goserver/core/logger" + "github.com/idealeak/goserver/core/module" + "github.com/idealeak/goserver/core/task" + "strings" +) + +var ThirdPlatformMgrSington = &ThirdPlatformMgr{ + Platforms: make(map[string]*PlatformOfThirdPlatform), +} + +type PlatformOfThirdPlatform struct { + *model.PlatformOfThirdPlatform + dirty bool +} + +func (this *PlatformOfThirdPlatform) AddCoin(platform string, coin int64) { + if this.ThdPlatform == nil { + this.ThdPlatform = make(map[string]*model.ThirdPlatform) + } + if this.ThdPlatform != nil { + if tpp, exist := this.ThdPlatform[strings.ToLower(platform)]; exist { + tpp.Coin += coin + + this.dirty = true + } else { + this.ThdPlatform[strings.ToLower(platform)] = &model.ThirdPlatform{ + Coin: coin, + } + this.dirty = true + } + } +} + +func (this *PlatformOfThirdPlatform) AddNextCoin(platform string, coin int64) { + if this.ThdPlatform == nil { + this.ThdPlatform = make(map[string]*model.ThirdPlatform) + } + if this.ThdPlatform != nil { + if tpp, exist := this.ThdPlatform[strings.ToLower(platform)]; exist { + tpp.NextCoin += coin + + this.dirty = true + } else { + this.ThdPlatform[strings.ToLower(platform)] = &model.ThirdPlatform{ + NextCoin: coin, + } + this.dirty = true + } + } +} + +func (this *PlatformOfThirdPlatform) SetCoin(platform string, coin int64) { + if this.ThdPlatform == nil { + this.ThdPlatform = make(map[string]*model.ThirdPlatform) + } + if this.ThdPlatform != nil { + if tpp, exist := this.ThdPlatform[strings.ToLower(platform)]; exist { + tpp.Coin = coin + this.dirty = true + } else { + this.ThdPlatform[strings.ToLower(platform)] = &model.ThirdPlatform{ + Coin: coin, + } + this.dirty = true + } + } +} + +func (this *PlatformOfThirdPlatform) SetNextCoin(platform string, coin int64) { + if this.ThdPlatform == nil { + this.ThdPlatform = make(map[string]*model.ThirdPlatform) + } + if this.ThdPlatform != nil { + if tpp, exist := this.ThdPlatform[strings.ToLower(platform)]; exist { + tpp.NextCoin = coin + this.dirty = true + } else { + this.ThdPlatform[strings.ToLower(platform)] = &model.ThirdPlatform{ + NextCoin: coin, + } + this.dirty = true + } + } +} + +func (this *PlatformOfThirdPlatform) GetCoin(platform string) int64 { + if this.ThdPlatform != nil { + if tpp, exist := this.ThdPlatform[strings.ToLower(platform)]; exist { + return tpp.Coin + } + } + return 0 +} + +func (this *PlatformOfThirdPlatform) GetNextCoin(platform string) int64 { + if this.ThdPlatform != nil { + if tpp, exist := this.ThdPlatform[strings.ToLower(platform)]; exist { + return tpp.NextCoin + } + } + return 0 +} + +func (this *PlatformOfThirdPlatform) Clone() *PlatformOfThirdPlatform { + var ptp PlatformOfThirdPlatform + data, err := json.Marshal(this) + if err == nil { + err = json.Unmarshal(data, &ptp) + if err == nil { + return &ptp + } + } + return nil +} + +type ThirdPlatformMgr struct { + BaseClockSinker + Platforms map[string]*PlatformOfThirdPlatform +} + +func (this *ThirdPlatformMgr) InitData() { + platformList, err := model.GetAllThirdPlatform() + if err != nil { + logger.Logger.Error("InitData count failed:", err) + } + + for i := 0; i < len(platformList); i++ { + p := &platformList[i] + if p != nil { + this.Platforms[p.Platform] = &PlatformOfThirdPlatform{PlatformOfThirdPlatform: p} + } + } +} + +func (this *ThirdPlatformMgr) AddPlatform(platform string) *PlatformOfThirdPlatform { + ptp := &PlatformOfThirdPlatform{ + PlatformOfThirdPlatform: model.NewThirdPlatform(platform), + } + this.Platforms[platform] = ptp + return ptp +} + +func (this *ThirdPlatformMgr) InsertPlatform(platform *PlatformOfThirdPlatform) { + if platform != nil { + pCopy := platform.Clone() + if pCopy != nil { + platform.dirty = false + task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { + return model.InsertThirdPlatform(pCopy.PlatformOfThirdPlatform) + }), nil, "UpdateThirdPlatform").StartByFixExecutor("ThirdPlatform") + } + } +} + +func (this *ThirdPlatformMgr) GetThirdPlatform(platform string) *PlatformOfThirdPlatform { + if p, exist := this.Platforms[platform]; exist && p != nil { + return p + } + return nil +} + +func (this *ThirdPlatformMgr) GetThirdPlatformCoin(platform, thirdPlatform string) int64 { + p := this.GetThirdPlatform(platform) + if p != nil { + return p.GetCoin(thirdPlatform) + } + return 0 +} + +func (this *ThirdPlatformMgr) AddThirdPlatformCoin(platform, thirdPlatform string, coin int64) bool { + p := this.GetThirdPlatform(platform) + if p != nil { + p.AddCoin(thirdPlatform, coin) + return true + } + return false +} + +func (this *ThirdPlatformMgr) ModuleName() string { + return "ThirdPlatformMgr" +} + +func (this *ThirdPlatformMgr) Init() { + this.InitData() +} + +func (this *ThirdPlatformMgr) Update() { + this.SaveAll(false) +} + +func (this *ThirdPlatformMgr) Shutdown() { + this.SaveAll(true) + module.UnregisteModule(this) +} + +//感兴趣所有clock event +func (this *ThirdPlatformMgr) InterestClockEvent() int { + return 1 << CLOCK_EVENT_MONTH +} + +func (this *ThirdPlatformMgr) OnMonthTimer() { + for _, p := range this.Platforms { + if p != nil { + p.dirty = true + for _, thr := range p.ThdPlatform { + if thr != nil { + if thr.Coin > thr.NextCoin { + thr.Coin = thr.NextCoin + } else { + thr.NextCoin = thr.Coin + } + } + } + } + } + + this.SaveAll(false) +} + +func (this *ThirdPlatformMgr) SaveAll(bImm bool) { + for _, p := range this.Platforms { + if p != nil && p.dirty { + pCopy := p.Clone() + if pCopy != nil { + if bImm { + err := model.UpdateThirdPlatform(pCopy.PlatformOfThirdPlatform) + if err != nil { + logger.Logger.Warnf("UpdateThirdPlatform err:%v", err) + } else { + p.dirty = false + } + } else { + p.dirty = false + task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} { + return model.UpdateThirdPlatform(pCopy.PlatformOfThirdPlatform) + }), nil, "UpdateThirdPlatform").StartByFixExecutor("ThirdPlatform") + } + } + } + } +} + +func init() { + //module.RegisteModule(ThirdPlatformMgrSington, time.Minute*5, 0) + //ClockMgrSington.RegisteSinker(ThirdPlatformMgrSington) +}