1using Dreamine.Identity;
2using Dreamine.Identity.Options;
3using Microsoft.EntityFrameworkCore;
10var
builder = WebApplication.CreateBuilder(args);
11builder.Configuration.AddUserSecrets(
"codemaru-oauth-2ba4e1b2");
19 builder.Configuration.GetSection(AuthOptions.SectionName).Get<AuthOptions>() ??
new AuthOptions();
21 builder.Configuration[$
"{AuthOptions.SectionName}:UsersDbPath"],
22 Path.Combine(AppContext.BaseDirectory,
"App_Data",
"codemaru.db"));
47 .AddInteractiveServerComponents();
50builder.Services.AddResponseCompression(o => o.EnableForHttps =
true);
55if (!
app.Environment.IsDevelopment())
57 app.UseExceptionHandler(
"/Error");
62app.UseForwardedHeaders();
63app.UseResponseCompression();
67app.UseStaticFiles(
new StaticFileOptions
69 FileProvider =
new Microsoft.Extensions.FileProviders.PhysicalFileProvider(
shopOpts.ResolvedDataPath),
70 RequestPath =
"/shop-img"
76app.UseAuthentication();
77app.UseAuthorization();
85app.MapGet(
"/healthz", () => Results.Text(
"OK",
"text/plain"));
88app.MapGet(
"/pay/{slug}/return", async (
90 string paymentKey,
string orderId,
int amount,
93 IHttpClientFactory httpFactory,
96 var config = await store.
GetAsync(slug);
97 if (config ==
null)
return Results.NotFound();
104 var result = await gateway.
ConfirmAsync(paymentKey, orderId, amount);
105 if (!result.Succeeded)
106 return Results.Redirect($
"/{slug}/checkout?error={Uri.EscapeDataString(result.Error ?? "결제 실패
")}");
109 using var db = dbFactory.
Create(slug);
110 var order = db.Orders
111 .Include(o => o.Lines)
112 .FirstOrDefault(o => o.OrderNo == orderId);
115 order.Status =
"paid";
116 order.TransactionId = result.TransactionId;
118 await db.SaveChangesAsync();
121 return Results.Redirect($
"/{slug}/order/{orderId}?paid=1");
124app.MapGet(
"/pay/{slug}/fail", (
string slug,
string? code,
string? message) =>
125 Results.Redirect($
"/{slug}/checkout?error={Uri.EscapeDataString(message ?? "결제가 취소되었습니다.
")}"));
129 .AddInteractiveServerRenderMode();
132var
wwwroot = Path.Combine(
app.Environment.ContentRootPath,
"wwwroot");
144#pragma warning disable CS1587
173 foreach (var line
in lines)
175 var product = db.Products.Find(line.ProductId);
176 if (product ==
null || product.IsUnlimitedStock)
continue;
177 product.Stock = Math.Max(0, product.Stock - line.Quantity);
180#pragma warning restore CS1587
183#pragma warning disable CS1587
220 if (
string.IsNullOrWhiteSpace(configuredPath))
225 return Path.IsPathRooted(configuredPath)
227 : Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, configuredPath));
229#pragma warning restore CS1587
static void DeductStock(TenantDbContext db, IEnumerable< OrderLine > lines)
static string ResolvePath(string? configuredPath, string fallback)
static async Task SeedCodemaruAsync(TenantDbContextFactory dbFactory, IShopTenantStore tenantStore, PaymentKeyProtector keyProtector)
TenantDbContext Create(string slug)
static ShopOptions From(IConfiguration cfg)
Task< PaymentConfirmResult > ConfirmAsync(string paymentKey, string orderId, int amount)
Task< ShopConfig?> GetAsync(string slug)
static void EnsureDefault(string wwwrootPath)