完整构建高可用、高安全的电商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
}

