You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1054 lines
40 KiB
1054 lines
40 KiB
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<TypeIDValueString>();
|
|
}
|
|
|
|
var list = new List<TypeIDValueString>();
|
|
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<int> 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<int>();
|
|
}
|
|
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<SSPayGoogleSuccessRes> parser = new StructMessageParser<SSPayGoogleSuccessRes>();
|
|
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;
|
|
}
|
|
|
|
}
|
|
}
|
|
|