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.
 
 
 
 
 
 

440 lines
18 KiB

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<SSPayGoogleReq>();
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<SSPayGoogleRes>();
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<SSPayGoogleRes>(player.worldSvrId, packet);
}
}
// 成功支付触发的PayGoogleSuccRes
private void OnPayGoogleSuccRes(uint remoteAppID, StructPacket packet)
{
ref var res = ref packet.GetMessage<SSPayGoogleSuccessRes>();
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<SSPayGoogleSuccessRes>(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<SSPayDBAddDiamondStatusReq>(dbServerID, packet);
}
private void OnDBAddDiamondStatusRes(uint remoteAppID, StructPacket packet)
{
var player = HttpProxyPayServerUtils.GetPlayerTableOp().GetPlayer(packet.ObjectID);
if (player != null)
{
HttpProxyPayServerUtils.GetPacketSender().SendToServerByID<SSPayDBAddDiamondStatusRes>(player.worldSvrId, packet);
}
}
private void OnQueryPayGoogleSuccOrder(uint remoteAppID, StructPacket packet)
{
ref var req = ref packet.GetMessage<SSQueryPayGoogleSuccOrder>();
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<SSQueryPayGoogleSuccOrder>(dbServerID, packet);
}
private void OnGMTestHeroPaySucc(uint remoteAppID, StructPacket packet)
{
ref var testReq = ref packet.GetMessage<SSGMTestHeroPaySucc>();
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<SSPaySendDBRefundRes>();
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<SSPayAddPlayerItemNotify>();
HeroUSDKSvc.OnPayAddItemNotify(ref notify);
}
private void OnSaveHttpContentRes(uint remoteAppID, StructPacket packet)
{
ref var res = ref packet.GetMessage<SSPayHeroSaveHttpContentRes>();
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<SSPayHeroSelectHttpContentRes>();
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<SSPayGoogleSuccessReq>();
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<CSWXJSPayReq>();
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);
}
}
}