/monday-shop

网上在线商城、综合网上购物平台

Primary LanguagePHP

seth-shi/monday-shop

QQ 群

  • 584453488

部署(新新新)

  1. 下载源码(也可直接下载压缩包, 然后解压)
    • git clone https://github.com/seth-shi/monday-shop.git
  2. 修改配置
    • cp .env.example .env
    • 修改.env文件中数据库,域名等配置信息
  3. 构建镜像
    • docker build . -t monday-shop
  4. 运行
    • -p 80:5200, 80代表本机的端口,5200写死是swoole服务运行的端口
    • docker run -d -p 80:5200 --name monday-shop-service monday-shop
  5. 执行命令迁移
    • docker exec monday-shop-service php artisan migrate

目录说明

演示地址

演示地址:http://shop.shiguopeng.cn

后台地址:http://shop.shiguopeng.cn/admin

  • 账号:admin
  • 密码:admin

  • 测试支付功能
    • 下载支付宝沙箱
    • 账号:eyxweq5099@sandbox.com
    • 密码:111111
    • 支付密码:111111
    • 当前账户余额:9999999.99
    • 余额不足,请联系我及时充值

页面展示

PC首页 支付 个人设置 个人中心 积分详情 后台仪表盘 后台订单列表 用户喜好数据

Feature

  • 库存问题
    • 普通订单使用乐观锁防止超卖
    • 秒杀订单使用Redis队列防止超卖
  • 首页数据全走缓存(推荐使用Redis驱动)
    • 未登录的首页,零数据库查询,通过缓存驱动
    • 计划任务每分钟会更新一次首页数据
    • 开启秒杀模块,零数据库查询,通过Redis驱动
    • 登录之后首页零数据库查询,Session驱动数据
  • 积分功能
    • 每日首次登录(访问网站)得到积分(bitmap 计算)
    • 连续登录 n 天得到积分(bitmap 计算)
    • 当天浏览商品数量 n 个得到积分(bitmap 计算)
    • 后台可新增 n+ 积分种类
    • 完成订单可获得金钱等比例积分
  • 优惠券功能
    • 满减优惠
    • 积分兑换满减优惠券
    • 发放兑换码,兑换优惠券
  • 物流功能
    • 运费设置
    • 快递物流
  • 秒杀功能
    • 秒杀过期,自动回退库存
    • 使用延时队列,当订单超过三十分钟(可配置)未付款,自动取消订单
    • 秒杀商品,如果用户收藏,发送邮件提醒活动
    • 后台秒杀模块的开启关闭
    • 秒杀的商品数量,皆通过Redis读取
  • 第三方授权登录 + 登录回跳
    • Github
    • QQ
    • 微博
  • 第三方支付(支持自动适应手机,web 支付)
    • 支付宝支付,退款
    • 微信支付
  • 购物车
    • 使用H5本地存储
    • 登录之后同时显示本地购物车和数据库购物车数量
    • 用户登录之后会询问是否需要持久化到数据库
  • 商品搜索
    • 使用ElasticSearch全文索引
    • 支持拼音首字母
    • AJAX无刷新显示
  • 订阅模块
    • 每周定时推送一封邮件包含最受欢迎,最新,最火卖商品
  • 分类排序
    • 后台使用拖动排序,可以设置在商城首页优先展示的分类
  • 订单模块
    • 订单下单
      • 买家支付
      • 后台发货 / 卖家申请退款
      • 买确认收货 / 后台确认收货
      • 买家确认订单获取积分
    • 用户下订单之后可以评论
  • 站内消息
    • 消息通知
    • 多模板类型通知, 兑换码通知、文章通知等等
    • 轮询通知消息,一点即达
  • 数据统计
    • 每天晚上一点进行站点数据统计
  • 全文搜索
  • 响应式网站

Commands

