单商户H5商城搭建:UNIAPP+小程序源码开源

134 阅读5分钟

1754405297366323.png

一、架构设计概览

核心思想:  前后端分离 (Decoupled Architecture)

  • uni-app 作为前端框架,负责渲染所有用户界面(H5、小程序、App),并通过 HTTP API 与后端交互。
  • ThinkPHP 作为后端框架,提供 RESTful API,处理业务逻辑、数据存储、安全性、并发等。
  • 两者通过 JSON 格式的数据进行通信。

架构图:

text

      [H5 | 微信小程序 | App | 其他平台]  (基于 uni-app)
                 | (HTTP/HTTPS + JSON)
                 |
          [API 网关 (可选) | Nginx]  (反向代理、负载均衡)
                 |
           [ThinkPHP API 服务器]  (核心业务逻辑)
                 |
[MySQL (主数据)]  [Redis (缓存/会话/队列)]  [Elasticsearch (搜索)]  [OSS/COS (文件存储)]

二、技术栈选型与职责

层级技术职责
前端 (uni-app)Vue.js 语法、Vuex(状态管理)、uni-ui 或 uView UI(组件库)渲染页面、用户交互、调用API、管理本地状态(如购物车)
后端 (ThinkPHP)ThinkPHP 6.x+(API开发模式)、JWT(令牌认证)、Redis、Elasticsearch提供RESTful API、用户认证、订单处理、支付回调、数据管理
数据与存储MySQL(主数据库)、Redis(缓存、秒杀)、阿里云OSS/腾讯云COS(文件存储)数据持久化、高性能访问、静态资源存储
部署与运维Nginx(Web服务器)、Linux、Docker(容器化,可选)服务部署、负载均衡、反向代理

三、核心功能模块设计与实现

1. 前后端数据交互规范

首先,必须定义一套统一的 API 响应格式,这是前后端协同开发的基础。
ThinkPHP 控制器示例:

php

<?php
namespace app\api\controller;

use think\Response;

class BaseController
{
    // 成功返回
    protected function success($data = null, $msg = 'success', $code = 200)
    {
        return Response::create([
            'code' => $code,
            'msg'  => $msg,
            'data' => $data
        ], 'json');
    }

    // 失败返回
    protected function error($msg = 'error', $code = 400, $data = null)
    {
        return Response::create([
            'code' => $code,
            'msg'  => $msg,
            'data' => $data
        ], 'json');
    }
}

uni-app 请求封装示例 (使用 uni.request):

javascript

// utils/request.js
import { baseUrl } from '@/config/config.js';

const request = (options) => {
    return new Promise((resolve, reject) => {
        uni.request({
            url: baseUrl + options.url,
            method: options.method || 'GET',
            data: options.data || {},
            header: {
                'Content-Type': 'application/json',
                'Authorization': uni.getStorageSync('token') // 从本地存储获取JWT Token
                ...options.header
            },
            success: (res) => {
                if (res.data.code === 200) {
                    resolve(res.data);
                } else {
                    // token过期等统一处理
                    if (res.data.code === 401) {
                        uni.navigateTo({ url: '/pages/login/login' })
                    }
                    uni.showToast({ title: res.data.msg, icon: 'none' });
                    reject(res.data);
                }
            },
            fail: (error) => {
                reject(error);
            }
        });
    });
};

export default request;

2. 用户认证与授权 (JWT)

  • 流程:  用户登录 -> ThinkPHP 验证账号密码 -> 生成 JWT Token -> 返回给 uni-app -> uni-app 存储 Token 并在后续请求头中携带。

  • ThinkPHP 生成 JWT:

    php

    use Firebase\JWT\JWT; // 使用composer安装firebase/php-jwt
    
    public function login()
    {
        $username = input('username');
        $password = input('password');
        // 1. 验证用户 (伪代码)
        $user = UserModel::where('username', $username)->find();
        if (!$user || !password_verify($password, $user->password)) {
            return $this->error('用户名或密码错误');
        }
        // 2. 生成JWT Payload
        $payload = [
            'iss' => 'your-issuer', // 签发者
            'iat' => time(),        // 签发时间
            'exp' => time() + 7200, // 过期时间(2小时)
            'uid' => $user->id,     // 自定义信息:用户ID
        ];
        // 3. 使用密钥生成Token
        $token = JWT::encode($payload, config('jwt.key'), 'HS256');
        // 4. 返回给客户端
        return $this->success(['token' => $token, 'user_info' => $user]);
    }
    
  • ThinkPHP 中间件验证 JWT:

    php

    <?php
    namespace app\api\middleware;
    
    use Firebase\JWT\JWT;
    use think\Response;
    
    class AuthMiddleware
    {
        public function handle($request, \Closure $next)
        {
            $token = $request->header('Authorization');
            if (!$token) {
                return Response::create(['code' => 401, 'msg' => 'Token不存在'], 'json');
            }
            try {
                $decoded = JWT::decode($token, config('jwt.key'), ['HS256']);
                // 将解码出的用户信息存入请求,方便后续控制器使用
                $request->uid = $decoded->uid;
            } catch (\Exception $e) {
                return Response::create(['code' => 401, 'msg' => 'Token无效或已过期'], 'json');
            }
            return $next($request);
        }
    }
    

