public IActionResult EPay95([FromForm] PayNotifyResult request) { String service = $"{this.GetType().FullName}.EPay95()"; if (request == null) { _logger.Trace(TraceType.API.ToString(), CallResultStatus.ERROR.ToString(), service, "request", LogPhase.ACTION, "通知参数为null"); return(DefaultPostbackFailureResult); } String requestHost = $"{Request.HttpContext.Connection.RemoteIpAddress}:{Request.HttpContext.Connection.RemotePort}"; _logger.Trace(TraceType.API.ToString(), CallResultStatus.OK.ToString(), service, "双乾代付通知", LogPhase.ACTION, "收到通知", new Object[] { requestHost, request }); if (!request.IsValid) { _logger.Error(TraceType.API.ToString(), CallResultStatus.ERROR.ToString(), service, $"{nameof(request)}.IsValid", $"通知参数验证失败:{request.ErrorMessage}"); return(DefaultPostbackFailureResult); } //将LoanJsonList参数解码 request.LoanJsonList = HttpUtility.UrlDecode(request.LoanJsonList); if (!EPay95Util.VerifySign(request)) { _logger.Error(TraceType.API.ToString(), CallResultStatus.ERROR.ToString(), service, "EPay95Util.VerifySign(...)", "通知参数验签失败", null, request); return(DefaultPostbackFailureResult); } String traceMethod = $"{nameof(_epay95FundOutPaymentService)}.UpdatePayStatus(...)"; _logger.Trace(TraceType.API.ToString(), CallResultStatus.OK.ToString(), service, traceMethod, LogPhase.BEGIN); var updateResult = _epay95FundOutPaymentService.UpdatePayStatus(request); _logger.Trace(TraceType.API.ToString(), (updateResult.Success ? CallResultStatus.OK : CallResultStatus.ERROR).ToString(), service, traceMethod, LogPhase.END); if (!updateResult.Success) { _logger.Error(TraceType.API.ToString(), CallResultStatus.ERROR.ToString(), service, "双乾代付通知", "处理双乾代付通知失败", updateResult.FirstException, request); return(DefaultPostbackFailureResult); } return(DefaultPostbackSuccessResult); }
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); } }