/// <summary> /// Paypal IPN callback /// </summary> /// <param name="token"></param> /// <param name="payerId"></param> /// <param name="cancel"></param> /// <returns></returns> public ActionResult PaypalExpressSuccess(string token, string payerId, bool? cancel) { var model = PrepareCheckoutModel(new CheckoutModel()); Payment payment = null; var order = _orderClient.GetOrderByAuthCode(token); if (order == null) { ModelState.AddModelError("", "Order cannot be found for current payment!".Localize()); } else { payment = order.OrderForms.SelectMany(f => f.Payments).First(p => p.AuthorizationCode == token); //If payment not cancelled proceed if (!cancel.HasValue || !cancel.Value) { var paymentMethod = _paymentClient.GetPaymentMethod(payment.PaymentMethodName ?? "Paypal"); var configMap = paymentMethod.CreateSettings(); var service = new PayPalAPIInterfaceServiceService(configMap); var getEcWrapper = new GetExpressCheckoutDetailsReq { GetExpressCheckoutDetailsRequest = new GetExpressCheckoutDetailsRequestType(token) }; GetExpressCheckoutDetailsResponseType getEcResponse = null; try { getEcResponse = service.GetExpressCheckoutDetails(getEcWrapper); } catch (Exception ex) { ModelState.AddModelError("", @"Paypal failure".Localize()); ModelState.AddModelError("", ex.Message); } if (getEcResponse != null) { if (getEcResponse.Ack.Equals(AckCodeType.FAILURE) || (getEcResponse.Errors != null && getEcResponse.Errors.Count > 0)) { ModelState.AddModelError("", @"Paypal failure".Localize()); foreach (var error in getEcResponse.Errors) { ModelState.AddModelError("", error.LongMessage); } } else { var details = getEcResponse.GetExpressCheckoutDetailsResponseDetails; if (details.CheckoutStatus.Equals("PaymentActionCompleted", StringComparison.OrdinalIgnoreCase)) { return RedirectToAction("ProcessCheckout", "Checkout", new {id = order.OrderGroupId}); } model.PaymentMethod = paymentMethod.Name; model.ShippingMethod = details.UserSelectedOptions.ShippingOptionName; if (!string.IsNullOrEmpty(details.UserSelectedOptions.ShippingOptionName)) { foreach (var lineItem in order.OrderForms.SelectMany(f => f.LineItems)) { var shippingMethod = Ch.GetShippingMethods(new List<string> {model.ShippingMethod}).First(); lineItem.ShippingMethodName = shippingMethod.DisplayName; lineItem.ShippingMethodId = shippingMethod.Id; } } var paymentDetails = details.PaymentDetails[0]; model.BillingAddress.Address = ConvertFromPaypalAddress(paymentDetails.ShipToAddress, "Billing"); model.BillingAddress.Address.Email = details.PayerInfo.Payer; model.ShippingAddress.Address = ConvertFromPaypalAddress(paymentDetails.ShipToAddress, "Shipping"); model.ShippingAddress.Address.Email = details.PayerInfo.Payer; #region Process billing address var billingAddress = OrderClient.FindAddressByName(order, "Billing"); if (billingAddress == null) { billingAddress = new OrderAddress(); order.OrderAddresses.Add(billingAddress); var orderAddressId = billingAddress.OrderAddressId; billingAddress.InjectFrom( new IgnorePropertiesInjection("OrderGroupId", "OrderGroup", "OrderAddressId", "Created"), model.BillingAddress.Address); billingAddress.Name = "Billing"; billingAddress.OrderAddressId = orderAddressId; order.AddressId = orderAddressId; order.OrderForms[0].BillingAddressId = orderAddressId; } #endregion #region Process shipping address var shippingAddress = OrderClient.FindAddressByName(order, "Shipping"); if (shippingAddress == null) { shippingAddress = new OrderAddress(); order.OrderAddresses.Add(shippingAddress); } shippingAddress.InjectFrom( new IgnorePropertiesInjection("OrderGroupId", "OrderGroup", "OrderAddressId", "Created"), model.ShippingAddress.Address); shippingAddress.Name = "Shipping"; shippingAddress.OrderAddressId = shippingAddress.OrderAddressId; //Update shipping address id foreach (var shipment in order.OrderForms.SelectMany(f => f.Shipments)) { shipment.ShippingAddressId = shippingAddress.OrderAddressId; } foreach (var lineItem in order.OrderForms.SelectMany(f => f.LineItems)) { lineItem.ShippingAddressId = shippingAddress.OrderAddressId; } #endregion //Recalcualte totals (User could have changed shipping method in paypal). Ch.RunWorkflow("ShoppingCartPrepareWorkflow", order); if (ModelState.IsValid) { payment.ContractId = payerId; payment.AuthorizationCode = token; payment.Amount = order.Total; //Normally this message should be shown to user when. This happens because address changes and Tax is recalculated if (decimal.Parse(paymentDetails.OrderTotal.value, CultureInfo.InvariantCulture) != order.Total) { ModelState.AddModelError("", "Paypal payment total does not match order total! Check the totals and try to pay again." .Localize()); } else { try { Ch.RunWorkflow("ShoppingCartCheckoutWorkflow", order); Ch.OrderRepository.UnitOfWork.Commit(); return RedirectToAction("ProcessCheckout", "Checkout", new {id = order.OrderGroupId}); } catch (Exception ex) { ModelState.AddModelError("", ex.Message); } } } } } } } if (order != null) { //Cancel old order order.Status = OrderStatus.Cancelled.ToString(); payment.Status = PaymentStatus.Canceled.ToString(); //Restore cart if order fails Ch.ToCart(order); //Add paypal payment to make it selected in UI var paypalPayment = new OtherPayment { PaymentMethodId = payment.PaymentMethodId, PaymentMethodName = payment.PaymentMethodName, Amount = payment.Amount }; Ch.OrderForm.Payments.Add(paypalPayment); Ch.SaveChanges(); } return View("Index", model); }
public static OrderAddress ConvertToOrderAddress(Address address) { var addr = new OrderAddress(); addr.InjectFrom(address); return addr; }