📅 Day 5:訂單提交與支付模擬
? 今日目標:
- 創建
Order
和OrderItem
模型 - 實現從購物車生成訂單的功能
- 模擬支付流程(成功/失敗頁面)
- 添加訂單狀態跟蹤(如“待付款”、“已發貨”等)
- 提交 Git 版本記錄進度
🧩 功能概覽
頁面 | 功能 |
---|---|
/Checkout/Index.cshtml | 確認訂單信息 |
/Checkout/Success.cshtml | 支付成功頁面 |
/Checkout/Failed.cshtml | 支付失敗頁面 |
/Orders/Index.cshtml | 我的訂單列表 |
數據庫模型 | Order , OrderItem |
🛠? 知識點預覽
技術 | 內容 |
---|---|
數據模型 | Order 表示訂單,OrderItem 表示訂單中的商品 |
購物車轉訂單 | 將 Session 中的購物車數據保存為訂單 |
支付模擬 | 使用按鈕或自動跳轉模擬支付結果 |
用戶身份驗證 | 只有登錄用戶才能下單 |
UI 設計 | Bootstrap + Razor Pages 構建訂單確認頁 |
🧱 第一步:創建訂單相關模型
在 Models
文件夾中創建以下兩個類:
? Order.cs
using System.ComponentModel.DataAnnotations;namespace ECommercePlatform.Models
{public enum OrderStatus{Pending,Paid,Shipped,Completed,Cancelled}public class Order{public int Id { get; set; }[Required]public string UserId { get; set; } = string.Empty;public DateTime OrderDate { get; set; } = DateTime.Now;public decimal TotalAmount { get; set; }public OrderStatus Status { get; set; } = OrderStatus.Pending;public List<OrderItem> Items { get; set; } = new();}
}
? OrderItem.cs
namespace ECommercePlatform.Models
{public class OrderItem{public int Id { get; set; }public int ProductId { get; set; }public string ProductName { get; set; } = string.Empty;public decimal Price { get; set; }public int Quantity { get; set; }public decimal TotalPrice => Price * Quantity;public int OrderId { get; set; }public Order Order { get; set; } = null!;}
}
🧰 第二步:更新數據庫上下文
打開 ApplicationDbContext.cs
并添加以下代碼:
public DbSet<Order> Orders { get; set; }
public DbSet<OrderItem> OrderItems { get; set; }
然后執行遷移命令:
dotnet ef migrations add AddOrderAndOrderItem
dotnet ef database update
🛒 第三步:創建訂單服務邏輯
? 創建 Services/IOrderService.cs
using ECommercePlatform.Models;public interface IOrderService
{Task<int> CreateOrderFromCart(string userId, IList<CartItem> cartItems);Task<IList<Order>> GetOrdersByUser(string userId);Task<Order?> GetOrderById(int id, string userId);
}
? 創建 Services/OrderService.cs
using Microsoft.AspNetCore.Identity;
using ECommercePlatform.Models;
using ECommercePlatform.Services;public class OrderService : IOrderService
{private readonly ApplicationDbContext _context;private readonly UserManager<IdentityUser> _userManager;public OrderService(ApplicationDbContext context, UserManager<IdentityUser> userManager){_context = context;_userManager = userManager;}public async Task<int> CreateOrderFromCart(string userId, IList<CartItem> cartItems){if (cartItems.Count == 0) throw new ArgumentException("購物車為空");var order = new Order{UserId = userId,OrderDate = DateTime.Now,TotalAmount = cartItems.Sum(i => i.TotalPrice),Items = cartItems.Select(i => new OrderItem{ProductId = i.ProductId,ProductName = i.Name,Price = i.Price,Quantity = i.Quantity}).ToList()};_context.Orders.Add(order);await _context.SaveChangesAsync();return order.Id;}public async Task<IList<Order>> GetOrdersByUser(string userId){return await _context.Orders.Include(o => o.Items).Where(o => o.UserId == userId).OrderByDescending(o => o.OrderDate).ToListAsync();}public async Task<Order?> GetOrderById(int id, string userId){return await _context.Orders.Include(o => o.Items).FirstOrDefaultAsync(o => o.Id == id && o.UserId == userId);}
}
注冊服務到 Program.cs
:
builder.Services.AddScoped<IOrderService, OrderService>();
📋 第四步:創建訂單確認頁面(Checkout/Index)
? Checkout/Index.cshtml.cs
using Microsoft.AspNetCore.Mvc.RazorPages;
using ECommercePlatform.Services;
using ECommercePlatform.Models;namespace ECommercePlatform.Pages.Checkout
{[Authorize]public class IndexModel : PageModel{private readonly IShoppingCartService _cartService;private readonly UserManager<IdentityUser> _userManager;public IndexModel(IShoppingCartService cartService, UserManager<IdentityUser> userManager){_cartService = cartService;_userManager = userManager;}public IList<CartItem> CartItems { get; set; } = new List<CartItem>();public decimal TotalPrice { get; set; }public async Task<IActionResult> OnGetAsync(){CartItems = _cartService.GetCartItems();TotalPrice = _cartService.GetTotalPrice();if (CartItems.Count == 0){return RedirectToPage("/Cart/Index");}return Page();}public async Task<IActionResult> OnPostAsync(){var user = await _userManager.GetUserAsync(User);if (user == null) return NotFound();var cartItems = _cartService.GetCartItems();if (cartItems.Count == 0) return BadRequest();// 創建訂單var orderService = HttpContext.RequestServices.GetService<IOrderService>();var orderId = await orderService.CreateOrderFromCart(user.Id, cartItems);// 清空購物車_cartService.ClearCart();return RedirectToPage("/Checkout/Success", new { id = orderId });}}
}
? Checkout/Index.cshtml
@page
@model ECommercePlatform.Pages.Checkout.IndexModel<h2>確認訂單</h2><table class="table"><thead><tr><th>名稱</th><th>單價</th><th>數量</th><th>總價</th></tr></thead><tbody>@foreach (var item in Model.CartItems){<tr><td>@item.Name</td><td>$@item.Price</td><td>@item.Quantity</td><td>$@item.TotalPrice</td></tr>}</tbody>
</table><h4>總計:$@Model.TotalPrice</h4><form method="post"><button type="submit" class="btn btn-success">立即支付</button>
</form>
? 第五步:創建支付成功頁面(Checkout/Success)
? Success.cshtml.cs
using Microsoft.AspNetCore.Mvc.RazorPages;namespace ECommercePlatform.Pages.Checkout
{public class SuccessModel : PageModel{public void OnGet(int id){// 這里可以顯示訂單編號或詳細信息}}
}
? Success.cshtml
@page
@model ECommercePlatform.Pages.Checkout.SuccessModel<h2>? 支付成功!</h2>
<p>您的訂單已提交。訂單號:@Request.Query["id"]</p>
<a asp-page="/Orders/Index" class="btn btn-primary">查看我的訂單</a>
? 第六步:創建支付失敗頁面(Checkout/Failed)
? Failed.cshtml.cs
using Microsoft.AspNetCore.Mvc.RazorPages;namespace ECommercePlatform.Pages.Checkout
{public class FailedModel : PageModel{public void OnGet(){}}
}
? Failed.cshtml
@page
@model ECommercePlatform.Pages.Checkout.FailedModel<h2>? 支付失敗</h2>
<p>請返回重新嘗試支付。</p>
<a asp-page="/Cart/Index" class="btn btn-warning">返回購物車</a>
📦 第七步:創建我的訂單頁面(Orders/Index)
? Orders/Index.cshtml.cs
using Microsoft.AspNetCore.Mvc.RazorPages;
using ECommercePlatform.Services;
using ECommercePlatform.Models;
using Microsoft.AspNetCore.Identity;namespace ECommercePlatform.Pages.Orders
{[Authorize]public class IndexModel : PageModel{private readonly IOrderService _orderService;private readonly UserManager<IdentityUser> _userManager;public IndexModel(IOrderService orderService, UserManager<IdentityUser> userManager){_orderService = orderService;_userManager = userManager;}public IList<Order> Orders { get; set; } = new List<Order>();public async Task OnGetAsync(){var user = await _userManager.GetUserAsync(User);if (user != null){Orders = await _orderService.GetOrdersByUser(user.Id);}}}
}
? Orders/Index.cshtml
@page
@model ECommercePlatform.Pages.Orders.IndexModel<h2>我的訂單</h2>@if (Model.Orders.Count == 0)
{<p>暫無訂單。</p>
}
else
{<table class="table"><thead><tr><th>訂單號</th><th>日期</th><th>總金額</th><th>狀態</th><th>操作</th></tr></thead><tbody>@foreach (var order in Model.Orders){<tr><td>@order.Id</td><td>@order.OrderDate.ToShortDateString()</td><td>$@order.TotalAmount</td><td>@order.Status</td><td><a asp-page="/Orders/Details" asp-route-id="@order.Id" class="btn btn-info btn-sm">查看詳情</a></td></tr>}</tbody></table>
}
📦 第八步:提交 Git 版本
git add .
git commit -m "Day5: Added order submission and payment simulation with order status tracking"
📝 今日總結
今天你完成了:
? 創建 Order
和 OrderItem
模型
? 實現從購物車生成訂單的功能
? 模擬支付流程(成功/失敗頁面)
? 訂單狀態跟蹤(Pending、Paid、Shipped 等)
? 提交版本控制記錄
📆 明日計劃(Day6)
我們將進入 后臺管理系統開發階段:
- 創建管理員頁面
- 實現商品管理(CRUD)
- 實現訂單管理(查看、狀態變更)
- 權限控制(僅管理員可見)