3. 商品模块

  • uni-app 端:  使用 swiper 组件做轮播图,scroll-view 做分类筛选,v-for 渲染商品列表。上拉加载更多通过 onReachBottom 生命周期实现。

  • ThinkPHP 端:  商品列表接口需要支持分页分类筛选排序关键词搜索

    php

    public function productList()
    {
        $page = input('page', 1);
        $size = input('size', 10);
        $categoryId = input('category_id');
        $keyword = input('keyword');
        $order = input('order', 'sales_desc'); // 默认按销量降序
    
        // 构建查询条件
        $model = ProductModel::where('status', 1); // 上架商品
        if ($categoryId) {
            $model->where('category_id', $categoryId);
        }
        if ($keyword) {
            $model->whereLike('name', "%{$keyword}%");
        }
        // 排序逻辑
        switch ($order) {
            case 'price_asc':
                $model->order('price asc');
                break;
            case 'price_desc':
                $model->order('price desc');
                break;
            default:
                $model->order('sales desc');
        }
        // 分页查询
        $list = $model->paginate(['page' => $page, 'list_rows' => $size]);
        return $this->success($list);
    }
    

4. 购物车模块

  • uni-app 端:  购物车数据可以同时存储在 Vuex (内存,保证多页面同步) 和 本地存储 (uni.setStorage, 防止刷新丢失) 中。
  • ThinkPHP 端:  提供添加、删除、修改数量、获取列表的接口。核心表:cart (id, user_id, product_id, num, selected)。

5. 订单与支付模块 (核心)

  • 下单流程:

    1. uni-app 提交商品和收货信息。
    2. ThinkPHP 创建订单(生成唯一订单号、校验库存、计算总价)、预扣库存(防止超卖)。
    3. 调用微信/支付宝统一支付接口,获取支付参数(如微信的 timeStampnonceStrpackagesignTypepaySign)。
    4. 返回支付参数给 uni-app。
    5. uni-app 调用 uni.requestPayment() 发起客户端支付。
  • 支付回调:

    1. 支付成功后,微信/支付宝服务器会异步通知 ThinkPHP 提供的回调接口
    2. 此接口需验证签名、更新订单状态为已支付、真实扣减库存、记录流水等。
    3. 重要:  回调接口内逻辑必须做幂等性处理(防止重复通知导致重复更新)。

四、全渠道适配要点

  1. 条件编译:  uni-app 的最大优势。

    javascript

    // #ifdef H5
    console.log('这是在H5平台上');
    // #endif
    // #ifdef MP-WEIXIN
    console.log('这是在微信小程序平台上');
    // #endif
    // #ifdef APP
    console.log('这是在App平台上');
    // #endif
    
  2. 支付对接:

    • H5:  通常使用微信H5支付或支付宝网页支付。
    • 微信小程序:  必须使用小程序支付,调用 uni.requestPayment(OBJECT) 传入微信返回的参数。
    • App:  使用App支付,同样使用 uni.requestPayment,但需要配置各自的支付SDK。
  3. 登录授权:

    • 微信小程序:  使用 uni.login() 获取 code,传给后端,后端用 code 换 openid 和 session_key 完成 unionid 体系下的登录。
    • H5/App:  使用传统的账号密码登录或手机号验证码登录。

五、性能与优化建议

  1. API 优化:  ThinkPHP 接口使用 Redis 缓存热点数据(如商品详情、首页数据)。

  2. 图片优化:  图片资源务必存放在 OSS/COS 上,并开启 CDN 加速。

  3. 数据库优化:  为高频查询字段建立索引(如 product 表的 category_idstatus)。

  4. uni-app 优化:

    • 使用图片懒加载
    • 长列表使用虚拟列表(可通过 uv-ui 等组件库实现)。
    • 减少不必要的 setData 操作。

总结

打造这样一个平台,本质上是将 ThinkPHP 的强大后端能力 与 uni-app 的跨端能力 完美结合。

  • ThinkPHP 侧重点:  稳健的API设计、安全的业务逻辑、高效的数据库操作、第三方服务集成(支付、短信、OSS)。
  • uni-app 侧重点:  优雅的页面实现、流畅的用户体验、跨端的平台适配、本地状态管理。

建议从一个小模块开始(如用户登录->商品列表->商品详情),逐步迭代开发,并持续进行跨端测试,最终构建出功能完备的全渠道电商平台。