public void SendEarlyRefundTicket(EarlyRefundTicket ticket, RefundReason reason) { if (Logger.IsTrace) { Logger.Trace($"{Session.RemoteNodeId} NDM sending: earlyrefundticket"); } Send(new EarlyRefundTicketMessage(ticket, reason)); }
public RefundReason SecondRefundReason() { var secondRefundReason = new RefundReason { RefundReasonId = 2, RefundReasonValue = "Other reasons" }; return secondRefundReason; }
public RefundReason FirstRefundReason() { var firstRefundReason = new RefundReason { RefundReasonId = 1, RefundReasonValue = "Item not as described" }; return firstRefundReason; }
public void MapSetsRefundReasonCorrectly() { const RefundReason expectedRefundReason = RefundReason.Other; Refund refund = _refundFactory.Map(new RefundEntity { ReasonId = (short)expectedRefundReason }); Assert.AreEqual(expectedRefundReason, refund.RefundReason, "Refund RefundReason mapped incorrectly."); }
public async Task set_early_refund_ticket_should_fail_if_deposit_does_not_exits() { const RefundReason reason = RefundReason.DataDiscontinued; var ticket = new EarlyRefundTicket(TestItem.KeccakA, 0, null); var refundService = new RefundService(_ndmBridge, _abiEncoder, _depositRepository, _contractAddress, LimboLogs.Instance); await refundService.SetEarlyRefundTicketAsync(ticket, reason); await _depositRepository.Received().GetAsync(ticket.DepositId); await _depositRepository.DidNotReceiveWithAnyArgs().UpdateAsync(null); }
public void MapMapsRefundReasonToEntityRefundReasonId() { const RefundReason expectedRefundReason = RefundReason.Other; Refund refund = GetValidRefund(); refund.RefundReason = expectedRefundReason; RefundEntity refundEntity = _refundFactory.Map(refund); Assert.AreEqual((short)expectedRefundReason, refundEntity.ReasonId, "RefundEntity ReasonID mapped incorrectly."); }
/// <summary> /// Process a product Return / Refund. /// </summary> /// <remarks> /// <para>This method does not wrap a single, dedicated "ReturnEvent" call in the point-js API.</para> /// <para>Instead:</para> /// <para> /// If no arguments are provided, we simply call <see cref="ShowGUI"/> with the shortcut "refund". /// Otherwise, if a Touch Transaction ID and Reason is supplied, we call the GUI-less /// <see cref="AddItem"/> /// with the shortcut = "refund" and a Dictionary containing the Touch Transaction ID and Reason. /// </para> /// </remarks> /// <param name="transactionId"></param> /// <param name="reason"></param> public void Refund(string transactionId = "", RefundReason reason = RefundReason.OTHER) { if (string.IsNullOrEmpty(transactionId)) { ShowGui("refund"); } else { var data = new Dictionary <string, string>(); data.Add("transactionId", transactionId); data.Add("reason", reason.ToString()); AddItem("refund", data); } }
public async Task set_early_refund_ticket_should_succeed_if_deposit_exists() { const RefundReason reason = RefundReason.DataDiscontinued; var deposit = new Deposit(TestItem.KeccakA, 1, 1, 1); var depositDetails = new DepositDetails(deposit, null, null, null, 0, null, 0); var ticket = new EarlyRefundTicket(deposit.Id, 0, null); var refundService = new RefundService(_ndmBridge, _abiEncoder, _depositRepository, _contractAddress, LimboLogs.Instance); _depositRepository.GetAsync(ticket.DepositId).Returns(depositDetails); await refundService.SetEarlyRefundTicketAsync(ticket, reason); depositDetails.EarlyRefundTicket.Should().Be(ticket); await _depositRepository.Received().GetAsync(ticket.DepositId); await _depositRepository.Received().UpdateAsync(depositDetails); }
public async Task SetEarlyRefundTicketAsync(EarlyRefundTicket ticket, RefundReason reason) { var depositDetails = await _depositRepository.GetAsync(ticket.DepositId); if (depositDetails is null) { return; } depositDetails.SetEarlyRefundTicket(ticket); await _depositRepository.UpdateAsync(depositDetails); if (_logger.IsInfo) { _logger.Info($"Early refund claim for deposit: '{ticket.DepositId}', reason: '{reason}'."); } }
public Task SetEarlyRefundTicketAsync(EarlyRefundTicket ticket, RefundReason reason) => _refundService.SetEarlyRefundTicketAsync(ticket, reason);
public async Task <IActionResult> ReturnOrder(OrderViewModel viewModel, RefundStatus refundStatus, RefundReason refundReason) { return(await ModifyOrderView("ReturnDone", viewModel, async order => { #region Fraud Protection Service var refund = new Refund { RefundId = Guid.NewGuid().ToString(), Amount = order.Total, Currency = order.RiskPurchase?.Currency, BankEventTimestamp = DateTimeOffset.Now, PurchaseId = order.RiskPurchase.PurchaseId, Reason = refundReason.ToString(), Status = refundStatus.ToString(), UserId = order.RiskPurchase.User.UserId, }; var correlationId = _fraudProtectionService.NewCorrelationId; var response = await _fraudProtectionService.PostRefund(refund, correlationId); var fraudProtectionIO = new FraudProtectionIOModel(correlationId, refund, response, "Refund"); TempData.Put(FraudProtectionIOModel.TempDataKey, fraudProtectionIO); #endregion order.ReturnOrChargebackReason = refundReason.ToString(); order.Status = refundStatus == RefundStatus.Approved ? OrderStatus.ReturnCompleted : OrderStatus.ReturnRejected; order.RiskRefund = refund; order.RiskRefundResponse = response; })); }
public EarlyRefundTicketMessage(EarlyRefundTicket ticket, RefundReason reason) { Ticket = ticket; Reason = reason; }
public async Task <Result <List <OrderRefund> > > ProceedRefund(int orderId, RefundReason refundReason, OrderStatus?setOrderStatus = null, decimal?requestRefundAmount = null) { if (_me.IsAnonymous) { return(new Failure <List <OrderRefund> >("需要先登录")); } var order = _db.Orders .Include(x => x.Payments).ThenInclude(x => x.Refunds) .Where(x => x.BuyerId == _me.Id) .Where(x => x.Id == orderId) .SingleOrDefault(); if (order == null) { return(new Failure <List <OrderRefund> >("退款失败,未找到订单")); } const int daysToRefundAfterOrderCompleted = 30; if (order.CompletedTime.HasValue && order.CompletedTime < DateTime.Now.AddDays(daysToRefundAfterOrderCompleted)) { return(new Failure <List <OrderRefund> >($"只能在订单完成后的 {daysToRefundAfterOrderCompleted} 天内进行退款")); } if (_alipay == null && order.Payments.Any(x => x.Choise == PaymentChoise.Alipay)) { throw new ArgumentNullException(nameof(_alipay)); } if (_wechat == null && order.Payments.Any(x => x.Choise == PaymentChoise.WeChat)) { throw new ArgumentNullException(nameof(_wechat)); } var totalPaid = order.Payments .Where(x => x.Status == PaymentStatus.Paid) .Sum(x => x.Amount); var refundedBefore = order.Payments.SelectMany(x => x.Refunds) .Where(x => x.Status != RefundStatus.Cancelled) .Sum(x => x.Amount); var refundMaxAllowed = totalPaid - refundedBefore; if (requestRefundAmount.HasValue && requestRefundAmount.Value > refundMaxAllowed) { return(new Failure <List <OrderRefund> >("超出总共可退款金额")); } var refundRemained = requestRefundAmount ?? refundMaxAllowed; var pending = new List <OrderRefund>(); //遍历该订单下的付款记录,依次轮询并使用可退款金额,并插入待退款记录(OrderRefund) foreach (var payment in order.Payments) { if (payment.Status != PaymentStatus.Paid) { continue; } var refundable = payment.Amount - payment.Refunds.Where(x => x.Status != RefundStatus.Cancelled).Sum(x => x.Amount); var refunding = Math.Min(refundRemained, refundable); var refund = new OrderRefund { RefundNo = OrderIdGen.New(), Amount = refunding, Reason = refundReason, Status = RefundStatus.Await }; payment.Refunds.Add(refund); pending.Add(refund); refundRemained -= refunding; if (refundRemained <= 0) { break; } } order.Logs.Add(new OrderLog { Remarks = $"发生退款 {refundRemained:f2} 元" }); if (setOrderStatus.HasValue && setOrderStatus != order.Status) { order.Logs.Add(new OrderLog { StatusFrom = order.Status, StatusChangedTo = setOrderStatus, Remarks = $"因退款,订单状态发生变化" }); order.Status = setOrderStatus.Value; } //先保存一次数据 await _db.Normalize().SaveChangesAsync(); //保存之后,再实际请求API进行退款;若退款成功,再改变新增退款记录的状态并保存 foreach (var refund in pending) { Result result = null !; switch (refund.OriginalPayment.Choise) { case PaymentChoise.WeChat: result = _wechat !.PayService().Refund( refund.OriginalPayment.AppId !, refund.OriginalPayment.PaymentNo, refund.RefundNo, refund.OriginalPayment.Amount, refund.Amount, refund.Reason.ToLabel() ); break; case PaymentChoise.Alipay: result = _alipay !.Refund( refund.OriginalPayment.PaymentNo, refund.RefundNo, refund.Amount, refund.Reason.ToLabel() ); break; } refund.Status = result.Ok ? RefundStatus.Refunded : RefundStatus.Checking; refund.ResultMessage = result.Message; } //再次保存数据,更新刚新插入 OrderRefund 的状态 await _db.Normalize().SaveChangesAsync(); //返回执行结果 if (pending.Any(x => x.Status != RefundStatus.Refunded)) { var choises = string.Join("及", pending.Select(x => x.OriginalPayment.Choise).Distinct().ToArray()); return(new Success <List <OrderRefund> >($"已提交退款,但{choises}返回信息未成功", pending)); } return(new Success <List <OrderRefund> >(pending)); }