/* Sog 游戏基础库 2016 by zouwei */ using System; using System.Collections.Generic; using Sog; using ProtoCSStruct; using LitJson; namespace Game { // 支付消息 public class PayHandler : BasePacketHandler { public override int GetServiceType() { return GameServiceType.PayHandler; } //销毁的时候置空 public override void Dispose() { } public override void HandlerClientPacket(PlayerSession playerSession, StructPacket packet) { switch (packet.MsgID) { case (int)CSGameMsgID.PayGoogleReq: ProcessPayGoogleReq(playerSession, packet, false); break; case (int)CSGameMsgID.PayGoogleSuccessReq: ProcessPayGoogleSuccessReq(playerSession, packet, false); break; case (int)CSGameMsgID.PayGetFreeItemReq: ProcessPayGetFreeItemReq(playerSession, packet); break; case (int)CSGameMsgID.ClientTriggerItemArriveReq: ProcessClientTriggerItemArriveReq(playerSession, packet); break; case (int)CSGameMsgID.PayItemStockInfoReq: OnPayItemStockInfoReq(playerSession, packet); break; case (int)CSGameMsgID.CardGetDailyAwardReq: MonthlyCardSvc.GetDailyReward(playerSession.Player, packet); break; case (int)CSGameMsgID.BattlePassAwardReq: BattlePassSvc.Award(playerSession.Player, packet); break; case (int)CSGameMsgID.SignGetAwardReq: SignSvc.Award(playerSession.Player, packet); break; case (int)CSGameMsgID.SignReSingReq: SignSvc.ReSingDaily(playerSession.Player, packet); break; case (int)CSGameMsgID.FistPaymentAwardReq: FistPaymentEvent.Award(playerSession.Player, packet); break; case (int)CSGameMsgID.FreeRewardReq: FreeRewardSvc.OnFreeDayReq(playerSession.Player, packet); break; default: TraceLog.Error("PayHandler.HandlerClientPacket msg {0} not handle", packet.MsgID); break; } } public override void HandlerServerPacket(uint serverID, StructPacket packet) { switch (packet.MsgID) { case (int)SSGameMsgID.PayGoogleRes: ProcessPayGoogleRes(serverID, packet); break; case (int)SSGameMsgID.PayGoogleSuccessRes: ProcessPayGoogleSuccessRes(serverID, packet); break; case (int)SSGameMsgID.PayDbAddDiamondStatusRes: ProcessDBAddDiamondStatusRes(serverID, packet); break; case (int)SSGameMsgID.PayItemStockInfoRes: OnPayItemStockInfoRes(serverID, packet); break; case (int)SSGameMsgID.NotifyItemStockInfo: OnNotifyItemStockInfo(serverID, packet); break; case (int)SSGameMsgID.OperationFakepay: ProcessFakePay(serverID, packet); break; default: TraceLog.Error("PayHandler.HandlerServerPacket msg {0} not handle", packet.MsgID); break; } } public int ProcessPayGoogleReq(PlayerSession playerSession, StructPacket packet, bool gmTestPay) { ref CSPayGoogleReq payReq = ref packet.GetMessage(); //开启代币支付 //var tokenSwitch=CommParamDescMgr.Instance.AdTokenSwitch.int_val; // if (tokenSwitch == 1) // { // payReq.PayChannel = PayChannel.GameToken; // } if (payReq.Uid != playerSession.UserID) { TraceLog.Error("PayHandler.ProcessPayGoogleReq invalid uid {0}", payReq.Uid); return -1; } PlayerOnGame player = playerSession.Player; if (player == null) { TraceLog.Error("PayHandler.ProcessPayGoogleReq no player object uid {0}", payReq.Uid); return -1; } PayType payType = PlayerPayUtil.GetPlayerPayType(player); PayDiamondDesc desc = PayCommSvc.GetPayDiamondDesc(payReq.ItemID); string paymentId = PayCommSvc.GetPaymentId(desc); if (string.IsNullOrEmpty(paymentId)) { //判断是否是扣物品 if (desc.consumeItemId != "" && desc.consumeItemCount > 0) { } else { player.Error("PayHandler.ProcessPayGoogleReq item {0} currency {1} money {2} no paymentId" , desc.itemID, desc.currencyId, desc.currencyRes); return -1; } } // 检查下是否有未完成订单 int index = PlayerPayUtil.GetPaySuccLockIndex(player, desc.itemID); if (index != -1) { ref var lockData = ref PlayerPayUtil.GetPaySuccLockByIndex(player, index); // svr成功后可以直接删除 if (lockData.SvrSuccTime != 0) { player.Trace("PayHandler.ProcessPayGoogleReq itemId {0} unlock by svr succ", desc.itemID); player.RoleData.PayData.PaySuccLock.RemoveAt(index); } // clt成功后最多锁定24小时 else if (lockData.CltSuccTime != 0 && GameServerUtils.GetTimeSecond() >= lockData.CltSuccTime + 86400) { player.Trace("PayHandler.ProcessPayGoogleReq itemId {0} unlock by timeout", desc.itemID); player.RoleData.PayData.PaySuccLock.RemoveAt(index); } else { player.Trace("PayHandler.ProcessPayGoogleReq itemId {0} is lock, order {1} order3rd {2} not finish" , desc.itemID, lockData.OrderId.GetString(), lockData.OrderId3rd.GetString()); CSPayGoogleRes res = new CSPayGoogleRes { Ret = (int)CSErrCode.PayItemOrderNotFinish, ItemID = payReq.ItemID }; player.SendToClient((int)CSGameMsgID.PayGoogleRes, ref res); return -1; } } // 有多笔成功订单没有加到背包 if (player.RoleData.PayData.PaySuccWaitAddRole.Count >= player.RoleData.PayData.PaySuccWaitAddRole.GetMaxCount()) { player.Debug("PayHandler.ProcessPayGoogleReq uid {0} wait list is full, try delete finish order", player.UserID); // 尝试删除最早成功的订单信息 PlayerPayUtil.DeleteEarliestPaySuccWaitAddRole(player); // 没有队列空间, 先不让玩家继续购买 if (player.RoleData.PayData.PaySuccWaitAddRole.Count >= player.RoleData.PayData.PaySuccWaitAddRole.GetMaxCount()) { player.Error("PayHandler.ProcessPayGoogleReq uid {0} wait list is full", player.UserID); CSPayGoogleRes res = new CSPayGoogleRes { Ret = -1, ItemID = payReq.ItemID }; player.SendToClient((int)CSGameMsgID.PayGoogleRes, ref res); return -1; } } //检查代币数量是否足够,切代币支付模式 var needTokenNum = desc.currencyRes; var costItemId = ItemId.Token; if (!string.IsNullOrEmpty(desc.consumeItemId) && desc.consumeItemCount > 0) { costItemId = desc.consumeItemId; needTokenNum = (uint)desc.consumeItemCount; } var token = UnifyOp.GetItemCount(player, GoodsType.Items, costItemId); if (desc.goodsType != PayGoodsType.Token && token >= needTokenNum) { payReq.PayChannel = PayChannel.GameToken; } //不能用代币买代币 if (desc.goodsType == PayGoodsType.Token) { payReq.PayChannel = PayChannel.TrdSdk; } if (payReq.Param1 >= 0) { int iRet = PayCommSvc.CheckPayLimit(player, desc); if (iRet != 0) { player.Error("PayHandler.ProcessPayGoogleReq CheckPayLimit failed, itemId {0} uid {1} ret {2}" , payReq.ItemID, payReq.Uid, iRet); CSPayGoogleRes res = new CSPayGoogleRes { Ret = iRet, ItemID = payReq.ItemID }; player.SendToClient((int)CSGameMsgID.PayGoogleRes, ref res); return -1; } } // 记录物品购买信息 int recordIndex = PlayerPayUtil.AddPaySuccRecordIfNotExist(player, desc); if (recordIndex == -1) { TraceLog.Error("PayHandler.ProcessPayGoogleReq uid {0} itemId {1} add pay record failed" , player.UserID, desc.itemID); return -1; } // 限制下TestPay的使用 gmTestPay =payReq.IsTestPay == 1 && GmCmdSvc.IsGM(player.UserID); //发给WorldServer,由WorldServer校验 SSPayGoogleReq ssReq = new SSPayGoogleReq(); ssReq.Uid = player.UserID; ssReq.PayType = (uint)payType; ssReq.ItemID = payReq.ItemID; ssReq.Diamond = desc.diamond; ssReq.Money = desc.currencyRes; ssReq.GmTestPay = gmTestPay; ssReq.JsApiPay = payReq.JsApiPay; // gm测试时, 使用server逻辑时间(含gm指令增加的时间)做支付时间 long payTime = gmTestPay ? GameServerUtils.GetTimeSecond() : 0; string orderId = ""; if (payType == PayType.MiniPay) {//时间戳去2024-1-1 00:00:00的秒数到现在 payTime = GameServerUtils.GetTimeSecond() - 1704038400; orderId = PayUtils.GenSimpleOrderIdForUser(player.UserID, desc.itemID, payTime); } else { orderId = PayUtils.GenOrderIdForUser(player.UserID, GameServerUtils.GetApp().ServerID, desc.itemID, payReq.Param1, payReq.Param2, paymentId, payTime); } ssReq.OrderId.SetString(orderId); ssReq.PaymentId.SetString(paymentId); TraceLog.Debug("PayHandler.ProcessPayGoogleReq uid {0} itemId {1} orderId {2} moneyUSD {3} gm {4}" , player.UserID, desc.itemID, ssReq.OrderId, desc.currencyRes, gmTestPay); GameBillLogUtils.LogPayGoogleReq(ref ssReq); switch (payReq.PayChannel) { case PayChannel.TrdSdk: { ssReq.Account.CopyFrom(ref player.AccountInfo); GameServerUtils.GetPacketSender().SendToWorldServer((int)SSGameMsgID.PayGoogleReq, ref ssReq, player.UserID); break; } break; case PayChannel.GameToken: PayCommSvc.TokenPay(player, payReq, ssReq); break; } return 0; } private void ProcessPayGoogleRes(uint serverID, StructPacket packet) { ref SSPayGoogleRes ssRes = ref packet.GetMessage(); TraceLog.Debug("PayHandler.ProcessPayGoogleRes uid {0} itemId {1} orderId {2} ret {3}" , ssRes.Uid, ssRes.ItemID, ssRes.OrderId, ssRes.Ret); GameBillLogUtils.LogPayGoogleRes(ref ssRes); //没有玩家对象可以不处理,订单也许废了,按理不应该发生 PlayerOnGame player = GameServerUtils.GetPlayerTableOp().GetPlayerByUid(ssRes.Uid); if (player == null) { player.Error("PayHandler.ProcessPayGoogleRes no player uid {0}", ssRes.Uid); return; } CSPayGoogleRes csRes = new CSPayGoogleRes { Ret = ssRes.Ret, Uid = ssRes.Uid, ItemID = ssRes.ItemID, OrderId = ssRes.OrderId, JsApiPay = ssRes.JsApiPay }; string paymentId = PayCommSvc.GetPaymentId(ssRes.ItemID); if (paymentId != null) { csRes.PaymentId.SetString(paymentId); } else { player.Error("PayHandler.ProcessPayGoogleRes item {0} invalid money {1}", ssRes.ItemID, ssRes.Money); csRes.Ret = ssRes.Ret = -1; } //拼装小程序支付信息 if (ssRes.PayType == (int)PayType.MiniPay) SetMiniPayData(ref ssRes, ref csRes); if (ssRes.Ret == 0 && ssRes.GmTestPay) { GmCmdSvc.OnGmTestPayReqSuccess(player, ref ssRes); } SendToPlayer(player, (int)CSGameMsgID.PayGoogleRes, ref csRes); if(ssRes.Ret == 0 && ssRes.JsApiPay == 1 ) { PayDiamondDesc desc = PayCommSvc.GetPayDiamondDesc(ssRes.ItemID); //处理jsapi支付 JsonData jsonData = new JsonData(); jsonData["description"] = desc.comm; jsonData["out_trade_no"] = "" + ssRes.OrderId.GetString(); JsonData jamount = new JsonData(); jamount["total"] = ssRes.Money * 100;//分 jamount["currency"] = "CNY"; jsonData["amount"] = jamount; JsonData jpayer = new JsonData(); jpayer["openid"] = ""+player.AccountInfo.AccountID.GetString(); jsonData["payer"] = jpayer; ref var req = ref CSWXJSPayReq.Parser.GetMessageClear(); req.DataJson.SetString(jsonData.ToJson()); req.Uid = player.UserID; //send to world->httpPay GameServerUtils.GetPacketSender().SendToWorldServer((int)CSGameMsgID.PayWsjsapiReq, ref req, player.UserID); } } //获取mini支付参数 void SetMiniPayData(ref SSPayGoogleRes ssRes, ref CSPayGoogleRes res) { var conf = PayDiamondDescMgr.Instance.GetConfig(ssRes.ItemID); var jsonData = new System.Text.Json.Nodes.JsonObject(); jsonData.Add("mode", "goods"); jsonData.Add("offerId", ssRes.OfferId.GetString()); jsonData.Add("buyQuantity", 1); jsonData.Add("currencyType", "CNY"); jsonData.Add("productId", conf.productID); jsonData.Add("goodsPrice", ssRes.Money * 100);//分 jsonData.Add("outTradeNo", ssRes.OrderId.GetString()); //非必要参数 /* jsonData.Add("env", 0); jsonData.Add("platform", "android"); jsonData.Add("zoneId", "1"); jsonData.Add("attach", ""); */ var signData = jsonData.ToJsonString(); // 将method和signData通过&符号连接起来 string needEncodeBody = "requestMidasPaymentGameItem" + "&" + signData; var paySig = HashHelper.GetHMACSHA256(ssRes.Appkey.GetString(), needEncodeBody); var signature = HashHelper.GetHMACSHA256(ssRes.SessionKey.GetString(), signData); res.SignData.SetString(signData); res.PaySig.SetString(paySig); res.Signature.SetString(signature); TraceLog.Error("PayHandler.ProcessPayGoogleRes.SetMiniPayData signData:{0} paySig:{1}, signature:{2}", res.SignData.GetString(), res.PaySig.GetString(), res.Signature.GetString()); } public void ProcessPayGoogleSuccessReq(PlayerSession playerSession, StructPacket packet, bool gmTestPay) { ref CSPayGoogleSuccessReq payReq = ref packet.GetMessage(); if (payReq.Uid != playerSession.UserID) { TraceLog.Error("PayHandler.ProcessPayGoogleSuccessReq invalid uid {0}", payReq.Uid); return; } PlayerOnGame player = playerSession.Player; if (player == null) { TraceLog.Error("PayHandler.ProcessPayGoogleSuccessReq no player uid {0}", payReq.Uid); return; } PayType payType = PlayerPayUtil.GetPlayerPayType(player); if (payType == PayType.Google) { GooglePaySvc.OnPaySuccessReq(player, ref payReq, gmTestPay); } else if (payType == PayType.IAP) { IAPPaySvc.OnPaySuccessReq(player, ref payReq, gmTestPay); } else if (payType == PayType.Hero) { OnHeroPayClientSuccReq(player, ref payReq, gmTestPay); } else if (payType == PayType.Huawei) { HuaweiPaySvc.OnCltPaySuccessReq(player, ref payReq, gmTestPay); } else { player.Error("PayHandler.ProcessPayGoogleSuccessReq payType {0} can not send PaySuccReq by client", payType); } } private static void OnHeroPayClientSuccReq(PlayerOnGame player, ref CSPayGoogleSuccessReq req, bool gmTestPay) { if (req.OrderId.Length == 0) { return; } // uid-time-orderIdSeq-serverId-payitemId-payParam1-payParam2-paymentId string orderId = req.OrderId.GetString(); string[] split = orderId.Split('-'); if (split.Length < 8) { TraceLog.Error("PayHandler.OnHeroPayClientSuccReq invalid orderId {0}", orderId); return; } GameBillLogUtils.LogPayGoogleSuccessReq(ref req, (int)PayType.Hero); int itemId = int.Parse(split[4]); int index = PlayerPayUtil.GetPaySuccLockIndex(player, itemId); // 没有lock, 创建lock并记录客户端成功的时间 if (index == -1) { index = PlayerPayUtil.CreatePaySuccLockIfNotExist(player, itemId, orderId, req.OrderId3rd.GetString()); if (index == -1) { TraceLog.Error("PayHandler.OnHeroPayClientSuccReq orderId {0} add lock failed", orderId); } else { TraceLog.Trace("PayHandler.OnHeroPayClientSuccReq item {0} create lock by clt", itemId); ref var lockData = ref PlayerPayUtil.GetPaySuccLockByIndex(player, index); lockData.CltSuccTime = GameServerUtils.GetTimeSecond(); } return; } // lock存在, 但是订单号不一致? 按道理应该不可能, 现在一旦client或者svr有一边成功后就被锁住了 ref var lockOne = ref PlayerPayUtil.GetPaySuccLockByIndex(player, index); if (!lockOne.OrderId.Equals(orderId)) { TraceLog.Error("PayHandler.OnHeroPayClientSuccReq order not equal, orderId local {0} req {1}" , lockOne.OrderId.GetString(), orderId); return; } if (!lockOne.OrderId3rd.Equals(req.OrderId3rd.GetPtr())) { TraceLog.Error("PayHandler.OnHeroPayClientSuccReq order not equal, orderId3rd local {0} req {1}" , lockOne.OrderId3rd.GetString(), req.OrderId3rd.GetString()); return; } // svr已经成功, 可以删除lock if (lockOne.SvrSuccTime != 0) { TraceLog.Trace("PayHandler.OnHeroPayClientSuccReq item {0} order {1} svr succ at {2}, delete lock now" , itemId, orderId, lockOne.SvrSuccTime); player.RoleData.PayData.PaySuccLock.RemoveAt(index); } else { TraceLog.Trace("PayHandler.OnHeroPayClientSuccReq item {0} lock by clt", itemId); lockOne.CltSuccTime = GameServerUtils.GetTimeSecond(); } player.MakeDirty(); } public int ProcessPayGoogleSuccessRes(uint serverID, StructPacket packet) { ref SSPayGoogleSuccessRes ssRes = ref packet.GetMessage(); TraceLog.Error("PayHandler.ProcessPayGoogleSuccessRes uid {0} itemId {1} orderId {2} pay status {3} ret {4}", ssRes.Uid, ssRes.ItemID, ssRes.OrderId, ssRes.Status, ssRes.Ret); // 没有玩家对象可以不处理, 下次上线时统一把支付成功未加钻石的订单全部处理一遍 PlayerOnGame player = GameServerUtils.GetPlayerTableOp().GetPlayerByUid(ssRes.Uid); if (player == null) { TraceLog.Error("PayHandler.ProcessPayGoogleSuccessRes uid {0} no player", ssRes.Uid); GameBillLogUtils.LogPayGoogleSuccessRes(ref ssRes, 0, 0, 0, 0, false, null); return -1; } CSPayGoogleSuccessRes csRes = new CSPayGoogleSuccessRes(); csRes.Ret = ssRes.Ret; csRes.Uid = ssRes.Uid; csRes.OrderId = ssRes.OrderId; csRes.ItemID = ssRes.ItemID; PayType payType = PlayerPayUtil.GetPlayerPayType(player); PayDiamondDesc desc = PayCommSvc.GetPayDiamondDesc(ssRes.ItemID); if (desc == null) { player.Error("PayHandler.ProcessPayGoogleSuccessRes invalid itemId {0}", ssRes.ItemID); ssRes.Ret = -1; GameBillLogUtils.LogPayGoogleSuccessRes(ref ssRes, 0, 0, 0, 0, false, player); csRes.Ret = -1; SendToPlayer(player, (int)CSGameMsgID.PayGoogleSuccessRes, ref csRes); return -1; } // 支付出错 if (ssRes.Ret != 0) { player.Error("PayHandler.ProcessPayGoogleSuccessRes uid {0} orderId {1} ret {2}" , ssRes.Uid, ssRes.OrderId, ssRes.Ret); GameBillLogUtils.LogPayGoogleSuccessRes(ref ssRes, (int)desc.currencyRes, 0, 0, 0, false, player); SendToPlayer(player, (int)CSGameMsgID.PayGoogleSuccessRes, ref csRes); return -1; } // 订单状态出错, 可能是处理同一笔订单产生的消息 if (ssRes.Status != 1) { player.Error("PayHandler.ProcessPayGoogleSuccessRes uid {0} orderId {1} pay status {2}" , ssRes.Uid, ssRes.OrderId, ssRes.Status); GameBillLogUtils.LogPayGoogleSuccessRes(ref ssRes, (int)desc.currencyRes, 0, 0, 0, false, player); return -1; } // mycard支付金额由用户输入, 支持支付金额不等于商品价格时, 需要根据规则兑换成钻石 bool isReplaceItem = false; uint diamondExchange = 0, amountExchange = 0; if (ssRes.PayType == (uint)PayType.Hero && PayCommSvc.IsMycardPay(ssRes.SubPayType) && ssRes.Amount != desc.currencyRes) { ExchangeDiamondByPayMoney(player, ref ssRes, desc, out amountExchange, out diamondExchange, out var newDesc); // 替换了玩家之前选择的item !!! if (desc.itemID != newDesc.itemID) { player.Debug("PayHandler.ProcessPayGoogleSuccessRes uid {0} item {1} change to {2}" , player.UserID, desc.itemID, newDesc.itemID); desc = newDesc; isReplaceItem = true; PlayerPayUtil.AddPaySuccRecordIfNotExist(player, desc); } } int recordIndex = PlayerPayUtil.GetPaySuccessRecordIndex(player, desc.itemID); if (recordIndex == -1) { player.Error("PayHandler.ProcessPayGoogleSuccessRes uid {0} itemId {1} no pay record", player.UserID, desc.itemID); return -1; } // 收到支付成功请求, 插入待添加列表 ref DBRolePayItemRecord record = ref PlayerPayUtil.GetPayItemRecordByIndex(player, recordIndex); int idx = InsertPaySuccWaitAddRole(player, desc, ref ssRes, ref record, amountExchange, diamondExchange, isReplaceItem); if (idx == -1) { return -1; } // 已经发货成功, 等待超时后删除 ref var addData = ref player.RoleData.PayData.PaySuccWaitAddRole[idx]; if (addData.AddItemSuccTime > 0) { player.Debug("PayHandler.ProcessPayGoogleSuccessRes uid {0} order {1} already add item {2}" , player.UserID, addData.OrderId.GetString(), addData.AddItemSuccTime); return -1; } // 成功后请求数据库修改支付订单状态, 先修改DB订单状态再添加物品 var addReq = new SSPayDBAddDiamondStatusReq { Uid = player.UserID, AmountExchange = amountExchange, DiamondExchange = diamondExchange, Money = addData.Money }; addReq.OrderId.SetString(ssRes.OrderId.GetPtr()); if (isReplaceItem) { addReq.ReplaceItemId = desc.itemID; } addData.LastSendDBTime = (int)GameServerUtils.GetTimeSecond(); player.Debug("PayHandler.ProcessPayGoogleSuccessRes uid {0} send DB add diamond status", player.UserID); if (ssRes.PayChannel == PayChannel.TrdSdk) { GameServerUtils.GetPacketSender().SendToWorldServer((int)SSGameMsgID.PayDbAddDiamondStatusReq, ref addReq, player.UserID); } return 0; } public void ExchangeDiamondByPayMoney(PlayerOnGame player, ref SSPayGoogleSuccessRes ssRes, PayDiamondDesc desc, out uint amountExchange, out uint diamondExchange, out PayDiamondDesc replaceItemDesc) { amountExchange = 0; diamondExchange = 0; replaceItemDesc = null; // 购买钻石礼包 if (desc.bdc_product_type == 1) { // 大买小 if (ssRes.Amount > desc.currencyRes) { replaceItemDesc = desc; } else { // 根据付款金额找一档最接近的, 然后把差额换算成钻石 replaceItemDesc = PayDiamondDescMgr.Instance.GetDiamondByMoney(ssRes.Amount); } if (replaceItemDesc != null) { amountExchange = ssRes.Amount - replaceItemDesc.currencyRes; } else { // 找不到金额最接近的钻石档位, 全部换算成钻石 //replaceItemDesc = PayDiamondDescMgr.Instance.GetConfig((int)PayType.Hero, "gp_dynamicDiamond"); replaceItemDesc = PayDiamondDescMgr.Instance.GetConfig(99999); amountExchange = ssRes.Amount; } } else { // 非钻石礼包, 付款超过商品价格时, 超出部分转换成钻石 if (ssRes.Amount > desc.currencyRes) { replaceItemDesc = desc; amountExchange = ssRes.Amount - desc.currencyRes; } else if (desc.currencyRes > ssRes.Amount) { // 付款少于商品价格时, 全部兑换成钻石 //replaceItemDesc = PayDiamondDescMgr.Instance.GetConfig((int)PayType.Hero, "gp_dynamicDiamond"); replaceItemDesc = PayDiamondDescMgr.Instance.GetConfig(99999); amountExchange = ssRes.Amount; } } if (amountExchange > 0) { diamondExchange = amountExchange * 6 / 10; } player.Debug("PayHandler.ExchangeDiamondByPayMoney uid {0} amount {1} exchange amount {2} diamond {3} origin item {4} replace item {5}" , player.UserID, ssRes.Amount, amountExchange, diamondExchange, desc.itemID, replaceItemDesc.itemID); } public int InsertPaySuccWaitAddRole(PlayerOnGame player, PayDiamondDesc desc, ref SSPayGoogleSuccessRes res, ref DBRolePayItemRecord record, uint amountExchange, uint diamondExchange, bool isReplaceItem) { // 删除超过保留时间的发货成功的waitAddRole数据 PlayerPayUtil.DeletePaySuccWaitAddRole(player); for (int i = 0; i < player.RoleData.PayData.PaySuccWaitAddRole.Count; i++) { ref var item = ref player.RoleData.PayData.PaySuccWaitAddRole[i]; // 重复收到了支付成功的消息 if (item.OrderId.Equals(res.OrderId.GetPtr())) { player.Debug("PayHandler.InsertPaySuccWaitAddRole uid {0} orderId {1} already exist" , player.UserID, res.OrderId.GetString()); return i; } } // 删除最早一笔发货成功的waitAddRole数据 if (player.RoleData.PayData.PaySuccWaitAddRole.Count >= player.RoleData.PayData.PaySuccWaitAddRole.GetMaxCount()) { PlayerPayUtil.DeleteEarliestPaySuccWaitAddRole(player); } // 数据库出问题了? 否则为什么累计了这么多笔订单未添加呢, 没关系, 每次上线时会重新处理未完成的订单 if (player.RoleData.PayData.PaySuccWaitAddRole.Count >= player.RoleData.PayData.PaySuccWaitAddRole.GetMaxCount()) { player.Error("PayHandler.InsertPaySuccWaitAddRole uid {0} wait add list is full", player.UserID); return -1; } string orderId = res.OrderId.GetString(); string orderId3rd = res.OrderId3rd.GetString(); // 支付成功时处理item锁, 要使用res.ItemID, 否则在点卡支付时可能会被替换成其他itemId ProcItemLockOnSvrSucc(player, res.ItemID, orderId, orderId3rd); var data = new DBPaySuccWaitAddRole { Money = desc.currencyRes > 0 ? desc.currencyRes : res.Amount, Amount = res.Amount, PayType = (int)res.PayType, IsPlayerFirstPay = PlayerPayUtil.IsFirstPayUser(player), PayTime3rd = res.PayTime3rd, IsTestPay = res.GmTestPay ? 1 : 0, AmountExchange = amountExchange, DiamondExchange = diamondExchange, IsReplaceItem = isReplaceItem, Sandbox = res.Sandbox, }; // item不能使用res.ItemID, 点卡支付时可能会替换成实际能购买的itemId data.ItemID = desc.itemID; data.OrderId.SetString(res.OrderId.GetPtr()); data.OrderId3rd.SetString(res.OrderId3rd.GetPtr()); data.Currency.SetString(res.Currency.GetPtr()); data.PurchaseToken.SetString(res.PurchaseToken.GetPtr()); player.RoleData.PayData.PaySuccWaitAddRole.Add(ref data); // 插入PaySuccWaitAddRole列表就算支付成功 record.PaySuccessCount++; record.PayCountToday++; record.PayCountWeek++; record.PayCountMonth++; if (res.PayChannel == PayChannel.TrdSdk) { player.RoleData.PayData.TotalPayMoney += res.Amount; player.RoleData.PayData.TotalPayMoneyUSD += res.Amount; SystemUnlockEvent.CheckUnlockSystem(player); } if (res.GmTestPay) { player.RoleData.PayData.GmTotalPayMoneyUSD += res.Amount; } // 支付成功时记录首冲礼包的版本号, 后续用于首冲礼包领取 PayDiamondDesc firstPayDesc = null; // 当天的购买记录保存在第一个 if (res.Amount > player.RoleData.PayData.MaxPayMoneyLast7Days[0]) { player.RoleData.PayData.MaxPayMoneyLast7Days[0] = (int)res.Amount; } // 充值统计 RoleStatChgOp statChgOp = new RoleStatChgOp(player); statChgOp.AddIDDaily((int)CSRoleStatisticsID.PayMoney, res.Amount); statChgOp.NotifyClient(); player.MakeDirty(); player.Debug("PayHandler.InsertPaySuccWaitAddRole uid {0} itemId {1} orderId {2} pay count total {3} today {4} week {5} month {6} pay money {7} dollar {8} playerFirstPay {9}" , player.UserID, desc.itemID, data.OrderId.GetString(), record.PaySuccessCount, record.PayCountToday , record.PayCountWeek, record.PayCountMonth, player.RoleData.PayData.TotalPayMoney , player.RoleData.PayData.TotalPayMoneyUSD, data.IsPlayerFirstPay); return player.RoleData.PayData.PaySuccWaitAddRole.Count - 1; } private void ProcItemLockOnSvrSucc(PlayerOnGame player, int itemId, string orderId, string orderId3rd) { int index = PlayerPayUtil.GetPaySuccLockIndex(player, itemId); // 没有lock, 创建lock并记录svr成功时间 if (index == -1) { index = PlayerPayUtil.CreatePaySuccLockIfNotExist(player, itemId, orderId, orderId3rd); if (index == -1) { TraceLog.Error("PayHandler.ProcItemLockOnSvrSucc item {0} order {1} add lock failed", itemId, orderId); } else { TraceLog.Trace("PayHandler.ProcItemLockOnSvrSucc item {0} create lock by svr", itemId); ref var lockData = ref PlayerPayUtil.GetPaySuccLockByIndex(player, index); lockData.SvrSuccTime = GameServerUtils.GetTimeSecond(); } } else { ref var lockOne = ref PlayerPayUtil.GetPaySuccLockByIndex(player, index); if (lockOne.OrderId.Equals(orderId) && lockOne.OrderId3rd.Equals(orderId3rd)) { // 支付完成删除锁 if (lockOne.CltSuccTime != 0) { TraceLog.Trace("PayHandler.ProcItemLockOnSvrSucc item {0} clt succ at {1}, delete lock now", itemId, lockOne.CltSuccTime); player.RoleData.PayData.PaySuccLock.RemoveAt(index); } else { TraceLog.Trace("PayHandler.ProcItemLockOnSvrSucc item {0} lock by svr", itemId); lockOne.SvrSuccTime = GameServerUtils.GetTimeSecond(); } } else { TraceLog.Error("PayHandler.ProcItemLockOnSvrSucc item {0} orderId local {1} res {2}, orderId3rd local {3} res {4} not equal" , itemId, lockOne.OrderId.GetString(), orderId, lockOne.OrderId3rd.GetString(), orderId3rd); } } } public void ProcessDBAddDiamondStatusRes(uint serverID, StructPacket packet) { ref SSPayDBAddDiamondStatusRes res = ref packet.GetMessage(); long uid = packet.ObjectID; OnDBAddDiamondStatusRes(uid, ref res, true); } public void OnDBAddDiamondStatusRes(long uid, ref SSPayDBAddDiamondStatusRes res, bool realPay) { //没有玩家对象可以不处理, 下次上线时会统一处理 PlayerOnGame player = GameServerUtils.GetPlayerTableOp().GetPlayerByUid(uid); if (player == null) { TraceLog.Error("PayHandler.OnDBAddDiamondStatusRes uid {0} no player", uid); return; } int idx = -1; for (int i = 0; i < player.RoleData.PayData.PaySuccWaitAddRole.Count; i++) { ref var item = ref player.RoleData.PayData.PaySuccWaitAddRole[i]; if (item.OrderId.Equals(res.OrderId.GetPtr())) { idx = i; break; } } // 没有可能是收到了重复的消息, 已经添加过钻石了 if (idx == -1) { player.Error("PayHandler.OnDBAddDiamondStatusRes uid {0} orderId {1} not in wait add list" , uid, res.OrderId.GetString()); return; } ref DBPaySuccWaitAddRole addData = ref player.RoleData.PayData.PaySuccWaitAddRole[idx]; // 已经添加成功, 无需再处理 if (addData.AddItemSuccTime > 0) { player.Error("PayHandler.OnDBAddDiamondStatusRes uid {0} orderId {1} already add succ {2}" , uid, res.OrderId.GetString(), addData.AddItemSuccTime); return; } // 如果DB状态是支付成功1或者添加钻石2, 则会统一更新成状态2 if (res.Status != 2) { addData.DbResFailCount++; TraceLog.Error("PayHandler.OnDBAddDiamondStatusRes uid {0} orderId {1} pay status {2} fail count {3}" , uid, res.OrderId, res.Status, addData.DbResFailCount); return; } int itemId = addData.ItemID; string orderId = addData.OrderId.GetString(); player.Debug("PayHandler.OnDBAddDiamondStatusRes uid {0} orderId {1} firstPay {2}", player.UserID, orderId, addData.IsPlayerFirstPay); PayType payType = PlayerPayUtil.GetPlayerPayType(player); PayDiamondDesc desc = PayCommSvc.GetPayDiamondDesc(itemId); if (desc == null) { player.Error("PayHandler.OnDBAddDiamondStatusRes invalid itemId {0} uid {1}", itemId, player.UserID); return; } var dailyPackDiamond = PayCommSvc.GetBuyOneClickDailyPackDiamond(player, desc.itemID); var csRes = new CSPayGoogleSuccessRes(); csRes.Uid = player.UserID; csRes.OrderId.SetString(res.OrderId.GetPtr()); csRes.ItemID = itemId; csRes.PurchaseToken.SetString(addData.PurchaseToken.GetPtr()); csRes.Money = addData.Amount; csRes.Diamond = desc.diamond; csRes.PayDiamond = desc.payDiamond; csRes.Diamond += (uint)dailyPackDiamond; uint addDiamond = addData.DiamondExchange; var isFirstPay = PlayerPayUtil.IsFirstPayThisItem(player, desc); List selfItems = new List(); { // if (SelfSelectBagScv.IsSelfSelectBag(desc.goodsType)) // { // selfItems = SelfSelectBagScv.GetPaySelectBagItems(player, desc.itemID); // } int vipEx = addData.DiamondExchange > 0 ? (int)addData.DiamondExchange : 0; var itemEx = GetPayAddItemEx(ref res); // if (PayCommSvc.IsLifeLongMenberCard(desc.vipCardType)) // { // int index = PlayerPayUtil.GetMonthlyCardDataIndex(player, desc.vipCardType); // if (index < 0) // { // csRes.Ret = CheckAddPayItemToPlayer(player, orderId, addDiamond, desc, vipEx, ref csRes, itemEx); // } // else // { // player.Error("PayHandler.OnDBAddDiamondStatusRes repay long card,uid={0},card={1},order={2}", player.UserID, desc.itemID, res.OrderId.GetString()); // csRes.Ret = 0; // SendToPlayer(player, (int)CSGameMsgID.PayGoogleSuccessRes, ref csRes); // return; // } // } // else { csRes.Ret = CheckAddPayItemToPlayer(player, orderId, addDiamond, desc, vipEx, ref csRes, itemEx, res.PayChannel); } } //正常来说不会存在这种情况吧,数据库成功,玩家身上不成功 if (csRes.Ret != 0) { SendToPlayer(player, (int)CSGameMsgID.PayGoogleSuccessRes, ref csRes); return; } // 首冲 bool isPlayerFirstPay = addData.IsPlayerFirstPay; long payTime3rd = addData.PayTime3rd; try { if (realPay) { if(addData.PayType != (int)PayType.MiniPay) { NotifyHttpPaySvrAddItemSucc(player, ref addData); } GameBillLogUtils.LogPayGoogleSuccessRes(ref addData, 0, addData.IsPlayerFirstPay, player); GameBDCLogUtils.ChargeInfo(player, ref addData, desc.bdc_product_type, addData.IsPlayerFirstPay); GameTALogUtils.UseSetCharge(player, ref addData); GameTALogUtils.UseSetOnceFirstPay(player, ref addData); GameTALogUtils.LogChargeInfo(player, ref addData, 0, ref res, selfItems); } else { if (string.IsNullOrEmpty(desc.consumeItemId))//砖石礼包不打 { GameTALogUtils.LogVoucherChargeInfo(player, ref addData, ref res, selfItems); } } } catch (Exception e) { TraceLog.Exception(e); var app = GameServerUtils.GetApp(); if (app != null) { app.Alerter.AlertException(e,uid); } } finally { // 记录添加成功时间 player.RoleData.PayData.PaySuccWaitAddRole[idx].AddItemSuccTime = (int)GameServerUtils.GetTimeSecond(); } //记录玩家进入购买钻石数量 player.RoleData.PayData.TodayPayDiamond += desc.payDiamond + dailyPackDiamond; //购买代币不触发任何支付后的事件 if (desc.goodsType != (int)PayGoodsType.None) { GameServerUtils.GetEventHandlerMgr().TriggerPlayerPaySuccess(player, desc.itemID, addData.DiamondExchange, addDiamond, addData.Amount, isPlayerFirstPay, payTime3rd, ref csRes); } else { //购买代币需要触发一下 // PlayerDataSvc.UnlockNewPlayerGift(player,desc.goodsType,desc.itemID); } if (isFirstPay && desc.firstPayAwardType > 0) { if (desc.firstPayAwardId ==ItemId.Diamond) { csRes.Diamond += (uint)desc.firstPayAwardNum; } else { if (desc.firstPayAwardType > 0) { csRes.Items.Add(new TypeIDValueString() { Type = desc.firstPayAwardType, Id = new FixedStructString64(desc.firstPayAwardId), Value = desc.firstPayAwardNum }); } } } if (!isFirstPay) { if (desc.followPayAwardId == ItemId.Diamond) { csRes.Diamond += (uint)desc.followPayAwardNum; } else { if (desc.followPayAwardType > 0) { csRes.Items.Add(new TypeIDValueString() { Type = desc.followPayAwardType, Id = new FixedStructString64(desc.followPayAwardId), Value = desc.followPayAwardNum }); } } } TraceLog.Error("add item success,itemID:" + desc.itemID + addData.DiamondExchange + " addDiamond:" + addDiamond + " payMoney:" + addData.Amount + "is irst:" + isPlayerFirstPay); PlayerNotify.NotifyPlayerPayDataChange(player); SendToPlayer(player, (int)CSGameMsgID.PayGoogleSuccessRes, ref csRes); } private List GetPayAddItemEx(ref SSPayDBAddDiamondStatusRes res) { List itemEx = null; for (int i = 0; i < res.SelectItems.Count; i++) { if (itemEx == null) { itemEx = new List(); } itemEx.Add(res.SelectItems[i]); } return itemEx; } private List GetPayAddItemEx(ref CSPayGetFreeItemReq req) { List itemEx = null; for (int i = 0; i < req.SelectItems.Count; i++) { if (itemEx == null) { itemEx = new List(); } itemEx.Add(req.SelectItems[i].Item); } return itemEx; } private int CheckAddPayItemToPlayer(PlayerOnGame player, string orderId, uint diamond, PayDiamondDesc desc, int vipEx, ref CSPayGoogleSuccessRes csRes, List itemEx, PayChannel payChannel) { int ret = CheckAddPayItem(player, orderId, diamond, desc, vipEx, itemEx, payChannel); if (ret != 0) { return ret; } // csRes.VipCardType = desc.vipCardType; for (int i = 0; i < desc.giveItem.Length; i++) { if (desc.giveItem[i].type > 0 && desc.giveItem[i].count > 0) { var one = new TypeIDValueString { Type = desc.giveItem[i].type, Id = new FixedStructString64(desc.giveItem[i].id) , Value = desc.giveItem[i].count }; csRes.Items.Add(ref one); } } var packGiveItem = PayCommSvc.GetBuyOneClickDailyPackGiveItem(player, desc.itemID); for (var i = 0; i < packGiveItem.Length; i++) { csRes.Items.Add(ref packGiveItem[i]); } // 不在PayDiamond表中的额外物品 if (itemEx != null) { foreach (var it in itemEx) { csRes.Items.Add(it); } } // //自选礼包的物品更新 // if (SelfSelectBagScv.IsSelfSelectBag(desc.goodsType)) // { // var selfItems = SelfSelectBagScv.GetPaySelectBagItems(player, desc.itemID, true); // foreach (var one in selfItems) // { // csRes.Items.Add(one); // } // } return 0; } private int CheckAddPayItem(PlayerOnGame player, string orderId, uint diamond, PayDiamondDesc desc, int vipEx, List itemEx, PayChannel payChannel) { player.Debug("PayHandler.CheckAddPayItem uid {0} itemId {1} orderId {2}" , player.UserID, desc.itemID, orderId); if (payChannel == PayChannel.GameToken) { var ret = CheckCostPayItem(player, desc, orderId, true); if (ret != 0) { return ret; } } // 添加钻石和物品 UnifyOp bagOp = new UnifyOp(player, BillChangeItemReason.Pay, orderId); if (diamond > 0) { bagOp.AddDiamond(diamond); // 现在这里的diamond只有diamoneExchange 首次充值额外赠送另外算 player.RoleData.PayData.TodayPayDiamond += diamond; } if (desc.diamond > 0) { bagOp.AddDiamond(desc.diamond); player.RoleData.PayData.TodayPayDiamond += desc.diamond; } if (desc.payDiamond > 0) { bagOp.AddDiamond(desc.payDiamond); } var firstPay = PlayerPayUtil.IsFirstPayThisItem(player, desc); if (firstPay && desc.firstPayAwardType > 0) { bagOp.AddGoods(desc.firstPayAwardType, desc.firstPayAwardId.ToString(), desc.firstPayAwardNum); if (desc.firstPayAwardId == ItemId.Diamond) { player.RoleData.PayData.TodayPayDiamond += desc.firstPayAwardNum; } } for (int i = 0; i < desc.giveItem.Length; i++) { if (desc.giveItem[i].type > 0 && desc.giveItem[i].count > 0) { bagOp.AddGoods(desc.giveItem[i].type, desc.giveItem[i].id, desc.giveItem[i].count); if ( desc.giveItem[i].id == ItemId.Diamond) { player.RoleData.PayData.TodayPayDiamond += desc.giveItem[i].count; } } } var packGiveItem = PayCommSvc.GetBuyOneClickDailyPackGiveItem(player, desc.itemID); for (var i = 0; i < packGiveItem.Length; i++) { bagOp.AddGoods(packGiveItem[i].Type, packGiveItem[i].Id.ToString(), packGiveItem[i].Value); if (packGiveItem[i].Id.ToString() == ItemId.Diamond) { player.RoleData.PayData.TodayPayDiamond += packGiveItem[i].Value; } } //非首充 if (!firstPay && desc.followPayAwardNum > 0) { bagOp.AddGoods(desc.followPayAwardType, desc.followPayAwardId, desc.followPayAwardNum); if (desc.followPayAwardId == ItemId.Diamond) { player.RoleData.PayData.TodayPayDiamond += desc.followPayAwardNum; } } // 不在PayDiamond表中的额外物品 if (itemEx != null) { foreach (var it in itemEx) { bagOp.AddGoods(it.Type, it.Id.ToString(), it.Value); } } // //自选礼包的物品更新 // if (SelfSelectBagScv.IsSelfSelectBag(desc.goodsType)) // { // var selfItems = SelfSelectBagScv.GetPaySelectBagItems(player, desc.itemID); // foreach (var one in selfItems) // { // bagOp.AddGoods(one.Type, one.Id.ToString(), one.Value); // } // } CSErrCode iRet = bagOp.DoOp(sendGetItemMsg: true); if (iRet != 0) { player.Error("PayHandler.CheckAddPayItem uid {0} bagOp.DoOp failed ret {1}", player.UserID, iRet); return (int)iRet; } // // 月卡/周卡 if (PayCommSvc.IsMonthlyCard(desc.vipCardType)) { MonthlyCardSvc.OnActiveMonthlyCard(player, desc.vipCardType); } player.Debug("PayHandler.CheckAddPayItem uid {0} add diamond {1} new diamond {2} succ" , player.UserID, diamond, player.RoleBase.Diamond); return 0; } public int CheckCostPayItem(PlayerOnGame player, PayDiamondDesc desc, string orderId, bool cost = true) { var consumeItemId = ItemId.Token; var consumeItemCount = desc.currencyRes; if (!string.IsNullOrEmpty(desc.consumeItemId) && desc.consumeItemCount > 0) { consumeItemId = desc.consumeItemId; consumeItemCount = (uint)desc.consumeItemCount; } var bagOpDelete = new UnifyOp(player, BillChangeItemReason.Pay, orderId); if (!cost) { return bagOpDelete.GetItemCount(consumeItemId) >= consumeItemCount ? 0 : -1; } bagOpDelete.CostGoods((int)GoodsType.Items, consumeItemId, consumeItemCount); CSErrCode iDeleteRet = bagOpDelete.CheckOp(); if (iDeleteRet != 0) { player.Error( "PayHandler.CheckAddPayItem uid {0} bagOp.DoOp failed ret {1} when delete consumeItem {2}" , player.UserID, iDeleteRet, consumeItemId); return -1; } iDeleteRet = bagOpDelete.DoOp(); if (iDeleteRet != 0) { player.Error( "PayHandler.CheckAddPayItem uid {0} bagOp.DoOp failed ret {1} when delete consumeItem {2}" , player.UserID, iDeleteRet, consumeItemId); return -1; } return 0; } public void ProcessPayGetFreeItemReq(PlayerSession playerSession, StructPacket packet) { PlayerOnGame player = playerSession.Player; if (player == null) { TraceLog.Trace("PayHandler.ProcessPayGetFreeItemReq no player, session id {0}", playerSession.SessionID); return; } // 这个系统解锁效率不高, 建议修改成按Bit来判断, 限制下外挂领取免费物品, 付费的就不限制了, 反正花钱了 ref CSPayGetFreeItemReq req = ref packet.GetMessage(); PayType payType = PlayerPayUtil.GetPlayerPayType(player); PayDiamondDesc desc = PayCommSvc.GetPayDiamondDesc(req.ItemID); if (desc == null) { player.Error("PayHandler.ProcessPayGetFreeItemReq invalid itemId {0} uid {1}", req.ItemID, player.UserID); return; } if (desc.currencyRes != 0) { player.Error("PayHandler.ProcessPayGetFreeItemReq itemId {0} not free", req.ItemID); return; } var res = new CSPayGetFreeItemRes(); res.ItemID = req.ItemID; res.Ret = PayCommSvc.CheckPayLimit(player, desc); if (res.Ret != 0) { player.Error("PayHandler.ProcessPayGetFreeItemReq CheckPayLimit failed, itemId {0} uid {1} ret {2}" , req.ItemID, player.UserID, res.Ret); SendToPlayer(player, (int)CSGameMsgID.PayGetFreeItemRes, ref res); return; } int recordIndex = PlayerPayUtil.AddPaySuccRecordIfNotExist(player, desc); if (recordIndex == -1) { TraceLog.Error("PayHandler.ProcessPayGetFreeItemReq uid {0} itemId {1} add pay record failed" , player.UserID, desc.itemID); res.Ret = -1; SendToPlayer(player, (int)CSGameMsgID.PayGetFreeItemRes, ref res); return; } // 不在PayDiamond表中的额外物品 var itemEx = GetPayAddItemEx(ref req); //res.Ret = CheckAddPayItem(player, PayCommSvc.FreeGiftPack, 0, desc, 0, itemEx,); //if (res.Ret != 0) //{ // SendToPlayer(player, (int)CSGameMsgID.PayGetFreeItemRes, ref res); // return; //} ref DBRolePayItemRecord record = ref PlayerPayUtil.GetPayItemRecordByIndex(player, recordIndex); record.PaySuccessCount++; record.PayCountToday++; record.PayCountWeek++; record.PayCountMonth++; PlayerNotify.NotifyPlayerPayDataChange(player); GameBillLogUtils.LogPayFreeGiftPack(player, desc, ref record); res.Diamond = desc.diamond; //res.VipCardType = desc.vipCardType; res.PayDiamond = desc.payDiamond; for (int i = 0; i < desc.giveItem.Length; i++) { if (desc.giveItem[i].type > 0 && desc.giveItem[i].count > 0) { var one = new TypeIDValueString { Type = desc.giveItem[i].type, Id = new FixedStructString64(desc.giveItem[i].id), Value = desc.giveItem[i].count }; res.Items.Add(ref one); } } // 不在PayDiamond表中的额外物品 if (itemEx != null) { foreach (var it in itemEx) { res.Items.Add(it); } } player.Trace("PayHandler.ProcessPayGetFreeItemReq uid {0} itemId {1} succ", player.UserID, req.ItemID); SendToPlayer(player, (int)CSGameMsgID.PayGetFreeItemRes, ref res); } private void NotifyHttpPaySvrAddItemSucc(PlayerOnGame player, ref DBPaySuccWaitAddRole data) { var notify = new SSPayAddPlayerItemNotify(); var playerSession = GameServerUtils.GetPlayerTableOp().GetPlayerSessionByUid(player.UserID); if (playerSession != null) { notify.CUid.SetString(playerSession.AccountInfo.AccountID.GetPtr()); notify.CName.SetString(playerSession.Nick); notify.ChannelId = playerSession.channelId; notify.ProductId.SetString(playerSession.clientInfo.pcode); } else { notify.CUid.SetString(player.AccountInfo.AccountID.GetPtr()); notify.CName.SetString(player.RoleBase.Nick.GetPtr()); notify.ChannelId = player.channelId; notify.ProductId.SetString(player.clientInfo.pcode); } string orderId = data.OrderId.GetString(); var arr = orderId.Split('-'); if (arr.Length >= 8) { notify.GoodsId.SetString(arr[7]); } notify.OrderNo.SetString(data.OrderId3rd.GetPtr()); notify.CpOrderId.SetString(orderId); notify.Amount = data.Amount; notify.Unit.SetString(data.Currency.GetPtr()); notify.PayTime = data.PayTime3rd; notify.RoleId = player.UserID; notify.RoleName.SetString(player.RoleBase.Nick.GetPtr()); notify.RoleLevel = player.RoleBase.Level; notify.VipLevel = player.RoleBase.VipLevel; notify.TotalCharge = player.RoleData.PayData.TotalPayMoneyUSD; notify.ServerId = player.RealmID; var realm = GameServerUtils.GetRealmBriefInfo(player.RealmID); if (realm != null) { notify.ServerName.SetString(realm.realmName); } notify.GetTime = GameServerUtils.GetTimeSecond(); notify.MoneyType = (int)CurrencyType.Diamond; // 付款方式:1(sdk支付:常规付款操作)、2(虚拟支付:测试使用,无真实消费)、3(英雄线下付款) notify.PaymentMethod = data.IsTestPay == 0 ? 1 : 2; notify.IsTestPay = data.IsTestPay; GameServerUtils.GetPacketSender().SendToWorldServer((int)SSGameMsgID.PayAddPlayerItemNotify, ref notify, player.UserID); } private void ProcessClientTriggerItemArriveReq(PlayerSession playerSession, StructPacket packet) { PlayerOnGame player = playerSession.Player; if (player == null) { TraceLog.Trace("PayHandler.ProcessClientTriggerItemArriveReq no player, session id {0}", playerSession.SessionID); return; } } private void OnPayItemStockInfoReq(PlayerSession playerSession, StructPacket packet) { PlayerOnGame player = playerSession.Player; if (player == null) { TraceLog.Trace("PayHandler.OnPayItemStockInfoReq no player, session id {0}", playerSession.SessionID); return; } var realmStock = GameServerUtils.GetGameServerData().m_realmItemStock; // gamesvr缓存中没有数据, 向worldsvr请求 if (!realmStock.TryGetValue(player.RealmID, out var realmInfo)) { var ssReq = new SSPayItemStockInfoReq { RealmId = player.RealmID, ReqUid = player.UserID }; GameServerUtils.GetPacketSender().SendToWorldServer((int)SSGameMsgID.PayItemStockInfoReq, ref ssReq, player.UserID); return; } var res = new CSPayItemStockInfoRes(); // realm的库存数据全部下发 foreach (ItemStockInfoOne stockInfo in realmInfo.stockDict.Values) { var item = new PayItemStockInfo(); item.ItemID = stockInfo.itemId; item.Count = stockInfo.remainCount; res.ItemInfo.Add(ref item); } SendToPlayer(player, (int)CSGameMsgID.PayItemStockInfoRes, ref res); } // 收到world的回包 public void OnPayItemStockInfoRes(uint serverID, StructPacket packet) { ref var res = ref packet.GetMessage(); if (res.ItemInfo.Count == 0) { TraceLog.Trace("PayHandler.OnPayItemStockInfoRes realm {0} no stockInfo", res.RealmId); return; } var realmInfo = new RealmItemStockInfo { realmId = res.RealmId }; for (int i = 0; i < res.ItemInfo.Count; i++) { var stockInfo = new ItemStockInfoOne { itemId = res.ItemInfo[i].ItemID, remainCount = res.ItemInfo[i].Count }; realmInfo.stockDict.Add(stockInfo.itemId, stockInfo); TraceLog.Trace("PayHandler.OnPayItemStockInfoRes realm {0} item {1} count {2}" , res.RealmId, stockInfo.itemId, stockInfo.remainCount); } // 刷新gamesvr的缓存 var realmStock = GameServerUtils.GetGameServerData().m_realmItemStock; if (realmStock.ContainsKey(res.RealmId)) { realmStock[res.RealmId] = realmInfo; } else { realmStock.Add(res.RealmId, realmInfo); } // 同步给玩家 if (res.ReqUid != 0) { PlayerOnGame player = GameServerUtils.GetPlayerTableOp().GetPlayerByUid(res.ReqUid); if (player == null) { return; } var csRes = new CSPayItemStockInfoRes(); foreach (ItemStockInfoOne stockInfo in realmInfo.stockDict.Values) { var item = new PayItemStockInfo(); item.ItemID = stockInfo.itemId; item.Count = stockInfo.remainCount; csRes.ItemInfo.Add(ref item); } SendToPlayer(player, (int)CSGameMsgID.PayItemStockInfoRes, ref csRes); } } public void OnNotifyItemStockInfo(uint serverID, StructPacket packet) { ref var notify = ref packet.GetMessage(); var realmStock = GameServerUtils.GetGameServerData().m_realmItemStock; if (realmStock.TryGetValue(notify.RealmId, out var realmInfo)) { int itemId = notify.ItemInfo.ItemID; if (realmInfo.stockDict.TryGetValue(itemId, out var stockInfo)) { stockInfo.remainCount = notify.ItemInfo.Count; } } } public void ProcessFakePay(uint serverID, StructPacket packet) { ref var req = ref packet.GetMessage(); bool success = false; for (var i = 0; i < req.ItemId.Count; i++) { var ret = PayCommSvc.FakePay(req.Uid, req.ItemId[i]); if (ret < 0) { success = false; break; } success = true; } SSOperationFakePayRes res = new SSOperationFakePayRes(); res.Ret = success ? 0 : -1; res.Id = req.Id; res.Data = req.Data; res.Uid = req.Uid; GameServerUtils.GetPacketSender().SendToWorldServer((int)SSGameMsgID.OperationFakepayRes, ref res, req.Uid); } } }