protected virtual async Task ProcessRefundResponseAsync(WebHookRequest request, RefundResponse refundResponse) { if (refundResponse.PaymentId == Guid.Empty) { return; } // only transferred refunds if (request.Type != "payment.refund_transferred") { return; } try { var paymentResponse = await _paymentApi.GetPaymentAsync(refundResponse.PaymentId); if (paymentResponse != null) { if (!Guid.TryParse(paymentResponse.OrderId, out var orderGuid)) { return; } var order = _orderService.GetOrderByGuid(orderGuid); if (order != null) { var refundIds = _genericAttributeService.GetAttribute <List <string> >(order, Defaults.RefundIdAttributeName) ?? new List <string>(); var refundId = refundResponse.Id.ToString(); if (!refundIds.Contains(refundId)) { if (paymentResponse.Amount == refundResponse.Amount) { if (_orderProcessingService.CanRefundOffline(order)) { _orderProcessingService.RefundOffline(order); } } else { if (_orderProcessingService.CanPartiallyRefundOffline(order, refundResponse.Amount / 100)) { _orderProcessingService.PartiallyRefundOffline(order, refundResponse.Amount / 100); } } refundIds.Add(refundId); _genericAttributeService.SaveAttribute(order, Defaults.RefundIdAttributeName, refundIds); } } } } catch (ApiException exception) { _logger.Error($"{Defaults.SystemName}: {exception.Message}", exception); } }
public IActionResult RefundWebhook() { try { //validate request var isValid = _serviceManager.ValidateWebhookRequest(Request.Form); if (!isValid) { return(BadRequest()); } //try to get an order for this transaction var orderGuid = Guid.Parse(Request.Form["transaction_id"]); var order = _orderService.GetOrderByGuid(orderGuid); if (order == null) { return(Ok()); } //add order note var details = Request.Form.Aggregate(string.Empty, (message, parameter) => $"{message}{parameter.Key}: {parameter.Value}; "); _orderService.InsertOrderNote(new OrderNote { OrderId = order.Id, Note = $"Webhook details: {Environment.NewLine}{details}", DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); //check transaction status switch (Request.Form["status"].ToString().ToLower()) { //refund processed case "2": //ensure that this refund has not been processed before var refundGuid = _genericAttributeService.GetAttribute <string>(order, Defaults.RefundGuidAttribute); if (refundGuid?.Equals(Request.Form["refund_guid"], StringComparison.InvariantCultureIgnoreCase) ?? false) { break; } if (decimal.TryParse(Request.Form["mb_amount"], out var refundedAmount) && _orderProcessingService.CanPartiallyRefundOffline(order, refundedAmount)) { _orderProcessingService.PartiallyRefundOffline(order, refundedAmount); } break; } } catch { } return(Ok()); }
/// <summary> /// Partially refund /// </summary> /// <param name="order">Order</param> /// <param name="refund">Refund</param> private void MarkOrderAsPartiallyRefunded(Core.Domain.Orders.Order order, PayPalCheckoutSdk.Payments.Refund refund) { if (!decimal.TryParse(refund.Amount?.Value, out var refundedAmount)) { return; } if (_orderProcessingService.CanPartiallyRefundOffline(order, refundedAmount)) { _orderProcessingService.PartiallyRefundOffline(order, refundedAmount); } }
/// <remarks>return 503 (HttpStatusCode.ServiceUnavailable) to ask paypal to resend it at later time again</remarks> public HttpStatusCode ProcessWebhook( PayPalApiSettingsBase settings, NameValueCollection headers, string rawJson, string providerSystemName) { if (rawJson.IsEmpty()) { return(HttpStatusCode.OK); } dynamic json = JObject.Parse(rawJson); var eventType = (string)json.event_type; //foreach (var key in headers.AllKeys)"{0}: {1}".FormatInvariant(key, headers[key]).Dump(); //string data = JsonConvert.SerializeObject(json, Formatting.Indented);data.Dump(); // validating against PayPal SDK failing using sandbox, so better we do not use it: //var apiContext = new global::PayPal.Api.APIContext //{ // AccessToken = "I do not have one here", // Config = new Dictionary<string, string> // { // { "mode", settings.UseSandbox ? "sandbox" : "live" }, // { "clientId", settings.ClientId }, // { "clientSecret", settings.Secret }, // { "webhook.id", setting.WebhookId }, // } //}; //var result = global::PayPal.Api.WebhookEvent.ValidateReceivedEvent(apiContext, headers, rawJson, webhookId); //} var paymentId = (string)json.resource.parent_payment; if (paymentId.IsEmpty()) { LogError(null, T("Plugins.SmartStore.PayPal.FoundOrderForPayment", 0, "".NaIfEmpty()), JsonConvert.SerializeObject(json, Formatting.Indented), isWarning: true); return(HttpStatusCode.OK); } var orders = _orderRepository.Value.Table .Where(x => x.PaymentMethodSystemName == providerSystemName && x.AuthorizationTransactionCode == paymentId) .ToList(); if (orders.Count != 1) { LogError(null, T("Plugins.SmartStore.PayPal.FoundOrderForPayment", orders.Count, paymentId), JsonConvert.SerializeObject(json, Formatting.Indented), isWarning: true); return(HttpStatusCode.OK); } var order = orders.First(); var store = _services.StoreService.GetStoreById(order.StoreId); var total = decimal.Zero; var currency = (string)json.resource.amount.currency; var primaryCurrency = store.PrimaryStoreCurrency.CurrencyCode; if (!primaryCurrency.IsCaseInsensitiveEqual(currency)) { LogError(null, T("Plugins.SmartStore.PayPal.CurrencyNotEqual", currency.NaIfEmpty(), primaryCurrency), JsonConvert.SerializeObject(json, Formatting.Indented), isWarning: true); return(HttpStatusCode.OK); } eventType = eventType.Substring(eventType.LastIndexOf('.') + 1); var newPaymentStatus = GetPaymentStatus(eventType, "authorization", order.PaymentStatus); var isValidTotal = decimal.TryParse((string)json.resource.amount.total, NumberStyles.Currency, CultureInfo.InvariantCulture, out total); if (newPaymentStatus == PaymentStatus.Refunded && (Math.Abs(order.OrderTotal) - Math.Abs(total)) > decimal.Zero) { newPaymentStatus = PaymentStatus.PartiallyRefunded; } switch (newPaymentStatus) { case PaymentStatus.Pending: break; case PaymentStatus.Authorized: if (_orderProcessingService.CanMarkOrderAsAuthorized(order)) { _orderProcessingService.MarkAsAuthorized(order); } break; case PaymentStatus.Paid: if (_orderProcessingService.CanMarkOrderAsPaid(order)) { _orderProcessingService.MarkOrderAsPaid(order); } break; case PaymentStatus.Refunded: if (_orderProcessingService.CanRefundOffline(order)) { _orderProcessingService.RefundOffline(order); } break; case PaymentStatus.PartiallyRefunded: if (_orderProcessingService.CanPartiallyRefundOffline(order, Math.Abs(total))) { _orderProcessingService.PartiallyRefundOffline(order, Math.Abs(total)); } break; case PaymentStatus.Voided: if (_orderProcessingService.CanVoidOffline(order)) { _orderProcessingService.VoidOffline(order); } break; } order.HasNewPaymentNotification = true; AddOrderNote(settings, order, (string)ToInfoString(json)); return(HttpStatusCode.OK); }
public ActionResult IPNHandler() { byte[] param = Request.BinaryRead(Request.ContentLength); string strRequest = Encoding.ASCII.GetString(param); Dictionary <string, string> values; var processor = _paymentService.LoadPaymentMethodBySystemName("Payments.PayPalStandard") as PayPalStandardPaymentProcessor; if (processor == null || !processor.IsPaymentMethodActive(_paymentSettings) || !processor.PluginDescriptor.Installed) { throw new NopException("PayPal Standard module cannot be loaded"); } if (processor.VerifyIpn(strRequest, out values)) { #region values decimal mc_gross = decimal.Zero; try { mc_gross = decimal.Parse(values["mc_gross"], new CultureInfo("en-US")); } catch { } string payer_status = string.Empty; values.TryGetValue("payer_status", out payer_status); string payment_status = string.Empty; values.TryGetValue("payment_status", out payment_status); string pending_reason = string.Empty; values.TryGetValue("pending_reason", out pending_reason); string mc_currency = string.Empty; values.TryGetValue("mc_currency", out mc_currency); string txn_id = string.Empty; values.TryGetValue("txn_id", out txn_id); string txn_type = string.Empty; values.TryGetValue("txn_type", out txn_type); string rp_invoice_id = string.Empty; values.TryGetValue("rp_invoice_id", out rp_invoice_id); string payment_type = string.Empty; values.TryGetValue("payment_type", out payment_type); string payer_id = string.Empty; values.TryGetValue("payer_id", out payer_id); string receiver_id = string.Empty; values.TryGetValue("receiver_id", out receiver_id); string invoice = string.Empty; values.TryGetValue("invoice", out invoice); string payment_fee = string.Empty; values.TryGetValue("payment_fee", out payment_fee); #endregion var sb = new StringBuilder(); sb.AppendLine("Paypal IPN:"); foreach (KeyValuePair <string, string> kvp in values) { sb.AppendLine(kvp.Key + ": " + kvp.Value); } var newPaymentStatus = PaypalHelper.GetPaymentStatus(payment_status, pending_reason); sb.AppendLine("New payment status: " + newPaymentStatus); switch (txn_type) { case "recurring_payment_profile_created": //do nothing here break; #region Recurring payment case "recurring_payment": { Guid orderNumberGuid = Guid.Empty; try { orderNumberGuid = new Guid(rp_invoice_id); } catch { } var initialOrder = _orderService.GetOrderByGuid(orderNumberGuid); if (initialOrder != null) { var recurringPayments = _orderService.SearchRecurringPayments(initialOrderId: initialOrder.Id); foreach (var rp in recurringPayments) { switch (newPaymentStatus) { case PaymentStatus.Authorized: case PaymentStatus.Paid: { var recurringPaymentHistory = rp.RecurringPaymentHistory; if (!recurringPaymentHistory.Any()) { //first payment var rph = new RecurringPaymentHistory { RecurringPaymentId = rp.Id, OrderId = initialOrder.Id, CreatedOnUtc = DateTime.UtcNow }; rp.RecurringPaymentHistory.Add(rph); _orderService.UpdateRecurringPayment(rp); } else { //next payments var processPaymentResult = new ProcessPaymentResult(); processPaymentResult.NewPaymentStatus = newPaymentStatus; if (newPaymentStatus == PaymentStatus.Authorized) { processPaymentResult.AuthorizationTransactionId = txn_id; } else { processPaymentResult.CaptureTransactionId = txn_id; } _orderProcessingService.ProcessNextRecurringPayment(rp, processPaymentResult); } } break; case PaymentStatus.Voided: //failed payment var failedPaymentResult = new ProcessPaymentResult { Errors = new[] { string.Format("PayPal IPN. Recurring payment is {0} .", payment_status) }, RecurringPaymentFailed = true }; _orderProcessingService.ProcessNextRecurringPayment(rp, failedPaymentResult); break; } } //this.OrderService.InsertOrderNote(newOrder.OrderId, sb.ToString(), DateTime.UtcNow); _logger.Information("PayPal IPN. Recurring info", new NopException(sb.ToString())); } else { _logger.Error("PayPal IPN. Order is not found", new NopException(sb.ToString())); } } break; case "recurring_payment_failed": var orderGuid = Guid.Empty; if (Guid.TryParse(rp_invoice_id, out orderGuid)) { var initialOrder = _orderService.GetOrderByGuid(orderGuid); if (initialOrder != null) { var recurringPayment = _orderService.SearchRecurringPayments(initialOrderId: initialOrder.Id).FirstOrDefault(); //failed payment if (recurringPayment != null) { _orderProcessingService.ProcessNextRecurringPayment(recurringPayment, new ProcessPaymentResult { Errors = new[] { txn_type }, RecurringPaymentFailed = true }); } } } break; #endregion default: #region Standard payment { string orderNumber = string.Empty; values.TryGetValue("custom", out orderNumber); Guid orderNumberGuid = Guid.Empty; try { orderNumberGuid = new Guid(orderNumber); } catch { } var order = _orderService.GetOrderByGuid(orderNumberGuid); if (order != null) { //order note order.OrderNotes.Add(new OrderNote { Note = sb.ToString(), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); _orderService.UpdateOrder(order); switch (newPaymentStatus) { case PaymentStatus.Pending: { } break; case PaymentStatus.Authorized: { //validate order total if (Math.Round(mc_gross, 2).Equals(Math.Round(order.OrderTotal, 2))) { //valid if (_orderProcessingService.CanMarkOrderAsAuthorized(order)) { _orderProcessingService.MarkAsAuthorized(order); } } else { //not valid string errorStr = string.Format("PayPal IPN. Returned order total {0} doesn't equal order total {1}. Order# {2}.", mc_gross, order.OrderTotal, order.Id); //log _logger.Error(errorStr); //order note order.OrderNotes.Add(new OrderNote { Note = errorStr, DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); _orderService.UpdateOrder(order); } } break; case PaymentStatus.Paid: { //validate order total if (Math.Round(mc_gross, 2).Equals(Math.Round(order.OrderTotal, 2))) { //valid if (_orderProcessingService.CanMarkOrderAsPaid(order)) { order.AuthorizationTransactionId = txn_id; _orderService.UpdateOrder(order); _orderProcessingService.MarkOrderAsPaid(order); } } else { //not valid string errorStr = string.Format("PayPal IPN. Returned order total {0} doesn't equal order total {1}. Order# {2}.", mc_gross, order.OrderTotal, order.Id); //log _logger.Error(errorStr); //order note order.OrderNotes.Add(new OrderNote { Note = errorStr, DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); _orderService.UpdateOrder(order); } } break; case PaymentStatus.Refunded: { var totalToRefund = Math.Abs(mc_gross); if (totalToRefund > 0 && Math.Round(totalToRefund, 2).Equals(Math.Round(order.OrderTotal, 2))) { //refund if (_orderProcessingService.CanRefundOffline(order)) { _orderProcessingService.RefundOffline(order); } } else { //partial refund if (_orderProcessingService.CanPartiallyRefundOffline(order, totalToRefund)) { _orderProcessingService.PartiallyRefundOffline(order, totalToRefund); } } } break; case PaymentStatus.Voided: { if (_orderProcessingService.CanVoidOffline(order)) { _orderProcessingService.VoidOffline(order); } } break; default: break; } } else { _logger.Error("PayPal IPN. Order is not found", new NopException(sb.ToString())); } } #endregion break; } } else { _logger.Error("PayPal IPN failed.", new NopException(strRequest)); } //nothing should be rendered to visitor return(Content("")); }
public ActionResult IPNHandler(FormCollection form, int?storeId) { Order order; if (!ValidateIPN(form, storeId, out order)) { return(new HttpStatusCodeResult(HttpStatusCode.OK)); } //order note var note = new StringBuilder(); foreach (string key in form.Keys) { note.AppendFormat("{0}: {1}{2}", key, form[key], Environment.NewLine); } order.OrderNotes.Add(new OrderNote() { Note = note.ToString(), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); _orderService.UpdateOrder(order); //change order status switch (form["status"].ToLowerInvariant()) { case "complete": //paid order if (_orderProcessingService.CanMarkOrderAsPaid(order)) { order.CaptureTransactionId = form["transactionId"]; _orderService.UpdateOrder(order); _orderProcessingService.MarkOrderAsPaid(order); } break; case "partial_refunded": //partially refund order decimal amount; if (decimal.TryParse(form["refundedAmount"], out amount) && _orderProcessingService.CanPartiallyRefund(order, amount)) { _orderProcessingService.PartiallyRefundOffline(order, amount); } break; case "refunded": //refund order if (_orderProcessingService.CanRefund(order)) { _orderProcessingService.RefundOffline(order); } break; case "pending": //do not logging for pending status break; default: _logger.Error(string.Format("G2A Pay IPN error: transaction is {0}", form["status"])); break; } return(new HttpStatusCodeResult(HttpStatusCode.OK)); }
protected virtual void ProcessPayment(string orderNumber, string ipnInfo, PaymentStatus newPaymentStatus, decimal mcGross, string transactionId) { Guid orderNumberGuid; try { orderNumberGuid = new Guid(orderNumber); } catch { orderNumberGuid = Guid.Empty; } var order = _orderService.GetOrderByGuid(orderNumberGuid); if (order == null) { _logger.Error("PayPal IPN. Order is not found", new NopException(ipnInfo)); return; } //order note _orderService.InsertOrderNote(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 = $"PayPal IPN. Returned order total {mcGross} doesn't equal order total {order.OrderTotal}. Order# {order.Id}."; //log _logger.Error(errorStr); //order note _orderService.InsertOrderNote(new OrderNote { OrderId = order.Id, Note = errorStr, DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); return; } switch (newPaymentStatus) { case PaymentStatus.Authorized: if (_orderProcessingService.CanMarkOrderAsAuthorized(order)) { _orderProcessingService.MarkAsAuthorized(order); } break; case PaymentStatus.Paid: if (_orderProcessingService.CanMarkOrderAsPaid(order)) { order.AuthorizationTransactionId = transactionId; _orderService.UpdateOrder(order); _orderProcessingService.MarkOrderAsPaid(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)) { _orderProcessingService.RefundOffline(order); } } else { //partial refund if (_orderProcessingService.CanPartiallyRefundOffline(order, totalToRefund)) { _orderProcessingService.PartiallyRefundOffline(order, totalToRefund); } } break; case PaymentStatus.Voided: if (_orderProcessingService.CanVoidOffline(order)) { _orderProcessingService.VoidOffline(order); } break; } }
/// <summary> /// Partially refunds an order (offline) /// </summary> /// <param name="order">Order</param> /// <param name="amountToRefund">Amount to refund</param> public void PartiallyRefundOffline(Order order, decimal amountToRefund) { _orderProcessingService.PartiallyRefundOffline(order, amountToRefund); }
public IActionResult IPNHandler(IFormCollection form) { //byte[] parameters; //using (var stream = new MemoryStream()) //{ // this.Request.Body.CopyTo(stream); // parameters = stream.ToArray(); //} //var strRequest = Encoding.ASCII.GetString(parameters); var processor = _paymentService.LoadPaymentMethodBySystemName("Payments.MOLPay") as MOLPayPaymentProcessor; if (processor == null || !processor.IsPaymentMethodActive(_paymentSettings) || !processor.PluginDescriptor.Installed) { throw new NopException("MOLPay module cannot be loaded"); } //if (processor.VerifyIpn(strRequest, out Dictionary<string, string> values)) //{ #region values var mc_gross = decimal.Zero; try { mc_gross = decimal.Parse(form["mc_gross"], new CultureInfo("en-US")); } catch { } //values.TryGetValue("payer_status", out string payer_status); //values.TryGetValue("payment_status", out string payment_status); //values.TryGetValue("pending_reason", out string pending_reason); //values.TryGetValue("mc_currency", out string mc_currency); //values.TryGetValue("txn_id", out string txn_id); //values.TryGetValue("txn_type", out string txn_type); //values.TryGetValue("rp_invoice_id", out string rp_invoice_id); //values.TryGetValue("payment_type", out string payment_type); //values.TryGetValue("payer_id", out string payer_id); //values.TryGetValue("receiver_id", out string receiver_id); //values.TryGetValue("invoice", out string _); //values.TryGetValue("payment_fee", out string payment_fee); #endregion var skey = form["skey"]; var tranID = form["tranID"]; var domain = form["domain"]; var status = form["status"]; var amount = form["amount"]; var currency = form["currency"]; var paydate = form["paydate"]; int orderid = Int32.Parse(form["orderid"]); var appcode = form["appcode"]; var error_code = form["error_code"]; var error_desc = form["error_desc"]; string txn_type = form["txn_type"]; var rp_invoice_id = form["rp_invoice_id"]; var txn_id = form["txn_id"]; var channel = form["channel"]; var sb = new StringBuilder(); sb.AppendLine("MOLPay IPN:"); foreach (var kvp in form) { sb.AppendLine(kvp.Key + ": " + kvp.Value); } var captured = _molPayPaymentSettings.CapturedMode; var failed = _molPayPaymentSettings.FailedMode; var pending = _molPayPaymentSettings.PendingMode; var result = pending; switch (status) { case "00": result = captured; break; case "11": result = failed; break; case "22": result = pending; break; default: break; } //var newPaymentStatus = MOLPayHelper.GetPaymentStatus(payment_status); var newPaymentStatus = result; sb.AppendLine("New payment status: " + newPaymentStatus); switch (txn_type) { case "recurring_payment_profile_created": //do nothing here break; #region Recurring payment case "recurring_payment": { var orderNumberGuid = Guid.Empty; try { orderNumberGuid = new Guid(rp_invoice_id); } catch { } var initialOrder = _orderService.GetOrderByGuid(orderNumberGuid); if (initialOrder != null) { var recurringPayments = _orderService.SearchRecurringPayments(initialOrderId: initialOrder.Id); foreach (var rp in recurringPayments) { switch (newPaymentStatus) { case PaymentStatus.Authorized: case PaymentStatus.Paid: { var recurringPaymentHistory = rp.RecurringPaymentHistory; if (!recurringPaymentHistory.Any()) { //first payment var rph = new RecurringPaymentHistory { RecurringPaymentId = rp.Id, OrderId = initialOrder.Id, CreatedOnUtc = DateTime.UtcNow }; rp.RecurringPaymentHistory.Add(rph); _orderService.UpdateRecurringPayment(rp); } else { //next payments var processPaymentResult = new ProcessPaymentResult { NewPaymentStatus = newPaymentStatus }; if (newPaymentStatus == PaymentStatus.Authorized) { processPaymentResult.AuthorizationTransactionId = txn_id; } else { processPaymentResult.CaptureTransactionId = txn_id; } _orderProcessingService.ProcessNextRecurringPayment(rp, processPaymentResult); } } break; case PaymentStatus.Voided: //failed payment var failedPaymentResult = new ProcessPaymentResult { Errors = new[] { $"MOLPay IPN. Recurring payment is {newPaymentStatus} ." }, RecurringPaymentFailed = true }; _orderProcessingService.ProcessNextRecurringPayment(rp, failedPaymentResult); break; } } //this.OrderService.InsertOrderNote(newOrder.OrderId, sb.ToString(), DateTime.UtcNow); _logger.Information("MOLPay IPN. Recurring info", new NopException(sb.ToString())); } else { _logger.Error("MOLPay IPN. Order is not found", new NopException(sb.ToString())); } } break; case "recurring_payment_failed": if (Guid.TryParse(rp_invoice_id, out Guid orderGuid)) { var initialOrder = _orderService.GetOrderByGuid(orderGuid); if (initialOrder != null) { var recurringPayment = _orderService.SearchRecurringPayments(initialOrderId: initialOrder.Id).FirstOrDefault(); //failed payment if (recurringPayment != null) { _orderProcessingService.ProcessNextRecurringPayment(recurringPayment, new ProcessPaymentResult { Errors = new[] { txn_type }, RecurringPaymentFailed = true }); } } } break; #endregion default: #region Standard payment { //values.TryGetValue("custom", out string orderNumber); var orderNumber = form["custom"]; var orderNumberGuid = Guid.Empty; try { orderNumberGuid = new Guid(orderNumber); } catch { } var order = _orderService.GetOrderByGuid(orderNumberGuid); if (order != null) { //order note order.OrderNotes.Add(new OrderNote { Note = sb.ToString(), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); _orderService.UpdateOrder(order); switch (newPaymentStatus) { case PaymentStatus.Pending: { } break; case PaymentStatus.Authorized: { //validate order total if (Math.Round(mc_gross, 2).Equals(Math.Round(order.OrderTotal, 2))) { //valid if (_orderProcessingService.CanMarkOrderAsAuthorized(order)) { _orderProcessingService.MarkAsAuthorized(order); } } else { //not valid var errorStr = $"MOLPay IPN. Returned order total {mc_gross} doesn't equal order total {order.OrderTotal}. Order# {order.Id}."; //log _logger.Error(errorStr); //order note order.OrderNotes.Add(new OrderNote { Note = errorStr, DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); _orderService.UpdateOrder(order); } } break; case PaymentStatus.Paid: { //validate order total if (Math.Round(mc_gross, 2).Equals(Math.Round(order.OrderTotal, 2))) { //valid if (_orderProcessingService.CanMarkOrderAsPaid(order)) { order.AuthorizationTransactionId = txn_id; _orderService.UpdateOrder(order); _orderProcessingService.MarkOrderAsPaid(order); } } else { //not valid var errorStr = $"MOLPay IPN. Returned order total {mc_gross} doesn't equal order total {order.OrderTotal}. Order# {order.Id}."; //log _logger.Error(errorStr); //order note order.OrderNotes.Add(new OrderNote { Note = errorStr, DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); _orderService.UpdateOrder(order); } } break; case PaymentStatus.Refunded: { var totalToRefund = Math.Abs(mc_gross); if (totalToRefund > 0 && Math.Round(totalToRefund, 2).Equals(Math.Round(order.OrderTotal, 2))) { //refund if (_orderProcessingService.CanRefundOffline(order)) { _orderProcessingService.RefundOffline(order); } } else { //partial refund if (_orderProcessingService.CanPartiallyRefundOffline(order, totalToRefund)) { _orderProcessingService.PartiallyRefundOffline(order, totalToRefund); } } } break; case PaymentStatus.Voided: { if (_orderProcessingService.CanVoidOffline(order)) { _orderProcessingService.VoidOffline(order); } } break; default: break; } } else { _logger.Error("MOLPay IPN. Order is not found", new NopException(sb.ToString())); } } #endregion break; } //} //else //{ // _logger.Error("MOLPay IPN failed.", new NopException(strRequest)); //} //nothing should be rendered to visitor return(Content("")); }