/// <summary> /// Inserts a recurring payment history entry /// </summary> /// <param name="recurringPaymentHistory">Recurring payment history entry</param> public virtual void InsertRecurringPaymentHistory(RecurringPaymentHistory recurringPaymentHistory) { if (recurringPaymentHistory == null) { throw new ArgumentNullException(nameof(recurringPaymentHistory)); } _recurringPaymentHistoryRepository.Insert(recurringPaymentHistory); //event notification _eventPublisher.EntityInserted(recurringPaymentHistory); }
public void Can_save_and_load_recurringPaymentHistory() { var rph = new RecurringPaymentHistory() { CreatedOnUtc = new DateTime(2010, 01, 03), RecurringPayment = new RecurringPayment() { StartDateUtc = new DateTime(2010, 01, 01), CreatedOnUtc = new DateTime(2010, 01, 02), InitialOrder = GetTestOrder(), }, }; var fromDb = SaveAndLoadEntity(rph); fromDb.ShouldNotBeNull(); fromDb.CreatedOnUtc.ShouldEqual(new DateTime(2010, 01, 03)); fromDb.RecurringPayment.ShouldNotBeNull(); fromDb.RecurringPayment.StartDateUtc.ShouldEqual(new DateTime(2010, 01, 01)); }
protected virtual void PrepareRecurringPaymentHistoryModel(RecurringPaymentModel.RecurringPaymentHistoryModel model, RecurringPaymentHistory history) { if (model == null) { throw new ArgumentNullException("model"); } if (history == null) { throw new ArgumentNullException("history"); } var order = _orderService.GetOrderById(history.OrderId); model.Id = history.Id; model.OrderId = history.OrderId; model.RecurringPaymentId = history.RecurringPaymentId; model.OrderStatus = order.OrderStatus.GetLocalizedEnum(_localizationService, _workContext); model.PaymentStatus = order.PaymentStatus.GetLocalizedEnum(_localizationService, _workContext); model.ShippingStatus = order.ShippingStatus.GetLocalizedEnum(_localizationService, _workContext); model.CreatedOn = _dateTimeHelper.ConvertToUserTime(history.CreatedOnUtc, DateTimeKind.Utc); }
public ActionResult IPNHandler() { byte[] param = Request.BinaryRead(Request.ContentLength); var strRequest = Encoding.UTF8.GetString(param); if (!PaymentService.IsPaymentMethodActive(SystemName, Services.StoreContext.CurrentStore.Id)) { Logger.Warn(new SmartException(strRequest), T("Plugins.Payments.PayPal.NoModuleLoading", "IPNHandler")); return(Content(string.Empty)); } var sb = new StringBuilder(); Dictionary <string, string> values; var settings = Services.Settings.LoadSetting <TSetting>(); if (VerifyIPN(settings, strRequest, out values)) { #region values decimal total = decimal.Zero; try { total = 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 sb.AppendLine("PayPal IPN:"); foreach (KeyValuePair <string, string> kvp in values.Where(x => x.Value.HasValue())) { sb.AppendLine(kvp.Key + ": " + kvp.Value); } switch (txn_type) { case "recurring_payment_profile_created": //do nothing here break; case "recurring_payment": #region Recurring payment { Guid orderNumberGuid = Guid.Empty; try { orderNumberGuid = new Guid(rp_invoice_id); } catch { } var initialOrder = OrderService.GetOrderByGuid(orderNumberGuid); if (initialOrder != null) { var newPaymentStatus = GetPaymentStatus(payment_status, pending_reason, total, initialOrder.OrderTotal); var recurringPayments = OrderService.SearchRecurringPayments(0, 0, initialOrder.Id, null); foreach (var rp in recurringPayments) { switch (newPaymentStatus) { case PaymentStatus.Authorized: case PaymentStatus.Paid: { var recurringPaymentHistory = rp.RecurringPaymentHistory; if (recurringPaymentHistory.Count == 0) { //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 OrderProcessingService.ProcessNextRecurringPayment(rp); } } break; } } Logger.Info(new SmartException(sb.ToString()), T("Plugins.Payments.PayPal.IpnRecurringPaymentInfo")); } else { if (rp_invoice_id.IsEmpty()) { Logger.Warn(new SmartException(sb.ToString()), T("Plugins.Payments.PayPal.IpnIrregular", "rp_invoice_id")); } else { Logger.Error(new SmartException(sb.ToString()), T("Plugins.Payments.PayPal.IpnOrderNotFound")); } } } #endregion break; default: #region Standard payment { var orderNumber = ""; var orderNumberGuid = Guid.Empty; values.TryGetValue("custom", out orderNumber); try { orderNumberGuid = new Guid(orderNumber); } catch { } var order = OrderService.GetOrderByGuid(orderNumberGuid); if (order != null) { order.HasNewPaymentNotification = true; OrderService.AddOrderNote(order, sb.ToString()); if (settings.IpnChangesPaymentStatus) { var newPaymentStatus = GetPaymentStatus(payment_status, pending_reason, total, order.OrderTotal); 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; default: break; } } } else { if (orderNumber.IsEmpty()) { Logger.Warn(new SmartException(sb.ToString()), T("Plugins.Payments.PayPal.IpnIrregular", "custom")); } else { Logger.Error(new SmartException(sb.ToString()), T("Plugins.Payments.PayPal.IpnOrderNotFound")); } } } #endregion break; } } else { Logger.Error(new SmartException(strRequest), T("Plugins.Payments.PayPal.IpnFailed")); } //nothing should be rendered to visitor return(Content("")); }
/// <summary> /// Inserts a recurring payment history entry /// </summary> /// <param name="recurringPaymentHistory">Recurring payment history entry</param> /// <returns>A task that represents the asynchronous operation</returns> public virtual async Task InsertRecurringPaymentHistoryAsync(RecurringPaymentHistory recurringPaymentHistory) { await _recurringPaymentHistoryRepository.InsertAsync(recurringPaymentHistory); }
public ActionResult IPNHandler() { Debug.WriteLine("PayPal Direct IPN: {0}".FormatWith(Request.ContentLength)); byte[] param = Request.BinaryRead(Request.ContentLength); string strRequest = Encoding.ASCII.GetString(param); Dictionary <string, string> values; var provider = _paymentService.LoadPaymentMethodBySystemName("Payments.PayPalDirect", true); var processor = provider != null ? provider.Value as PayPalDirectProvider : null; if (processor == null) { throw new SmartException(_helper.GetResource("NoModuleLoading")); } if (processor.VerifyIPN(strRequest, out values)) { #region values decimal total = decimal.Zero; try { total = 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("{0}: {1}".FormatWith(_helper.GetResource("NewPaymentStatus"), newPaymentStatus)); switch (txn_type) { case "recurring_payment_profile_created": //do nothing here break; case "recurring_payment": #region 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(0, 0, initialOrder.Id, null); foreach (var rp in recurringPayments) { switch (newPaymentStatus) { case PaymentStatus.Authorized: case PaymentStatus.Paid: { var recurringPaymentHistory = rp.RecurringPaymentHistory; if (recurringPaymentHistory.Count == 0) { //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 _orderProcessingService.ProcessNextRecurringPayment(rp); } } break; } } //this.OrderService.InsertOrderNote(newOrder.OrderId, sb.ToString(), DateTime.UtcNow); Logger.Information(_helper.GetResource("IpnLogInfo"), new SmartException(sb.ToString())); } else { Logger.Error(_helper.GetResource("IpnOrderNotFound"), new SmartException(sb.ToString())); } } #endregion break; 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.HasNewPaymentNotification = true; 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: { 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.Voided: { if (_orderProcessingService.CanVoidOffline(order)) { _orderProcessingService.VoidOffline(order); } } break; default: break; } } else { Logger.Error(_helper.GetResource("IpnOrderNotFound"), new SmartException(sb.ToString())); } } #endregion break; } } else { Logger.Error(_helper.GetResource("IpnFailed"), new SmartException(strRequest)); } //nothing should be rendered to visitor return(Content("")); }
/// <summary> /// Places an order /// </summary> /// <param name="processPaymentRequest">Process payment request</param> /// <returns>Place order result</returns> public override PlaceOrderResult PlaceOrder(ProcessPaymentRequest processPaymentRequest) { //think about moving functionality of processing recurring orders (after the initial order was placed) to ProcessNextRecurringPayment() method if (processPaymentRequest == null) throw new ArgumentNullException("processPaymentRequest"); var result = new PlaceOrderResult(); try { if (processPaymentRequest.OrderGuid == Guid.Empty) processPaymentRequest.OrderGuid = Guid.NewGuid(); //prepare order details var details = PreparePlaceOrderDetails(processPaymentRequest); #region Payment workflow //process payment ProcessPaymentResult processPaymentResult = null; //skip payment workflow if order total equals zero var skipPaymentWorkflow = details.OrderTotal == decimal.Zero; if (!skipPaymentWorkflow) { var paymentMethod = _paymentService.LoadPaymentMethodBySystemName(processPaymentRequest.PaymentMethodSystemName); if (paymentMethod == null) throw new NopException("Payment method couldn't be loaded"); //ensure that payment method is active if (!paymentMethod.IsPaymentMethodActive(_paymentSettings)) throw new NopException("Payment method is not active"); if (!processPaymentRequest.IsRecurringPayment) { if (details.IsRecurringShoppingCart) { //recurring cart var recurringPaymentType = _paymentService.GetRecurringPaymentType(processPaymentRequest.PaymentMethodSystemName); switch (recurringPaymentType) { case RecurringPaymentType.NotSupported: throw new NopException("Recurring payments are not supported by selected payment method"); case RecurringPaymentType.Manual: case RecurringPaymentType.Automatic: processPaymentResult = _paymentService.ProcessRecurringPayment(processPaymentRequest); break; default: throw new NopException("Not supported recurring payment type"); } } else { //standard cart processPaymentResult = _paymentService.ProcessPayment(processPaymentRequest); } } else { if (details.IsRecurringShoppingCart) { //Old credit card info processPaymentRequest.CreditCardType = details.InitialOrder.AllowStoringCreditCardNumber ? _encryptionService.DecryptText(details.InitialOrder.CardType) : ""; processPaymentRequest.CreditCardName = details.InitialOrder.AllowStoringCreditCardNumber ? _encryptionService.DecryptText(details.InitialOrder.CardName) : ""; processPaymentRequest.CreditCardNumber = details.InitialOrder.AllowStoringCreditCardNumber ? _encryptionService.DecryptText(details.InitialOrder.CardNumber) : ""; processPaymentRequest.CreditCardCvv2 = details.InitialOrder.AllowStoringCreditCardNumber ? _encryptionService.DecryptText(details.InitialOrder.CardCvv2) : ""; try { processPaymentRequest.CreditCardExpireMonth = details.InitialOrder.AllowStoringCreditCardNumber ? Convert.ToInt32(_encryptionService.DecryptText(details.InitialOrder.CardExpirationMonth)) : 0; processPaymentRequest.CreditCardExpireYear = details.InitialOrder.AllowStoringCreditCardNumber ? Convert.ToInt32(_encryptionService.DecryptText(details.InitialOrder.CardExpirationYear)) : 0; } catch { } var recurringPaymentType = _paymentService.GetRecurringPaymentType(processPaymentRequest.PaymentMethodSystemName); switch (recurringPaymentType) { case RecurringPaymentType.NotSupported: throw new NopException("Recurring payments are not supported by selected payment method"); case RecurringPaymentType.Manual: processPaymentResult = _paymentService.ProcessRecurringPayment(processPaymentRequest); break; case RecurringPaymentType.Automatic: //payment is processed on payment gateway site processPaymentResult = new ProcessPaymentResult(); break; default: throw new NopException("Not supported recurring payment type"); } } else { throw new NopException("No recurring products"); } } } else { //payment is not required if (processPaymentResult == null) processPaymentResult = new ProcessPaymentResult(); processPaymentResult.NewPaymentStatus = PaymentStatus.Paid; } if (processPaymentResult == null) throw new NopException("processPaymentResult is not available"); #endregion if (processPaymentResult.Success) { #region Save order details var order = new Order { StoreId = processPaymentRequest.StoreId, OrderGuid = processPaymentRequest.OrderGuid, CustomerId = details.Customer.Id, CustomerLanguageId = details.CustomerLanguage.Id, CustomerTaxDisplayType = details.CustomerTaxDisplayType, CustomerIp = _webHelper.GetCurrentIpAddress(), OrderSubtotalInclTax = details.OrderSubTotalInclTax, OrderSubtotalExclTax = details.OrderSubTotalExclTax, OrderSubTotalDiscountInclTax = details.OrderSubTotalDiscountInclTax, OrderSubTotalDiscountExclTax = details.OrderSubTotalDiscountExclTax, OrderShippingInclTax = details.OrderShippingTotalInclTax, OrderShippingExclTax = details.OrderShippingTotalExclTax, PaymentMethodAdditionalFeeInclTax = details.PaymentAdditionalFeeInclTax, PaymentMethodAdditionalFeeExclTax = details.PaymentAdditionalFeeExclTax, TaxRates = details.TaxRates, OrderTax = details.OrderTaxTotal, OrderTotal = details.OrderTotal, RefundedAmount = decimal.Zero, OrderDiscount = details.OrderDiscountAmount, CheckoutAttributeDescription = details.CheckoutAttributeDescription, CheckoutAttributesXml = details.CheckoutAttributesXml, CustomerCurrencyCode = details.CustomerCurrencyCode, CurrencyRate = details.CustomerCurrencyRate, AffiliateId = details.AffiliateId, OrderStatus = OrderStatus.Pending, AllowStoringCreditCardNumber = processPaymentResult.AllowStoringCreditCardNumber, CardType = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardType) : string.Empty, CardName = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardName) : string.Empty, CardNumber = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardNumber) : string.Empty, MaskedCreditCardNumber = _encryptionService.EncryptText(_paymentService.GetMaskedCreditCardNumber(processPaymentRequest.CreditCardNumber)), CardCvv2 = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardCvv2) : string.Empty, CardExpirationMonth = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardExpireMonth.ToString()) : string.Empty, CardExpirationYear = processPaymentResult.AllowStoringCreditCardNumber ? _encryptionService.EncryptText(processPaymentRequest.CreditCardExpireYear.ToString()) : string.Empty, PaymentMethodSystemName = processPaymentRequest.PaymentMethodSystemName, AuthorizationTransactionId = processPaymentResult.AuthorizationTransactionId, AuthorizationTransactionCode = processPaymentResult.AuthorizationTransactionCode, AuthorizationTransactionResult = processPaymentResult.AuthorizationTransactionResult, CaptureTransactionId = processPaymentResult.CaptureTransactionId, CaptureTransactionResult = processPaymentResult.CaptureTransactionResult, SubscriptionTransactionId = processPaymentResult.SubscriptionTransactionId, PaymentStatus = processPaymentResult.NewPaymentStatus, PaidDateUtc = null, BillingAddress = details.BillingAddress, ShippingAddress = details.ShippingAddress, ShippingStatus = details.ShippingStatus, ShippingMethod = details.ShippingMethodName, PickUpInStore = details.PickUpInStore, ShippingRateComputationMethodSystemName = details.ShippingRateComputationMethodSystemName, CustomValuesXml = processPaymentRequest.SerializeCustomValues(), VatNumber = details.VatNumber, CreatedOnUtc = DateTime.UtcNow }; _orderService.InsertOrder(order); #region Promo _promoService.SendConfirmedBasket(order); BasketResponse basketResponse = _promoUtilities.GetBasketResponse(); if (basketResponse == null) { throw new NopException(string.Format("Failed to create PromoOrder for order: {0}", order.Id)); } else { PromoOrder promoOrder = new PromoOrder() { RequestXml = _workContext.CurrentCustomer.GetAttribute<string>(PromoCustomerAttributeNames.PromoBasketRequest, _genericAttributeService, _storeContext.CurrentStore.Id), ResponseXml = basketResponse.ToXml(), OrderId = order.Id, DeliveryOriginalPrice = basketResponse.DeliveryOriginalPrice }; _promoOrderService.InsertPromoOrder(promoOrder); basketResponse.Items.ForEach(bi => { PromoOrderItem promoOrderItem = new PromoOrderItem() { LineAmount = bi.LineAmount, OrderId = order.Id, PromoOrderId = promoOrder.Id, IsDelivery = bi.IsDelivery, ProductCode = bi.ProductCode, VariantCode = bi.VariantCode, LinePromotionDiscount = bi.LinePromotionDiscount, Barcode = bi.Barcode, Generated = bi.Generated, ManualDiscount = bi.ManualDiscount, OriginalAmount = bi.OriginalAmount, OriginalPrice = bi.OriginalPrice, OriginalQuantity = bi.OriginalQuantity, Price = bi.Price, ProductDescription = bi.ProductDescription, Quantity = bi.Quantity, SplitFromLineId = bi.SplitFromLineId, TotalDiscount = bi.TotalDiscount, TotalIssuedPoints = bi.TotalIssuedPoints }; promoOrder.PromoOrderItems.Add(promoOrderItem); _promoOrderService.UpdatePromoOrder(promoOrder); bi.AppliedPromotions.ForEach(ap => { string promotionTypeDisplay = string.Empty; string promotionType = string.Empty; string promotionName = string.Empty; string promotionDisplayText = string.Empty; var appliedPromo = (from sap in basketResponse.Summary.AppliedPromotions where sap.PromotionId == ap.PromotionId select sap).FirstOrDefault(); if (appliedPromo != null) { promotionName = appliedPromo.PromotionName; promotionType = appliedPromo.PromotionType; promotionTypeDisplay = appliedPromo.PromotionTypeDisplay; promotionDisplayText = appliedPromo.DisplayText; } PromoOrderItemPromotion promoOrderItemPromotion = new PromoOrderItemPromotion() { BasketLevel = ap.BasketLevelPromotion, DeliveryLevel = ap.DeliveryLevelPromotion, DiscountAmount = ap.DiscountAmount, ForLineId = ap.AssociatedLine, Instance = ap.InstanceId, PointsIssued = ap.PointsIssued, PromotionId = ap.PromotionId, DisplayText = promotionDisplayText, PromotionTypeDisplay = promotionTypeDisplay, PromotionName = promotionName, PromotionType = promotionType, ExternalIdentifier = ap.ExternalIdentifier, ReportingGroupCode = ap.ReportingGroupCode }; promoOrderItem.PromoOrderItemPromotions.Add(promoOrderItemPromotion); _promoOrderService.UpdatePromoOrder(promoOrder); }); }); basketResponse.Coupons.ForEach(c => { PromoOrderCoupon promoOrderCoupon = new PromoOrderCoupon() { CouponCode = c.CouponCode, Issued = c.Issued, OrderId = order.Id, PromoOrderId = promoOrder.Id, CouponName = c.CouponName, IssuedConfirmed = c.IssuedConfirmed, DisplayText = c.DisplayText }; promoOrder.PromoOrderCoupons.Add(promoOrderCoupon); _promoOrderService.UpdatePromoOrder(promoOrder); }); } #region clean up Customer customer = _workContext.CurrentCustomer; // basket guid _genericAttributeService.SaveAttribute<string>(customer, PromoCustomerAttributeNames.PromoBasketUniqueReference, null, _storeContext.CurrentStore.Id); // basket response _genericAttributeService.SaveAttribute<string>(customer, PromoCustomerAttributeNames.PromoBasketResponse, null, _storeContext.CurrentStore.Id); // basket request _genericAttributeService.SaveAttribute<string>(customer, PromoCustomerAttributeNames.PromoBasketRequest, null, _storeContext.CurrentStore.Id); // coupon code _genericAttributeService.SaveAttribute<string>(customer, SystemCustomerAttributeNames.DiscountCouponCode, null); #endregion #endregion result.PlacedOrder = order; if (!processPaymentRequest.IsRecurringPayment) { //move shopping cart items to order items foreach (var sc in details.Cart) { var basketResponseItems = basketResponse.FindBasketResponseItems(sc); if (basketResponseItems == null) { // TODO: handle this error } else { //prices decimal taxRate; decimal discountAmount = basketResponseItems.Sum(i => i.LinePromotionDiscount); decimal scUnitPrice = _priceCalculationService.GetUnitPrice(sc); decimal scSubTotal = basketResponseItems.Sum(i => i.LineAmount); decimal scUnitPriceInclTax = _taxService.GetProductPrice(sc.Product, scUnitPrice, true, details.Customer, out taxRate); decimal scUnitPriceExclTax = _taxService.GetProductPrice(sc.Product, scUnitPrice, false, details.Customer, out taxRate); decimal scSubTotalInclTax = _taxService.GetProductPrice(sc.Product, scSubTotal, true, details.Customer, out taxRate); decimal scSubTotalExclTax = _taxService.GetProductPrice(sc.Product, scSubTotal, false, details.Customer, out taxRate); decimal discountAmountInclTax = _taxService.GetProductPrice(sc.Product, discountAmount, true, details.Customer, out taxRate); decimal discountAmountExclTax = _taxService.GetProductPrice(sc.Product, discountAmount, false, details.Customer, out taxRate); //attributes string attributeDescription = _productAttributeFormatter.FormatAttributes(sc.Product, sc.AttributesXml, details.Customer); var itemWeight = _shippingService.GetShoppingCartItemWeight(sc); //save order item var orderItem = new OrderItem { OrderItemGuid = Guid.NewGuid(), Order = order, ProductId = sc.ProductId, UnitPriceInclTax = scUnitPriceInclTax, UnitPriceExclTax = scUnitPriceExclTax, PriceInclTax = scSubTotalInclTax, PriceExclTax = scSubTotalExclTax, OriginalProductCost = _priceCalculationService.GetProductCost(sc.Product, sc.AttributesXml), AttributeDescription = attributeDescription, AttributesXml = sc.AttributesXml, Quantity = sc.Quantity, DiscountAmountInclTax = discountAmountInclTax, DiscountAmountExclTax = discountAmountExclTax, DownloadCount = 0, IsDownloadActivated = false, LicenseDownloadId = 0, ItemWeight = itemWeight, RentalStartDateUtc = sc.RentalStartDateUtc, RentalEndDateUtc = sc.RentalEndDateUtc }; order.OrderItems.Add(orderItem); _orderService.UpdateOrder(order); //gift cards if (sc.Product.IsGiftCard) { string giftCardRecipientName, giftCardRecipientEmail, giftCardSenderName, giftCardSenderEmail, giftCardMessage; _productAttributeParser.GetGiftCardAttribute(sc.AttributesXml, out giftCardRecipientName, out giftCardRecipientEmail, out giftCardSenderName, out giftCardSenderEmail, out giftCardMessage); for (int i = 0; i < sc.Quantity; i++) { var gc = new GiftCard { GiftCardType = sc.Product.GiftCardType, PurchasedWithOrderItem = orderItem, Amount = scUnitPriceExclTax, IsGiftCardActivated = false, GiftCardCouponCode = _giftCardService.GenerateGiftCardCode(), RecipientName = giftCardRecipientName, RecipientEmail = giftCardRecipientEmail, SenderName = giftCardSenderName, SenderEmail = giftCardSenderEmail, Message = giftCardMessage, IsRecipientNotified = false, CreatedOnUtc = DateTime.UtcNow }; _giftCardService.InsertGiftCard(gc); } } //inventory _productService.AdjustInventory(sc.Product, -sc.Quantity, sc.AttributesXml); } } //clear shopping cart details.Cart.ToList().ForEach(sci => _shoppingCartService.DeleteShoppingCartItem(sci, false)); } else { //recurring payment var initialOrderItems = details.InitialOrder.OrderItems; foreach (var orderItem in initialOrderItems) { //save item var newOrderItem = new OrderItem { OrderItemGuid = Guid.NewGuid(), Order = order, ProductId = orderItem.ProductId, UnitPriceInclTax = orderItem.UnitPriceInclTax, UnitPriceExclTax = orderItem.UnitPriceExclTax, PriceInclTax = orderItem.PriceInclTax, PriceExclTax = orderItem.PriceExclTax, OriginalProductCost = orderItem.OriginalProductCost, AttributeDescription = orderItem.AttributeDescription, AttributesXml = orderItem.AttributesXml, Quantity = orderItem.Quantity, DiscountAmountInclTax = orderItem.DiscountAmountInclTax, DiscountAmountExclTax = orderItem.DiscountAmountExclTax, DownloadCount = 0, IsDownloadActivated = false, LicenseDownloadId = 0, ItemWeight = orderItem.ItemWeight, RentalStartDateUtc = orderItem.RentalStartDateUtc, RentalEndDateUtc = orderItem.RentalEndDateUtc }; order.OrderItems.Add(newOrderItem); _orderService.UpdateOrder(order); //gift cards if (orderItem.Product.IsGiftCard) { string giftCardRecipientName, giftCardRecipientEmail, giftCardSenderName, giftCardSenderEmail, giftCardMessage; _productAttributeParser.GetGiftCardAttribute(orderItem.AttributesXml, out giftCardRecipientName, out giftCardRecipientEmail, out giftCardSenderName, out giftCardSenderEmail, out giftCardMessage); for (int i = 0; i < orderItem.Quantity; i++) { var gc = new GiftCard { GiftCardType = orderItem.Product.GiftCardType, PurchasedWithOrderItem = newOrderItem, Amount = orderItem.UnitPriceExclTax, IsGiftCardActivated = false, GiftCardCouponCode = _giftCardService.GenerateGiftCardCode(), RecipientName = giftCardRecipientName, RecipientEmail = giftCardRecipientEmail, SenderName = giftCardSenderName, SenderEmail = giftCardSenderEmail, Message = giftCardMessage, IsRecipientNotified = false, CreatedOnUtc = DateTime.UtcNow }; _giftCardService.InsertGiftCard(gc); } } //inventory _productService.AdjustInventory(orderItem.Product, -orderItem.Quantity, orderItem.AttributesXml); } } //discount usage history // TODO: replace with Promo discount usage history? //gift card usage history if (!processPaymentRequest.IsRecurringPayment) if (details.AppliedGiftCards != null) foreach (var agc in details.AppliedGiftCards) { decimal amountUsed = agc.AmountCanBeUsed; var gcuh = new GiftCardUsageHistory { GiftCard = agc.GiftCard, UsedWithOrder = order, UsedValue = amountUsed, CreatedOnUtc = DateTime.UtcNow }; agc.GiftCard.GiftCardUsageHistory.Add(gcuh); _giftCardService.UpdateGiftCard(agc.GiftCard); } //reward points history if (details.RedeemedRewardPointsAmount > decimal.Zero) { details.Customer.AddRewardPointsHistoryEntry(-details.RedeemedRewardPoints, string.Format(_localizationService.GetResource("RewardPoints.Message.RedeemedForOrder", order.CustomerLanguageId), order.Id), order, details.RedeemedRewardPointsAmount); _customerService.UpdateCustomer(details.Customer); } //recurring orders if (!processPaymentRequest.IsRecurringPayment && details.IsRecurringShoppingCart) { //create recurring payment (the first payment) var rp = new RecurringPayment { CycleLength = processPaymentRequest.RecurringCycleLength, CyclePeriod = processPaymentRequest.RecurringCyclePeriod, TotalCycles = processPaymentRequest.RecurringTotalCycles, StartDateUtc = DateTime.UtcNow, IsActive = true, CreatedOnUtc = DateTime.UtcNow, InitialOrder = order, }; _orderService.InsertRecurringPayment(rp); var recurringPaymentType = _paymentService.GetRecurringPaymentType(processPaymentRequest.PaymentMethodSystemName); switch (recurringPaymentType) { case RecurringPaymentType.NotSupported: { //not supported } break; case RecurringPaymentType.Manual: { //first payment var rph = new RecurringPaymentHistory { RecurringPayment = rp, CreatedOnUtc = DateTime.UtcNow, OrderId = order.Id, }; rp.RecurringPaymentHistory.Add(rph); _orderService.UpdateRecurringPayment(rp); } break; case RecurringPaymentType.Automatic: { //will be created later (process is automated) } break; default: break; } } #endregion #region Notifications & notes //notes, messages if (_workContext.OriginalCustomerIfImpersonated != null) { //this order is placed by a store administrator impersonating a customer order.OrderNotes.Add(new OrderNote { Note = string.Format("Order placed by a store owner ('{0}'. ID = {1}) impersonating the customer.", _workContext.OriginalCustomerIfImpersonated.Email, _workContext.OriginalCustomerIfImpersonated.Id), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); _orderService.UpdateOrder(order); } else { order.OrderNotes.Add(new OrderNote { Note = "Order placed", DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); _orderService.UpdateOrder(order); } //send email notifications int orderPlacedStoreOwnerNotificationQueuedEmailId = _workflowMessageService.SendOrderPlacedStoreOwnerNotification(order, _localizationSettings.DefaultAdminLanguageId); if (orderPlacedStoreOwnerNotificationQueuedEmailId > 0) { order.OrderNotes.Add(new OrderNote { Note = string.Format("\"Order placed\" email (to store owner) has been queued. Queued email identifier: {0}.", orderPlacedStoreOwnerNotificationQueuedEmailId), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); _orderService.UpdateOrder(order); } var orderPlacedAttachmentFilePath = _orderSettings.AttachPdfInvoiceToOrderPlacedEmail ? _pdfService.PrintOrderToPdf(order, order.CustomerLanguageId) : null; var orderPlacedAttachmentFileName = _orderSettings.AttachPdfInvoiceToOrderPlacedEmail ? "order.pdf" : null; int orderPlacedCustomerNotificationQueuedEmailId = _workflowMessageService .SendOrderPlacedCustomerNotification(order, order.CustomerLanguageId, orderPlacedAttachmentFilePath, orderPlacedAttachmentFileName); if (orderPlacedCustomerNotificationQueuedEmailId > 0) { order.OrderNotes.Add(new OrderNote { Note = string.Format("\"Order placed\" email (to customer) has been queued. Queued email identifier: {0}.", orderPlacedCustomerNotificationQueuedEmailId), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); _orderService.UpdateOrder(order); } var vendors = GetVendorsInOrder(order); foreach (var vendor in vendors) { int orderPlacedVendorNotificationQueuedEmailId = _workflowMessageService.SendOrderPlacedVendorNotification(order, vendor, order.CustomerLanguageId); if (orderPlacedVendorNotificationQueuedEmailId > 0) { order.OrderNotes.Add(new OrderNote { Note = string.Format("\"Order placed\" email (to vendor) has been queued. Queued email identifier: {0}.", orderPlacedVendorNotificationQueuedEmailId), DisplayToCustomer = false, CreatedOnUtc = DateTime.UtcNow }); _orderService.UpdateOrder(order); } } //check order status CheckOrderStatus(order); //reset checkout data if (!processPaymentRequest.IsRecurringPayment) _customerService.ResetCheckoutData(details.Customer, processPaymentRequest.StoreId, clearCouponCodes: true, clearCheckoutAttributes: true); if (!processPaymentRequest.IsRecurringPayment) { _customerActivityService.InsertActivity( "PublicStore.PlaceOrder", _localizationService.GetResource("ActivityLog.PublicStore.PlaceOrder"), order.Id); } //raise event _eventPublisher.Publish(new OrderPlacedEvent(order)); if (order.PaymentStatus == PaymentStatus.Paid) { ProcessOrderPaid(order); } #endregion } else { foreach (var paymentError in processPaymentResult.Errors) result.AddError(string.Format(_localizationService.GetResource("Checkout.PaymentError"), paymentError)); } } catch (Exception exc) { _logger.Error(exc.Message, exc); result.AddError(exc.Message); } #region Process errors string error = ""; for (int i = 0; i < result.Errors.Count; i++) { error += string.Format("Error {0}: {1}", i + 1, result.Errors[i]); if (i != result.Errors.Count - 1) error += ". "; } if (!String.IsNullOrEmpty(error)) { //log it string logError = string.Format("Error while placing order. {0}", error); _logger.Error(logError); } #endregion return result; }
public void HandleIPN(string ipnData) { Dictionary <string, string> values; if (VerifyIPN(ipnData, out values)) { #region values decimal total = decimal.Zero; try { total = 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 = GetPaymentStatus(payment_status, pending_reason); sb.AppendLine("New payment status: " + newPaymentStatus); switch (txn_type) { case "recurring_payment_profile_created": //do nothing here break; case "recurring_payment": #region 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(0, 0, initialOrder.Id, null, 0, int.MaxValue); foreach (var rp in recurringPayments) { switch (newPaymentStatus) { case PaymentStatus.Authorized: case PaymentStatus.Paid: { var recurringPaymentHistory = rp.RecurringPaymentHistory; if (recurringPaymentHistory.Count == 0) { //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 _orderProcessingService.ProcessNextRecurringPayment(rp); } } 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())); } } #endregion break; 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: { 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.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(ipnData)); } }
/// <summary> /// Process recurring payment /// </summary> /// <param name="transactionId">AuthorizeNet transaction ID</param> public void ProcessRecurringPayment(string transactionId) { PrepareAuthorizeNet(); var request = new getTransactionDetailsRequest { transId = transactionId }; // instantiate the controller that will call the service var controller = new getTransactionDetailsController(request); controller.Execute(); // get the response from the service (errors contained if any) var response = controller.GetApiResponse(); if (response != null && response.messages.resultCode == messageTypeEnum.Ok) { var transaction = response.transaction; if (transaction == null) { _logger.Error(String.Format("Authorize.NET: Transaction data is missing (transactionId: {0})", transactionId)); return; } if (transaction.transactionStatus == "refundTransaction") { return; } var orderDescriptions = transaction.order.description.Split('#'); if (orderDescriptions.Length < 2) { _logger.Error(String.Format("Authorize.NET: Missing order GUID (transactionId: {0})", transactionId)); return; } var order = _orderService.GetOrderByGuid(new Guid(orderDescriptions[1])); if (order == null) { _logger.Error(String.Format("Authorize.NET: Order cannot be loaded (order GUID: {0})", orderDescriptions[1])); return; } var recurringPayments = _orderService.SearchRecurringPayments(initialOrderId: order.Id); foreach (var rp in recurringPayments) { var recurringPaymentHistory = rp.RecurringPaymentHistory; var orders = _orderService.GetOrdersByIds(recurringPaymentHistory.Select(rph => rph.OrderId).ToArray()).ToList(); var transactionsIds = new List <string>(); transactionsIds.AddRange(orders.Select(o => o.AuthorizationTransactionId).Where(tId => !string.IsNullOrEmpty(tId))); transactionsIds.AddRange(orders.Select(o => o.CaptureTransactionId).Where(tId => !string.IsNullOrEmpty(tId))); //skip the re-processing of transactions if (transactionsIds.Contains(transactionId)) { continue; } var newPaymentStatus = transaction.transactionType == "authOnlyTransaction" ? PaymentStatus.Authorized : PaymentStatus.Paid; if (recurringPaymentHistory.Count == 0) { //first payment var rph = new RecurringPaymentHistory { RecurringPaymentId = rp.Id, OrderId = order.Id, CreatedOnUtc = DateTime.UtcNow }; rp.RecurringPaymentHistory.Add(rph); if (newPaymentStatus == PaymentStatus.Authorized) { rp.InitialOrder.AuthorizationTransactionId = transactionId; } else { rp.InitialOrder.CaptureTransactionId = transactionId; } _orderService.UpdateRecurringPayment(rp); } else { //next payments var processPaymentResult = new ProcessPaymentResult(); processPaymentResult.NewPaymentStatus = newPaymentStatus; if (newPaymentStatus == PaymentStatus.Authorized) { processPaymentResult.AuthorizationTransactionId = transactionId; } else { processPaymentResult.CaptureTransactionId = transactionId; } _orderProcessingService.ProcessNextRecurringPayment(rp, processPaymentResult); } } } else if (response != null) { _logger.Error(String.Format("Authorize.Net Error: {0} - {1} (transactionId: {2})", response.messages.message[0].code, response.messages.message[0].text, transactionId)); } else { _logger.Error(String.Format("Authorize.NET unknown error (transactionId: {0})", transactionId)); } }
/// <summary> /// Process recurring payment /// </summary> /// <param name="transactionId">AuthorizeNet transaction ID</param> public void ProcessRecurringPayment(string transactionId) { PrepareAuthorizeNet(); var request = new getTransactionDetailsRequest { transId = transactionId }; // instantiate the controller that will call the service var controller = new getTransactionDetailsController(request); controller.Execute(); // get the response from the service (errors contained if any) var response = controller.GetApiResponse(); if (response != null && response.messages.resultCode == messageTypeEnum.Ok) { var transaction = response.transaction; if (transaction == null) { _logger.Error(String.Format("Authorize.NET: Transaction data is missing (transactionId: {0})", transactionId)); return; } if (transaction.transactionStatus != "settledSuccessfully") { return; } var orderDescriptions = transaction.order.description.Split('#'); if (orderDescriptions.Length < 2) { _logger.Error(String.Format("Authorize.NET: Missing order GUID (transactionId: {0})", transactionId)); return; } var order = _orderService.GetOrderByGuid(new Guid(orderDescriptions[1])); if (order == null) { _logger.Error(String.Format("Authorize.NET: Order cannot be loaded (order GUID: {0})", orderDescriptions[1])); return; } var recurringPayments = _orderService.SearchRecurringPayments(initialOrderId: order.Id); foreach (var rp in recurringPayments) { var recurringPaymentHistory = rp.RecurringPaymentHistory; if (recurringPaymentHistory.Count == 0) { //first payment var rph = new RecurringPaymentHistory { RecurringPaymentId = rp.Id, OrderId = order.Id, CreatedOnUtc = DateTime.UtcNow }; rp.RecurringPaymentHistory.Add(rph); _orderService.UpdateRecurringPayment(rp); } else { //next payments _orderProcessingService.ProcessNextRecurringPayment(rp); } } } else if (response != null) { _logger.Error(String.Format("Authorize.Net Error: {0} - {1} (transactionId: {2})", response.messages.message[0].code, response.messages.message[0].text, transactionId)); } else { _logger.Error(String.Format("Authorize.NET unknown error (transactionId: {0})", transactionId)); } }
private void PrepareRecurringPaymentHistoryModel(RecurringPaymentModel.RecurringPaymentHistoryModel model, RecurringPaymentHistory history) { Guard.NotNull(model, nameof(model)); Guard.NotNull(history, nameof(history)); var order = _orderService.GetOrderById(history.OrderId); model.Id = history.Id; model.OrderId = history.OrderId; model.RecurringPaymentId = history.RecurringPaymentId; model.OrderStatus = order.OrderStatus.GetLocalizedEnum(_localizationService, _workContext); model.PaymentStatus = order.PaymentStatus.GetLocalizedEnum(_localizationService, _workContext); model.ShippingStatus = order.ShippingStatus.GetLocalizedEnum(_localizationService, _workContext); model.CreatedOn = _dateTimeHelper.ConvertToUserTime(history.CreatedOnUtc, DateTimeKind.Utc); }
public void HandleIPN(string ipnData) { if (VerifyIPN(ipnData, out var values)) { values.TryGetValue("payer_status", out _); values.TryGetValue("payment_status", out var paymentStatus); values.TryGetValue("pending_reason", out var pendingReason); values.TryGetValue("mc_currency", out _); values.TryGetValue("txn_id", out _); values.TryGetValue("txn_type", out var txnType); values.TryGetValue("rp_invoice_id", out var rpInvoiceId); values.TryGetValue("payment_type", out _); values.TryGetValue("payer_id", out _); values.TryGetValue("receiver_id", out _); values.TryGetValue("invoice", out _); values.TryGetValue("payment_fee", out _); var sb = new StringBuilder(); sb.AppendLine("Paypal IPN:"); foreach (var kvp in values) { sb.AppendLine(kvp.Key + ": " + kvp.Value); } var newPaymentStatus = GetPaymentStatus(paymentStatus, pendingReason); sb.AppendLine("New payment status: " + newPaymentStatus); switch (txnType) { case "recurring_payment_profile_created": //do nothing here break; case "recurring_payment": { var orderNumberGuid = Guid.Empty; try { orderNumberGuid = new Guid(rpInvoiceId); } catch { // ignored } var initialOrder = _orderService.GetOrderByGuid(orderNumberGuid); if (initialOrder != null) { var recurringPayments = _orderService.SearchRecurringPayments(0, 0, initialOrder.Id); foreach (var rp in recurringPayments) { switch (newPaymentStatus) { case PaymentStatus.Authorized: case PaymentStatus.Paid: { var recurringPaymentHistory = rp.RecurringPaymentHistory; if (recurringPaymentHistory.Count == 0) { //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 _orderProcessingService.ProcessNextRecurringPayment(rp); } } 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; default: { values.TryGetValue("custom", out var orderNumber); var orderNumberGuid = Guid.Empty; try { orderNumberGuid = new Guid(orderNumber); } catch { // ignored } 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: 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.Voided: if (_orderProcessingService.CanVoidOffline(order)) { _orderProcessingService.VoidOffline(order); } break; default: break; } } else { _logger.Error("PayPal IPN. Order is not found", new NopException(sb.ToString())); } } break; } } else { _logger.Error("PayPal IPN failed.", new NopException(ipnData)); } }
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("")); }
/// <summary> /// Inserts a recurring payment history entry /// </summary> /// <param name="recurringPaymentHistory">Recurring payment history entry</param> public virtual void InsertRecurringPaymentHistory(RecurringPaymentHistory recurringPaymentHistory) { _recurringPaymentHistoryRepository.Insert(recurringPaymentHistory); }
/// <summary> /// Process recurring payment /// </summary> /// <param name="transactionId">AuthorizeNet transaction ID</param> public void ProcessRecurringPayment(string transactionId) { var transactionDetails = GetTransactionDetails(transactionId); if (transactionDetails.TransactionStatus == "refundTransaction") { return; } var orderDescriptions = transactionDetails.OrderDescriptions; if (orderDescriptions.Length < 2) { _logger.Error($"Authorize.NET: Missing order GUID (transactionId: {transactionId})"); return; } if (orderDescriptions[0].Contains("Full order")) { return; } var order = _orderService.GetOrderByGuid(new Guid(orderDescriptions[1])); if (order == null) { _logger.Error($"Authorize.NET: Order cannot be loaded (order GUID: {orderDescriptions[1]})"); return; } var recurringPayments = _orderService.SearchRecurringPayments(initialOrderId: order.Id); foreach (var rp in recurringPayments) { if (transactionDetails.IsOk) { var recurringPaymentHistory = rp.RecurringPaymentHistory; var orders = _orderService.GetOrdersByIds(recurringPaymentHistory.Select(rph => rph.OrderId).ToArray()).ToList(); var transactionsIds = new List <string>(); transactionsIds.AddRange(orders.Select(o => o.AuthorizationTransactionId).Where(tId => !string.IsNullOrEmpty(tId))); transactionsIds.AddRange(orders.Select(o => o.CaptureTransactionId).Where(tId => !string.IsNullOrEmpty(tId))); //skip the re-processing of transactions if (transactionsIds.Contains(transactionId)) { continue; } var newPaymentStatus = transactionDetails.TransactionType == "authOnlyTransaction" ? PaymentStatus.Authorized : PaymentStatus.Paid; if (recurringPaymentHistory.Count == 0) { //first payment var rph = new RecurringPaymentHistory { RecurringPaymentId = rp.Id, OrderId = order.Id, CreatedOnUtc = DateTime.UtcNow }; rp.RecurringPaymentHistory.Add(rph); if (newPaymentStatus == PaymentStatus.Authorized) { rp.InitialOrder.AuthorizationTransactionId = transactionId; } else { rp.InitialOrder.CaptureTransactionId = transactionId; } _orderService.UpdateRecurringPayment(rp); } else { //next payments var processPaymentResult = new ProcessPaymentResult { NewPaymentStatus = newPaymentStatus }; if (newPaymentStatus == PaymentStatus.Authorized) { processPaymentResult.AuthorizationTransactionId = transactionId; } else { processPaymentResult.CaptureTransactionId = transactionId; } _orderProcessingService.ProcessNextRecurringPayment(rp, processPaymentResult); } } else { var processPaymentResult = new ProcessPaymentResult(); processPaymentResult.AuthorizationTransactionId = processPaymentResult.CaptureTransactionId = transactionId; processPaymentResult.RecurringPaymentFailed = true; processPaymentResult.Errors.Add( $"Authorize.Net Error: {transactionDetails.Message?.code} - {transactionDetails.Message?.text} (transactionId: {transactionId})"); _orderProcessingService.ProcessNextRecurringPayment(rp, processPaymentResult); } } }
protected void Page_Load(object sender, EventArgs e) { CommonHelper.SetResponseNoCache(Response); if (!Page.IsPostBack) { byte[] param = Request.BinaryRead(Request.ContentLength); string strRequest = Encoding.ASCII.GetString(param); Dictionary <string, string> values; PayPalStandardPaymentProcessor processor = new PayPalStandardPaymentProcessor(); if (processor.VerifyIPN(strRequest, out values)) { #region values decimal total = decimal.Zero; try { total = 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 StringBuilder sb = new StringBuilder(); sb.AppendLine("Paypal IPN:"); foreach (KeyValuePair <string, string> kvp in values) { sb.AppendLine(kvp.Key + ": " + kvp.Value); } PaymentStatusEnum newPaymentStatus = PaypalHelper.GetPaymentStatus(payment_status, pending_reason); sb.AppendLine("New payment status: " + newPaymentStatus.GetPaymentStatusName()); switch (txn_type) { case "recurring_payment_profile_created": //do nothing here break; case "recurring_payment": #region Recurring payment { Guid orderNumberGuid = Guid.Empty; try { orderNumberGuid = new Guid(rp_invoice_id); } catch { } Order initialOrder = this.OrderService.GetOrderByGuid(orderNumberGuid); if (initialOrder != null) { var recurringPayments = this.OrderService.SearchRecurringPayments(0, initialOrder.OrderId, null); foreach (var rp in recurringPayments) { switch (newPaymentStatus) { case PaymentStatusEnum.Authorized: case PaymentStatusEnum.Paid: { var recurringPaymentHistory = rp.RecurringPaymentHistory; if (recurringPaymentHistory.Count == 0) { //first payment var rph = new RecurringPaymentHistory() { RecurringPaymentId = rp.RecurringPaymentId, OrderId = initialOrder.OrderId, CreatedOn = DateTime.UtcNow }; this.OrderService.InsertRecurringPaymentHistory(rph); } else { //next payments this.OrderService.ProcessNextRecurringPayment(rp.RecurringPaymentId); //UNDONE change new order status according to newPaymentStatus //UNDONE refund/void is not supported } } break; } } //this.OrderService.InsertOrderNote(newOrder.OrderId, sb.ToString(), DateTime.UtcNow); this.LogService.InsertLog(LogTypeEnum.Unknown, "PayPal IPN. Recurring info", new NopException(sb.ToString())); } else { this.LogService.InsertLog(LogTypeEnum.OrderError, "PayPal IPN. Order is not found", new NopException(sb.ToString())); } } #endregion break; default: #region Standard payment { string orderNumber = string.Empty; values.TryGetValue("custom", out orderNumber); Guid orderNumberGuid = Guid.Empty; try { orderNumberGuid = new Guid(orderNumber); } catch { } Order order = this.OrderService.GetOrderByGuid(orderNumberGuid); if (order != null) { this.OrderService.InsertOrderNote(order.OrderId, sb.ToString(), false, DateTime.UtcNow); switch (newPaymentStatus) { case PaymentStatusEnum.Pending: { } break; case PaymentStatusEnum.Authorized: { if (this.OrderService.CanMarkOrderAsAuthorized(order)) { this.OrderService.MarkAsAuthorized(order.OrderId); } } break; case PaymentStatusEnum.Paid: { if (this.OrderService.CanMarkOrderAsPaid(order)) { this.OrderService.MarkOrderAsPaid(order.OrderId); } } break; case PaymentStatusEnum.Refunded: { if (this.OrderService.CanRefundOffline(order)) { this.OrderService.RefundOffline(order.OrderId); } } break; case PaymentStatusEnum.Voided: { if (this.OrderService.CanVoidOffline(order)) { this.OrderService.VoidOffline(order.OrderId); } } break; default: break; } } else { this.LogService.InsertLog(LogTypeEnum.OrderError, "PayPal IPN. Order is not found", new NopException(sb.ToString())); } } #endregion break; } } else { this.LogService.InsertLog(LogTypeEnum.OrderError, "PayPal IPN failed.", strRequest); } } }
protected virtual void ProcessRecurringPayment(string invoiceId, PaymentStatus newPaymentStatus, string transactionId, string ipnInfo) { Guid orderNumberGuid; try { orderNumberGuid = new Guid(invoiceId); } catch { orderNumberGuid = Guid.Empty; } var order = _orderService.GetOrderByGuid(orderNumberGuid); if (order == null) { _logger.Error("PayPal IPN. Order is not found", new NopException(ipnInfo)); return; } var recurringPayments = _orderService.SearchRecurringPayments(initialOrderId: order.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 = order.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 = transactionId; } else { processPaymentResult.CaptureTransactionId = transactionId; } _orderProcessingService.ProcessNextRecurringPayment(rp, processPaymentResult); } } break; case PaymentStatus.Voided: //failed payment var failedPaymentResult = new ProcessPaymentResult { Errors = new[] { $"PayPal IPN. Recurring payment is {nameof(PaymentStatus.Voided).ToLower()} ." }, RecurringPaymentFailed = true }; _orderProcessingService.ProcessNextRecurringPayment(rp, failedPaymentResult); break; } } //OrderService.InsertOrderNote(newOrder.OrderId, sb.ToString(), DateTime.UtcNow); _logger.Information("PayPal IPN. Recurring info", new NopException(ipnInfo)); }
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("")); }
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 total = decimal.Zero; try { total = 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; case "recurring_payment": #region 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(0, 0, initialOrder.Id, null, 0, int.MaxValue); foreach (var rp in recurringPayments) { switch (newPaymentStatus) { case PaymentStatus.Authorized: case PaymentStatus.Paid: { var recurringPaymentHistory = rp.RecurringPaymentHistory; if (recurringPaymentHistory.Count == 0) { //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 _orderProcessingService.ProcessNextRecurringPayment(rp); } } 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())); } } #endregion break; 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: { if (_orderProcessingService.CanMarkOrderAsAuthorized(order)) { _orderProcessingService.MarkAsAuthorized(order); } } break; case PaymentStatus.Paid: { if (_orderProcessingService.CanMarkOrderAsPaid(order)) { order.AuthorizationTransactionId = txn_id; _orderService.UpdateOrder(order); _orderProcessingService.MarkOrderAsPaid(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("")); }
/// <summary> /// Process next recurring psayment /// </summary> /// <param name="recurringPayment">Recurring payment</param> public virtual async Task ProcessNextRecurringPayment(RecurringPayment recurringPayment) { if (recurringPayment == null) { throw new ArgumentNullException("recurringPayment"); } try { if (!recurringPayment.IsActive) { throw new GrandException("Recurring payment is not active"); } var initialOrder = recurringPayment.InitialOrder; if (initialOrder == null) { throw new GrandException("Initial order could not be loaded"); } var customer = await _customerService.GetCustomerById(initialOrder.CustomerId); if (customer == null) { throw new GrandException("Customer could not be loaded"); } var nextPaymentDate = recurringPayment.NextPaymentDate; if (!nextPaymentDate.HasValue) { throw new GrandException("Next payment date could not be calculated"); } //payment info var paymentInfo = new ProcessPaymentRequest { StoreId = initialOrder.StoreId, CustomerId = customer.Id, OrderGuid = Guid.NewGuid(), IsRecurringPayment = true, InitialOrderId = initialOrder.Id, RecurringCycleLength = recurringPayment.CycleLength, RecurringCyclePeriod = recurringPayment.CyclePeriod, RecurringTotalCycles = recurringPayment.TotalCycles, }; //place a new order var orderConfirmationService = _serviceProvider.GetRequiredService <IOrderConfirmationService>(); var result = await orderConfirmationService.PlaceOrder(paymentInfo); if (result.Success) { if (result.PlacedOrder == null) { throw new GrandException("Placed order could not be loaded"); } var rph = new RecurringPaymentHistory { RecurringPaymentId = recurringPayment.Id, CreatedOnUtc = DateTime.UtcNow, OrderId = result.PlacedOrder.Id, }; recurringPayment.RecurringPaymentHistory.Add(rph); await _orderService.UpdateRecurringPayment(recurringPayment); } else { 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 += ". "; } } throw new GrandException(error); } } catch (Exception exc) { _logger.Error(string.Format("Error while processing recurring order. {0}", exc.Message), exc); throw; } }