/// <returns>A task that represents the asynchronous operation</returns> protected virtual async Task ProcessPaymentAsync(string orderNumber, string ipnInfo, PaymentStatus newPaymentStatus, decimal mcGross, string transactionId) { Guid orderNumberGuid; try { orderNumberGuid = new Guid(orderNumber); } catch { orderNumberGuid = Guid.Empty; } var order = await _orderService.GetOrderByGuidAsync(orderNumberGuid); if (order == null) { await _logger.ErrorAsync("Paytm IPN. Order is not found", new NopException(ipnInfo)); return; } //order note await _orderService.InsertOrderNoteAsync(new OrderNote { OrderId = order.Id, Note = ipnInfo, DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); //validate order total if ((newPaymentStatus == PaymentStatus.Authorized || newPaymentStatus == PaymentStatus.Paid) && !Math.Round(mcGross, 2).Equals(Math.Round(order.OrderTotal, 2))) { var errorStr = $"Paytm IPN. Returned order total {mcGross} doesn't equal order total {order.OrderTotal}. Order# {order.Id}."; //log await _logger.ErrorAsync(errorStr); //order note await _orderService.InsertOrderNoteAsync(new OrderNote { OrderId = order.Id, Note = errorStr, DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); return; } switch (newPaymentStatus) { case PaymentStatus.Authorized: if (_orderProcessingService.CanMarkOrderAsAuthorized(order)) { await _orderProcessingService.MarkAsAuthorizedAsync(order); } break; case PaymentStatus.Paid: if (_orderProcessingService.CanMarkOrderAsPaid(order)) { order.AuthorizationTransactionId = transactionId; await _orderService.UpdateOrderAsync(order); await _orderProcessingService.MarkOrderAsPaidAsync(order); } break; case PaymentStatus.Refunded: var totalToRefund = Math.Abs(mcGross); if (totalToRefund > 0 && Math.Round(totalToRefund, 2).Equals(Math.Round(order.OrderTotal, 2))) { //refund if (_orderProcessingService.CanRefundOffline(order)) { await _orderProcessingService.RefundOfflineAsync(order); } } else { //partial refund if (_orderProcessingService.CanPartiallyRefundOffline(order, totalToRefund)) { await _orderProcessingService.PartiallyRefundOfflineAsync(order, totalToRefund); } } break; case PaymentStatus.Voided: if (_orderProcessingService.CanVoidOffline(order)) { await _orderProcessingService.VoidOfflineAsync(order); } break; } }