diff --git a/BillingCore/BillingCore.csproj b/BillingCore/BillingCore.csproj new file mode 100644 index 0000000..9a9dc18 --- /dev/null +++ b/BillingCore/BillingCore.csproj @@ -0,0 +1,17 @@ + + + + net5.0 + Teknik.BillingCore + Teknik.BillingCore + + + + + + + + + + + diff --git a/BillingCore/BillingService.cs b/BillingCore/BillingService.cs new file mode 100644 index 0000000..41839fc --- /dev/null +++ b/BillingCore/BillingService.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Teknik.Configuration; + +namespace Teknik.BillingCore +{ + public abstract class BillingService + { + protected readonly BillingConfig Config; + + public BillingService(BillingConfig billingConfig) + { + Config = billingConfig; + } + + public abstract bool CreateCustomer(string email); + public abstract Tuple CreateSubscription(string customerId, string priceId); + + public abstract bool EditSubscription(); + + public abstract Subscription GetSubscription(string subscriptionId); + + public abstract bool RemoveSubscription(); + + public abstract void SyncSubscriptions(); + } +} diff --git a/BillingCore/IBillingService.cs b/BillingCore/IBillingService.cs new file mode 100644 index 0000000..1653f5e --- /dev/null +++ b/BillingCore/IBillingService.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Teknik.BillingCore +{ + public interface IBillingService + { + public bool AddSubscription(); + public bool EditSubscription(); + public bool RemoveSubscription(); + public void GetSubscription(); + public void SyncSubscriptions(); + } +} diff --git a/BillingCore/IntervalType.cs b/BillingCore/IntervalType.cs new file mode 100644 index 0000000..a7e519d --- /dev/null +++ b/BillingCore/IntervalType.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Teknik.BillingCore +{ + public enum IntervalType + { + Monthly, + Yearly + } +} diff --git a/BillingCore/Product.cs b/BillingCore/Product.cs new file mode 100644 index 0000000..2df3327 --- /dev/null +++ b/BillingCore/Product.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Teknik.BillingCore +{ + public class Product + { + public int ProductId { get; set; } + public string Name { get; set; } + public string Description { get; set; } + } +} diff --git a/BillingCore/StripeService.cs b/BillingCore/StripeService.cs new file mode 100644 index 0000000..deee621 --- /dev/null +++ b/BillingCore/StripeService.cs @@ -0,0 +1,84 @@ +using Stripe; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Teknik.Configuration; + +namespace Teknik.BillingCore +{ + public class StripeService : BillingService + { + public StripeService(BillingConfig config) : base(config) + { } + + public override bool CreateCustomer(string email) + { + var options = new CustomerCreateOptions + { + Email = email, + }; + var service = new CustomerService(); + var customer = service.Create(options); + return customer != null; + } + + public override Subscription GetSubscription(string subscriptionId) + { + throw new NotImplementedException(); + } + + public override Tuple CreateSubscription(string customerId, string priceId) + { + // Create the subscription. Note we're expanding the Subscription's + // latest invoice and that invoice's payment_intent + // so we can pass it to the front end to confirm the payment + var subscriptionOptions = new SubscriptionCreateOptions + { + Customer = customerId, + Items = new List + { + new SubscriptionItemOptions + { + Price = priceId, + }, + }, + PaymentBehavior = "default_incomplete", + }; + subscriptionOptions.AddExpand("latest_invoice.payment_intent"); + var subscriptionService = new SubscriptionService(); + try + { + Stripe.Subscription subscription = subscriptionService.Create(subscriptionOptions); + + return new Tuple(true, subscription.Id, subscription.LatestInvoice.PaymentIntent.ClientSecret); + } + catch (StripeException e) + { + return new Tuple(false, $"Failed to create subscription. {e}", null); + } + } + + public override bool EditSubscription() + { + throw new NotImplementedException(); + } + + public override bool RemoveSubscription() + { + throw new NotImplementedException(); + } + + public override void SyncSubscriptions() + { + throw new NotImplementedException(); + } + + private Customer GetCustomer(string id) + { + var service = new CustomerService(); + return service.Get(id); + } + } +} diff --git a/BillingCore/Subscription.cs b/BillingCore/Subscription.cs new file mode 100644 index 0000000..5dc5884 --- /dev/null +++ b/BillingCore/Subscription.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Teknik.BillingCore +{ + public class Subscription + { + public int SubscriptionId { get; set; } + public string Name { get; set; } + public string Description { get; set; } + public double Amount { get; set; } + } +} diff --git a/BillingCore/UserSubscription.cs b/BillingCore/UserSubscription.cs new file mode 100644 index 0000000..1c2a476 --- /dev/null +++ b/BillingCore/UserSubscription.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Teknik.BillingCore +{ + public class UserSubscription + { + public int UserId { get; set; } + public int SubscriptionId { get; set; } + public Subscription Subscription { get; set; } + public int ProductId { get; set; } + public Product Product { get; set; } + } +} diff --git a/BillingService/ArgumentOptions.cs b/BillingService/ArgumentOptions.cs new file mode 100644 index 0000000..ca37a96 --- /dev/null +++ b/BillingService/ArgumentOptions.cs @@ -0,0 +1,20 @@ +using CommandLine; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Teknik.BillingService +{ + public class ArgumentOptions + { + [Option('s', "sync", Default = false, Required = false, HelpText = "Syncs the current subscriptions with the invoice system")] + public bool SyncSubscriptions { get; set; } + + [Option('c', "config", Required = false, HelpText = "The path to the teknik config file")] + public string Config { get; set; } + + // Omitting long name, default --verbose + [Option(HelpText = "Prints all messages to standard output.")] + public bool Verbose { get; set; } + } +} diff --git a/BillingService/BillingService.csproj b/BillingService/BillingService.csproj new file mode 100644 index 0000000..2f8e28f --- /dev/null +++ b/BillingService/BillingService.csproj @@ -0,0 +1,19 @@ + + + + Exe + net5.0 + Teknik.BillingService + Teknik.BillingService + + + + + + + + + + + + diff --git a/BillingService/Program.cs b/BillingService/Program.cs new file mode 100644 index 0000000..30de78e --- /dev/null +++ b/BillingService/Program.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using CommandLine; +using Microsoft.EntityFrameworkCore; +using Teknik.Configuration; +using Teknik.Data; +using Teknik.Utilities; + +namespace Teknik.BillingService +{ + public class Program + { + private static string currentPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); + private static string errorFile = Path.Combine(currentPath, "errorLogs.txt"); + private static string configPath = currentPath; + + private static readonly object dbLock = new object(); + private static readonly object scanStatsLock = new object(); + + public static event Action OutputEvent; + + public static int Main(string[] args) + { + try + { + Parser.Default.ParseArguments(args).WithParsed(options => + { + if (!string.IsNullOrEmpty(options.Config)) + configPath = options.Config; + + if (Directory.Exists(configPath)) + { + Config config = Config.Load(configPath); + Output(string.Format("[{0}] Started Billing Service Process.", DateTime.Now)); + + var optionsBuilder = new DbContextOptionsBuilder(); + optionsBuilder.UseSqlServer(config.DbConnection); + + using (TeknikEntities db = new TeknikEntities(optionsBuilder.Options)) + { + if (options.SyncSubscriptions) + { + // Sync subscription information + } + } + + Output(string.Format("[{0}] Finished Billing Service Process.", DateTime.Now)); + } + else + { + string msg = string.Format("[{0}] Config File does not exist.", DateTime.Now); + File.AppendAllLines(errorFile, new List { msg }); + Output(msg); + } + }); + } + catch (Exception ex) + { + string msg = string.Format("[{0}] Exception: {1}", DateTime.Now, ex.GetFullMessage(true)); + File.AppendAllLines(errorFile, new List { msg }); + Output(msg); + } + return -1; + } + + public static void Output(string message) + { + Console.WriteLine(message); + if (OutputEvent != null) + { + OutputEvent(message); + } + } + } +} diff --git a/Configuration/BillingConfig.cs b/Configuration/BillingConfig.cs new file mode 100644 index 0000000..4e857b5 --- /dev/null +++ b/Configuration/BillingConfig.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Teknik.Configuration +{ + public class BillingConfig + { + public string StripePublishApiKey { get; set; } + public string StripeSecretApiKey { get; set; } + + public BillingConfig() + { + StripePublishApiKey = null; + StripeSecretApiKey = null; + } + } +} diff --git a/Configuration/Config.cs b/Configuration/Config.cs index 143f6f9..02a9ed6 100644 --- a/Configuration/Config.cs +++ b/Configuration/Config.cs @@ -52,6 +52,7 @@ namespace Teknik.Configuration private LoggingConfig _LoggingConfig; private PiwikConfig _PiwikConfig; private IRCConfig _IRCConfig; + private BillingConfig _BillingConfig; public bool DevEnvironment { get { return _DevEnvironment; } set { _DevEnvironment = value; } } public bool Migrate { get { return _Migrate; } set { _Migrate = value; } } @@ -120,9 +121,12 @@ namespace Teknik.Configuration // Piwik Configuration public PiwikConfig PiwikConfig { get { return _PiwikConfig; } set { _PiwikConfig = value; } } - // Piwik Configuration + // IRC Configuration public IRCConfig IRCConfig { get { return _IRCConfig; } set { _IRCConfig = value; } } + // Billing Configuration + public BillingConfig BillingConfig { get { return _BillingConfig; } set { _BillingConfig = value; } } + public Config() { _ConfigRWLock = new ReaderWriterLockSlim(); @@ -167,6 +171,7 @@ namespace Teknik.Configuration LoggingConfig = new LoggingConfig(); PiwikConfig = new PiwikConfig(); IRCConfig = new IRCConfig(); + BillingConfig = new BillingConfig(); } public static Config Deserialize(string text) diff --git a/ServiceWorker/Program.cs b/ServiceWorker/Program.cs index af8336c..5ee3145 100644 --- a/ServiceWorker/Program.cs +++ b/ServiceWorker/Program.cs @@ -1,7 +1,6 @@ using CommandLine; using Microsoft.EntityFrameworkCore; using nClam; -using StorageService; using System; using System.Collections.Generic; using System.IO; @@ -17,6 +16,7 @@ using Teknik.Areas.Users.Models; using Teknik.Areas.Users.Utility; using Teknik.Configuration; using Teknik.Data; +using Teknik.StorageService; using Teknik.Utilities; using Teknik.Utilities.Cryptography; diff --git a/StorageService/IStorageService.cs b/StorageService/IStorageService.cs index 4758697..9818696 100644 --- a/StorageService/IStorageService.cs +++ b/StorageService/IStorageService.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.IO; using Teknik.Configuration; -namespace StorageService +namespace Teknik.StorageService { public interface IStorageService { diff --git a/StorageService/LocalStorageService.cs b/StorageService/LocalStorageService.cs index d567ced..4a44887 100644 --- a/StorageService/LocalStorageService.cs +++ b/StorageService/LocalStorageService.cs @@ -8,7 +8,7 @@ using Teknik.Configuration; using Teknik.Utilities; using Teknik.Utilities.Cryptography; -namespace StorageService +namespace Teknik.StorageService { public class LocalStorageService : StorageService { diff --git a/StorageService/MemoryStorageService.cs b/StorageService/MemoryStorageService.cs index cb2939e..a7e7c42 100644 --- a/StorageService/MemoryStorageService.cs +++ b/StorageService/MemoryStorageService.cs @@ -8,7 +8,7 @@ using Teknik.Configuration; using Teknik.Utilities; using Teknik.Utilities.Cryptography; -namespace StorageService +namespace Teknik.StorageService { public class MemoryStorageService : StorageService { diff --git a/StorageService/StorageService.cs b/StorageService/StorageService.cs index 4d724cd..55e9c05 100644 --- a/StorageService/StorageService.cs +++ b/StorageService/StorageService.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.IO; using Teknik.Configuration; -namespace StorageService +namespace Teknik.StorageService { public abstract class StorageService : IStorageService { diff --git a/StorageService/StorageService.csproj b/StorageService/StorageService.csproj index 3261d92..dfd6cc2 100644 --- a/StorageService/StorageService.csproj +++ b/StorageService/StorageService.csproj @@ -1,7 +1,9 @@ - + net5.0 + Teknik.StorageService + Teknik.StorageService diff --git a/StorageService/StorageServiceFactory.cs b/StorageService/StorageServiceFactory.cs index df042e7..83c6c1d 100644 --- a/StorageService/StorageServiceFactory.cs +++ b/StorageService/StorageServiceFactory.cs @@ -5,7 +5,7 @@ using System.Text; using System.Threading.Tasks; using Teknik.Configuration; -namespace StorageService +namespace Teknik.StorageService { public static class StorageServiceFactory { diff --git a/Teknik.sln b/Teknik.sln index 61353a0..8be588c 100644 --- a/Teknik.sln +++ b/Teknik.sln @@ -34,7 +34,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ContentScanningService", "C EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebCommon", "WebCommon\WebCommon.csproj", "{32E85A7F-871A-437C-9BA3-00499AAB442C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StorageService", "StorageService\StorageService.csproj", "{4A600C17-C772-462F-A37F-307E7893B2DB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StorageService", "StorageService\StorageService.csproj", "{4A600C17-C772-462F-A37F-307E7893B2DB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BillingService", "BillingService\BillingService.csproj", "{AF417E48-8137-4677-9058-E4DD2745FEC5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BillingCore", "BillingCore\BillingCore.csproj", "{A9ED275B-4004-4A5B-8F1C-134A29B999E7}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -115,6 +119,18 @@ Global {4A600C17-C772-462F-A37F-307E7893B2DB}.Release|Any CPU.Build.0 = Release|Any CPU {4A600C17-C772-462F-A37F-307E7893B2DB}.Test|Any CPU.ActiveCfg = Debug|Any CPU {4A600C17-C772-462F-A37F-307E7893B2DB}.Test|Any CPU.Build.0 = Debug|Any CPU + {AF417E48-8137-4677-9058-E4DD2745FEC5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AF417E48-8137-4677-9058-E4DD2745FEC5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AF417E48-8137-4677-9058-E4DD2745FEC5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AF417E48-8137-4677-9058-E4DD2745FEC5}.Release|Any CPU.Build.0 = Release|Any CPU + {AF417E48-8137-4677-9058-E4DD2745FEC5}.Test|Any CPU.ActiveCfg = Debug|Any CPU + {AF417E48-8137-4677-9058-E4DD2745FEC5}.Test|Any CPU.Build.0 = Debug|Any CPU + {A9ED275B-4004-4A5B-8F1C-134A29B999E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A9ED275B-4004-4A5B-8F1C-134A29B999E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A9ED275B-4004-4A5B-8F1C-134A29B999E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A9ED275B-4004-4A5B-8F1C-134A29B999E7}.Release|Any CPU.Build.0 = Release|Any CPU + {A9ED275B-4004-4A5B-8F1C-134A29B999E7}.Test|Any CPU.ActiveCfg = Debug|Any CPU + {A9ED275B-4004-4A5B-8F1C-134A29B999E7}.Test|Any CPU.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Teknik/App_Data/endpointMappings.json b/Teknik/App_Data/endpointMappings.json index 9c2dc8f..d07bb2b 100644 --- a/Teknik/App_Data/endpointMappings.json +++ b/Teknik/App_Data/endpointMappings.json @@ -1045,6 +1045,50 @@ "action": "ViewRawPGP" } }, + { + "Name": "Billing.Index", + "HostTypes": [ "Full" ], + "SubDomains": [ "billing" ], + "Pattern": "", + "Area": "Billing", + "Defaults": { + "controller": "Billing", + "action": "Index" + } + }, + { + "Name": "Billing.Subscriptions", + "HostTypes": [ "Full" ], + "SubDomains": [ "billing" ], + "Pattern": "Subscriptions", + "Area": "Billing", + "Defaults": { + "controller": "Billing", + "action": "Subscriptions" + } + }, + { + "Name": "Billing.ViewPaymentInfo", + "HostTypes": [ "Full" ], + "SubDomains": [ "billing" ], + "Pattern": "PaymentInfo", + "Area": "Billing", + "Defaults": { + "controller": "Billing", + "action": "ViewPaymentInfo" + } + }, + { + "Name": "Billing.Action", + "HostTypes": [ "Full" ], + "SubDomains": [ "billing" ], + "Pattern": "Action/{action}", + "Area": "Billing", + "Defaults": { + "controller": "Billing", + "action": "Index" + } + }, { "Name": "Vault.Index", "HostTypes": [ "Full" ], diff --git a/Teknik/Areas/Billing/Controllers/BillingController.cs b/Teknik/Areas/Billing/Controllers/BillingController.cs new file mode 100644 index 0000000..4a96c21 --- /dev/null +++ b/Teknik/Areas/Billing/Controllers/BillingController.cs @@ -0,0 +1,39 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.Logging; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Teknik.Areas.Billing.ViewModels; +using Teknik.Configuration; +using Teknik.Controllers; +using Teknik.Data; +using Teknik.Logging; + +namespace Teknik.Areas.Billing.Controllers +{ + [Area("Billing")] + public class BillingController : DefaultController + { + public BillingController(ILogger logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { } + + [AllowAnonymous] + public IActionResult Index() + { + return View(new BillingViewModel() { StripePublishKey = _config.BillingConfig.StripePublishApiKey }); + } + + [AllowAnonymous] + public IActionResult Subscriptions() + { + return View(new BillingViewModel() { StripePublishKey = _config.BillingConfig.StripePublishApiKey }); + } + + [AllowAnonymous] + public IActionResult ViewPaymentInfo() + { + return View(new PaymentViewModel() { StripePublishKey = _config.BillingConfig.StripePublishApiKey }); + } + } +} diff --git a/Teknik/Areas/Billing/ViewModels/BillingViewModel.cs b/Teknik/Areas/Billing/ViewModels/BillingViewModel.cs new file mode 100644 index 0000000..002e179 --- /dev/null +++ b/Teknik/Areas/Billing/ViewModels/BillingViewModel.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Teknik.ViewModels; + +namespace Teknik.Areas.Billing.ViewModels +{ + public class BillingViewModel : ViewModelBase + { + public string StripePublishKey { get; set; } + } +} diff --git a/Teknik/Areas/Billing/ViewModels/PaymentViewModel.cs b/Teknik/Areas/Billing/ViewModels/PaymentViewModel.cs new file mode 100644 index 0000000..91c7f12 --- /dev/null +++ b/Teknik/Areas/Billing/ViewModels/PaymentViewModel.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Teknik.ViewModels; + +namespace Teknik.Areas.Billing.ViewModels +{ + public class PaymentViewModel : ViewModelBase + { + public string StripePublishKey { get; set; } + public string PaymentName { get; set; } + public string CreditCardNumber { get; set; } + public string ExpirationMonth { get; set; } + public string ExpirationYear { get; set; } + public string CCV { get; set; } + public string ZipCode { get; set; } + } +} diff --git a/Teknik/Areas/Billing/Views/Billing/PaymentDetails.cshtml b/Teknik/Areas/Billing/Views/Billing/PaymentDetails.cshtml new file mode 100644 index 0000000..9f54583 --- /dev/null +++ b/Teknik/Areas/Billing/Views/Billing/PaymentDetails.cshtml @@ -0,0 +1,54 @@ +@model Teknik.Areas.Billing.ViewModels.PaymentViewModel + + + +@{ +
+
+
+ @if (Model.Error) + { +
@Model.ErrorMessage
+ } +
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+

+ By registering for Teknik, you agree to the Terms of Service. +

+
+ +
+
+} + + + \ No newline at end of file diff --git a/Teknik/Areas/Billing/Views/Billing/Subscriptions.cshtml b/Teknik/Areas/Billing/Views/Billing/Subscriptions.cshtml new file mode 100644 index 0000000..28ae1ae --- /dev/null +++ b/Teknik/Areas/Billing/Views/Billing/Subscriptions.cshtml @@ -0,0 +1,89 @@ +@model Teknik.Areas.Billing.ViewModels.BillingViewModel + +@{ + string extraUsage = "If you need more than 100 GB of monthly upload bandwidth, please contact support for assistance."; +} + +
+

Upload Bandwidth Subscriptions

+
+
+
+
+
+

Basic Account

+
+
+

Free

+
+ No Overage Allowed +
+

+ 5 GB Uploads / month +

+

Sign up for free

+
+
+
+
+
+
+

Standalone 10 GB

+
+
+

$0.99 / month

+
+ Overage at $0.30 / GB (Up to 100 GB)* +
+

+ 10 GB Uploads / month +

+

Subscribe

+
+
+
+
+
+
+

Standalone 50 GB

+
+
+

$3.99 / month

+
+ Overage at $0.30 / GB (Up to 100 GB)* +
+

+ 50 GB Uploads / month +

+

Subscribe

+
+
+
+
+
+
+

By Upload Usage

+
+
+

$0.15 / GB

+
+ No Overage Fee +
+

+ Up to 100 GB* Uploads / month +

+

Subscribe

+
+
+
+
+
+
+

+ + * @extraUsage + +

+
+
+
\ No newline at end of file diff --git a/Teknik/Areas/Billing/Views/Billing/ViewPaymentInfo.cshtml b/Teknik/Areas/Billing/Views/Billing/ViewPaymentInfo.cshtml new file mode 100644 index 0000000..8e307cd --- /dev/null +++ b/Teknik/Areas/Billing/Views/Billing/ViewPaymentInfo.cshtml @@ -0,0 +1,14 @@ +@model Teknik.Areas.Billing.ViewModels.PaymentViewModel + +
+
+
+
+

Payment Information

+
+ @await Html.PartialAsync("../../Areas/Billing/Views/Billing/PaymentDetails", Model) +
+
+
+
+
\ No newline at end of file diff --git a/Teknik/Areas/Paste/Controllers/PasteController.cs b/Teknik/Areas/Paste/Controllers/PasteController.cs index 75c9e1c..28af97d 100644 --- a/Teknik/Areas/Paste/Controllers/PasteController.cs +++ b/Teknik/Areas/Paste/Controllers/PasteController.cs @@ -22,7 +22,7 @@ using System.IO; using System.Threading.Tasks; using Microsoft.AspNetCore.Diagnostics; using Teknik.Utilities.Routing; -using StorageService; +using Teknik.StorageService; namespace Teknik.Areas.Paste.Controllers { diff --git a/Teknik/Areas/Paste/PasteHelper.cs b/Teknik/Areas/Paste/PasteHelper.cs index dd551e5..64991c9 100644 --- a/Teknik/Areas/Paste/PasteHelper.cs +++ b/Teknik/Areas/Paste/PasteHelper.cs @@ -9,7 +9,7 @@ using Teknik.Models; using Teknik.Utilities.Cryptography; using Teknik.Data; using System.IO; -using StorageService; +using Teknik.StorageService; using Teknik.Logging; using Microsoft.Extensions.Logging; diff --git a/Teknik/Areas/Upload/Controllers/UploadController.cs b/Teknik/Areas/Upload/Controllers/UploadController.cs index 2ef0ee8..a80f7c9 100644 --- a/Teknik/Areas/Upload/Controllers/UploadController.cs +++ b/Teknik/Areas/Upload/Controllers/UploadController.cs @@ -24,7 +24,7 @@ using Teknik.Logging; using Teknik.Areas.Users.Models; using Teknik.ContentScanningService; using Teknik.Utilities.Routing; -using StorageService; +using Teknik.StorageService; namespace Teknik.Areas.Upload.Controllers { diff --git a/Teknik/Areas/Upload/UploadHelper.cs b/Teknik/Areas/Upload/UploadHelper.cs index 9ec0408..da99fda 100644 --- a/Teknik/Areas/Upload/UploadHelper.cs +++ b/Teknik/Areas/Upload/UploadHelper.cs @@ -9,7 +9,7 @@ using Teknik.Utilities; using System.Text; using Teknik.Utilities.Cryptography; using Teknik.Data; -using StorageService; +using Teknik.StorageService; using Teknik.Logging; using Microsoft.Extensions.Logging; diff --git a/Teknik/Areas/Vault/Controllers/VaultController.cs b/Teknik/Areas/Vault/Controllers/VaultController.cs index 1895882..8846642 100644 --- a/Teknik/Areas/Vault/Controllers/VaultController.cs +++ b/Teknik/Areas/Vault/Controllers/VaultController.cs @@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; -using StorageService; +using Teknik.StorageService; using System; using System.Collections.Generic; using System.IO; diff --git a/Teknik/Scripts/Billing/Billing.js b/Teknik/Scripts/Billing/Billing.js new file mode 100644 index 0000000..c187452 --- /dev/null +++ b/Teknik/Scripts/Billing/Billing.js @@ -0,0 +1,20 @@ +// Set your publishable key: remember to change this to your live publishable key in production +// See your keys here: https://dashboard.stripe.com/apikeys +let stripe = Stripe(stripePublishKey); +let elements = stripe.elements(); + +let card = elements.create('card'); +card.mount('#card-element'); + +card.on('change', function (event) { + displayError(event); +}); +function displayError(event) { + changeLoadingStatePrices(false); + let displayError = document.getElementById('card-element-errors'); + if (event.error) { + displayError.textContent = event.error.message; + } else { + displayError.textContent = ''; + } +} \ No newline at end of file diff --git a/Teknik/bundleconfig.json b/Teknik/bundleconfig.json index 11f55e7..b3bd304 100644 --- a/Teknik/bundleconfig.json +++ b/Teknik/bundleconfig.json @@ -291,6 +291,12 @@ "./wwwroot/lib/bootstrap/css/bootstrap-switch.css" ] }, + { + "outputFileName": "./wwwroot/js/billing.min.js", + "inputFiles": [ + "./wwwroot/js/app/Billing/Billing.js" + ] + }, { "outputFileName": "./wwwroot/js/vault.min.js", "inputFiles": [