using Newtonsoft.Json; using ServerCore; using ServerBase; using ServerCommon; namespace GameServer; public class BillingServerConnector { static public string makeBillingServerURL(string url) { return $"{GameServerApp.getServerLogic().getServerConfig().BillingConfig.BaseAddress}{url}"; } //테스트 유저의 JWT 발급 static public async Task<(Result, string jwt)> TestUserJwtIssue() { var result = OnlineConnectConfigCheck(); if (result.isFail()) return (result, string.Empty); var billing = new BillingTestAccount() { email = "calilab@caliverse.io", password = "calilab1234!" }; var body = JsonConvert.SerializeObject(billing); var fullUrl = makeBillingServerURL($"/v1/wallet/auth/login"); (bool isSuccess, string resMsg) = await HttpClientHelper.sendHttpRequest( "POST", fullUrl, null, body , "application/json" , "caliverse", "1.0" ); if (isSuccess == false) { Log.getLogger().error($"Failed billing server action : TestUserJwtIssue, msg : {resMsg}"); result.setFail(ServerErrorCode.BillingGetPurchaseInfoFailed); return (result, string.Empty); } try { var test_jwt = JsonConvert.DeserializeObject(resMsg); NullReferenceCheckHelper.throwIfNull(test_jwt, () => $"test_jwt is null !!!"); return (result, test_jwt.jwt); } catch (Exception ex) { Log.getLogger().error($"Exception !!!, DeserializeObject : exception:{ex}, resMsg:{resMsg}"); return (result, string.Empty); } } //유저의 구매내역들 조회 static public async Task<(Result, BillingPurchaseInfos?)> GetBillingPurchaseInfos(BillingPurchaseRequest billingPurchaseRequest, string jwt) { var result = OnlineConnectConfigCheck(); if (result.isFail()) return (result, null); var body = JsonConvert.SerializeObject(billingPurchaseRequest); var fullUrl = makeBillingServerURL($"/v1/shop/products"); (bool isSuccess, string resMsg) = await HttpClientHelper.sendHttpRequest("GET", fullUrl, jwt, body , "application/json" , "caliverse", "1.0"); if (isSuccess == false) { Log.getLogger().error($"Failed billing server action : GetBillingPurchaseInfos, fullUrl : {fullUrl}, jwt : {jwt}, order_id : {billingPurchaseRequest.order_id}, web_account_id : {billingPurchaseRequest.account_id}, msg : {resMsg}"); result.setFail(ServerErrorCode.BillingGetPurchaseInfoFailed); return (result, null); } try { var res = JsonConvert.DeserializeObject(resMsg); NullReferenceCheckHelper.throwIfNull(res, () => $"res is null !!!"); if (res.status_code != 200) { Log.getLogger().error($"Failed billing server action : GetBillingPurchaseInfo, fullUrl : {fullUrl}, jwt : {jwt}, order_id : {billingPurchaseRequest.order_id}, web_account_id : {billingPurchaseRequest.account_id}, msg : {res.status_message}"); result.setFail(ServerErrorCode.BillingGetPurchaseInfoFailed); return (result, null); } res.data.Sort((x, y) => { return x.buyDateTime.CompareTo(y.buyDateTime); }); return (result, res); } catch (Exception ex) { Log.getLogger().error($"Exception !!!, DeserializeObject : exception:{ex}, resMsg:{resMsg}"); return (result, null); } } //유저의 특정 구매 상태 조회 static public async Task<(Result, BillingPurchaseState?)> GetBillingPurchaseInfo(BillingPurchaseRequest billingPurchaseRequest, string jwt) { var result = OnlineConnectConfigCheck(); if (result.isFail()) return (result, null); var body = JsonConvert.SerializeObject(billingPurchaseRequest); var fullUrl = makeBillingServerURL($"/v1/shop/product"); (bool isSuccess, string resMsg) = await HttpClientHelper.sendHttpRequest("GET", fullUrl, jwt, body , "application/json" , "caliverse", "1.0"); if (isSuccess == false) { Log.getLogger().error($"Failed billing server action : GetBillingPurchaseInfo, fullUrl : {fullUrl}, jwt : {jwt}, order_id : {billingPurchaseRequest.order_id}, web_account_id : {billingPurchaseRequest.account_id}, msg : {resMsg}"); result.setFail(ServerErrorCode.BillingGetPurchaseInfoFailed); return (result, null); } try { var res = JsonConvert.DeserializeObject(resMsg); NullReferenceCheckHelper.throwIfNull(res, () => $"res is null !!!"); if (res.status_code != 200) { Log.getLogger().error($"Failed billing server action : GetBillingPurchaseInfo, fullUrl : {fullUrl}, jwt : {jwt}, order_id : {billingPurchaseRequest.order_id}, web_account_id : {billingPurchaseRequest.account_id}, msg : {res.status_message}"); result.setFail(ServerErrorCode.BillingGetPurchaseInfoFailed); return (result, null); } return (result, res); } catch (Exception ex) { Log.getLogger().error($"Exception !!!, DeserializeObject : exception:{ex}, resMsg:{resMsg}"); return (result, null); } } //유저의 구매 상태 업데이트 static public async Task<(Result, string)> UpdateBillingState(BillingChangeState billingChangeState, string jwt) { var result = OnlineConnectConfigCheck(); if (result.isFail()) return (result, string.Empty); var body = JsonConvert.SerializeObject(billingChangeState); var fullUrl = makeBillingServerURL($"/v1/shop/update"); (bool isSuccess, string resMsg) = await HttpClientHelper.sendHttpRequest("PUT", fullUrl, jwt, body , "application/json" , "caliverse", "1.0"); string orders_string = string.Empty; string states_string = string.Empty; foreach (var stateInfo in billingChangeState.state_list) { orders_string += $"{stateInfo.order_id},"; states_string += $"{stateInfo.state},"; } if (isSuccess == false) { Log.getLogger().error($"Failed billing server action : UpdateBillingState, fullUrl : {fullUrl}, jwt : {jwt}, web_account_id : {billingChangeState.account_id}, order_ids : {orders_string}, update state : {states_string}, msg : {resMsg}"); result.setFail(ServerErrorCode.BillingUpdateStateFailed); return (result, resMsg); } try { var res = JsonConvert.DeserializeObject(resMsg); NullReferenceCheckHelper.throwIfNull(res, () => $"res is null !!!"); if (res.status_code != 200) { Log.getLogger().error($"Failed billing server action : UpdateBillingState, fullUrl : {fullUrl}, jwt : {jwt}, web_account_id : {billingChangeState.account_id}, order_id : {orders_string}, update state : {states_string}, msg : {res.status_message}"); result.setFail(ServerErrorCode.BillingUpdateStateFailed); return (result, res.status_message); } return (result, res.status_message); } catch (Exception ex) { Log.getLogger().error($"Exception !!!, DeserializeObject : exception:{ex}, resMsg:{resMsg}"); return (result, string.Empty); } } static public async Task<(Result, BillingStateType)> GetBillingState(string jwt, string account_id, string packageOrderId) { var result = new Result(); var err_msg = string.Empty; var billingPurchaseRequest = new BillingPurchaseRequest() { account_id = account_id.ToString(), order_id = packageOrderId }; (result, var state) = await GetBillingPurchaseInfo(billingPurchaseRequest, jwt); if (result.isFail()) { return (result, BillingStateType.none); } NullReferenceCheckHelper.throwIfNull(state, () => $"state is null !!!"); if (EnumHelper.tryParse(state.data.state, out var stateType) == false) { err_msg = $"Enum Parse Failed. BillingStateType : {state.data.state}"; result.setFail(ServerErrorCode.BillingStateTypeInvalid, err_msg); Log.getLogger().error(err_msg); return (result, BillingStateType.none); } return (result, stateType); } //빌링 상태값 업데이트 가능 여부 확인 static public async Task<(Result, bool isUpdated)> AbleToChangeBillingState(string jwt, string account_id, string packageOrderId, BillingStateType toBillingStateType) { var result = new Result(); var err_msg = string.Empty; var billingPurchaseRequest = new BillingPurchaseRequest() { account_id = account_id.ToString(), order_id = packageOrderId }; (result, var state) = await GetBillingPurchaseInfo(billingPurchaseRequest, jwt); if (result.isFail()) { return (result, false); } NullReferenceCheckHelper.throwIfNull(state, () => $"state is null !!!"); if (EnumHelper.tryParse(state.data.state, out var stateType) == false) { err_msg = $"Enum Parse Failed. BillingStateType : {state.data.state}"; result.setFail(ServerErrorCode.BillingStateTypeInvalid, err_msg); Log.getLogger().error(err_msg); return (result, false); } switch (toBillingStateType) { case BillingStateType.received: if (stateType != BillingStateType.paid) { err_msg = $"Invalid BillingState. current BillingStateType : {stateType}, toBillingStateType {toBillingStateType}"; result.setFail(ServerErrorCode.BillingStateTypeInvalid, err_msg); Log.getLogger().error(err_msg); return (result, false); } break; case BillingStateType.opening: if (stateType == BillingStateType.refund || stateType == BillingStateType.refund_request) { err_msg = $"Invalid BillingState. current BillingStateType : {stateType}, toBillingStateType {toBillingStateType}"; result.setFail(ServerErrorCode.BillingStateTypeRefund, err_msg); Log.getLogger().error(err_msg); return (result, false); } else if (stateType == BillingStateType.canceled) { err_msg = $"Invalid BillingState. current BillingStateType : {stateType}, toBillingStateType {toBillingStateType}"; result.setFail(ServerErrorCode.BillingStateTypeRefundComplete, err_msg); Log.getLogger().error(err_msg); return (result, false); } else if (stateType == BillingStateType.opening || stateType == BillingStateType.opened) { return (result, true); } break; case BillingStateType.opened: if (stateType == BillingStateType.opened) { return (result, true); } else if (stateType != BillingStateType.opening) { err_msg = $"Invalid BillingState. current BillingStateType : {stateType}, toBillingStateType {toBillingStateType}"; result.setFail(ServerErrorCode.BillingStateTypeInvalid, err_msg); Log.getLogger().error(err_msg); return (result, false); } break; default: err_msg = $"Invalid BillingState. current BillingStateType : {stateType}, toBillingStateType {toBillingStateType}"; result.setFail(ServerErrorCode.BillingStateTypeInvalid, err_msg); Log.getLogger().error(err_msg); return (result, false); } return (result, false); } static private Result OnlineConnectConfigCheck() { var result = new Result(); var server_config = GameServerApp.getServerLogic().getServerConfig(); var billing_address = server_config.BillingConfig.BaseAddress; if (server_config.OfflineMode == true || billing_address == string.Empty) { result.setFail(ServerErrorCode.ServerOfflineModeEnable); return result; } return result; } }