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
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]);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|