命令 一句话描述
php artisan moon:install 安装应用程序
php artisan add:shop-to-search 生成全文索引
php artisan moon:uninstall 卸载网站(清空数据库,缓存,路由)
php artisan moon:cache 执行缓存(缓存配置,路由,类映射)
php artisan moon:clear 清除缓存
php artisan moon:copy 复制项目内置的静态资源
php artisan moon:delete 删除项目及上传的基本静态资源
php artisan moon:export 导出用户数据到json文件
php artisan moon:count-site 统计站点任务(每天夜里一点执行)
php artisan moon:del-seckills 删除秒杀数据 (每小时自动执行一次)
php artisan moon:moon:del-score-data 删除积分缓存数据 (每天夜里 0 点执行)
php artisan moon:update-home 更新首页数据 (每分钟自动执行一次)
php artisan moon:send-subscribes 发送订阅邮件 (每个礼拜六早上八点)
php artisan queue:work --tries=3 监听队列(邮件发送,处理过期的秒杀数据 !!!

秒杀处理逻辑

## 初始化抢购数据
<?php

// 假设当前秒杀活动的 id 为 9
// 可以在模型的 created 事件做这个事情
$id = 9;

// 填充一个 redis 队列,数量为抢购的数量,后面的 9 无意义
\Redis::lpush("seckills:{$id}:queue", array_fill(0, $seckill->number, 9));

?>

## 抢购
<?php

// 从路由或者参数中得到当前秒杀活动的 id
$id = 9;
$userId = auth()->id();

// 判断是否已经开始了秒杀

// 返回 0,代表当前用户已经抢购过了
if (0 == Redis::hset("seckills:{$id}:users:{$userId}", 'id', $userId)) {

    return responseJson(403, '你已经抢购过了');
}

// 如果从队列中读取到了 null,代表已经没有库存
if (is_null(Redis::lpop("seckills:{$id}:queue"))) {

    return responseJson(403, '已经抢购完了');
}

// 这里就可以开始入库订单

?>

## 利用 crontab 定时扫描过期数据,回滚库存,删除过期 redis (可选)
<?php

 // 查出已经过期确没有回滚过的秒杀,
Seckill::query()
       ->where('end_at', '<', date('Y-m-d H:i:s'))
       ->get()
       ->map(function (Seckill $seckill) {
           
           // 先模糊查找到所有用户 key
           $ids = Redis::keys("seckills:{$seckill->id}:*");
           Redis::del($ids);
           
           // 回滚库存
           // 做更多的事
       };
       
?>

API

  • 接口响应数据说明
    • 响应的数据格式总是保证拥有基本元素(code, msg, data)
    • code 请参考接口全局状态码说明
    • msg 此次请求消息,如果返回状态码为非成功,可直接展示msg
    • data 如果为列表页将会一个数组类型(如商品列表),否则为一个对象类型(商品详情)
    • 如有额外扩展字段, 将于基本元素平级, 如分页的count
{
	"code": 401,
	"msg": "无效的token",
	"data": []
}
  • 刷新token说明
    • 为了保证安全性,token的有效时间为60分钟
    • 当旧的token失效时,服务器会主动刷新,并在响应头加入Authorization
    • 这时候旧的token将会加入黑名单不能再使用, 请将在响应头中新的token保存使用
    • 当服务器主动刷新之后,会有一个期限(2周).服务器将无法再刷新,将返回402状态码,请重新登录账户
  • token使用流程说明
// 全局请求类
function request(_method, _url, _param, _func) {

    $.ajax({
        method: _method,
        url: _url,
        data: _param,
        beforeSend: function (xhr) {
            console.log(xhr);
            xhr.setRequestHeader('Authorization', localStorage.getItem('api_token'))
        },
        complete: function (xhr, a, b) {

            if (xhr.getResponseHeader('Authorization')) {
                localStorage.setItem('api_token', xhr.getResponseHeader('Authorization'))
            }
        },
        success: function (res) {

            // token 永久过期
            if (res.code === 402) {
                // 跳去登录页面
                return false;
            }
            // 更多状态码判断
        }
    });
}

// 第一次登录保存 token, 之后使用全局类请求数据即可
  • 接口全局状态码说明(建议封装一个全局请求类或者中间件,统一处理全局状态码)
    • 200
      • 请求数据成功
    • 401
      • 身份验证出错(未登录就请求数据)
      • 非法无效的token
      • token已被加入黑名单(一般不会出现这个问题,出现这个问题那么就是你刷新 token 的逻辑有问题)
    • 402
      • token已完全失效,后台暂设为 2 周,再也无法刷新,请重新登录账户
    • 500
      • 服务器出错,具体请参考响应的消息
  • 接口文档(重要的事情说三遍)

接口文档

接口文档

接口文档

Packages

扩展包 一句话描述 在本项目中的使用案例
z-song/laravel-admin 后台 快速搭建后台系统
mews/captcha 验证码 登录注册功能使用验证码验证
overtrue/laravel-socialite 第三方登录 用户登录可以使用Github,QQ,新浪微博
intervention/image 图片处理 是为 Laravel 定制的图片处理工具,加水印
webpatser/laravel-uuid uuid生成 商品添加增加一个uuid,订单号
renatomarinho/laravel-page-speed 压缩页面DOM 打包优化您的网站自动导致35%以上的优化(已移除使用)
overtrue/laravel-pinyin 汉语拼音翻译 分类首字母查询
acelaya/doctrine-enum-type 枚举 优化代码中的映射

Reference

Notice

  • 建议开启bcmath扩展保证字符串数字运算正确
  • 监听队列如果长时间没反应,或者一直重复任务
    • 数据库没配置好,导致队列任务表连接不上
    • 邮件配置出错,导致发送邮件一直失败
  • composer install安装不上依赖
    • 请删除composer.lock文件,重新运行composer install
  • SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint
    • 数据库引擎切换到InnoDB
  • composer install 安装依赖错误
    • composer.lock锁定了镜像源,删除composer.lock再执行即可

License

The MIT License (MIT)