diff --git a/Plugins/BTCPayServer.Plugins.TicketTailor/BTCPayServer.Plugins.TicketTailor.csproj b/Plugins/BTCPayServer.Plugins.TicketTailor/BTCPayServer.Plugins.TicketTailor.csproj index 9aef82c..b11b943 100644 --- a/Plugins/BTCPayServer.Plugins.TicketTailor/BTCPayServer.Plugins.TicketTailor.csproj +++ b/Plugins/BTCPayServer.Plugins.TicketTailor/BTCPayServer.Plugins.TicketTailor.csproj @@ -9,7 +9,7 @@ TicketTailor Allows you to integrate with TicketTailor.com to sell tickets for Bitcoin - 1.0.11 + 1.0.12 diff --git a/Plugins/BTCPayServer.Plugins.TicketTailor/TicketTailorClient.cs b/Plugins/BTCPayServer.Plugins.TicketTailor/TicketTailorClient.cs index 96e5e1b..1c12437 100644 --- a/Plugins/BTCPayServer.Plugins.TicketTailor/TicketTailorClient.cs +++ b/Plugins/BTCPayServer.Plugins.TicketTailor/TicketTailorClient.cs @@ -335,4 +335,44 @@ public class TicketTailorClient : IDisposable [JsonPropertyName("venue")] public Venue Venue { get; set; } } + + public async Task GetDiscountCode(string code) + { + var response = await _httpClient.GetAsync($"/v1/discounts?code={code}"); + if (!response.IsSuccessStatusCode) + { + return null; + } + var result = await response.Content.ReadFromJsonAsync>(); + return result?.Data?.FirstOrDefault(); + } + public class DiscountCode +{ + public string id { get; set; } + public string code { get; set; } + public Expires? expires { get; set; } + public int? max_redemptions { get; set; } + public string name { get; set; } + public int? face_value_amount { get; set; } + public int? face_value_percentage { get; set; } + public string[] ticket_types { get; set; } + public int? times_redeemed { get; set; } + public string type { get; set; } + public class Expires + { + public string date { get; set; } + public string formatted { get; set; } + public string iso { get; set; } + public string time { get; set; } + public string timezone { get; set; } + public long unix { get; set; } + } } + + + + + + +} + diff --git a/Plugins/BTCPayServer.Plugins.TicketTailor/TicketTailorController.cs b/Plugins/BTCPayServer.Plugins.TicketTailor/TicketTailorController.cs index 6c9b10a..8255866 100644 --- a/Plugins/BTCPayServer.Plugins.TicketTailor/TicketTailorController.cs +++ b/Plugins/BTCPayServer.Plugins.TicketTailor/TicketTailorController.cs @@ -50,7 +50,7 @@ namespace BTCPayServer.Plugins.TicketTailor [AllowAnonymous] [HttpPost("")] - public async Task Purchase(string storeId, TicketTailorViewModel request) + public async Task Purchase(string storeId, TicketTailorViewModel request, bool preview = false) { var config = await _ticketTailorService.GetTicketTailorForStore(storeId); (TicketTailorClient.Hold, string error)? hold = null; @@ -66,6 +66,17 @@ namespace BTCPayServer.Plugins.TicketTailor } var price = 0m; + TicketTailorClient.DiscountCode discountCode = null; + if (!string.IsNullOrEmpty(request.DiscountCode) && config.AllowDiscountCodes) + { + discountCode = await client.GetDiscountCode(request.DiscountCode); + if (discountCode?.expires?.unix is not null && DateTimeOffset.FromUnixTimeSeconds(discountCode.expires.unix) < DateTimeOffset.Now) + { + discountCode = null; + } + } + + var discountedAmount = 0m; foreach (var purchaseRequestItem in request.Items) { if (purchaseRequestItem.Quantity <= 0) @@ -73,7 +84,7 @@ namespace BTCPayServer.Plugins.TicketTailor continue; } var ticketType = evt.TicketTypes.FirstOrDefault(type => type.Id == purchaseRequestItem.TicketTypeId); - + var specificTicket = config.SpecificTickets?.SingleOrDefault(ticket => ticketType?.Id == ticket.TicketTypeId); if ((config.SpecificTickets?.Any() is true && specificTicket is null) || ticketType is null || @@ -107,7 +118,36 @@ namespace BTCPayServer.Plugins.TicketTailor ticketCost =specificTicket.Price.GetValueOrDefault(ticketType.Price); } - price += ticketCost * purchaseRequestItem.Quantity; + var originalTicketCost = ticketCost; + if (discountCode?.ticket_types.Contains(ticketType?.Id) is true) + { + switch (discountCode.type) + { + case "fixed_amount" when discountCode.face_value_amount is not null: + ticketCost -= (discountCode.face_value_amount.Value / 100m); + break; + case "percentage" when discountCode.face_value_percentage is not null: + + var percentageOff = (discountCode.face_value_percentage.Value / 100m); + + ticketCost -= (ticketCost * percentageOff); + break; + } + } + + var thisTicketBatchCost = ticketCost * purchaseRequestItem.Quantity; + discountedAmount += (originalTicketCost * purchaseRequestItem.Quantity) - thisTicketBatchCost; + + price += thisTicketBatchCost; + } + + if (preview) + { + return Json(new + { + discountedAmount, + total = price + }); } hold = await client.CreateHold(new TicketTailorClient.CreateHoldRequest() @@ -172,7 +212,9 @@ namespace BTCPayServer.Plugins.TicketTailor buyerName = request.Name, buyerEmail = request.Email, holdId = hold.Value.Item1.Id, - orderId="tickettailor" + orderId="tickettailor", + discountCode, + discountedAmount }) }); @@ -300,6 +342,7 @@ namespace BTCPayServer.Plugins.TicketTailor vm.BypassAvailabilityCheck = TicketTailor.BypassAvailabilityCheck; vm.CustomCSS = TicketTailor.CustomCSS; vm.RequireFullName = TicketTailor.RequireFullName; + vm.AllowDiscountCodes = TicketTailor.AllowDiscountCodes; vm.SpecificTickets = TicketTailor.SpecificTickets; } } @@ -395,7 +438,8 @@ namespace BTCPayServer.Plugins.TicketTailor CustomCSS = vm.CustomCSS, SpecificTickets = vm.SpecificTickets, BypassAvailabilityCheck = vm.BypassAvailabilityCheck, - RequireFullName = vm.RequireFullName + RequireFullName = vm.RequireFullName, + AllowDiscountCodes = vm.AllowDiscountCodes }; diff --git a/Plugins/BTCPayServer.Plugins.TicketTailor/TicketTailorSettings.cs b/Plugins/BTCPayServer.Plugins.TicketTailor/TicketTailorSettings.cs index 31bccb1..88be59a 100644 --- a/Plugins/BTCPayServer.Plugins.TicketTailor/TicketTailorSettings.cs +++ b/Plugins/BTCPayServer.Plugins.TicketTailor/TicketTailorSettings.cs @@ -12,5 +12,6 @@ namespace BTCPayServer.Plugins.TicketTailor public List SpecificTickets { get; set; } public bool BypassAvailabilityCheck { get; set; } public bool RequireFullName { get; set; } + public bool AllowDiscountCodes { get; set; } } } diff --git a/Plugins/BTCPayServer.Plugins.TicketTailor/UpdateTicketTailorSettingsViewModel.cs b/Plugins/BTCPayServer.Plugins.TicketTailor/UpdateTicketTailorSettingsViewModel.cs index c3c52e1..44e9d2a 100644 --- a/Plugins/BTCPayServer.Plugins.TicketTailor/UpdateTicketTailorSettingsViewModel.cs +++ b/Plugins/BTCPayServer.Plugins.TicketTailor/UpdateTicketTailorSettingsViewModel.cs @@ -16,6 +16,7 @@ public class UpdateTicketTailorSettingsViewModel public List SpecificTickets { get; set; } public bool BypassAvailabilityCheck { get; set; } public bool RequireFullName { get; set; } + public bool AllowDiscountCodes { get; set; } } public class SpecificTicket @@ -37,6 +38,7 @@ public class TicketTailorViewModel public PurchaseRequestItem[] Items { get; set; } public string AccessCode { get; set; } + public string DiscountCode { get; set; } public class PurchaseRequestItem { diff --git a/Plugins/BTCPayServer.Plugins.TicketTailor/Views/TicketTailor/UpdateTicketTailorSettings.cshtml b/Plugins/BTCPayServer.Plugins.TicketTailor/Views/TicketTailor/UpdateTicketTailorSettings.cshtml index d3985d1..549c921 100644 --- a/Plugins/BTCPayServer.Plugins.TicketTailor/Views/TicketTailor/UpdateTicketTailorSettings.cshtml +++ b/Plugins/BTCPayServer.Plugins.TicketTailor/Views/TicketTailor/UpdateTicketTailorSettings.cshtml @@ -59,6 +59,11 @@ +
+ + + +
diff --git a/Plugins/BTCPayServer.Plugins.TicketTailor/Views/TicketTailor/View.cshtml b/Plugins/BTCPayServer.Plugins.TicketTailor/Views/TicketTailor/View.cshtml index 5f6b030..16e2348 100644 --- a/Plugins/BTCPayServer.Plugins.TicketTailor/Views/TicketTailor/View.cshtml +++ b/Plugins/BTCPayServer.Plugins.TicketTailor/Views/TicketTailor/View.cshtml @@ -3,10 +3,15 @@ @using Microsoft.AspNetCore.Mvc.TagHelpers @model BTCPayServer.Plugins.TicketTailor.TicketTailorViewModel @{ + var storeId = Context.GetRouteValue("storeId"); Layout = "_LayoutSimple"; var available = Model.Settings.BypassAvailabilityCheck || (Model.Event.Unavailable != "true" && Model.Event.TicketsAvailable == "true"); Model.Settings.SpecificTickets ??= new List(); Context.Request.Query.TryGetValue("accessCode", out var accessCode); + if (Context.Request.Query.TryGetValue("discount", out var discount)) + { + Model.DiscountCode = discount; + } }