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.
 
 
 
 
 
 

431 lines
17 KiB

using System;
using System.Linq;
using System.Text;
using System.Text.Encodings.Web;
using LitJson;
using Sog;
using ProtoCSStruct;
using SimpleHttpServer;
using System.Text.Json;
using System.Web;
using System.Net.Http;
using System.Collections.Generic;
namespace HttpProxyPay
{
public static class MessageTaskHandler
{
public static void HandlerPacket(uint remoteAppID, StructPacket packet)
{
switch (packet.MsgID)
{
case (int)SSGameMsgID.PayGoogleRes:
OnPayGoogleRes(remoteAppID, packet);
break;
case (int)SSGameMsgID.PayGoogleSuccessReq:
OnPayGoogleSuccReq(remoteAppID, packet);
break;
case (int)SSGameMsgID.PayGoogleSuccessRes:
OnPayGoogleSuccRes(remoteAppID, packet);
break;
case (int)SSGameMsgID.PaySendDbRefundRes:
OnPaySendDBRefundRes(remoteAppID, packet);
break;
case (int)SSGameMsgID.PayHeroSaveHttpContentRes:
OnSaveHttpContentRes(remoteAppID, packet);
break;
case (int)SSGameMsgID.PayHeroSelectHttpContentRes:
OnSelectHttpContentRes(remoteAppID, packet);
break;
case (int)CSGameMsgID.PayWsjsapiReq:
WXHandler.PayWsjsapiReq(remoteAppID, packet);
break;
default:
TraceLog.Error("MessageTaskHandler.HandlerPacket unknow MsgID {0}", packet.MsgID);
break;
}
}
private static void OnPayGoogleRes(uint remoteAppID, StructPacket packet)
{
ref var res = ref packet.GetMessage<SSPayGoogleRes>();
TraceLog.Trace("MessageTaskHandler.OnPayGoogleRes orderId {0} httpCtx {1} uid {2} ret {3}"
, res.OrderId, res.HttpCtxId, res.Uid, res.Ret);
var httpCtx = HttpContextCache.GetContext(res.HttpCtxId);
if (httpCtx == null)
{
TraceLog.Error("MessageTaskHandler.OnPayGoogleRes httpContext {0} is null", res.HttpCtxId);
return;
}
var args = httpCtx.callbackArgs as HeroPayCallbackArgs;
if (args == null)
{
TraceLog.Error("MessageTaskHandler.OnPayGoogleRes httpContext {0} callbackArgs is null", res.HttpCtxId);
return;
}
string orderId = args.orderId;
if (! res.OrderId.Equals(orderId))
{
TraceLog.Error("MessageTaskHandler.OnPayGoogleRes res orderId {0} httpCtx {1} orderId {2} not same"
, res.OrderId, res.HttpCtxId, orderId);
return;
}
if (args.status != HeroPayCallbackStatus.order)
{
TraceLog.Error("MessageTaskHandler.OnPayGoogleRes httpContext {0} invalid status {1}"
, res.HttpCtxId, args.status);
return;
}
var httpRes = new HeroWebPayGoogleRes();
if (res.Ret == 0)
{
httpRes.code = 0;
httpRes.data = new HeroWebPayData
{
roleId = res.Uid.ToString(),
cpOrderNo = orderId,
cpSku = res.PaymentId.GetString()
};
var urls = HttpProxyPayServerUtils.GetServerConfig().heroWebPaySuccCallbackUrls;
if (urls != null)
{
TraceLog.Trace("MessageTaskHandler.OnPayGoogleRes urls count {0} http ctx pcode {1}"
, urls.Count, args.pcode);
foreach (HeroWebPayCallbackUrl item in urls)
{
if (args.pcode.Equals(item.pcode))
{
httpRes.data.cpNotifyUrl = item.url;
break;
}
}
}
if (res.WorldId > 0)
{
var msg = new HeroPayCpCustomMsg { worldId = res.WorldId};
var msgByte = Encoding.ASCII.GetBytes(JsonSerializer.Serialize(msg));
httpRes.data.cpCustomMsg = HttpUtility.UrlDecode(Convert.ToBase64String(msgByte));
}
}
else
{
httpRes.code = -1;
httpRes.msg = "order failed";
}
string ret = JsonSerializer.Serialize(httpRes);
TraceLog.Trace("MessageTaskHandler.OnPayGoogleRes httpContext {0} res {1}", res.HttpCtxId, ret);
httpCtx.httpResponse = new HttpResponse { StatusCode = "200", Content = Encoding.UTF8.GetBytes(ret) };
HttpServer.SendResponse(httpCtx);
HttpContextCache.RemoveContext(httpCtx);
}
private static void OnPayGoogleSuccReq(uint remoteAppID, StructPacket packet)
{
ref var req = ref packet.GetMessage<SSPayGoogleSuccessReq>();
if (req.PayType == (int)PayType.Huawei)
{
SendToHuaweiCheckPayToken(remoteAppID, ref req);
}
else
{
TraceLog.Error("MessageTaskHandler.OnPayGoogleSuccReq pay type {0} not handle", req.PayType);
}
}
private static void SendToHuaweiCheckPayToken(uint remoteAppID, ref SSPayGoogleSuccessReq req)
{
int ret = SendToHuaweiCheckPayToken(ref req);
if (ret != 0)
{
var res = new SSPayGoogleSuccessRes
{
Ret = -1,
Uid = req.Uid,
PayType = req.PayType,
PayParam1 = req.PayParam1,
PayParam2 = req.PayParam2,
PayTime3rd = req.PayTime3rd,
GmTestPay = req.GmTestPay,
Sandbox = req.Sandbox,
};
res.ItemID = req.ItemID;
res.OrderId.SetString(req.OrderId.GetPtr());
res.OrderId3rd.SetString(req.OrderId3rd.GetPtr());
HttpProxyPayServerUtils.GetPacketSender().SendToServerByID(
remoteAppID, (int)SSGameMsgID.PayGoogleSuccessRes, ref res, req.Uid);
}
}
private static int SendToHuaweiCheckPayToken(ref SSPayGoogleSuccessReq req)
{
string reqOrderId = req.OrderId.GetString();
TraceLog.Trace("MessageTaskHandler.SendToHuaweiCheckPayToken uid {0} req orderId {1}", req.Uid, reqOrderId);
string purchaseData = req.PurchaseData.GetString();
JsonData purchaseJson = JsonMapper.ToObject(purchaseData);
if (purchaseJson == null)
{
TraceLog.Error("MessageTaskHandler.SendToHuaweiCheckPayToken uid {0} PurchaseData to Json error", req.Uid);
return -1;
}
JsonData tokenData = purchaseJson["purchaseToken"];
if (tokenData == null)
{
TraceLog.Error("MessageTaskHandler.SendToHuaweiCheckPayToken uid {0} no [purchaseToken]", req.Uid);
return -1;
}
JsonData productIdData = purchaseJson["productId"];
if (productIdData == null)
{
TraceLog.Error("MessageTaskHandler.SendToHuaweiCheckPayToken uid {0} no [productId]", req.Uid);
return -1;
}
string purchaseToken = tokenData.ToString();
string productId = productIdData.ToString();
JsonData jsonData = null;
// 发送到华为服务器校验payToken是否存在
int ret = HuaweiPaySvc.HttpPostCheckPayTokenInner(purchaseToken, productId, out jsonData);
// 401代表token过期, 过期时重新获取新的token后再试一次
// 注意这里是多线程处理http请求, 存在多个线程同时刷新token的情况!!!
// 华为的客服回复: accessToken在有效期内无论申请几次都是同一个token, 所以同时刷新也没关系
if (ret == 401)
{
var svrData = HttpProxyPayServerUtils.GetHttpProxyServerData();
svrData.huaweiAppAccessToken = HuaweiPaySvc.GetAppAccessToken();
ret = HuaweiPaySvc.HttpPostCheckPayTokenInner(purchaseToken, productId, out jsonData);
}
// token校验失败, 或者没有返回购买数据
if (ret != 0 || jsonData == null)
{
TraceLog.Error("HuaweiPaySvc.SendToHuaweiCheckPayToken uid {0} item {1} check fail {2}"
, req.Uid, reqOrderId, ret);
return -1;
}
// 游戏内部自己的订单号
JsonData payload = jsonData["developerPayload"];
if (payload == null)
{
TraceLog.Error("HuaweiPaySvc.SendToHuaweiCheckPayToken uid {0} no [developerPayload]", req.Uid);
return -1;
}
// 校验华为服务器传回的订单号和客户端上报的订单号是否一致
string resOrderId = payload.ToString();
if (string.IsNullOrEmpty(resOrderId) || ! resOrderId.Equals(reqOrderId))
{
TraceLog.Error("HuaweiPaySvc.SendToHuaweiCheckPayToken uid {0} req order {1} res order {2} not same"
, req.Uid, reqOrderId, resOrderId);
return -1;
}
int payState = -1;
JsonData payStateJson = jsonData["purchaseState"];
if (payStateJson != null && int.TryParse(payStateJson.ToString(), out payState))
{
TraceLog.Trace("HuaweiPaySvc.OnPaySuccessReq orderId {0} purchaseState {1}", resOrderId, payState);
}
else
{
payState = -1;
}
// 订单不是已购买状态
if (payState != 0)
{
TraceLog.Error("HuaweiPaySvc.OnPaySuccessReq orderId {0} purchaseState {1} not pay", resOrderId, payState);
return -1;
}
// uid-time-orderIdSeq-serverId-payitemId-payParam1-payParam2-paymentId-payUrlId
string[] split = resOrderId.Split('-');
if (split.Length < 9)
{
TraceLog.Error("HuaweiPaySvc.OnPaySuccessReq invalid orderId {0}, need >= 9 params", resOrderId);
return -1;
}
JsonData productIdJson = jsonData["productId"];
if (productIdJson == null)
{
TraceLog.Error("HuaweiPaySvc.OnPaySuccessReq uid {0} no [productId]", req.Uid);
return -1;
}
string goodsId = split[7];
productId = productIdJson.ToString();
// 商品id不是同一个
if (string.IsNullOrEmpty(productId) || !goodsId.Equals(productId))
{
TraceLog.Error("HuaweiPaySvc.OnPaySuccessReq itemId svr {0} clt {1} not same", productId, goodsId);
return -1;
}
JsonData currencyJson = jsonData["currency"];
if (currencyJson == null)
{
TraceLog.Error("HuaweiPaySvc.OnPaySuccessReq uid {0} no [currency]", req.Uid);
return -1;
}
JsonData priceJson = jsonData["price"];
if (priceJson == null)
{
TraceLog.Error("HuaweiPaySvc.OnPaySuccessReq uid {0} no [price]", req.Uid);
return -1;
}
// 钱相关的字段还是用华为服务器返回的数据赋值
req.PurchaseToken.SetString(purchaseToken);
req.Currency.SetString(currencyJson.ToString());
if (long.TryParse(priceJson.ToString(), out long amount))
{
req.Amount = (uint)amount;
}
// 校验成功将req发到DBServer
uint dbServerID = DBServerSelect.GetDBServerID(req.Uid);
HttpProxyPayServerUtils.GetPacketSender().SendToServerByID(dbServerID,
(int)SSGameMsgID.PayGoogleSuccessReq, ref req, req.Uid);
return 0;
}
private static void OnPayGoogleSuccRes(uint remoteAppID, StructPacket packet)
{
ref var res = ref packet.GetMessage<SSPayGoogleSuccessRes>();
TraceLog.Trace("MessageTaskHandler.OnPayGoogleSuccRes orderId {0} httpCtx {1} uid {2} ret {3}"
, res.OrderId, res.HttpCtxId, res.Uid, res.Ret);
if (res.Ret == 0 && res.HttpCtxId != 0)
{
var httpCtx = HttpContextCache.GetContext(res.HttpCtxId);
if (httpCtx == null)
{
// 找不到没关系, SDK会重试, 只要服务器的逻辑保证不重复加钱就行
TraceLog.Error("MessageTaskHandler.OnPayGoogleSuccRes httpContext {0} is null", res.HttpCtxId);
return;
}
var args = httpCtx.callbackArgs as HeroPayCallbackArgs;
if (args == null)
{
TraceLog.Error("MessageTaskHandler.OnPayGoogleSuccRes httpContext {0} callbackArgs is null", res.HttpCtxId);
return;
}
string orderId = args.orderId;
if (!res.OrderId.Equals(orderId))
{
TraceLog.Error("MessageTaskHandler.OnPayGoogleSuccRes res orderId {0} httpCtx {1} orderId {2}"
, res.OrderId, res.HttpCtxId, orderId);
return;
}
if (args.status != HeroPayCallbackStatus.paySucc)
{
TraceLog.Error("MessageTaskHandler.OnPayGoogleSuccRes httpContext {0} invalid status {1}"
, res.HttpCtxId, args.status);
return;
}
if (res.PayType == (int)PayType.MiniPay)
{
httpCtx.httpResponse = new HttpResponse { StatusCode = "200", Content = Encoding.UTF8.GetBytes("{\"ErrCode\":0,\"ErrMsg\":\"Success\"}") };
}
else
{
httpCtx.httpResponse = new HttpResponse { StatusCode = "200", Content = Encoding.UTF8.GetBytes("SUCCESS") };
}
HttpServer.SendResponse(httpCtx);
HttpContextCache.RemoveContext(httpCtx);
}
}
private static void OnPaySendDBRefundRes(uint remoteAppID, StructPacket packet)
{
ref var res = ref packet.GetMessage<SSPaySendDBRefundRes>();
TraceLog.Trace("MessageTaskHandler.OnPaySendDBRefundRes orderId {0} httpCtx {1} uid {2} ret {3}"
, res.OrderId, res.HttpCtxId, res.Uid, res.Ret);
var httpCtx = HttpContextCache.GetContext(res.HttpCtxId);
if (httpCtx == null)
{
TraceLog.Error("MessageTaskHandler.OnPaySendDBRefundRes httpContext {0} is null", res.HttpCtxId);
return;
}
var args = httpCtx.callbackArgs as HeroPayCallbackArgs;
if (args == null)
{
TraceLog.Error("MessageTaskHandler.OnPaySendDBRefundRes httpContext {0} callbackArgs is null", res.HttpCtxId);
return;
}
string orderId = args.orderId;
if (!res.OrderId.Equals(orderId))
{
TraceLog.Error("MessageTaskHandler.OnPaySendDBRefundRes res orderId {0} httpCtx {1} orderId {2} not same"
, res.OrderId, res.HttpCtxId, orderId);
return;
}
if (args.status != HeroPayCallbackStatus.refund)
{
TraceLog.Error("MessageTaskHandler.OnPaySendDBRefundRes httpContext {0} invalid status {1}"
, res.HttpCtxId, args.status);
return;
}
if (res.Ret == 0)
{
httpCtx.httpResponse = new HttpResponse { StatusCode = "200", Content = Encoding.UTF8.GetBytes("SUCCESS") };
HttpServer.SendResponse(httpCtx);
}
HttpContextCache.RemoveContext(httpCtx);
}
private static void OnSaveHttpContentRes(uint remoteAppID, StructPacket packet)
{
ref var res = ref packet.GetMessage<SSPayHeroSaveHttpContentRes>();
HeroUSDKSvc.PostHttpRequest(ref res.Http);
}
private static void OnSelectHttpContentRes(uint remoteAppID, StructPacket packet)
{
ref var res = ref packet.GetMessage<SSPayHeroSelectHttpContentRes>();
for (int i = 0; i < res.Http.Count; i++)
{
HeroUSDKSvc.PostHttpRequest(ref res.Http[i]);
}
}
}
}