private void UpdateFundOutOrder(FundOutOrder fundoutOrder) { fundoutOrder.UpdateTime = DateTime.Now; _fundOutOrderRepository.Update(fundoutOrder); var updateResult = _fundOutOrderRepository.SaveChanges(); if (!updateResult.Success) { _logger.Error(TraceType.BLL.ToString(), CallResultStatus.ERROR.ToString(), $"{this.GetType().FullName}.Pay(...)", $"{nameof(_fundOutOrderRepository)}.SaveChanges()", "更新支付状态失败", updateResult.FirstException, fundoutOrder); } }
public XResult <SingleSettlementPaymentApplyResponse> Pay(SingleSettlementPaymentApplyRequest request) { if (request == null) { return(new XResult <SingleSettlementPaymentApplyResponse>(null, ErrorCode.INVALID_ARGUMENT, new ArgumentNullException($"{nameof(request)}为null"))); } if (!request.IsValid) { return(new XResult <SingleSettlementPaymentApplyResponse>(null, ErrorCode.INVALID_ARGUMENT, new ArgumentException(request.ErrorMessage))); } String service = $"{this.GetType().FullName}.{nameof(Pay)}(...)"; var requestHash = $"{nameof(Pay)}:{request.OrderNo}".GetHashCode(); if (_lockProvider.Exists(requestHash)) { return(new XResult <SingleSettlementPaymentApplyResponse>(null, ErrorCode.SUBMIT_REPEAT)); } try { if (!_lockProvider.Lock(requestHash)) { return(new XResult <SingleSettlementPaymentApplyResponse>(null, ErrorCode.SUBMIT_REPEAT)); } Boolean existOrder = true; try { existOrder = (from t0 in _fundOutOrderRepository.QueryProvider where t0.OutTradeNo == request.OrderNo select t0.Id).Count() > 0; } catch (Exception ex) { _logger.Error(TraceType.BLL.ToString(), CallResultStatus.ERROR.ToString(), service, "existOrder", "查询订单失败", ex, request); return(new XResult <SingleSettlementPaymentApplyResponse>(null, ErrorCode.DB_QUERY_FAILED, new DbQueryException($"查询订单号失败,订单号:{request.OrderNo}"))); } if (existOrder) { return(new XResult <SingleSettlementPaymentApplyResponse>(null, ErrorCode.OUT_TRADE_NO_EXISTED)); } Int64 newId = IDGenerator.GenerateID(); String tradeNo = newId.ToString(); var fundoutOrder = new FundOutOrder() { Id = newId, AppId = request.AppId, TradeNo = tradeNo, OutTradeNo = request.OrderNo, Amount = request.Amount, RealName = request.CreditName, PayStatus = PayStatus.PROCESSING.ToString(), FeeAction = request.FeeAction, BankCardNo = request.BankCardNo, BankName = request.BankName, Mobile = request.Mobile, CreateTime = DateTime.Now, Remark = request.Remark }; //入库 _fundOutOrderRepository.Add(fundoutOrder); var saveResult = _fundOutOrderRepository.SaveChanges(); if (!saveResult.Success) { _logger.Error(TraceType.BLL.ToString(), nameof(CallResultStatus.ERROR), service, $"{nameof(_fundOutOrderRepository)}.SaveChanges()", "保存订单失败", saveResult.FirstException, fundoutOrder); return(new XResult <SingleSettlementPaymentApplyResponse>(null, ErrorCode.DB_UPDATE_FAILED, new DbUpdateException($"保存订单失败,订单编号:{fundoutOrder.OutTradeNo}"))); } //开始执行代付 var requestBuilder = new RequestBuilder(_serializer, _logger) { EncryptKey = CryptoHelper.GenerateRandomKey(), RequestType = "pay2BankRequest", RequestHead = "pay2bankHead", RequestBodyType = "requestBody", RequestBody = request }; var postXml = requestBuilder.Build(doc => { var amountEl = doc.Root.Element("amount"); if (amountEl != null) { var amountText = amountEl.Value; if (Decimal.TryParse(amountText, out Decimal amount)) { amountEl.Value = Convert.ToInt32(amount * 100m).ToString(); } } }); //更新申请时间 fundoutOrder.ApplyTime = DateTime.Now; String callMethod = $"{nameof(_client)}.PostXml(...)"; _logger.Trace(TraceType.BLL.ToString(), nameof(CallResultStatus.OK), service, callMethod, LogPhase.BEGIN, $"开始调用{callMethod}", new Object[] { ApiConfig.Bill99FOSinglePayApplyRequestUrl, postXml }); var postResult = _client.PostXml(ApiConfig.Bill99FOSinglePayApplyRequestUrl, postXml); _logger.Trace(TraceType.BLL.ToString(), (postResult.Success ? CallResultStatus.OK : CallResultStatus.ERROR).ToString(), service, callMethod, LogPhase.ACTION, $"完成调用{callMethod}"); if (!postResult.Success) { return(new XResult <SingleSettlementPaymentApplyResponse>(null, ErrorCode.DEPENDENT_API_CALL_FAILED, postResult.FirstException)); } String resp = null; try { resp = postResult.Value.Content.ReadAsStringAsync().GetAwaiter().GetResult(); _logger.Trace(TraceType.BLL.ToString(), nameof(CallResultStatus.OK), service, callMethod, LogPhase.END, $"调用{callMethod}结果", resp); } catch (Exception ex) { _logger.Error(TraceType.BLL.ToString(), nameof(CallResultStatus.ERROR), service, callMethod, "读取第三方返回的消息内容失败", ex, postXml); return(new XResult <SingleSettlementPaymentApplyResponse>(null, ErrorCode.DEPENDENT_API_CALL_FAILED, ex)); } if (String.IsNullOrWhiteSpace(resp)) { return(new XResult <SingleSettlementPaymentApplyResponse>(null, ErrorCode.REMOTE_RETURN_NOTHING)); } //更新结束时间 fundoutOrder.EndTime = DateTime.Now; var parseResult = ParseXml(resp); if (!parseResult.Success) { _logger.Error(TraceType.BLL.ToString(), nameof(CallResultStatus.ERROR), service, "ParseXml(...)", "解析返回数据失败", parseResult.FirstException, resp); return(new XResult <SingleSettlementPaymentApplyResponse>(null, ErrorCode.XML_PARSE_FAILED, new SystemException("解析返回数据失败"))); } var root = parseResult.Value.Root; var memberCodeEl = root.Descendants("memberCode").FirstOrDefault(); if (memberCodeEl == null) { _logger.Error(TraceType.BLL.ToString(), nameof(CallResultStatus.ERROR), service, "memberCodeEl", "返回数据中未包含<memberCode></memberCode>元素"); return(new XResult <SingleSettlementPaymentApplyResponse>(null, ErrorCode.XML_ELEMENT_NOT_EXIST, new RemoteException("<memberCode> not found"))); } var decodeResult = Decode(root, "responseBody"); if (!decodeResult.Success) { _logger.Error(TraceType.BLL.ToString(), nameof(CallResultStatus.ERROR), service, $"Decode(...)", "解码失败"); return(new XResult <SingleSettlementPaymentApplyResponse>(null, ErrorCode.DECODE_FAILED, decodeResult.FirstException)); } var deserializeResult = Deserialize <SingleSettlementPaymentApplyResponse>(decodeResult.Value); if (deserializeResult.Success && deserializeResult.Value != null) { var result = deserializeResult.Value; result.MemberCode = memberCodeEl.Value; var errorCodeEl = root.Descendants("errorCode").FirstOrDefault(); if (errorCodeEl != null) { result.ErrorCode = errorCodeEl.Value; } var errorMsgEl = root.Descendants("errorMsg").FirstOrDefault(); if (errorMsgEl != null) { result.ErrorMessage = errorMsgEl.Value; } //将以分为单位的金额转成以元为单位 result.Amount *= 0.01m; //更新时间 fundoutOrder.UpdateTime = DateTime.Now; //将申请时间、结束时间和更新时间更新到数据库 _fundOutOrderRepository.Update(fundoutOrder); var updateResult = _fundOutOrderRepository.SaveChanges(); if (!updateResult.Success) { _logger.Error(TraceType.BLL.ToString(), nameof(CallResultStatus.ERROR), service, $"{nameof(_fundOutOrderRepository)}.SaveChanges()", "更新代付订单申请时间|结束时间|更新时间失败", updateResult.FirstException, fundoutOrder); } return(new XResult <SingleSettlementPaymentApplyResponse>(result)); } return(new XResult <SingleSettlementPaymentApplyResponse>(null, ErrorCode.DESERIALIZE_FAILED, deserializeResult.FirstException)); } finally { _lockProvider.UnLock(requestHash); } }
public XResult <PayResponse> Pay(PayRequest request) { if (request == null) { return(new XResult <PayResponse>(null, ErrorCode.INVALID_ARGUMENT, new ArgumentNullException(nameof(request)))); } String service = $"{this.GetType().FullName}.Pay(...)"; if (!request.IsValid) { return(new XResult <PayResponse>(null, ErrorCode.INVALID_ARGUMENT, new ArgumentException(request.ErrorMessage))); } var requestHash = $"pay:{request.AppId}.{request.OutTradeNo}".GetHashCode(); if (_lockProvider.Exists(requestHash)) { return(new XResult <PayResponse>(null, ErrorCode.SUBMIT_REPEAT)); } try { if (!_lockProvider.Lock(requestHash)) { return(new XResult <PayResponse>(null, ErrorCode.SUBMIT_REPEAT)); } var existsOutTradeNo = _fundOutOrderRepository.Exists(x => x.OutTradeNo == request.OutTradeNo); if (existsOutTradeNo) { return(new XResult <PayResponse>(null, ErrorCode.OUT_TRADE_NO_EXISTED)); } //申请冻结商户放款余额 var applyFreezeLoanParas = new Dictionary <String, String>(4); applyFreezeLoanParas["MerchantNo"] = request.MerchantNo; applyFreezeLoanParas["OrderNo"] = request.OutTradeNo; applyFreezeLoanParas["FrozenLoanBalance"] = request.Amount; applyFreezeLoanParas["Sign"] = MerchantUtil.MD5Sign(applyFreezeLoanParas); var client = GetClient(); String traceMethod = $"{nameof(client)}.PostForm(...)"; _logger.Trace(TraceType.BLL.ToString(), CallResultStatus.OK.ToString(), service, traceMethod, LogPhase.BEGIN, "开始请求商户系统冻结放款余额", new Object[] { ApiConfig.SystemMerchantAccountBalanceFreezeRequestUrl, applyFreezeLoanParas }); var freezeResult = client.PostForm <ApiResult>(ApiConfig.SystemMerchantAccountBalanceFreezeRequestUrl, applyFreezeLoanParas); _logger.Trace(TraceType.BLL.ToString(), (freezeResult.Success ? CallResultStatus.OK : CallResultStatus.ERROR).ToString(), service, traceMethod, LogPhase.END, "结束请求商户系统冻结放款余额", freezeResult.Value); if (!freezeResult.Success) { _logger.Error(TraceType.BLL.ToString(), CallResultStatus.ERROR.ToString(), service, traceMethod, "商户系统冻结放款余额失败", freezeResult.FirstException, applyFreezeLoanParas); return(new XResult <PayResponse>(null, ErrorCode.DEPENDENT_API_CALL_FAILED, new RemoteException("商户系统冻结放款余额失败"))); } if (freezeResult.Value == null) { _logger.Error(TraceType.BLL.ToString(), CallResultStatus.ERROR.ToString(), service, traceMethod, "商户系统冻结放款余额返回的业务数据为空", null, applyFreezeLoanParas); return(new XResult <PayResponse>(null, ErrorCode.DEPENDENT_API_CALL_FAILED, new RemoteException("商户系统冻结放款余额返回的业务数据为空"))); } if (freezeResult.Value.Status != "SUCCESS") { _logger.Trace(TraceType.BLL.ToString(), CallResultStatus.ERROR.ToString(), service, traceMethod, LogPhase.ACTION, "商户系统冻结放款余额失败", freezeResult.Value); return(new XResult <PayResponse>(null, ErrorCode.DEPENDENT_API_CALL_FAILED, new RemoteException("商户系统冻结放款余额失败"))); } var now = DateTime.Now; var newId = IDGenerator.GenerateID(); var fundoutOrder = new FundOutOrder() { Id = newId, TradeNo = newId.ToString(), AppId = request.AppId, OutTradeNo = request.OutTradeNo, Amount = request.Amount.ToDecimal(), RealName = request.RealName, BankCardNo = request.BankCardNo, Mobile = request.Mobile, Remark = request.Remark, PayStatus = PayStatus.APPLY.ToString(), CreateTime = DateTime.Now }; _fundOutOrderRepository.Add(fundoutOrder); var saveResult = _fundOutOrderRepository.SaveChanges(); if (!saveResult.Success) { _logger.Error(TraceType.BLL.ToString(), CallResultStatus.ERROR.ToString(), service, $"{nameof(_fundOutOrderRepository)}.SaveChanges()", "保存代付订单数据失败", saveResult.FirstException, fundoutOrder); return(new XResult <PayResponse>(null, ErrorCode.DB_UPDATE_FAILED, new DbUpdateException("保存订单数据失败"))); } var dic = new Dictionary <String, String>(6); dic["LoanJsonList"] = JsonUtil.SerializeObject(new FundOutLoanInfo() { Amount = request.Amount, CardNumber = CryptoHelper.RSAEncrypt(request.BankCardNo, KeyConfig.EPay95_FundOut_PublicKey).Value, IdentificationNo = request.IDCardNo, Mobile = request.Mobile, OrderNo = request.OutTradeNo, RealName = request.RealName, Type = "0" }).Value; dic["PlatformMoneymoremore"] = GlobalConfig.X95epay_FundOut_Hehua_PlatformMoneymoremore; dic["BatchNo"] = request.OutTradeNo; dic["Remark"] = request.Remark; dic["NotifyURL"] = ApiConfig.EPay95_FundOut_Pay_NotifyUrl; var signResult = EPay95Util.MakeSign(dic); if (signResult.IsNullOrWhiteSpace()) { return(new XResult <PayResponse>(null, ErrorCode.SIGN_FAILED)); } dic["LoanJsonList"] = HttpUtility.UrlEncode(dic["LoanJsonList"]); dic["SignInfo"] = signResult; _logger.Trace(TraceType.BLL.ToString(), CallResultStatus.OK.ToString(), service, traceMethod, LogPhase.BEGIN, $"开始调用{ApiConfig.EPay95_FundOut_Pay_RequestUrl}", new Object[] { ApiConfig.EPay95_FundOut_Pay_RequestUrl, dic }); //记录请求开始时间 fundoutOrder.ApplyTime = DateTime.Now; var respMsgResult = client.PostForm(ApiConfig.EPay95_FundOut_Pay_RequestUrl, dic); _logger.Trace(TraceType.BLL.ToString(), (respMsgResult.Success ? CallResultStatus.OK : CallResultStatus.ERROR).ToString(), service, traceMethod, LogPhase.ACTION, $"结束调用{ApiConfig.EPay95_FundOut_Pay_RequestUrl}"); if (!respMsgResult.Success) { _logger.Error(TraceType.BLL.ToString(), CallResultStatus.ERROR.ToString(), service, traceMethod, "代付失败", respMsgResult.FirstException, dic); return(new XResult <PayResponse>(null, ErrorCode.DEPENDENT_API_CALL_FAILED, new RequestException(respMsgResult.ErrorMessage))); } String respContent = null; try { respContent = respMsgResult.Value.Content.ReadAsStringAsync().GetAwaiter().GetResult(); _logger.Trace(TraceType.BLL.ToString(), CallResultStatus.OK.ToString(), service, traceMethod, LogPhase.END, $"调用{ApiConfig.EPay95_FundOut_Pay_RequestUrl}返回结果", respContent); } catch (Exception ex) { _logger.Error(TraceType.BLL.ToString(), CallResultStatus.ERROR.ToString(), service, traceMethod, "读取代付返回的消息内容出现异常", ex, dic); return(new XResult <PayResponse>(null, ErrorCode.RESPONSE_READ_FAILED, ex)); } if (respContent.IsNullOrWhiteSpace()) { _logger.Error(TraceType.BLL.ToString(), CallResultStatus.ERROR.ToString(), service, traceMethod, "双乾未返回任何数据", null, dic); return(new XResult <PayResponse>(null, ErrorCode.REMOTE_RETURN_NOTHING)); } EPay95PayReturnResult respResult = JsonUtil.DeserializeObject <EPay95PayReturnResult>(respContent).Value; if (respResult == null) { _logger.Error(TraceType.BLL.ToString(), CallResultStatus.ERROR.ToString(), service, "respResult", "无法将代付结果反序列化为EPay95PayReturnResult对象", null, respContent); return(new XResult <PayResponse>(null, ErrorCode.DESERIALIZE_FAILED)); } //记录请求结束时间 fundoutOrder.EndTime = DateTime.Now; switch (respResult.ResultCode) { case "88": case "90": case "15": //修改支付状态为正在处理中 fundoutOrder.PayStatus = PayStatus.PROCESSING.ToString(); break; default: //修改支付状态为正在处理中 fundoutOrder.PayStatus = PayStatus.FAILURE.ToString(); break; } fundoutOrder.UpdateTime = DateTime.Now; _fundOutOrderRepository.Update(fundoutOrder); var updateResult = _fundOutOrderRepository.SaveChanges(); if (!updateResult.Success) { _logger.Error(TraceType.BLL.ToString(), CallResultStatus.ERROR.ToString(), service, $"{nameof(_fundOutOrderRepository)}.SaveChanges()", "更新支付状态失败", updateResult.FirstException, fundoutOrder); } var payResp = new PayResponse() { Status = fundoutOrder.PayStatus, Msg = respResult.Message.HasValue() ? respResult.Message : PayStatus.PROCESSING.GetDescription() }; if (respResult.LoanJsonList != null) { payResp.Amount = respResult.LoanJsonList.Amount; payResp.BankCardNo = respResult.LoanJsonList.CardNumber; payResp.OutTradeNo = respResult.LoanJsonList.OrderNo; } return(new XResult <PayResponse>(payResp)); } finally { _lockProvider.UnLock(requestHash); } }
public XResult <YeePaySinglePayResponse> Pay(YeePaySinglePayRequest request) { if (request == null) { return(new XResult <YeePaySinglePayResponse>(null, ErrorCode.INVALID_ARGUMENT, new ArgumentNullException(nameof(request)))); } if (!request.IsValid) { return(new XResult <YeePaySinglePayResponse>(null, ErrorCode.INVALID_ARGUMENT, new ArgumentException(request.ErrorMessage))); } String service = $"{this.GetType().FullName}.Pay(...)"; var requestHash = $"pay:{request.AppId}.{request.OutTradeNo}".GetHashCode(); if (_lockProvider.Exists(requestHash)) { return(new XResult <YeePaySinglePayResponse>(null, ErrorCode.SUBMIT_REPEAT)); } try { if (!_lockProvider.Lock(requestHash)) { return(new XResult <YeePaySinglePayResponse>(null, ErrorCode.SUBMIT_REPEAT)); } var existsOutTradeNo = _fundOutOrderRepository.Exists(x => x.OutTradeNo == request.OutTradeNo); if (existsOutTradeNo) { return(new XResult <YeePaySinglePayResponse>(null, ErrorCode.OUT_TRADE_NO_EXISTED)); } var now = DateTime.Now; var newId = IDGenerator.GenerateID(); var fundoutOrder = new FundOutOrder() { Id = newId, TradeNo = newId.ToString(), AppId = request.AppId, OutTradeNo = request.OutTradeNo, Amount = request.Amount.ToDecimal(), RealName = request.AccountName, BankCardNo = request.BankCardNo, Remark = request.Remark, PayStatus = PayStatus.APPLY.ToString(), CreateTime = DateTime.Now }; _fundOutOrderRepository.Add(fundoutOrder); var saveResult = _fundOutOrderRepository.SaveChanges(); if (!saveResult.Success) { _logger.Error(TraceType.BLL.ToString(), CallResultStatus.ERROR.ToString(), service, $"{nameof(_fundOutOrderRepository)}.SaveChanges()", "保存代付订单数据失败", saveResult.FirstException, fundoutOrder); return(new XResult <YeePaySinglePayResponse>(null, ErrorCode.DB_UPDATE_FAILED, new DbUpdateException("保存代付订单数据失败"))); } String traceMethod = $"{nameof(YeePayFundOutUtil)}.Execute(...)"; _logger.Trace(TraceType.BLL.ToString(), CallResultStatus.OK.ToString(), service, traceMethod, LogPhase.BEGIN, "开始调用易宝代付支付接口", request); //记录请求开始时间 fundoutOrder.ApplyTime = DateTime.Now; var execResult = YeePayFundOutUtil.Execute <RawYeePaySinglePayRequest, RawYeePaySinglePayResult>("/rest/v1.0/balance/transfer_send", new RawYeePaySinglePayRequest() { orderId = request.OutTradeNo, accountName = request.AccountName, accountNumber = request.BankCardNo, amount = request.Amount, bankCode = request.BankCode, batchNo = fundoutOrder.TradeNo, customerNumber = GlobalConfig.YeePay_FundOut_MerchantNo, groupNumber = GlobalConfig.YeePay_FundOut_MerchantNo, feeType = request.FeeType }); //记录请求结束时间 fundoutOrder.EndTime = DateTime.Now; _logger.Trace(TraceType.BLL.ToString(), (execResult.Success ? CallResultStatus.OK : CallResultStatus.ERROR).ToString(), service, traceMethod, LogPhase.ACTION, "结束调用易宝代付支付接口"); if (!execResult.Success) { _logger.Error(TraceType.BLL.ToString(), CallResultStatus.ERROR.ToString(), service, traceMethod, "代付失败", execResult.FirstException, execResult); return(new XResult <YeePaySinglePayResponse>(null, ErrorCode.DEPENDENT_API_CALL_FAILED, new RequestException(execResult.ErrorMessage))); } var respResult = execResult.Value; if (respResult.errorCode != "BAC001") { fundoutOrder.PayStatus = PayStatus.FAILURE.ToString(); UpdateFundOutOrder(fundoutOrder); return(new XResult <YeePaySinglePayResponse>(null, ErrorCode.FAILURE, new RemoteException(respResult.errorMsg.HasValue() ? respResult.errorMsg : "发送请求失败"))); } fundoutOrder.PayStatus = PayStatus.PROCESSING.ToString(); switch (respResult.transferStatusCode) { case "0028": fundoutOrder.PayStatus = PayStatus.FAILURE.ToString(); break; } UpdateFundOutOrder(fundoutOrder); var payResp = new YeePaySinglePayResponse() { BatchNo = respResult.batchNo, OutTradeNo = request.OutTradeNo, Status = fundoutOrder.PayStatus, Msg = GetPayStatusDescription(fundoutOrder.PayStatus) }; return(new XResult <YeePaySinglePayResponse>(payResp)); } finally { _lockProvider.UnLock(requestHash); } }