using System; using System.Text; using Sog; using Sog.Service; using ProtoCSStruct; using System.Text.Json; using System.Web; using System.Text.Json.Nodes; using LitJson; using System.Collections.Generic; using System.Net.Http; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Security; using System.Security.Cryptography; using Org.BouncyCastle.Crypto; using System.IO; using Org.BouncyCastle.OpenSsl; using Org.BouncyCastle.Utilities.Encoders; using System.Runtime.InteropServices; using System.Security; using static System.Net.Mime.MediaTypeNames; using System.Security.Cryptography.X509Certificates; using System.Linq; using Org.BouncyCastle.Asn1.Ocsp; using World; namespace HttpProxyPay { public class HttpProxyPayMsgHandler : BaseReloadableService { private ServerApp m_app; public override int GetServiceType() { return HttpProxyPayServiceType.HttpProxyMsgHandler; } //销毁的时候置空 public override void Dispose() { m_app = null; } public HttpProxyPayMsgHandler(ServerApp app) { m_app = app; } public ServerApp GetApp() { return m_app; } public void HandlerMessage(uint remoteAppID, MessageData message) { StructPacket packet; bool bSuccess = HttpProxyPayServerUtils.GetProtoPacker().UnpackMessage(message, out packet); if(bSuccess == false) { TraceLog.Error("HttpProxyPayMsgHandler.HandlerMessage ,unpack msg failed {0}, remoteAppID {1}" , message.Header.Type, remoteAppID); return; } //消息多线程处理,这里需要clone一个才行 packet = packet.Clone(); //预先判断,提高效率 if (TraceLog.GetLogLevel() <= Sog.Log.LogLevel.TraceDetail && TraceLog.IsSkipLogMsgID(packet.MsgID) == false) { TraceLog.TraceDetail("HttpProxyPayMsgHandler.HandlerMessage recv message from server {0}, message type {1} length {2} : {3}->{4}" , ServerIDUtils.IDToString(remoteAppID) , message.Header.Type , message.Header.Length , packet.MessageName() , packet.ToString()); } switch (packet.MsgID) { //转给db处理 case (int)SSGameMsgID.PayGoogleReq: OnPayGoogleReq(remoteAppID, packet); break; // 请求订单存DB成功, 转给gamesvr继续处理 case (int)SSGameMsgID.PayGoogleRes: OnPayGoogleRes(remoteAppID, packet); break; // 处理客户端发起的支付成功通知, 比如google支付, 华为支付 case (int)SSGameMsgID.PayGoogleSuccessReq: OnPayGoogleSuccReq(remoteAppID, packet); break; // DB支付状态修改为支付成功, 转给gamesvr预备加钱 case (int)SSGameMsgID.PayGoogleSuccessRes: OnPayGoogleSuccRes(remoteAppID, packet); break; // DB支付状态修改为加钻石成功 case (int)SSGameMsgID.PayDbAddDiamondStatusReq: OnDBAddDiamondStatusReq(remoteAppID, packet); break; // DB支付状态修改为已加钱, 转给gamesvr真正加钱 case (int)SSGameMsgID.PayDbAddDiamondStatusRes: OnDBAddDiamondStatusRes(remoteAppID, packet); break; // 玩家上线时会查询所有支付成功但没有加钻石的订单, 并且触发后续加钱操作 case (int)SSGameMsgID.QueryPayGoogleSuccOrder: OnQueryPayGoogleSuccOrder(remoteAppID, packet); break; // gm测试支付 case (int)SSGameMsgID.GmTestHeroPaySucc: OnGMTestHeroPaySucc(remoteAppID, packet); break; // 退款 case (int)SSGameMsgID.PaySendDbRefundRes: OnPaySendDBRefundRes(remoteAppID, packet); break; case (int)SSGameMsgID.PayAddPlayerItemNotify: OnPayAddPlayerItemNotify(remoteAppID, packet); break; case (int)SSGameMsgID.PayHeroSaveHttpContentRes: OnSaveHttpContentRes(remoteAppID, packet); break; case (int)SSGameMsgID.PayHeroSelectHttpContentRes: OnSelectHttpContentRes(remoteAppID, packet); break; case (int)SSGameMsgID.HomeAdSendHttpSyn: OnHomeAdSendHttpSyn(remoteAppID, packet); break; case (int)CSGameMsgID.PayWsjsapiReq: PayWsjsapiReq(remoteAppID, packet); break; default: TraceLog.Error("HttpProxyPayMsgHandler.HandlerMessage unknow MsgID {0}", packet.MsgID); break; } } private void OnPayGoogleReq(uint remoteAppID, StructPacket packet) { var player = HttpProxyPayServerUtils.GetPlayerTableOp().GetPlayer(packet.ObjectID); if (player == null) { player = new PlayerOnPay {uid = packet.ObjectID, worldSvrId = remoteAppID}; HttpProxyPayServerUtils.GetPlayerTableOp().AddPlayer(player); } player.lastPayReqTime = (int) HttpProxyPayServerUtils.GetTimeSecond(); ref var req = ref packet.GetMessage(); string orderId = req.OrderId.GetString(); string[] split = orderId.Split('-'); // uid-time-orderIdSeq-serverId-payitemId-payParam1-payParam2-paymentId if (split.Length != 8) { TraceLog.Error("HttpProxyPayMsgHandler.OnPayGoogleReq invalid orderId {0}, must 8 params", orderId); var res = new SSPayGoogleRes(); res.Ret = -1; res.Uid = req.Uid; res.ItemID = req.ItemID; res.OrderId = req.OrderId; res.Diamond = req.Diamond; res.Money = req.Money; res.GmTestPay = req.GmTestPay; res.PayType = req.PayType; res.PaymentId = req.PaymentId; HttpProxyPayServerUtils.GetPacketSender().SendToServerByID(remoteAppID , (int)SSGameMsgID.PayGoogleRes, ref res, packet.ObjectID); return; } var svrData = HttpProxyPayServerUtils.GetHttpProxyServerData(); req.OrderId.SetString($"{orderId}-{svrData.selfPayId}"); uint dbServerID = DBServerSelect.GetDBServerID(packet.ObjectID); HttpProxyPayServerUtils.GetPacketSender().SendToServerByID(dbServerID , (int)SSGameMsgID.PayGoogleReq, ref req, packet.ObjectID); } private void OnPayGoogleRes(uint remoteAppID, StructPacket packet) { ref var res = ref packet.GetMessage(); TraceLog.Trace("HttpProxyPayMsgHandler.OnPayGoogleRes orderId {0} httpCtx {1} uid {2} ret {3}" , res.OrderId, res.HttpCtxId, res.Uid, res.Ret); // gamesvr发起的PayGoogleReq的HttpCtxId是0 // HttpCtxId != 0表示Hero网页商城发起的下单请求, 需要回复订单号, http应答交给线程去处理 if (res.PayType == (int)PayType.Hero && res.HttpCtxId != 0) { int iTaskIndex = (int)(res.Uid % HttpProxyPayServerUtils.HttpWorkThreadCount); TraceLog.Debug("HttpProxyPayMsgHandler.OnPayGoogleRes uid {0} distribute to task {1}", res.Uid, iTaskIndex); MessageTaskDistributor.Instance.Distribute(remoteAppID, packet, iTaskIndex); return; } //minipay if (res.PayType == (int)PayType.MiniPay) { res.OfferId.SetString(HttpProxyPayServerUtils.GetServerConfig().offerId); res.Appkey.SetString(HttpProxyPayServerUtils.GetServerConfig().appkey); } var player = HttpProxyPayServerUtils.GetPlayerTableOp().GetPlayer(packet.ObjectID); if (player != null) { HttpProxyPayServerUtils.GetPacketSender().SendToServerByID(player.worldSvrId, packet); } } // 成功支付触发的PayGoogleSuccRes private void OnPayGoogleSuccRes(uint remoteAppID, StructPacket packet) { ref var res = ref packet.GetMessage(); TraceLog.Trace("HttpProxyPayMsgHandler.OnPayGoogleSuccRes orderId {0} httpCtx {1} uid {2} ret {3}" , res.OrderId, res.HttpCtxId, res.Uid, res.Ret); var player = HttpProxyPayServerUtils.GetPlayerTableOp().GetPlayer(res.Uid); if (player != null) { HttpProxyPayServerUtils.GetPacketSender().SendToServerByID(player.worldSvrId, packet); } else if (res.Ret == 0 && (res.PayType == (int)PayType.Hero || res.PayType == (int)PayType.MiniPay)) { // 英雄网页商城支付成功时, PaySvr可能没有player缓存, 直接转发到worldsvr去确认player是否在线 int itemId = res.ItemID; var desc = PayDiamondDescMgr.Instance.GetConfig(itemId); if (desc == null) { TraceLog.Error("HttpProxyPayMsgHandler.OnPayGoogleSuccRes {0} no desc", itemId); return; } } // login发起的查询操作触发的PayGoogleSuccRes的HttpCtxId是0 // HttpCtxId != 0表示Hero支付服务器发起的Http回调, 需要回复succ, http应答交给线程去处理 if (res.Ret == 0 && (res.PayType == (int)PayType.Hero || res.PayType == (int)PayType.MiniPay) && res.HttpCtxId != 0) { int iTaskIndex = (int)(res.Uid % HttpProxyPayServerUtils.HttpWorkThreadCount); TraceLog.Debug("HttpProxyPayMsgHandler.OnPayGoogleSuccRes uid {0} distribute to task {1}", res.Uid, iTaskIndex); MessageTaskDistributor.Instance.Distribute(remoteAppID, packet, iTaskIndex); } } private void OnDBAddDiamondStatusReq(uint remoteAppID, StructPacket packet) { var player = HttpProxyPayServerUtils.GetPlayerTableOp().GetPlayer(packet.ObjectID); if (player == null) { player = new PlayerOnPay { uid = packet.ObjectID, worldSvrId = remoteAppID }; HttpProxyPayServerUtils.GetPlayerTableOp().AddPlayer(player); } player.lastPayReqTime = (int)HttpProxyPayServerUtils.GetTimeSecond(); uint dbServerID = DBServerSelect.GetDBServerID(packet.ObjectID); HttpProxyPayServerUtils.GetPacketSender().SendToServerByID(dbServerID, packet); } private void OnDBAddDiamondStatusRes(uint remoteAppID, StructPacket packet) { var player = HttpProxyPayServerUtils.GetPlayerTableOp().GetPlayer(packet.ObjectID); if (player != null) { HttpProxyPayServerUtils.GetPacketSender().SendToServerByID(player.worldSvrId, packet); } } private void OnQueryPayGoogleSuccOrder(uint remoteAppID, StructPacket packet) { ref var req = ref packet.GetMessage(); var player = HttpProxyPayServerUtils.GetPlayerTableOp().GetPlayer(req.Uid); if (player == null) { player = new PlayerOnPay { uid = req.Uid, worldSvrId = remoteAppID }; HttpProxyPayServerUtils.GetPlayerTableOp().AddPlayer(player); } player.lastPayReqTime = (int)HttpProxyPayServerUtils.GetTimeSecond(); uint dbServerID = DBServerSelect.GetDBServerID(req.Uid); HttpProxyPayServerUtils.GetPacketSender().SendToServerByID(dbServerID, packet); } private void OnGMTestHeroPaySucc(uint remoteAppID, StructPacket packet) { ref var testReq = ref packet.GetMessage(); var player = HttpProxyPayServerUtils.GetPlayerTableOp().GetPlayer(testReq.Uid); if (player == null) { player = new PlayerOnPay { uid = testReq.Uid, worldSvrId = remoteAppID }; HttpProxyPayServerUtils.GetPlayerTableOp().AddPlayer(player); } player.lastPayReqTime = (int)HttpProxyPayServerUtils.GetTimeSecond(); var req = new SSPayGoogleSuccessReq { Uid = testReq.Uid, PayType = (uint)testReq.PayType, CheckSuccess3rd = 1 }; req.ItemID = testReq.ItemID; req.PurchaseData.SetString("gm_test_no_data"); req.Signature.SetString("gm_test_no_signature"); req.OrderId.SetString(testReq.OrderId.GetPtr()); req.OrderId3rd.SetString(testReq.OrderId3rd.GetPtr()); req.Amount = (uint)testReq.MoneyUSD; if(testReq.PayType == (int)PayType.Hero) { req.Currency.SetString("USD"); } else if(testReq.PayType == (int)PayType.MiniPay) { req.Currency.SetString("CNY"); } else { req.Currency.SetString("USD"); } req.PayParam1 = testReq.PayParam1; req.PayParam2 = testReq.PayParam2; req.GmTestPay = true; req.PayTime3rd = testReq.PayTime; uint dbServerID = DBServerSelect.GetDBServerID(testReq.Uid); HttpProxyPayServerUtils.GetPacketSender().SendToServerByID(dbServerID, (int)SSGameMsgID.PayGoogleSuccessReq, ref req, req.Uid); } private void OnPaySendDBRefundRes(uint remoteAppID, StructPacket packet) { ref var res = ref packet.GetMessage(); int iTaskIndex = (int)(res.Uid % HttpProxyPayServerUtils.HttpWorkThreadCount); TraceLog.Debug("HttpProxyPayMsgHandler.OnPaySendDBRefundRes uid {0} distribute to task {1}", res.Uid, iTaskIndex); MessageTaskDistributor.Instance.Distribute(remoteAppID, packet, iTaskIndex); } private void OnPayAddPlayerItemNotify(uint remoteAppID, StructPacket packet) { ref var notify = ref packet.GetMessage(); HeroUSDKSvc.OnPayAddItemNotify(ref notify); } private void OnSaveHttpContentRes(uint remoteAppID, StructPacket packet) { ref var res = ref packet.GetMessage(); int iTaskIndex = (int)(res.Http.Uid % HttpProxyPayServerUtils.HttpWorkThreadCount); TraceLog.Debug("HttpProxyPayMsgHandler.OnSaveHttpContentRes uid {0} distribute to task {1}", res.Http.Uid, iTaskIndex); MessageTaskDistributor.Instance.Distribute(remoteAppID, packet, iTaskIndex); } private void OnSelectHttpContentRes(uint remoteAppID, StructPacket packet) { ref var res = ref packet.GetMessage(); if (res.Http.Count > 0) { TraceLog.Debug("HttpProxyPayMsgHandler.OnSelectHttpContentRes distribute to task 0"); // 交给线程1处理, 此条消息频率比较低, 正常情况下不会有太多条记录未提交, http发货通知可以慢慢处理, 只要不卡主线程就好 MessageTaskDistributor.Instance.Distribute(remoteAppID, packet, 0); } } private void OnPayGoogleSuccReq(uint remoteAppID, StructPacket packet) { ref var req = ref packet.GetMessage(); TraceLog.Trace("HttpProxyPayMsgHandler.OnPayGoogleSuccReq uid {0} payType {1}", req.Uid, (PayType)req.PayType); var player = HttpProxyPayServerUtils.GetPlayerTableOp().GetPlayer(packet.ObjectID); if (player == null) { player = new PlayerOnPay { uid = packet.ObjectID, worldSvrId = remoteAppID }; HttpProxyPayServerUtils.GetPlayerTableOp().AddPlayer(player); } player.lastPayReqTime = (int)HttpProxyPayServerUtils.GetTimeSecond(); if (req.PayType == (int)PayType.Google) { GooglePaySvc.OnCltPayGoogleSuccReq(remoteAppID, ref req); } else if (req.PayType == (int)PayType.Huawei) { HuaweiPaySvc.OnCltPayGoogleSuccReq(remoteAppID, packet); } else { TraceLog.Error("HttpProxyPayMsgHandler.OnPayGoogleSuccReq uid {0} invalid payType {1}" , req.Uid, (PayType)req.PayType); } } private void OnHomeAdSendHttpSyn(uint remoteAppID, StructPacket packet) { //添加用户信息 var player = HttpProxyPayServerUtils.GetPlayerTableOp().GetPlayer(packet.ObjectID); if (player == null) { player = new PlayerOnPay { uid = packet.ObjectID, worldSvrId = remoteAppID , lastAdTime = HttpProxyPayServerUtils.GetTimeSecond()}; HttpProxyPayServerUtils.GetPlayerTableOp().AddPlayer(player); } } public static void PayWsjsapiReq(uint remoteAppID, StructPacket packet) { ref var req = ref packet.GetMessage(); int iTaskIndex = (int)(req.Uid % HttpProxyPayServerUtils.HttpWorkThreadCount); ; MessageTaskDistributor.Instance.Distribute(remoteAppID, packet, iTaskIndex); TraceLog.Debug("HttpProxyMsgHandler.PayWsjsapiReq type {0} distribute to task {1}" , req.Uid , iTaskIndex); } } }