private List <SessionLineItemOptions> CreateRecharge(int userId, decimal Amount) { List <SessionLineItemOptions> Items = new List <SessionLineItemOptions>(); SessionLineItemOptions ItemOptions = new SessionLineItemOptions(); SessionLineItemPriceDataOptions priceData = new SessionLineItemPriceDataOptions(); SessionLineItemPriceDataProductDataOptions prdData = new SessionLineItemPriceDataProductDataOptions(); prdData.Name = "Customer Recharge Wallet | " + userId; prdData.Images = new List <string>() { "https://valhallaplanet.art/img/Logo.png" }; prdData.Description = "Valhallaplanet User Wallet Recharge"; priceData.ProductData = prdData; priceData.Currency = "eur"; priceData.UnitAmountDecimal = Amount * 100; ItemOptions.Quantity = 1; ItemOptions.PriceData = priceData; Items.Add(ItemOptions); return(Items); }
public void Purchase() { if (Session["payment_amt"] != null) { try { List <SessionLineItemOptions> cartList = new List <SessionLineItemOptions>(); using (fashionUtilityApplication.Logic.ShoppingCartActions usersShoppingCart = new fashionUtilityApplication.Logic.ShoppingCartActions()) { List <CartItem> myOrderList = usersShoppingCart.GetCartItems(); // Add OrderDetail information to the DB for each product purchased. for (int i = 0; i < myOrderList.Count; i++) { long convertValue = 100; var item = new SessionLineItemOptions(); item.Name = myOrderList[i].Product.ProductName; item.Amount = (long)myOrderList[i].Product.UnitPrice * convertValue; item.Currency = "cad"; item.Quantity = myOrderList[i].Quantity; item.Description = myOrderList[i].Product.Description; cartList.Add(item); } } string amt = Session["payment_amt"].ToString(); StripeConfiguration.ApiKey = System.Configuration.ConfigurationManager.AppSettings["stripeSecretKeyTest"]; var options = new SessionCreateOptions { SuccessUrl = "https://fashionutilityapplication.azurewebsites.net/Checkout/CheckoutComplete.aspx", CancelUrl = "https://fashionutilityapplication.azurewebsites.net/Checkout/CheckoutCancel.aspx", PaymentMethodTypes = new List <string> { "card", }, LineItems = cartList }; var service = new SessionService(); Session session = service.Create(options); sessionId = session.Id; Session["token"] = sessionId; Session["userCheckoutCompleted"] = "true"; } catch (Exception e) { Response.Redirect("CheckoutError.aspx?"); } } else { Response.Redirect("CheckoutError.aspx?ErrorCode=AmtMissing"); } }
private List <SessionLineItemOptions> AddProducts(BasketModel basket, decimal wallet, Barayand.DAL.Interfaces.IWalletHistoryRepository _walletrepository, int user) { List <SessionLineItemOptions> Items = new List <SessionLineItemOptions>(); var shippingCost = (basket.CartItems.Count > 0) ? basket.ShippingCost / basket.TotalQuantity() : basket.ShippingCost; decimal WALLET = wallet; decimal USEDWALLET = 0; foreach (var item in basket.CartItems) { SessionLineItemOptions ItemOptions = new SessionLineItemOptions(); SessionLineItemPriceDataOptions priceData = new SessionLineItemPriceDataOptions(); SessionLineItemPriceDataProductDataOptions prdData = new SessionLineItemPriceDataProductDataOptions(); prdData.Name = item.Product.P_Code + "|" + item.Product.P_Title; prdData.Images = new List <string>() { Barayand.Common.Services.UtilesService.MediaUrls("ProductMainImage") + item.Product.P_Image }; //prdData.Description = (!string.IsNullOrEmpty(item.Product.P_Description)) ? Regex.Replace(item.Product.P_Description, "<.*?>", String.Empty) : "Valhallaplanet Product"; //priceData.ProductData = prdData; //priceData.Currency = "eur"; //priceData.UnitAmountDecimal = item.Product.FinalPrice(basket.SumDiscount(), shippingCost) * 100; //decimal TotalUnit = item.Product.FinalPrice(basket.SumDiscount(), shippingCost); if (WALLET > 0) { //if (TotalUnit <= WALLET) //{ // priceData.UnitAmountDecimal = 0; // USEDWALLET += TotalUnit; // WALLET = WALLET - TotalUnit; //} //else //{ // USEDWALLET += WALLET; // priceData.UnitAmountDecimal = ((priceData.UnitAmountDecimal / 100) - WALLET) * 100; //} } ItemOptions.Quantity = item.Quantity; ItemOptions.PriceData = priceData; Items.Add(ItemOptions); } if (USEDWALLET > 0) { _walletrepository.DecreaseWallet(user, USEDWALLET); } return(Items); }
protected void Page_Load(object sender, EventArgs e) { HttpCookie cookie = Request.Cookies["user_id"];//getting the user_id Process_Executor exec = new Process_Executor(); if (cookie != null) { List <CART_INFO_SUMMARY> items = exec.get_cart_summary(cookie.Value); List <SessionLineItemOptions> transactions = new List <SessionLineItemOptions>(); foreach (CART_INFO_SUMMARY transaction_summary in items) { SessionLineItemOptions item_list = new SessionLineItemOptions { Name = transaction_summary.get_product_name(), Description = transaction_summary.get_prod_desc(), Amount = Convert.ToInt64(decimal.Round(transaction_summary.get_sub_total()).ToString()), Currency = transaction_summary.get_currecy(), Quantity = Convert.ToInt64(transaction_summary.get_quantity().ToString()), }; transactions.Add(item_list); } StripeConfiguration.ApiKey = "sk_test_4eC39HqLyjWDarjtT1zdp7dc"; var options = new SessionCreateOptions { //todo: change routes to a success or failure page (both woudld be nice ) //test card numbers cn=an be found at https://stripe.com/docs/testing#cards //also if error occurs remove above link SuccessUrl = "https://localhost:44324/CART_DATA/INSERT_HISTORY.aspx", CancelUrl = "https://localhost:44324/Default.aspx", PaymentMethodTypes = new List <string> { "card", }, //line items stores the items that are being checkout to be sent to stripe server LineItems = transactions, Mode = "payment", }; var service = new SessionService(); Session session = service.Create(options); sessionId = session.Id; } }
public Session GetSession(OrdersVM ordersVM) { int?subTotal = 0; // Set your secret key. Remember to switch to your live secret key in production! // See your keys here: https://dashboard.stripe.com/account/apikeys //testkey // StripeConfiguration.ApiKey = "sk_test_51Gzi07G3ZOAC0jt8niPlnlVoIWVWr7mNHGOFGXKwDPh4bFwDGSySN1miCyhS6yl2pqBfLbrPYUBZI61UAYtgtxkg00norJ7l27"; //activekey StripeConfiguration.ApiKey = "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"; var options = new SessionCreateOptions(); var lineItems = new List <SessionLineItemOptions>(); options.PaymentMethodTypes = new List <string> { "card", }; options.Mode = "payment"; options.SuccessUrl = "https://traincel.azurewebsites.net/order/success"; options.CancelUrl = "https://traincel.azurewebsites.net/order/failure"; options.LineItems = new List <SessionLineItemOptions>(); ordersVM.OrderItems.ForEach((item) => { var price = _webinarPurchasedOptionsDetailsRepo.GetWebinarPrice(item.WebinarId, item.PurchaseOptionId); string priceString = String.Concat(item.Price.ToString(), "00"); price = Convert.ToInt32(priceString); var lineItem = new SessionLineItemOptions { PriceData = new SessionLineItemPriceDataOptions { Currency = "usd", ProductData = new SessionLineItemPriceDataProductDataOptions { Name = item.Webinar.WebinarName, }, UnitAmountDecimal = price }, Quantity = 1, }; options.LineItems.Add(lineItem); }); var service = new SessionService(); Session session = service.Create(options); return(session); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "checkoutSession")] HttpRequest req, [Queue("orders", Connection = "StorageConnectionString")] IAsyncCollector <Order> orderQueue, ILogger log) { try { log.LogInformation("C# HTTP trigger function processed the checkoutSession request."); StripeConfiguration.ApiKey = Environment.GetEnvironmentVariable("stripe_api_key"); string requestBody = await new StreamReader(req.Body).ReadToEndAsync(); CheckoutBody checkoutBody = JsonConvert.DeserializeObject <CheckoutBody>(requestBody); SessionLineItemOptions product = new SessionLineItemOptions { Price = checkoutBody.productId, Quantity = 1, }; string localUri = Environment.GetEnvironmentVariable("local_uri"); SessionCreateOptions options = new SessionCreateOptions { PaymentMethodTypes = new List <string> { "card", }, LineItems = new List <SessionLineItemOptions> { product }, Mode = "payment", SuccessUrl = localUri + "/checkout/success?session_id={CHECKOUT_SESSION_ID}", CancelUrl = localUri + "/checkout/cancel", }; SessionService service = new SessionService(); Session session = service.Create(options); return(new OkObjectResult(new { id = session.Id })); } catch (Exception ex) { return(new BadRequestObjectResult(ex)); } }
private async Task <ActionResult> PayWithStripeCheckout(Sjop.Models.Order order) { // Read Stripe API key from config StripeConfiguration.ApiKey = _stripeSettings.SecretKey; // Add orderlines to Checkout session var lines = new List <SessionLineItemOptions>(); foreach (var ol in order.OrderLines) { _logger.LogInformation($"linjepris: {ol.TotalPrice}"); var newline = new SessionLineItemOptions { Name = ol.ProductName, Description = ol.ProductDescription, Amount = Convert.ToInt64(ol.TotalPrice * 100), Currency = "nok", Quantity = ol.Quantity }; lines.Add(newline); } var options = new SessionCreateOptions { ClientReferenceId = order.Id.ToString(), CustomerEmail = order.Customer.Email, Locale = "nb", PaymentMethodTypes = new List <string> { "card", }, LineItems = lines, SuccessUrl = _site.BaseUrl + "/PaymentSuccess?session_id={CHECKOUT_SESSION_ID}", CancelUrl = _site.BaseUrl + "/PaymentFailed", }; var service = new SessionService(); Session session = await service.CreateAsync(options); order.PaymentProviderSessionId = session.Id; _context.Update(order); await _context.SaveChangesAsync(); return(Ok(session)); }
private async Task <ActionResult> PayWithStripeCheckout([FromBody] CustomerOrder order) { StripeConfiguration.ApiKey = StripeOptions.SecretKey; var lines = new List <SessionLineItemOptions>(); foreach (var ol in order.orderItems) { var newline = new SessionLineItemOptions { Name = ol.Product.name, Description = ol.Product.description, Amount = Convert.ToInt64(ol.total_payable), Currency = "usd", Quantity = ol.qty }; lines.Add(newline); } var options = new SessionCreateOptions { ClientReferenceId = order.order_id.ToString(), CustomerEmail = order.customer.email, Locale = "nb", PaymentMethodTypes = new List <string> { "card", }, LineItems = lines, SuccessUrl = SiteBaseUrl + "/PaymentSuccess?session_id={CHECKOUT_SESSION_ID}", CancelUrl = SiteBaseUrl + "/PaymentFailed", }; var service = new SessionService(); Session session = await service.CreateAsync(options); order.PaymentProviderSessionId = session.Id; //_context.Update(order); //await _context.SaveChangesAsync(); return(Ok(session)); }
public Session CreateSession(OrderReadOnly order, string continueUrl, string cancelUrl, StripeCheckoutSettings settings) { var secretKey = settings.TestMode ? settings.TestSecretKey : settings.LiveSecretKey; ConfigureStripe(secretKey); var currency = Vendr.Services.CurrencyService.GetCurrency(order.CurrencyId); var billingCountry = order.PaymentInfo.CountryId.HasValue ? Vendr.Services.CountryService.GetCountry(order.PaymentInfo.CountryId.Value) : null; Customer customer; var customerService = new CustomerService(); // If we've created a customer already, keep using it but update it incase // any of the billing details have changed if (!string.IsNullOrWhiteSpace(order.Properties["stripeCustomerId"])) { var customerOptions = new CustomerUpdateOptions { Name = $"{order.CustomerInfo.FirstName} {order.CustomerInfo.LastName}", Email = order.CustomerInfo.Email, Description = order.OrderNumber, Address = new AddressOptions { Line1 = !string.IsNullOrWhiteSpace(settings.BillingAddressLine1PropertyAlias) ? order.Properties[settings.BillingAddressLine1PropertyAlias] : "", Line2 = !string.IsNullOrWhiteSpace(settings.BillingAddressLine2PropertyAlias) ? order.Properties[settings.BillingAddressLine2PropertyAlias] : "", City = !string.IsNullOrWhiteSpace(settings.BillingAddressCityPropertyAlias) ? order.Properties[settings.BillingAddressCityPropertyAlias] : "", State = !string.IsNullOrWhiteSpace(settings.BillingAddressStatePropertyAlias) ? order.Properties[settings.BillingAddressStatePropertyAlias] : "", PostalCode = !string.IsNullOrWhiteSpace(settings.BillingAddressZipCodePropertyAlias) ? order.Properties[settings.BillingAddressZipCodePropertyAlias] : "", Country = billingCountry?.Code } }; // Pass billing country / zipcode as meta data as currently // this is the only way it can be validated via Radar // Block if ::customer:billingCountry:: != :card_country: customerOptions.Metadata = new Dictionary <string, string> { { "billingCountry", customerOptions.Address.Country }, { "billingZipCode", customerOptions.Address.PostalCode } }; customer = customerService.Update(order.Properties["stripeCustomerId"].Value, customerOptions); } else { var customerOptions = new CustomerCreateOptions { Name = $"{order.CustomerInfo.FirstName} {order.CustomerInfo.LastName}", Email = order.CustomerInfo.Email, Description = order.OrderNumber, Address = new AddressOptions { Line1 = !string.IsNullOrWhiteSpace(settings.BillingAddressLine1PropertyAlias) ? order.Properties[settings.BillingAddressLine1PropertyAlias] : "", Line2 = !string.IsNullOrWhiteSpace(settings.BillingAddressLine2PropertyAlias) ? order.Properties[settings.BillingAddressLine2PropertyAlias] : "", City = !string.IsNullOrWhiteSpace(settings.BillingAddressCityPropertyAlias) ? order.Properties[settings.BillingAddressCityPropertyAlias] : "", State = !string.IsNullOrWhiteSpace(settings.BillingAddressStatePropertyAlias) ? order.Properties[settings.BillingAddressStatePropertyAlias] : "", PostalCode = !string.IsNullOrWhiteSpace(settings.BillingAddressZipCodePropertyAlias) ? order.Properties[settings.BillingAddressZipCodePropertyAlias] : "", Country = billingCountry?.Code } }; // Pass billing country / zipcode as meta data as currently // this is the only way it can be validated via Radar // Block if ::customer:billingCountry:: != :card_country: customerOptions.Metadata = new Dictionary <string, string> { { "billingCountry", customerOptions.Address.Country }, { "billingZipCode", customerOptions.Address.PostalCode } }; customer = customerService.Create(customerOptions); } var metaData = new Dictionary <string, string> { { "orderReference", order.GenerateOrderReference() }, { "orderId", order.Id.ToString("D") }, { "orderNumber", order.OrderNumber } }; if (!string.IsNullOrWhiteSpace(settings.OrderProperties)) { foreach (var alias in settings.OrderProperties.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Select(x => x.Trim()) .Where(x => !string.IsNullOrWhiteSpace(x))) { if (!string.IsNullOrWhiteSpace(order.Properties[alias])) { metaData.Add(alias, order.Properties[alias]); } } } var hasRecurringItems = false; long recurringTotalPrice = 0; long orderTotalPrice = AmountToMinorUnits(order.TransactionAmount.Value); var lineItems = new List <SessionLineItemOptions>(); foreach (var orderLine in order.OrderLines.Where(IsRecurringOrderLine)) { var orderLinePrice = AmountToMinorUnits(orderLine.TotalPrice.Value.WithTax); var lineItemOpts = new SessionLineItemOptions(); if (orderLine.Properties.ContainsKey("stripePriceId") && !string.IsNullOrWhiteSpace(orderLine.Properties["stripePriceId"])) { // NB: When using stripe prices there is an inherit risk that values may not // actually be in sync and so the price displayed on the site might not match // that in stripe and so this may cause inconsistant payments lineItemOpts.Price = orderLine.Properties["stripePriceId"].Value; // If we are using a stripe price, then assume the quantity of the line item means // the quantity of the stripe price you want to buy. lineItemOpts.Quantity = (long)orderLine.Quantity; } else { // We don't have a stripe price defined on the order line // so we'll create one on the fly using th order lines total // value var priceData = new SessionLineItemPriceDataOptions { Currency = currency.Code, UnitAmount = orderLinePrice, Recurring = new SessionLineItemPriceDataRecurringOptions { Interval = orderLine.Properties["stripeRecurringInterval"].Value.ToLower(), IntervalCount = long.TryParse(orderLine.Properties["stripeRecurringIntervalCount"], out var intervalCount) ? intervalCount : 1 } }; if (orderLine.Properties.ContainsKey("stripeProductId") && !string.IsNullOrWhiteSpace(orderLine.Properties["stripeProductId"])) { priceData.Product = orderLine.Properties["stripeProductId"].Value; } else { priceData.ProductData = new SessionLineItemPriceDataProductDataOptions { Name = orderLine.Name, Metadata = new Dictionary <string, string> { { "ProductReference", orderLine.ProductReference } } }; } lineItemOpts.PriceData = priceData; // For dynamic subscriptions, regardless of line item quantity, treat the line // as a single subscription item with one price being the line items total price lineItemOpts.Quantity = 1; } lineItems.Add(lineItemOpts); recurringTotalPrice += orderLinePrice; hasRecurringItems = true; } if (recurringTotalPrice < orderTotalPrice) { // If the total value of the order is not covered by the subscription items // then we add another line item for the remainder of the order value var lineItemOpts = new SessionLineItemOptions { PriceData = new SessionLineItemPriceDataOptions { Currency = currency.Code, UnitAmount = orderTotalPrice - recurringTotalPrice, ProductData = new SessionLineItemPriceDataProductDataOptions { Name = hasRecurringItems ? !string.IsNullOrWhiteSpace(settings.OneTimeItemsHeading) ? settings.OneTimeItemsHeading : "One time items" : !string.IsNullOrWhiteSpace(settings.OrderHeading) ? settings.OrderHeading : "#" + order.OrderNumber, Description = hasRecurringItems || string.IsNullOrWhiteSpace(settings.OrderHeading) ? null : "#" + order.OrderNumber, } }, Quantity = 1 }; lineItems.Add(lineItemOpts); } // Add image to the first item (only if it's not a product link) if (!string.IsNullOrWhiteSpace(settings.OrderImage) && lineItems.Count > 0 && lineItems[0].PriceData?.ProductData != null) { lineItems[0].PriceData.ProductData.Images = new[] { settings.OrderImage }.ToList(); } var sessionOptions = new SessionCreateOptions { Customer = customer.Id, PaymentMethodTypes = new List <string> { "card", }, LineItems = lineItems, Mode = hasRecurringItems ? "subscription" : "payment", ClientReferenceId = order.GenerateOrderReference(), SuccessUrl = continueUrl, CancelUrl = cancelUrl, }; if (hasRecurringItems) { sessionOptions.SubscriptionData = new SessionSubscriptionDataOptions { Metadata = metaData }; } else { sessionOptions.PaymentIntentData = new SessionPaymentIntentDataOptions { CaptureMethod = settings.Capture ? "automatic" : "manual", Metadata = metaData }; } if (settings.SendStripeReceipt) { sessionOptions.PaymentIntentData.ReceiptEmail = order.CustomerInfo.Email; } var sessionService = new SessionService(); var session = sessionService.Create(sessionOptions); return(session); }
public IActionResult Purchase() { // get all items in the user's cart Guid userId = GetUserId(); List <CartItem> cartItems = _cartService.GetUsersCart(userId); if (cartItems.Count == 0) { return(BadRequest(new { err = "Your cart is empty" })); } // create a list of session line items to pass them to stripe var lineItems = new List <SessionLineItemOptions>(); cartItems.ForEach(item => { // get the product's price decimal productPrice = _productService.GetProductPrice(item.Product.ID); SessionLineItemOptions itemOptions = new SessionLineItemOptions { PriceData = new SessionLineItemPriceDataOptions { // the unit amount is in cents, therefore, it needs to be multiplied by 100 UnitAmount = (int)(productPrice * 100), // add the name of the item ProductData = new SessionLineItemPriceDataProductDataOptions { Name = item.Product.Title }, Currency = "USD" }, Quantity = item.Quantity }; lineItems.Add(itemOptions); }); // create session options var options = new SessionCreateOptions { // attach user's id in metadata, so that the webhook can verify it later PaymentIntentData = new SessionPaymentIntentDataOptions { Metadata = new Dictionary <string, string> { { "userId", userId.ToString() } } }, PaymentMethodTypes = new List <string> { "card", }, LineItems = lineItems, Mode = "payment", // take the user to the client app's homepage if the payment is successful SuccessUrl = $"{Request.Scheme}://{Request.Host}", // take the user back to the checkout page if the payment was cancelled CancelUrl = $"{Request.Scheme}://{Request.Host}/checkout" }; var service = new SessionService(); Session session = service.Create(options); return(Ok(new { res = session.Id })); }
public SessionModel CreateCheckoutSession(OrderModel order) { _validator.ValidateOrder(order); bool isExisting = order.Id is not null; PaymentEntity payment = isExisting ? new PaymentEntity { Id = order.PaymentId } : null; if (!isExisting) { order.Status = Enums.OrderStatusType.Unpaid; order.Date = DateTime.UtcNow; payment = new PaymentEntity { TransactionId = string.Empty }; _paymentRepository.Insert(payment); } var dbOrder = _mapper.Map <OrderEntity>(order); if (!isExisting) { dbOrder.PaymentId = payment.Id; dbOrder.Total = order.CurrentItems.Sum(item => item.Price); _orderRepository.Insert(dbOrder); } var items = new List <SessionLineItemOptions>(); var editionIds = order.CurrentItems.Select(item => item.PrintingEditionId).ToList(); var editionFilter = new PrintingEditionFilterModel { EditionIds = editionIds }; var printingEditions = _printingEditionService.GetPrintingEditionsRange(editionFilter); var dbItems = _mapper.Map <List <OrderItemEntity> >(order.CurrentItems); dbItems.ForEach(item => item.OrderId = dbOrder.Id); foreach (var item in dbItems) { var printingEdition = printingEditions.Where(edition => edition.Id == item.PrintingEditionId).FirstOrDefault(); var lineItem = new SessionLineItemOptions { PriceData = new SessionLineItemPriceDataOptions { UnitAmountDecimal = printingEdition.Price * Constants.CENTMULTIPLIER, Currency = item.Currency.ToString(), ProductData = new SessionLineItemPriceDataProductDataOptions { Name = printingEdition.Title, Description = printingEdition.Description } }, Quantity = item.Amount }; items.Add(lineItem); } if (!isExisting) { _itemRepository.InsertRange(dbItems); } string successUrl = new UriBuilder { Scheme = _urlConfig.Scheme, Port = _urlConfig.Port, Host = _urlConfig.Host, Path = Constants.STRIPESUCCESSPATH }.ToString(); string cancelUrl = new UriBuilder { Scheme = _urlConfig.Scheme, Port = _urlConfig.Port, Host = _urlConfig.Host, Path = Constants.STRIPECANCELPATH }.ToString(); var options = new SessionCreateOptions { PaymentMethodTypes = new List <string> { Constants.DEFAULTPAYMENTMETHOD }, LineItems = items, Mode = Constants.DEFAULTPAYMENTMODE, SuccessUrl = successUrl, CancelUrl = cancelUrl }; var service = new SessionService(); Session session = service.Create(options); payment.TransactionId = session.PaymentIntentId; _paymentRepository.Update(payment); return(new SessionModel { Id = session.Id, PaymentIntentId = session.PaymentIntentId }); }
public override async Task <PaymentFormResult> GenerateFormAsync(PaymentProviderContext <StripeCheckoutSettings> ctx) { var secretKey = ctx.Settings.TestMode ? ctx.Settings.TestSecretKey : ctx.Settings.LiveSecretKey; var publicKey = ctx.Settings.TestMode ? ctx.Settings.TestPublicKey : ctx.Settings.LivePublicKey; ConfigureStripe(secretKey); var currency = Vendr.Services.CurrencyService.GetCurrency(ctx.Order.CurrencyId); var billingCountry = ctx.Order.PaymentInfo.CountryId.HasValue ? Vendr.Services.CountryService.GetCountry(ctx.Order.PaymentInfo.CountryId.Value) : null; Customer customer; var customerService = new CustomerService(); // If we've created a customer already, keep using it but update it incase // any of the billing details have changed if (!string.IsNullOrWhiteSpace(ctx.Order.Properties["stripeCustomerId"])) { var customerOptions = new CustomerUpdateOptions { Name = $"{ctx.Order.CustomerInfo.FirstName} {ctx.Order.CustomerInfo.LastName}", Email = ctx.Order.CustomerInfo.Email, Description = ctx.Order.OrderNumber, Address = new AddressOptions { Line1 = !string.IsNullOrWhiteSpace(ctx.Settings.BillingAddressLine1PropertyAlias) ? ctx.Order.Properties[ctx.Settings.BillingAddressLine1PropertyAlias] : "", Line2 = !string.IsNullOrWhiteSpace(ctx.Settings.BillingAddressLine2PropertyAlias) ? ctx.Order.Properties[ctx.Settings.BillingAddressLine2PropertyAlias] : "", City = !string.IsNullOrWhiteSpace(ctx.Settings.BillingAddressCityPropertyAlias) ? ctx.Order.Properties[ctx.Settings.BillingAddressCityPropertyAlias] : "", State = !string.IsNullOrWhiteSpace(ctx.Settings.BillingAddressStatePropertyAlias) ? ctx.Order.Properties[ctx.Settings.BillingAddressStatePropertyAlias] : "", PostalCode = !string.IsNullOrWhiteSpace(ctx.Settings.BillingAddressZipCodePropertyAlias) ? ctx.Order.Properties[ctx.Settings.BillingAddressZipCodePropertyAlias] : "", Country = billingCountry?.Code } }; // Pass billing country / zipcode as meta data as currently // this is the only way it can be validated via Radar // Block if ::customer:billingCountry:: != :card_country: customerOptions.Metadata = new Dictionary <string, string> { { "billingCountry", customerOptions.Address.Country }, { "billingZipCode", customerOptions.Address.PostalCode } }; customer = customerService.Update(ctx.Order.Properties["stripeCustomerId"].Value, customerOptions); } else { var customerOptions = new CustomerCreateOptions { Name = $"{ctx.Order.CustomerInfo.FirstName} {ctx.Order.CustomerInfo.LastName}", Email = ctx.Order.CustomerInfo.Email, Description = ctx.Order.OrderNumber, Address = new AddressOptions { Line1 = !string.IsNullOrWhiteSpace(ctx.Settings.BillingAddressLine1PropertyAlias) ? ctx.Order.Properties[ctx.Settings.BillingAddressLine1PropertyAlias] : "", Line2 = !string.IsNullOrWhiteSpace(ctx.Settings.BillingAddressLine2PropertyAlias) ? ctx.Order.Properties[ctx.Settings.BillingAddressLine2PropertyAlias] : "", City = !string.IsNullOrWhiteSpace(ctx.Settings.BillingAddressCityPropertyAlias) ? ctx.Order.Properties[ctx.Settings.BillingAddressCityPropertyAlias] : "", State = !string.IsNullOrWhiteSpace(ctx.Settings.BillingAddressStatePropertyAlias) ? ctx.Order.Properties[ctx.Settings.BillingAddressStatePropertyAlias] : "", PostalCode = !string.IsNullOrWhiteSpace(ctx.Settings.BillingAddressZipCodePropertyAlias) ? ctx.Order.Properties[ctx.Settings.BillingAddressZipCodePropertyAlias] : "", Country = billingCountry?.Code } }; // Pass billing country / zipcode as meta data as currently // this is the only way it can be validated via Radar // Block if ::customer:billingCountry:: != :card_country: customerOptions.Metadata = new Dictionary <string, string> { { "billingCountry", customerOptions.Address.Country }, { "billingZipCode", customerOptions.Address.PostalCode } }; customer = customerService.Create(customerOptions); } var metaData = new Dictionary <string, string> { { "ctx.OrderReference", ctx.Order.GenerateOrderReference() }, { "ctx.OrderId", ctx.Order.Id.ToString("D") }, { "ctx.OrderNumber", ctx.Order.OrderNumber } }; if (!string.IsNullOrWhiteSpace(ctx.Settings.OrderProperties)) { foreach (var alias in ctx.Settings.OrderProperties.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Select(x => x.Trim()) .Where(x => !string.IsNullOrWhiteSpace(x))) { if (!string.IsNullOrWhiteSpace(ctx.Order.Properties[alias])) { metaData.Add(alias, ctx.Order.Properties[alias]); } } } var hasRecurringItems = false; long recurringTotalPrice = 0; long orderTotalPrice = AmountToMinorUnits(ctx.Order.TransactionAmount.Value); var lineItems = new List <SessionLineItemOptions>(); foreach (var orderLine in ctx.Order.OrderLines.Where(IsRecurringOrderLine)) { var orderLineTaxRate = orderLine.TaxRate * 100; var lineItemOpts = new SessionLineItemOptions(); if (orderLine.Properties.ContainsKey("stripePriceId") && !string.IsNullOrWhiteSpace(orderLine.Properties["stripePriceId"])) { // NB: When using stripe prices there is an inherit risk that values may not // actually be in sync and so the price displayed on the site might not match // that in stripe and so this may cause inconsistant payments lineItemOpts.Price = orderLine.Properties["stripePriceId"].Value; // If we are using a stripe price, then assume the quantity of the line item means // the quantity of the stripe price you want to buy. lineItemOpts.Quantity = (long)orderLine.Quantity; // Because we are in charge of what taxes apply, we need to setup a tax rate // to ensure the price defined in stripe has the relevant taxes applied var stripePricesIncludeTax = PropertyIsTrue(orderLine.Properties, "stripePriceIncludesTax"); var stripeTaxRate = GetOrCreateStripeTaxRate(ctx, "Subscription Tax", orderLineTaxRate, stripePricesIncludeTax); if (stripeTaxRate != null) { lineItemOpts.TaxRates = new List <string>(new[] { stripeTaxRate.Id }); } } else { // We don't have a stripe price defined on the ctx.Order line // so we'll create one on the fly using the ctx.Order lines total // value var priceData = new SessionLineItemPriceDataOptions { Currency = currency.Code, UnitAmount = AmountToMinorUnits(orderLine.TotalPrice.Value.WithoutTax / orderLine.Quantity), // Without tax as Stripe will apply the tax Recurring = new SessionLineItemPriceDataRecurringOptions { Interval = orderLine.Properties["stripeRecurringInterval"].Value.ToLower(), IntervalCount = long.TryParse(orderLine.Properties["stripeRecurringIntervalCount"], out var intervalCount) ? intervalCount : 1 } }; if (orderLine.Properties.ContainsKey("stripeProductId") && !string.IsNullOrWhiteSpace(orderLine.Properties["stripeProductId"])) { priceData.Product = orderLine.Properties["stripeProductId"].Value; } else { priceData.ProductData = new SessionLineItemPriceDataProductDataOptions { Name = orderLine.Name, Metadata = new Dictionary <string, string> { { "ProductReference", orderLine.ProductReference } } }; } lineItemOpts.PriceData = priceData; // For dynamic subscriptions, regardless of line item quantity, treat the line // as a single subscription item with one price being the line items total price lineItemOpts.Quantity = (long)orderLine.Quantity; // If we define the price, then create tax rates that are set to be inclusive // as this means that we can pass prices inclusive of tax and Stripe works out // the pre-tax price which would be less suseptable to rounding inconsistancies var stripeTaxRate = GetOrCreateStripeTaxRate(ctx, "Subscription Tax", orderLineTaxRate, false); if (stripeTaxRate != null) { lineItemOpts.TaxRates = new List <string>(new[] { stripeTaxRate.Id }); } } lineItems.Add(lineItemOpts); recurringTotalPrice += AmountToMinorUnits(orderLine.TotalPrice.Value.WithTax); hasRecurringItems = true; } if (recurringTotalPrice < orderTotalPrice) { // If the total value of the ctx.Order is not covered by the subscription items // then we add another line item for the remainder of the ctx.Order value var lineItemOpts = new SessionLineItemOptions { PriceData = new SessionLineItemPriceDataOptions { Currency = currency.Code, UnitAmount = orderTotalPrice - recurringTotalPrice, ProductData = new SessionLineItemPriceDataProductDataOptions { Name = hasRecurringItems ? !string.IsNullOrWhiteSpace(ctx.Settings.OneTimeItemsHeading) ? ctx.Settings.OneTimeItemsHeading : "One time items (inc Tax)" : !string.IsNullOrWhiteSpace(ctx.Settings.OrderHeading) ? ctx.Settings.OrderHeading : "#" + ctx.Order.OrderNumber, Description = hasRecurringItems || !string.IsNullOrWhiteSpace(ctx.Settings.OrderHeading) ? "#" + ctx.Order.OrderNumber : null, } }, Quantity = 1 }; lineItems.Add(lineItemOpts); } // Add image to the first item (only if it's not a product link) if (!string.IsNullOrWhiteSpace(ctx.Settings.OrderImage) && lineItems.Count > 0 && lineItems[0].PriceData?.ProductData != null) { lineItems[0].PriceData.ProductData.Images = new[] { ctx.Settings.OrderImage }.ToList(); } var sessionOptions = new SessionCreateOptions { Customer = customer.Id, PaymentMethodTypes = !string.IsNullOrWhiteSpace(ctx.Settings.PaymentMethodTypes) ? ctx.Settings.PaymentMethodTypes.Split(',') .Select(tag => tag.Trim()) .Where(tag => !string.IsNullOrEmpty(tag)) .ToList() : new List <string> { "card", }, LineItems = lineItems, Mode = hasRecurringItems ? "subscription" : "payment", ClientReferenceId = ctx.Order.GenerateOrderReference(), SuccessUrl = ctx.Urls.ContinueUrl, CancelUrl = ctx.Urls.CancelUrl }; if (hasRecurringItems) { sessionOptions.SubscriptionData = new SessionSubscriptionDataOptions { Metadata = metaData }; } else { sessionOptions.PaymentIntentData = new SessionPaymentIntentDataOptions { CaptureMethod = ctx.Settings.Capture ? "automatic" : "manual", Metadata = metaData }; } if (ctx.Settings.SendStripeReceipt) { sessionOptions.PaymentIntentData.ReceiptEmail = ctx.Order.CustomerInfo.Email; } var sessionService = new SessionService(); var session = await sessionService.CreateAsync(sessionOptions); return(new PaymentFormResult() { MetaData = new Dictionary <string, string> { { "stripeSessionId", session.Id }, { "stripeCustomerId", session.CustomerId } }, Form = new PaymentForm(ctx.Urls.ContinueUrl, PaymentFormMethod.Post) .WithAttribute("onsubmit", "return handleStripeCheckout(event)") .WithJsFile("https://js.stripe.com/v3/") .WithJs(@" var stripe = Stripe('" + publicKey + @"'); window.handleStripeCheckout = function (e) { e.preventDefault(); stripe.redirectToCheckout({ sessionId: '" + session.Id + @"' }).then(function (result) { // If `redirectToCheckout` fails due to a browser or network // error, display the localized error message to your customer // using `result.error.message`. }); return false; } ") }); }