完整构建高可用、高安全的电商API系统,涵盖商品、订单、支付等核心模块
一、系统架构设计与技术选型
基于ThinkPHP 8.0构建现代化电商API系统,采用分层架构设计,确保系统的高可用性和可扩展性。
1.1 系统架构层次
层次 | 职责 | 核心技术 |
---|---|---|
表现层 | API接口、参数验证 | ThinkPHP控制器、验证器 |
业务层 | 业务逻辑处理 | Service服务层、事件系统 |
数据层 | 数据持久化 | 模型层、Repository模式 |
基础设施层 | 缓存、队列、文件存储 | Redis、消息队列、OSS |
1.2 项目目录结构
app/ ├── controller/ # 控制器层 ├── service/ # 业务服务层 ├── model/ # 数据模型层 ├── repository/ # 数据仓库层 ├── middleware/ # 中间件 ├── event/ # 事件定义 ├── listener/ # 事件监听器 ├── validate/ # 验证器 └── common.php # 公共函数 config/ ├── route.php # 路由配置 ├── middleware.php # 中间件配置 ├── database.php # 数据库配置 └── cache.php # 缓存配置
二、数据库设计与优化
2.1 核心数据表设计
-- 商品表 CREATE TABLE `product` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) NOT NULL COMMENT '商品名称', `description` text COMMENT '商品描述', `price` decimal(10,2) NOT NULL COMMENT '商品价格', `stock` int(11) NOT NULL DEFAULT '0' COMMENT '库存数量', `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态:1-上架 0-下架', `category_id` int(11) NOT NULL COMMENT '分类ID', `created_at` datetime DEFAULT CURRENT_TIMESTAMP, `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_category` (`category_id`), KEY `idx_status` (`status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 订单表 CREATE TABLE `order` ( `id` varchar(32) NOT NULL COMMENT '订单号', `user_id` int(11) NOT NULL COMMENT '用户ID', `total_amount` decimal(10,2) NOT NULL COMMENT '订单总金额', `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态:0-待支付 1-已支付 2-已发货 3-已完成 4-已取消', `payment_method` varchar(50) DEFAULT NULL COMMENT '支付方式', `shipping_address` text COMMENT '收货地址', `created_at` datetime DEFAULT CURRENT_TIMESTAMP, `updated_at` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_user` (`user_id`), KEY `idx_status` (`status`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 订单商品表 CREATE TABLE `order_item` ( `id` int(11) NOT NULL AUTO_INCREMENT, `order_id` varchar(32) NOT NULL COMMENT '订单ID', `product_id` int(11) NOT NULL COMMENT '商品ID', `product_name` varchar(255) NOT NULL COMMENT '商品名称', `product_price` decimal(10,2) NOT NULL COMMENT '商品单价', `quantity` int(11) NOT NULL COMMENT '购买数量', PRIMARY KEY (`id`), KEY `idx_order` (`order_id`), KEY `idx_product` (`product_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
2.2 模型关系定义
<?php namespace appmodel; use thinkModel; class Product extends Model { protected $table = 'product'; // 定义分类关联 public function category() { return $this->belongsTo(Category::class); } // 自动时间戳 protected $autoWriteTimestamp = true; // 价格访问器 public function getPriceAttribute($value) { return number_format($value, 2); } } class Order extends Model { protected $table = 'order'; protected $pk = 'id'; // 订单商品关联 public function items() { return $this->hasMany(OrderItem::class, 'order_id'); } // 用户关联 public function user() { return $this->belongsTo(User::class); } // 状态获取器 public function getStatusTextAttr() { $status = [ 0 => '待支付', 1 => '已支付', 2 => '已发货', 3 => '已完成', 4 => '已取消' ]; return $status[$this->status] ?? '未知'; } }
三、JWT认证授权系统
3.1 JWT工具类实现
<?php namespace appservice; use FirebaseJWTJWT; use FirebaseJWTKey; class JwtService { private static $key = 'your-secret-key'; private static $alg = 'HS256'; public static function generateToken($userId, $expire = 7200) { $payload = [ 'iss' => 'ecommerce-api', 'iat' => time(), 'exp' => time() + $expire, 'user_id' => $userId ]; return JWT::encode($payload, self::$key, self::$alg); } public static function verifyToken($token) { try { $decoded = JWT::decode($token, new Key(self::$key, self::$alg)); return (array)$decoded; } catch (Exception $e) { return false; } } public static function refreshToken($token) { $payload = self::verifyToken($token); if ($payload && isset($payload['user_id'])) { return self::generateToken($payload['user_id']); } return false; } }
3.2 认证中间件
<?php namespace appmiddleware; class AuthMiddleware { public function handle($request, Closure $next) { $token = $request->header('Authorization'); if (!$token) { return json(['code' => 401, 'message' => '缺少认证令牌'], 401); } // 提取Bearer token if (str_starts_with($token, 'Bearer ')) { $token = substr($token, 7); } $payload = appserviceJwtService::verifyToken($token); if (!$payload) { return json(['code' => 401, 'message' => '令牌无效或已过期'], 401); } // 将用户信息存入请求上下文 $request->user = appmodelUser::find($payload['user_id']); if (!$request->user) { return json(['code' => 401, 'message' => '用户不存在'], 401); } return $next($request); } }
3.3 用户登录接口
<?php namespace appcontroller; use appserviceAuthService; use appvalidateLoginValidate; class AuthController { public function login() { $data = request()->post(); // 参数验证 validate(LoginValidate::class)->check($data); $result = AuthService::login($data['username'], $data['password']); if (!$result) { return json([ 'code' => 400, 'message' => '用户名或密码错误' ]); } return json([ 'code' => 200, 'message' => '登录成功', 'data' => [ 'token' => $result['token'], 'user' => $result['user'] ] ]); } public function logout() { // 记录登出日志 event('UserLogout', [request()->user->id]); return json([ 'code' => 200, 'message' => '登出成功' ]); } }
四、商品模块完整实现
4.1 商品服务层
<?php namespace appservice; use appmodelProduct; use apprepositoryProductRepository; use thinkfacadeCache; class ProductService { protected $productRepo; public function __construct() { $this->productRepo = new ProductRepository(); } public function getProductList($page = 1, $limit = 20, $filters = []) { $cacheKey = "product_list:{$page}:{$limit}:" . md5(serialize($filters)); return Cache::remember($cacheKey, 300, function() use ($page, $limit, $filters) { return $this->productRepo->getPaginatedList($page, $limit, $filters); }); } public function getProductDetail($id) { $product = $this->productRepo->findWithRelations($id, ['category']); if (!$product) { throw new Exception('商品不存在'); } // 记录商品访问 event('ProductViewed', [$product->id]); return $product; } public function updateStock($productId, $quantity) { $product = Product::find($productId); if (!$product) { throw new Exception('商品不存在'); } if ($product->stock where('stock', '>=', $quantity) ->dec('stock', $quantity) ->update(); if (!$result) { throw new Exception('库存更新失败'); } // 清除缓存 Cache::delete("product_detail:{$productId}"); return true; } }
4.2 商品控制器
<?php namespace appcontroller; use appserviceProductService; use appvalidateProductValidate; class ProductController { protected $productService; public function __construct() { $this->productService = new ProductService(); } public function index() { $page = request()->param('page', 1); $limit = request()->param('limit', 20); $categoryId = request()->param('category_id'); $filters = []; if ($categoryId) { $filters['category_id'] = $categoryId; } $result = $this->productService->getProductList($page, $limit, $filters); return json([ 'code' => 200, 'data' => $result ]); } public function read($id) { try { $product = $this->productService->getProductDetail($id); return json([ 'code' => 200, 'data' => $product ]); } catch (Exception $e) { return json([ 'code' => 404, 'message' => $e->getMessage() ], 404); } } }
五、订单模块与事务处理
5.1 订单创建服务
<?php namespace appservice; use appmodelOrder; use appmodelOrderItem; use appmodelProduct; use thinkfacadeDb; use thinkfacadeEvent; class OrderService { public function createOrder($userId, $items, $address) { Db::startTrans(); try { // 验证商品库存 $productList = []; $totalAmount = 0; foreach ($items as $item) { $product = Product::where('id', $item['product_id']) ->where('status', 1) ->lock(true) ->find(); if (!$product) { throw new Exception("商品 {$item['product_id']} 不存在或已下架"); } if ($product->stock name} 库存不足"); } $productList[] = $product; $totalAmount += $product->price * $item['quantity']; } // 生成订单号 $orderNo = date('YmdHis') . str_pad(mt_rand(1, 9999), 4, '0', STR_PAD_LEFT); // 创建订单 $order = new Order(); $order->save([ 'id' => $orderNo, 'user_id' => $userId, 'total_amount' => $totalAmount, 'shipping_address' => json_encode($address), 'status' => 0 ]); // 创建订单商品 foreach ($items as $index => $item) { $product = $productList[$index]; OrderItem::create([ 'order_id' => $orderNo, 'product_id' => $product->id, 'product_name' => $product->name, 'product_price' => $product->price, 'quantity' => $item['quantity'] ]); // 扣减库存 $product->stock -= $item['quantity']; $product->save(); } Db::commit(); // 触发订单创建事件 Event::trigger('OrderCreated', $order); return $order; } catch (Exception $e) { Db::rollback(); throw $e; } } public function cancelOrder($orderId, $userId) { Db::startTrans(); try { $order = Order::where('id', $orderId) ->where('user_id', $userId) ->lock(true) ->find(); if (!$order) { throw new Exception('订单不存在'); } if ($order->status != 0) { throw new Exception('当前状态无法取消订单'); } // 恢复库存 $items = $order->items; foreach ($items as $item) { Product::where('id', $item->product_id) ->inc('stock', $item->quantity) ->update(); } // 更新订单状态 $order->status = 4; $order->save(); Db::commit(); Event::trigger('OrderCancelled', $order); return true; } catch (Exception $e) { Db::rollback(); throw $e; } } }
六、支付系统集成
6.1 支付服务抽象层
<?php namespace appservicepayment; interface PaymentInterface { public function pay($order, $config); public function verify($data); public function refund($order, $amount); } class AlipayService implements PaymentInterface { public function pay($order, $config) { // 支付宝支付逻辑 $params = [ 'out_trade_no' => $order->id, 'total_amount' => $order->total_amount, 'subject' => '商品订单支付', 'body' => '订单描述' ]; // 调用支付宝SDK return $this->buildPaymentForm($params); } public function verify($data) { // 验证支付宝回调签名 return $this->verifySignature($data); } public function refund($order, $amount) { // 退款逻辑 $params = [ 'out_trade_no' => $order->id, 'refund_amount' => $amount ]; return $this->requestRefund($params); } } class WechatPayService implements PaymentInterface { public function pay($order, $config) { // 微信支付逻辑 $params = [ 'out_trade_no' => $order->id, 'total_fee' => intval($order->total_amount * 100), 'body' => '商品订单支付' ]; return $this->unifiedOrder($params); } // 其他方法实现... }
6.2 支付控制器
<?php namespace appcontroller; use appservicePaymentService; class PaymentController { public function pay($orderId) { $order = appmodelOrder::where('id', $orderId) ->where('user_id', request()->user->id) ->find(); if (!$order) { return json(['code' => 404, 'message' => '订单不存在']); } if ($order->status != 0) { return json(['code' => 400, 'message' => '订单状态异常']); } $paymentType = request()->param('type', 'alipay'); $result = PaymentService::createPayment($order, $paymentType); return json([ 'code' => 200, 'data' => $result ]); } public function notify($type) { $data = request()->post(); $result = PaymentService::handleNotify($type, $data); if ($result) { return 'success'; } else { return 'fail'; } } }
七、API文档与测试
7.1 路由配置
<?php use thinkfacadeRoute; // 认证路由 Route::post('auth/login', 'auth/login'); Route::post('auth/logout', 'auth/logout')->middleware(appmiddlewareAuthMiddleware::class); // 商品路由 Route::get('products', 'product/index'); Route::get('products/:id', 'product/read'); // 订单路由 Route::post('orders', 'order/create')->middleware(appmiddlewareAuthMiddleware::class); Route::get('orders/:id', 'order/read')->middleware(appmiddlewareAuthMiddleware::class); Route::put('orders/:id/cancel', 'order/cancel')->middleware(appmiddlewareAuthMiddleware::class); // 支付路由 Route::post('orders/:id/pay', 'payment/pay')->middleware(appmiddlewareAuthMiddleware::class); Route::post('payment/notify/:type', 'payment/notify');
7.2 接口响应规范
{ "code": 200, // 状态码 "message": "success", // 消息 "data": { // 数据 "id": 1, "name": "商品名称" }, "timestamp": 1634567890 }