public async Task <IList <string> > Handle(CaptureCommand command, CancellationToken cancellationToken)
        {
            var paymentTransaction = command.PaymentTransaction;

            if (paymentTransaction == null)
            {
                throw new ArgumentNullException(nameof(command.PaymentTransaction));
            }

            var canCapture = await _mediator.Send(new CanCaptureQuery()
            {
                PaymentTransaction = paymentTransaction
            });

            if (!canCapture)
            {
                throw new GrandException("Cannot do capture for order.");
            }

            CapturePaymentResult result = null;

            try
            {
                result = await _paymentService.Capture(paymentTransaction);

                //event notification
                await _mediator.CapturePaymentTransactionDetailsEvent(result, paymentTransaction);

                if (result.Success)
                {
                    paymentTransaction = await _paymentTransaction.GetById(paymentTransaction.Id);

                    paymentTransaction.PaidAmount               = paymentTransaction.TransactionAmount;
                    paymentTransaction.CaptureTransactionId     = result.CaptureTransactionId;
                    paymentTransaction.CaptureTransactionResult = result.CaptureTransactionResult;
                    paymentTransaction.TransactionStatus        = result.NewPaymentStatus;

                    await _paymentTransaction.UpdatePaymentTransaction(paymentTransaction);

                    var order = await _orderService.GetOrderByGuid(paymentTransaction.OrderGuid);

                    if (order != null && paymentTransaction.TransactionStatus == TransactionStatus.Paid)
                    {
                        order.PaidAmount      = paymentTransaction.PaidAmount;
                        order.PaymentStatusId = PaymentStatus.Paid;
                        order.PaidDateUtc     = DateTime.UtcNow;
                        await _orderService.UpdateOrder(order);

                        await _mediator.Send(new CheckOrderStatusCommand()
                        {
                            Order = order
                        });

                        if (order.PaymentStatusId == PaymentStatus.Paid)
                        {
                            await _mediator.Send(new ProcessOrderPaidCommand()
                            {
                                Order = order
                            });
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                if (result == null)
                {
                    result = new CapturePaymentResult();
                }
                result.AddError(string.Format("Error: {0}. Full exception: {1}", exc.Message, exc));
            }


            //process errors
            string error = "";

            for (int i = 0; i < result.Errors.Count; i++)
            {
                error += string.Format("Error {0}: {1}", i, result.Errors[i]);
                if (i != result.Errors.Count - 1)
                {
                    error += ". ";
                }
            }
            if (!String.IsNullOrEmpty(error))
            {
                //log it
                await _logger.InsertLog(LogLevel.Error, $"Error capturing order code # {paymentTransaction.OrderCode}. Error: {error}", $"Error capturing order code # {paymentTransaction.OrderCode}. Error: {error}");
            }
            return(result.Errors);
        }
        public async Task <IList <string> > Handle(PartiallyRefundCommand command, CancellationToken cancellationToken)
        {
            var paymentTransaction = command.PaymentTransaction;

            if (paymentTransaction == null)
            {
                throw new ArgumentNullException(nameof(command.PaymentTransaction));
            }

            var amountToRefund = command.AmountToRefund;

            var canPartiallyRefund = await _mediator.Send(new CanPartiallyRefundQuery()
            {
                AmountToRefund = amountToRefund, PaymentTransaction = paymentTransaction
            });

            if (!canPartiallyRefund)
            {
                throw new GrandException("Cannot do partial refund for order.");
            }

            var request = new RefundPaymentRequest();
            RefundPaymentResult result = null;

            try
            {
                request.PaymentTransaction = paymentTransaction;
                request.AmountToRefund     = amountToRefund;
                request.IsPartialRefund    = true;

                result = await _paymentService.Refund(request);

                if (result.Success)
                {
                    paymentTransaction = await _paymentTransactionService.GetById(paymentTransaction.Id);

                    paymentTransaction.TransactionStatus = result.NewTransactionStatus;
                    paymentTransaction.RefundedAmount   += amountToRefund;
                    await _paymentTransactionService.UpdatePaymentTransaction(paymentTransaction);

                    var order = await _orderService.GetOrderByGuid(paymentTransaction.OrderGuid);

                    if (order == null)
                    {
                        throw new ArgumentNullException(nameof(order));
                    }

                    //total amount refunded
                    if (paymentTransaction.TransactionStatus == Domain.Payments.TransactionStatus.Refunded)
                    {
                        double totalAmountRefunded = order.RefundedAmount + amountToRefund;

                        order.RefundedAmount  = totalAmountRefunded;
                        order.PaymentStatusId = order.RefundedAmount == order.OrderTotal ? Domain.Payments.PaymentStatus.Refunded : Domain.Payments.PaymentStatus.PartiallyRefunded;
                        await _orderService.UpdateOrder(order);

                        //check order status
                        await _mediator.Send(new CheckOrderStatusCommand()
                        {
                            Order = order
                        });

                        //notifications
                        var orderRefundedStoreOwnerNotificationQueuedEmailId = await _messageProviderService.SendOrderRefundedStoreOwnerMessage(order, amountToRefund, _languageSettings.DefaultAdminLanguageId);

                        if (orderRefundedStoreOwnerNotificationQueuedEmailId > 0)
                        {
                            await _orderService.InsertOrderNote(new OrderNote
                            {
                                Note = "Order refunded email (to store owner) has been queued.",
                                DisplayToCustomer = false,
                                CreatedOnUtc      = DateTime.UtcNow,
                                OrderId           = order.Id,
                            });
                        }


                        var orderRefundedCustomerNotificationQueuedEmailId = await _messageProviderService.SendOrderRefundedCustomerMessage(order, amountToRefund, order.CustomerLanguageId);

                        if (orderRefundedCustomerNotificationQueuedEmailId > 0)
                        {
                            await _orderService.InsertOrderNote(new OrderNote
                            {
                                Note = "Order refunded email (to customer) has been queued.",
                                DisplayToCustomer = false,
                                CreatedOnUtc      = DateTime.UtcNow,
                                OrderId           = order.Id,
                            });
                        }
                    }
                    //raise event
                    await _mediator.Publish(new PaymentTransactionRefundedEvent(paymentTransaction, amountToRefund));
                }
            }
            catch (Exception exc)
            {
                if (result == null)
                {
                    result = new RefundPaymentResult();
                }
                result.AddError(string.Format("Error: {0}. Full exception: {1}", exc.Message, exc.ToString()));
            }

            //process errors
            string error = "";

            for (int i = 0; i < result.Errors.Count; i++)
            {
                error += string.Format("Error {0}: {1}", i, result.Errors[i]);
                if (i != result.Errors.Count - 1)
                {
                    error += ". ";
                }
            }
            if (!String.IsNullOrEmpty(error))
            {
                string logError = string.Format("Error refunding order #{0}. Error: {1}", paymentTransaction.OrderCode, error);
                await _logger.InsertLog(LogLevel.Error, logError, logError);
            }
            return(result.Errors);
        }
Example #3
0
        public async Task <IActionResult> Edit(string id)
        {
            var paymentTransaction = await _paymentTransactionService.GetById(id);

            if (paymentTransaction == null)
            {
                return(RedirectToAction("List", "PaymentTransaction"));
            }

            if (await _groupService.IsStaff(_workContext.CurrentCustomer) && paymentTransaction.StoreId != _workContext.CurrentCustomer.StaffStoreId)
            {
                return(RedirectToAction("List", "PaymentTransaction"));
            }

            var order = await _orderService.GetOrderByGuid(paymentTransaction.OrderGuid);

            var model = new PaymentTransactionModel();

            model.Id                      = paymentTransaction.Id;
            model.OrderCode               = paymentTransaction.OrderCode;
            model.CustomerEmail           = paymentTransaction.CustomerEmail;
            model.CustomerId              = paymentTransaction.CustomerId;
            model.CurrencyCode            = paymentTransaction.CurrencyCode;
            model.TransactionAmount       = paymentTransaction.TransactionAmount;
            model.PaidAmount              = paymentTransaction.PaidAmount;
            model.PaymentMethodSystemName = paymentTransaction.PaymentMethodSystemName;
            model.RefundedAmount          = paymentTransaction.RefundedAmount;
            model.OrderId                 = order?.Id;
            model.OrderNumber             = order?.OrderNumber;
            model.CreatedOn               = _dateTimeService.ConvertToUserTime(paymentTransaction.CreatedOnUtc, DateTimeKind.Utc);
            model.TransactionStatus       = paymentTransaction.TransactionStatus;
            model.Status                  = paymentTransaction.TransactionStatus.GetTranslationEnum(_translationService, _workContext);
            model.IPAddress               = paymentTransaction.IPAddress;
            model.Description             = paymentTransaction.Description;
            model.AdditionalInfo          = paymentTransaction.AdditionalInfo;


            //payment method buttons
            //model.CanCancelOrder = await _mediator.Send(new CanCancelOrderQuery() { Order = order });
            model.CanCapture = await _mediator.Send(new CanCaptureQuery()
            {
                PaymentTransaction = paymentTransaction
            });

            model.CanMarkAsPaid = await _mediator.Send(new CanMarkPaymentTransactionAsPaidQuery()
            {
                PaymentTransaction = paymentTransaction
            });

            model.CanRefund = await _mediator.Send(new CanRefundQuery()
            {
                PaymentTransaction = paymentTransaction
            });

            model.CanRefundOffline = await _mediator.Send(new CanRefundOfflineQuery()
            {
                PaymentTransaction = paymentTransaction
            });

            model.CanPartiallyRefund = await _mediator.Send(new CanPartiallyRefundQuery()
            {
                PaymentTransaction = paymentTransaction, AmountToRefund = 0
            });

            model.CanPartiallyRefundOffline = await _mediator.Send(new CanPartiallyRefundOfflineQuery()
            {
                PaymentTransaction = paymentTransaction, AmountToRefund = 0
            });

            model.CanPartiallyPaidOffline = await _mediator.Send(new CanPartiallyPaidOfflineQuery()
            {
                PaymentTransaction = paymentTransaction, AmountToPaid = 0
            });

            model.CanVoid = await _mediator.Send(new CanVoidQuery()
            {
                PaymentTransaction = paymentTransaction
            });

            model.CanVoidOffline = await _mediator.Send(new CanVoidOfflineQuery()
            {
                PaymentTransaction = paymentTransaction
            });

            model.MaxAmountToRefund = paymentTransaction.TransactionAmount - paymentTransaction.RefundedAmount;
            model.MaxAmountToPaid   = paymentTransaction.TransactionAmount - paymentTransaction.PaidAmount;

            return(View(model));
        }