using System.Net.Http.Headers; using System; using System.Collections.Generic; using System.Linq; using Sog; using ProtoCSStruct; using Sog.Log; namespace Game { public static class PayCommSvc { // 注意: 所有的首次/第一次的限定条件, 不能和其他条件组合, 除非策划保证首次条件一定在最后满足, 否则可能会失败!!!!!! // 例如: 首次10连抽获得2张紫卡, 同时vip等级超过5级, 可能满足首次条件时, vip等级不满足 // 等vip等级满足时, 首次条件已经不可能再达成, 从而导致无法触发 //enum PayLimitEvent //{ // PlayerBorn = 1, // VipLevel = 2, // PlayerLevel = 3, // SystemFuncId = 4, // MainlineFail3BeforeChapter6 = 5, // 主线前6章连续失败3次 // EquipIntensify = 6, // 装备强化次数 // CommDraw = 7, // 高抽 // RaceDraw = 8, // 定向抽 // UpPoolDraw = 9, // 限定抽 // FirstPGRelease = 10, // 共鸣水晶首次卸下英雄 // First2PurpleDraw10 = 11, // 首次一次10连抽获得2张紫卡 // FirstDrawRealPurpleCard = 12, // 首次抽到紫卡, 即获得第4张紫卡, 前3张是固定送的不算 // FirstUseItemAddHero45 = 13, // 首次兑换RaceType为4或5的英雄 // MainlandFinish = 14, // RealmOpen = 15, // 开服 // GetEquipRed = 16, // 获得红色装备 // HeroWeaponUnlock = 17, // 专武解锁 //} public static readonly string FreeGiftPack = "FreeGiftPack"; public static readonly int MaxPayMoneyValidTime = 7 * 86400; // 月卡叠加购买限制时间 public static readonly int MonthlyCardLimitDays = 30; // 月卡有效时长 public static readonly int MonthlyCardValidTime = 30 * 86400; public static readonly int WeeklyCardLimitDays = 7; public static readonly int WeeklyCardValidTime = 7 * 86400; public static readonly int WeekSec = 7 * 86400; public static readonly string MonthlyCardDailyMailTitle = "#Mail36"; public static readonly string MonthlyCardDailyMailContent = "#Mail37"; // 周卡领取邮件的内容暂时和月卡一致 public static readonly string WeeklyCardDailyMailTitle = "#Mail36"; public static readonly string WeeklyCardDailyMailContent = "#Mail37"; public static readonly string VipWeeklyMailTitle = "#Mail40"; public static readonly string VipWeeklyMailContent = "#Mail41"; public static readonly string[] PrepayItemMailTitle = { "#Mail51", "#Mail54" }; public static readonly string[] PrepayItemMailContent = { "#Mail52", "#Mail_103" }; public static void OnPlayerOnline(PlayerOnGame player) { player.Trace("PayCommSvc.OnPlayerOnline player {0} ", player.UserID); int nowSec = (int)GameServerUtils.GetTimeSecond(); // 先更新玩家身上的支付数据, 如果其他逻辑依赖最新的支付数据, 那么不要把代码写在该函数前面 UpdatePlayerPayRecord(player, nowSec, false); AddNewItemOnPlayerOnline(player); //CheckSendMonthlyCardDailyReward(player, nowSec); //CheckSendVipWeeklyReward(player, nowSec); // 每次上线清掉失败次数, 开始尝试加钱 for (int i = 0; i < player.RoleData.PayData.PaySuccWaitAddRole.Count; i++) { player.RoleData.PayData.PaySuccWaitAddRole[i].DbResFailCount = 0; // 平滑一下时间 player.RoleData.PayData.PaySuccWaitAddRole[i].LastSendDBTime = nowSec + i; } // 华为等着客户端发起补单流程, 因为DB没有保存inAppPurchaseData if (player.AccountInfo.AccountType != (int)AccountType.AccountType_Huawei) { var query = new SSQueryPayGoogleSuccOrder { Uid = player.UserID }; GameServerUtils.GetPacketSender().SendToWorldServer((int)SSGameMsgID.QueryPayGoogleSuccOrder, ref query, player.UserID); } } public static void OnNewDayStart(PlayerOnGame player, bool notifyClient) { player.Trace("PayCommSvc.OnNewDayStart player {0} ", player.UserID); int nowSec = (int)GameServerUtils.GetTimeSecond(); // 先更新玩家身上的支付数据, 如果其他逻辑依赖最新的支付数据, 那么不要把代码写在该函数前面 UpdatePlayerPayRecord(player, nowSec, notifyClient); AddNewItemOnPlayerOnline(player); } public static void OnPlayerLevelUp(PlayerOnGame player) { } public static void OnVipLevelUp(PlayerOnGame player) { UpdateVipWeeklyRewardStartTime(player); } // 统计数据变化 public static void OnTotalStatisticsChanged(PlayerOnGame player, int statId, long newVal, long chgVal) { //if (statId == (int) CSRoleStatisticsID.EquipIntensifyNum) //{ // CheckNewItemOnEvent(player, PayLimitEvent.EquipIntensify, (int) newVal, 0); //} } public static void OnAddHero(PlayerOnGame player, int descId, int star, string reason) { } private static void UpdateVipWeeklyRewardStartTime(PlayerOnGame player) { if (player.RoleData.PayData.StartVipWeeklyRewardTime > 0) { return; } // 升级到满足vip周奖励的时间 int rewardLv = 0;//CommParamDescMgr.Instance.GetConfig((int)CommParamKey.VipWeeklyRewardLevel).int_val; if (player.RoleBase.VipLevel < rewardLv) { return; } var configRealm = GameServerUtils.GetGameServerData().m_configRealm; var realmBrief = configRealm.FirstOrDefault(r => r.realmId == player.RealmID); if (realmBrief == null || realmBrief.openTime == 0) { return; } long startTime = AppTime.GetTodayStartTime(realmBrief.openTime); long week = (GameServerUtils.GetTimeSecond() - startTime) / WeekSec; player.RoleData.PayData.StartVipWeeklyRewardTime = (int)(startTime + week * WeekSec); player.Debug("PayCommSvc.UpdateVipWeeklyRewardStartTime player {0} week {1} start time {2}" , player.UserID, week, player.RoleData.PayData.StartVipWeeklyRewardTime); } // public static void DeleteItemData(PlayerOnGame player, PayLimitEvent limitEvent,int value) // { // //删除指定 // for (int i = player.RoleData.PayData.PayItemRecord.Count - 1; i >= 0 ; i--) // { // ref var record = ref player.RoleData.PayData.PayItemRecord[i]; // PayDiamondDesc desc = PayCommSvc.GetPayDiamondDesc(record.ItemId); // if (desc != null && desc.timeLimitType == (int)limitEvent) // { // if (desc.vipCardType <= 0 || PlayerPayUtil.GetMonthlyCardRemainDays(player, (VipCardType)desc.vipCardType) <= 0) // { // player.RoleData.PayData.PayItemRecord.RemoveAt(i); // } // } // } // } private static void CheckNewItemOnEvent(PlayerOnGame player, PayLimitEvent limitEvent, int value, int value2,int timeLimitParam2 = 0) { foreach (PayDiamondDesc desc in PayDiamondDescMgr.Instance.ItemTable.Values) { // 特殊条件, 限时商品, 通行证, 在满足条件时需要记录额外的数据, 并通知客户端 // 如果不是这几类商品, 客户端会判断是否显示在商城中 if (! CheckEventCond(player, desc, limitEvent, value, value2)) { continue; } NewItemArrival(player, desc, (int)limitEvent); } } // PayLimitEvent发生时检查是否满足配置要求 private static bool CheckEventCond(PlayerOnGame player, PayDiamondDesc desc, PayLimitEvent limitEvent, int value, int value2) { switch (limitEvent) { default: TraceLog.Error("PayCommSvc.CheckEventCond uid {0} {1} not hanle", player.UserID, limitEvent); break; } return false; } // 月卡/周卡属于时长类卡, 保存在RoleData.PayData.MonthlyCard public static bool IsTimeCard(int type) { return IsMonthlyCard(type); } public static bool IsMonthlyCard(int cardId) { var desc = MonthlyCardDescMgr.Instance.GetConfig(cardId); return desc != null; } public static bool IsOneClickDailyPack(int itemId) { var desc = PayDiamondDescMgr.Instance.GetConfig(itemId); return desc is { goodsType: PayGoodsType.DailyPack, itemID: PayDiamondId.DailyPack4 }; } public static int[] SubDailyPackIds() { return new[] { PayDiamondId.DailyPack1, PayDiamondId.DailyPack2, PayDiamondId.DailyPack3 }; } public static long GetBuyOneClickDailyPackDiamond(PlayerOnGame player, int itemId) { if (!IsOneClickDailyPack(itemId)) { return 0; } var ret = 0L; var list = SubDailyPackIds(); for (int i = 0; i < list.Length; i++) { var add = false; var tempDesc = PayDiamondDescMgr.Instance.GetConfig(list[i]); for (int j = 0; j < player.RoleData.PayData.PayItemRecord.Count; j++) { var record = player.RoleData.PayData.PayItemRecord[j]; if (list[i] == record.ItemId) { if (record.PayCountToday > 0) { add = true; continue; } //今天购买了总礼包就不能购买子礼包了 ret += tempDesc.diamond; add = true; } } if (!add) { ret += tempDesc.diamond; } } return ret; } public static TypeIDValueString[] GetBuyOneClickDailyPackGiveItem(PlayerOnGame player, int itemId) { if (!IsOneClickDailyPack(itemId)) { return Array.Empty(); } var list = new List(); var listIds = SubDailyPackIds(); for (int i = 0; i < listIds.Length; i++) { var add = false; var tempDesc = PayDiamondDescMgr.Instance.GetConfig(listIds[i]); //今天购买了总礼包就不能购买子礼包了 for (int j = 0; j < player.RoleData.PayData.PayItemRecord.Count; j++) { var record = player.RoleData.PayData.PayItemRecord[j]; if (listIds[i] == record.ItemId) { if (record.PayCountToday > 0) { add = true;//今天购买了总礼包就不能购买子礼包了 continue; } var giveItem = tempDesc.giveItem; foreach (var give in giveItem) { GenericUtils.Merge(list, give.type,give.id, give.count); } add = true; break; } } if (!add) { var giveItem = tempDesc.giveItem; foreach (var give in giveItem) { GenericUtils.Merge(list, give.type,give.id, give.count); } } } return list.ToArray(); } // 新品上架, 是否上架的逻辑应该在调用此接口之前完成 private static void NewItemArrival(PlayerOnGame player, PayDiamondDesc desc, int triggerEvent) { player.Trace("PayCommSvc.NewItemArrival uid {0} itemId {1}", player.UserID, desc.itemID); // 特殊条件, 或者限时Item, 增加一条PaySuccRecord记录 if ( PlayerPayUtil.GetPaySuccessRecordIndex(player, desc.itemID) == -1) { PlayerPayUtil.AddPaySuccRecordIfNotExist(player, desc); PlayerNotify.NotifyPlayerPayDataChange(player); var notify = new CSPayNewItemNotify(); notify.ItemID = desc.itemID; notify.TriggerEvent = triggerEvent; player.SendToClient((int) CSGameMsgID.PayNewItemNotify, ref notify); } } public static PayDiamondDesc GetPayDiamondDesc(int itemid) { // 目前商城策划只配置了一种支付类型的商品 return PayDiamondDescMgr.Instance.GetConfig(itemid); } public static int CheckPayLimit(PlayerOnGame player, PayDiamondDesc desc,PayLimitEvent excludeType = 0) { if (desc == null) { player.Error("PayCommSvc.CheckPayLimit uid {0} desc is null", player.UserID); return -1; } if (desc.vipCardType > 0) { // 月卡/周卡 if (IsTimeCard(desc.vipCardType)) { int remainDays = PlayerPayUtil.GetMonthlyCardRemainDays(player, desc.vipCardType); int limitDays = GetMonthlyCardLimitDay((VipCardType) desc.vipCardType); if (remainDays > limitDays) { player.Trace("PayCommSvc.CheckPayLimit uid {0} MonthlyCard {1} remainDays {2} should <= {3}" , player.UserID, desc.vipCardType, remainDays, limitDays); return -1; } // 数据不够存储了 int idx = PlayerPayUtil.GetMonthlyCardDataIndex(player, desc.vipCardType); if (idx == -1 && player.RoleData.PayData.MonthlyCard.Count >= player.RoleData.PayData.MonthlyCard.GetMaxCount()) { player.Error("PayCommSvc.CheckPayLimit uid {0} MonthlyCard {1} not enough Length" , player.UserID, desc.vipCardType); return -1; } } } { int recordIndex = PlayerPayUtil.GetPaySuccessRecordIndex(player, desc.itemID); if (recordIndex != -1) { ref DBRolePayItemRecord record = ref PlayerPayUtil.GetPayItemRecordByIndex(player, recordIndex); // 有效支付时间 if (record.EndTime > 0 && (int)GameServerUtils.GetTimeSecond() >= record.EndTime) { player.Error("PayCommSvc.CheckPayLimit uid {0} payItem {1} endTime {2} not valid pay time" , player.UserID, desc.itemID, record.EndTime); return (int)CSErrCode.PayItemNotValid; } } // 校验特殊限制条件 if (desc.timeLimitType > 0 && desc.timeLimitType != (int)excludeType && !CheckPayTimeLimit(player, desc)) { player.Error("PayCommSvc.CheckPayLimit itemId {0} timeLimitType {1} check failed" , desc.itemID, desc.timeLimitType); return (int)CSErrCode.PayItemNotValid; } //总购买次数限制 if (CheckPayTimesLimit(player, desc)) { player.Error("PayCommSvc.CheckPayLimit itemId {0} timeLimitType {1} buy count limit check failed" , desc.itemID, desc.timeLimitType); return (int)CSErrCode.PayItemNotValid; } //今日购买次数限制 if (CheckPayTimesDailyLimit(player, desc)) { player.Error( "PayCommSvc.CheckPayLimit itemId {0} timeLimitType {1} day buy count limit check failed" , desc.itemID, desc.timeLimitType); return (int)CSErrCode.PayItemNotValid; } } // 指定时间之后充值1笔后可免费领取的礼包 if (CheckValidFixedPayTime(desc) != 0) { return (int)CSErrCode.PayInvalidTime; } //章节礼包 if (desc.goodsType == PayGoodsType.ChapterPack && desc.chapterCondition.Length == 2) { var chapterId = desc.chapterCondition[0]; var battleId = desc.chapterCondition[1]; if (chapterId > player.RoleData.ChapterData.ChapterId) { return (int)CSErrCode.PayItemNotValid; } if (battleId > player.RoleData.ChapterData.BattleId) { return (int)CSErrCode.PayItemNotValid; } } if (desc.goodsType == PayGoodsType.DailyPack) { var subDailyPackIds = SubDailyPackIds(); if (subDailyPackIds.Contains(desc.itemID))//购买的是子礼包 { for (int i = 0; i < player.RoleData.PayData.PayItemRecord.Count; i++) { var record = player.RoleData.PayData.PayItemRecord[i]; var tempDesc = PayDiamondDescMgr.Instance.GetConfig(record.ItemId);//今天购买了总礼包就不能购买子礼包了 if (IsOneClickDailyPack(tempDesc.itemID) && record.PayCountToday > 0) { return (int)CSErrCode.PayItemNotValid; } } } else //子礼包都购买玩了,就不能购买总礼包了 { var ret = true; foreach (var dailyPackId in subDailyPackIds) { var index = -1; for (int i = 0; i < player.RoleData.PayData.PayItemRecord.Count; i++) { var record = player.RoleData.PayData.PayItemRecord[i]; if (record.ItemId == dailyPackId&& record.PayCountToday>0) { index = i; break; } } ret = ret && index != -1; } if (ret) { return (int)CSErrCode.PayItemNotValid; } } } return 0; } // 根据PayDiamondDesc中的timeLimitType字段, 检查玩家是否满足条件 private static bool CheckPayTimeLimit(PlayerOnGame player, PayDiamondDesc desc) { switch ((PayLimitEvent)desc.timeLimitType) { case PayLimitEvent.None: return true; case PayLimitEvent.PopGift: return PopPackageSvc.IsPopPackageEffective(player, desc.popUpPackageType); case PayLimitEvent.ActivityGift: { var state = ActivitySvc.GetActivityState(player, desc.activityId); return state == ActivityState.InProgress; } } return false; } private static bool CheckPayTimesLimit(PlayerOnGame player, PayDiamondDesc desc) { if (desc.buyCountLimit <= 0) { return false; } ref var record = ref player.RoleData.PayData.PayItemRecord; for (int i = 0; i < record.Count; i++) { if (record[i].ItemId == desc.itemID) { return record[i].PaySuccessCount >= desc.buyCountLimit; } } return false; } private static bool CheckPayTimesDailyLimit(PlayerOnGame player, PayDiamondDesc desc) { // 总购买次数限制判断 if (desc.dailyLimit > 0) { ref var record = ref player.RoleData.PayData.PayItemRecord; for (int i = 0; i < record.Count; i++) { if (record[i].ItemId == desc.itemID) { return record[i].PayCountToday >= desc.dailyLimit; } } } return false; } public static int CheckValidFixedPayTime(PayDiamondDesc desc) { //配置的静态时间段限制 long startTime = desc.startTimeInt; long endTime = desc.endTimeInt; long nowSec = GameServerUtils.GetTimeSecond(); if ((startTime > 0 && nowSec < startTime) || (endTime > 0 && nowSec > endTime)) { TraceLog.Trace("PayCommSvc.CheckValidFixedPayTime item {0} can not pay, need startTime {1} endTime {2}" , desc.itemID, startTime, endTime); return (int)CSErrCode.PayInvalidTime; } return 0; } // 角色创建后多少天, 商品可以购买, 如果需要限制购买时间, 填写validTime private static bool CheckPlayerBornEvent(PlayerOnGame player, PayDiamondDesc desc) { long startTime = AppTime.GetTodayStartTime(player.RoleBase.CreateTime) + (desc.timeLimitParam - 1) * 86400; long endTime = 0; player.Trace("PayCommSvc.CheckPlayerBornEvent uid {0} payItem {1} start {2} end {3}" , player.UserID, desc.itemID, startTime, endTime); long nowSec = GameServerUtils.GetTimeSecond(); return startTime <= nowSec && (endTime == 0 || nowSec < endTime); } // 开服多少天后, 商品可以购买, 如果需要限制购买时间, 填写validTime private static bool CheckRealmOpenEvent(PlayerOnGame player, PayDiamondDesc desc) { var realm = GameServerUtils.GetGameServerData().m_configRealm.FirstOrDefault(r => r.realmId == player.RealmID); if (realm == null || realm.openTime <= 0) { return false; } long startTime = AppTime.GetTodayStartTime(realm.openTime) + (desc.timeLimitParam - 1) * 86400; long endTime = 0; player.Trace("PayCommSvc.CheckRealmOpenEvent uid {0} item {1} start {2} end {3}" , player.UserID, desc.itemID, startTime, endTime); long nowSec = GameServerUtils.GetTimeSecond(); return startTime <= nowSec && (endTime == 0 || nowSec < endTime); } public static void OnTick(PlayerOnGame player, long nowSecond) { // 对于没有收到DB回应的订单, 再次发起修改成状态2的请求 for (int i = 0; i < player.RoleData.PayData.PaySuccWaitAddRole.Count; i++) { ref var addData = ref player.RoleData.PayData.PaySuccWaitAddRole[i]; // 订单发货成功, 无需处理, 等待超时后删除 if (addData.AddItemSuccTime > 0) { continue; } // 每次上线每笔订单尝试3次, 如果失败就等下次上线再尝试 if (addData.DbResFailCount >= 3) { continue; } // 每隔5秒尝试一次修改DB订单状态 if ((int)nowSecond >= addData.LastSendDBTime + 5) { addData.LastSendDBTime = (int)nowSecond; var addReq = new SSPayDBAddDiamondStatusReq { Uid = player.UserID, AmountExchange = addData.AmountExchange, DiamondExchange = addData.DiamondExchange, Money = addData.Money, }; addReq.OrderId.SetString(addData.OrderId.GetPtr()); if (addData.IsReplaceItem) { addReq.ReplaceItemId = addData.ItemID; } GameServerUtils.GetPacketSender().SendToWorldServer( (int)SSGameMsgID.PayDbAddDiamondStatusReq, ref addReq, player.UserID); } } } public static void UpdatePlayerPayRecord(PlayerOnGame player, int nowSec, bool notifyClient) { bool changed = false; List deleteList = null; for (int i = 0; i < player.RoleData.PayData.PayItemRecord.Count; i++) { ref var record = ref player.RoleData.PayData.PayItemRecord[i]; // 版本号变化, 代表物品配置变了 var desc = GetPayDiamondDesc(record.ItemId); if (desc == null) { if (deleteList == null) { deleteList = new List(); } deleteList.Add(record.ItemId); changed = true; continue; } // 每天刷新一次购买次数限制 if (AppTime.IsSameDay(nowSec, record.LastUpdateRecordTime)) { continue; } if (record.PayCountToday != 0) { player.Trace("PayCommSvc.UpdatePlayerPayRecord uid {0} itemId {1} PayCountToday {2} reset to 0" , player.UserID, record.ItemId, record.PayCountToday); record.PayCountToday = 0; } if (!AppTime.IsSameWeek127(nowSec, record.LastUpdateRecordTime)) { player.Trace("PayCommSvc.UpdatePlayerPayRecord uid {0} itemId {1} PayCountWeek {2} reset to 0" , player.UserID, record.ItemId, record.PayCountWeek); record.PayCountWeek = 0; } if (record.PayCountMonth != 0 && !AppTime.IsSameMonth(nowSec, record.LastUpdateRecordTime)) { player.Trace("PayCommSvc.UpdatePlayerPayRecord uid {0} itemId {1} PayCountMonth {2} reset to 0" , player.UserID, record.ItemId, record.PayCountMonth); record.PayCountMonth = 0; } //清理玩家每日购买钻石数 player.RoleData.PayData.TodayPayDiamond = 0; record.LastUpdateRecordTime = nowSec; changed = true; } // 商城物品被删除了 if (deleteList != null) { for (int i = 0; i < deleteList.Count; i++) { for (int j = 0; j < player.RoleData.PayData.PayItemRecord.Count; j++) { if (deleteList[i] == player.RoleData.PayData.PayItemRecord[j].ItemId) { player.Debug("PayCommSvc.UpdatePlayerPayRecord uid {0} delete itemId {1}", player.UserID, deleteList[i]); player.RoleData.PayData.PayItemRecord.RemoveAt(j); break; } } } } // 更新最近7天内单笔最大购买金额列表 int dayGap = AppTime.GetDayElapse(nowSec, player.RoleData.PayData.LastUpdateMaxPayMoneyTime); if (dayGap >= 7) { // 距离上次更新超过7天 player.RoleData.PayData.MaxPayMoneyLast7Days.Clear(); for (int i = 0; i < 7; i++) { player.RoleData.PayData.MaxPayMoneyLast7Days.Add(0); } player.RoleData.PayData.LastUpdateMaxPayMoneyTime = nowSec; changed = true; } else if (dayGap > 0) // 1 <= dayGap <= 6 { // 有效值后移 int tail = 7 - dayGap - 1; for (int i = tail; i >= 0; i--) { player.RoleData.PayData.MaxPayMoneyLast7Days[i + dayGap] = player.RoleData.PayData.MaxPayMoneyLast7Days[i]; } // 前面补0 for (int i = 0; i < dayGap; i++) { player.RoleData.PayData.MaxPayMoneyLast7Days[i] = 0; } player.RoleData.PayData.LastUpdateMaxPayMoneyTime = nowSec; changed = true; } bool isMonthlyCardChange = false; // 更新月卡数据 for (int i = player.RoleData.PayData.MonthlyCard.Count - 1; i >= 0; i--) { ref var cardData = ref player.RoleData.PayData.MonthlyCard[i]; if (nowSec >= cardData.ExpireTime && cardData.ExpireTime>0)//第二个条件是为了永远不删除永久卡 { player.Debug("PayCommSvc.UpdatePlayerPayRecord uid {0} delete monthly card {1}" , player.UserID, cardData.CardId); player.RoleData.PayData.MonthlyCard[i].IsTimeOutCard = true; changed = true; isMonthlyCardChange = true; //GameServerUtils.GetEventHandlerMgr().TriggerMonthCartTimeOut(player, 0); } else { player.RoleData.PayData.MonthlyCard[i].IsTimeOutCard = false; } } PlayerPayUtil.DeletePaySuccWaitAddRole(player); if (changed) { player.MakeDirty(); if (notifyClient) { PlayerNotify.NotifyPlayerPayDataChange(player); } } //检查一遍有激活下一个礼包的 if (isMonthlyCardChange) { MonthlyCardSvc.SyncInfo(player); } } public static int GetMonthlyCardLimitDay(VipCardType cardType) { var desc = MonthlyCardDescMgr.Instance.GetConfig((int)cardType); return desc?.duration ?? 0; } // 上线时检查是否有新的可购买商品需要通知客户端 public static void AddNewItemOnPlayerOnline(PlayerOnGame player) { foreach (PayDiamondDesc desc in PayDiamondDescMgr.Instance.ItemTable.Values) { // 特殊条件, 限时商品, 通行证, 在满足条件时需要记录额外的数据, 并通知客户端 // 如果不是这几类商品, 客户端会判断是否显示在商城中 if (desc.timeLimitType > 0 ) { PlayerPayUtil.AddPaySuccRecordIfNotExist(player, desc); } } PlayerNotify.NotifyPlayerPayDataChange(player); } // 英雄支付, 子类型3~10是台湾mycard支付, 支付金额由用户控制, 不一定等于商品金额, 需要特殊逻辑处理 public static bool IsMycardPay(int heroPaySubType) { return 3 <= heroPaySubType && heroPaySubType <= 10; } public static string GetPaymentId(int itemId) { var desc = PayDiamondDescMgr.Instance.GetConfig(itemId); if (desc != null) { return GetPaymentId(desc); } return null; } public static string GetPaymentId(PayDiamondDesc desc) { if (!string.IsNullOrEmpty(desc.productID)) { return desc.productID; } return null; } //代币支付 public static int TokenPay(PlayerOnGame player, CSPayGoogleReq payReq, SSPayGoogleReq ssReq) { var desc = PayDiamondDescMgr.Instance.GetConfig(payReq.ItemID); 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 (token < needTokenNum) { return (int)CSErrCode.Fail; } GameServerUtils.GetGameServerData().m_packetHandlerTable.TryGetValue((int)SSGameMsgID.PayGoogleSuccessRes, out var handler); PayHandler payHandler = handler as PayHandler; if (payHandler == null) { return (int)CSErrCode.Fail; } StructPacket packet = new StructPacket(); packet.Header.Type = (int)SSGameMsgID.PayGoogleSuccessRes; StructMessageParser parser = new StructMessageParser(); packet.Parser = parser; long payTime = GameServerUtils.GetTimeSecond(); var paymentId = GetPaymentId(desc); string orderId = PayUtils.GenOrderIdForUser(player.UserID, GameServerUtils.GetApp().ServerID, desc.itemID, payReq.Param1, payReq.Param2, paymentId, payTime); PayType payType = PlayerPayUtil.GetPlayerPayType(player); ref SSPayGoogleSuccessRes req = ref parser.GetMessage(); req.Uid = player.UserID; req.OrderId.SetString(orderId); req.Currency.SetString(""+desc.currencyId); req.PayType = (uint)payType; req.PayParam1 = payReq.Param1; req.PayParam2 = payReq.Param2; req.ItemID = desc.itemID; req.Amount = needTokenNum; req.OrderId3rd.SetString("tokenpay_" + orderId); req.PayChannel = payReq.PayChannel; req.Ret = 0; req.Status = 1; var ret = payHandler.CheckCostPayItem(player, desc, orderId, false); if (ret != 0) { return ret; } ret = payHandler.ProcessPayGoogleSuccessRes(GameServerUtils.GetAppID(), packet); if (ret < 0) { return ret; } var ssDBAddRes = new SSPayDBAddDiamondStatusRes { Uid = player.UserID, Diamond = desc.diamond, Status = 2, PayChannel = payReq.PayChannel, }; ssDBAddRes.Ret = 0; for (int i = 0; i < ssReq.SelectItems.Count; i++) { var t = ssReq.SelectItems[i]; ssDBAddRes.SelectItems.Add(t.Item); } ssDBAddRes.OrderId.SetString(orderId); payHandler.OnDBAddDiamondStatusRes(player.UserID, ref ssDBAddRes, false); var res = new CSPayGoogleRes(); res.OrderId.SetString(orderId); res.Uid = player.UserID; res.PayChannel = payReq.PayChannel; res.ItemID = payReq.ItemID; res.OrderId.SetString(orderId); res.JsApiPay = payReq.JsApiPay; res.PaymentId.SetString(paymentId); res.SelectItems.CopyFrom(ref payReq.SelectItems); player.SendToClient((int)CSGameMsgID.PayGoogleRes, ref res); return (int)CSErrCode.None; } //伪造支付 public static int FakePay(long uid, int itemId, int payParam1 = 0, int payParam2 = 0) { // 打错误日志避免被冲掉 TraceLog.Error("GmCmdSvc.FakePay uid {0}", uid); PlayerOnGame player = GameServerUtils.GetPlayerTableOp().GetPlayerByUid(uid); if (player == null) { TraceLog.Error("GmCmdSvc.FakePay uid {0} no player", uid); return -1; } if (itemId == 0) { TraceLog.Error("GmCmdSvc.FakePay no itemId"); return -1; } PayType payType = PlayerPayUtil.GetPlayerPayType(player); PayDiamondDesc desc = PayCommSvc.GetPayDiamondDesc(itemId); if (desc == null) { player.Error("GmCmdSvc.FakePay uid {0} invalid itemId {1}", uid, itemId); return -1; } var paymentId = PayCommSvc.GetPaymentId(desc); if (paymentId == null) { player.Error("GmCmdSvc.FakePay item {0} currency {1} money {2} no paymentId" , desc.itemID, desc.currencyId, desc.currencyRes); return -1; } var iRet = PayCommSvc.CheckPayLimit(player, desc); if (iRet != 0) { return iRet; } // 记录物品购买信息 int recordIndex = PlayerPayUtil.AddPaySuccRecordIfNotExist(player, desc); if (recordIndex == -1) { TraceLog.Error("GmCmdSvc.FakePay uid {0} itemId {1} add pay record failed" , player.UserID, desc.itemID); return -1; } // 生成订单号 long payTime = GameServerUtils.GetTimeSecond(); string orderId = PayUtils.GenOrderIdForUser(player.UserID, GameServerUtils.GetApp().ServerID, desc.itemID, payParam1, payParam2, paymentId, payTime); GameServerUtils.GetGameServerData().m_packetHandlerTable.TryGetValue((int)SSGameMsgID.PayGoogleSuccessRes, out var handler); PayHandler payHandler = handler as PayHandler; if (payHandler == null) { TraceLog.Error("GmCmdSvc.FakePay get PayHandler failed"); return -1; } // 伪造支付成功请求, 插入待添加列表 var ssPaySuccRes = new SSPayGoogleSuccessRes { Uid = uid, PayType = (uint)payType, Status = 1, PayParam1 = payParam1, PayParam2 = payParam2, PayTime3rd = payTime, Amount = desc.currencyRes, }; ssPaySuccRes.ItemID = itemId; ssPaySuccRes.OrderId.SetString(orderId); ssPaySuccRes.OrderId3rd.SetString("fakepay_" + orderId); ssPaySuccRes.Currency.SetString("USD"); ref DBRolePayItemRecord record = ref PlayerPayUtil.GetPayItemRecordByIndex(player, recordIndex); int idx = payHandler.InsertPaySuccWaitAddRole(player, desc, ref ssPaySuccRes, ref record, 0, 0, false); if (idx == -1) { return -1; } ref DBPaySuccWaitAddRole addData = ref player.RoleData.PayData.PaySuccWaitAddRole[idx]; // 已经添加成功, 无需再处理 if (addData.AddItemSuccTime > 0) { TraceLog.Error("GmCmdSvc.FakePay uid {0} orderId {1} already add succ {2}", uid, orderId, addData.AddItemSuccTime); return -1; } // 伪造修改DB状态成功请求 var ssDBAddRes = new SSPayDBAddDiamondStatusRes { Uid = uid, Diamond = desc.diamond, Status = 2 }; ssDBAddRes.OrderId.SetString(orderId); payHandler.OnDBAddDiamondStatusRes(uid, ref ssDBAddRes, false); GameBillLogUtils.LogFakePay(ref addData, 0, addData.IsPlayerFirstPay, player); return 0; } } }