在这里插入图片描述

–queue 只运行指定的参数队列里的任务
–daemon 该参数已经废弃
–once 执行一次就推出
–stop–when-empty当队列为空的时候停止掉了
–delay 设置失败任务的间隔时间
–force 如果开了维护模式的话 队列斗能正常工作
–memory 进入休眠
–timeout 任务超时时间




//订单状态机
订单表

CREATE TABLE `litemall_order` (`id` int(11) NOT NULL AUTO_INCREMENT,`user_id` int(11) NOT NULL COMMENT '用户表的用户ID',`order_sn` varchar(63) NOT NULL COMMENT '订单编号',`order_status` smallint(6) NOT NULL COMMENT '订单状态',`aftersale_status` smallint(6) DEFAULT '0' COMMENT '售后状态,0是可申请,1是用户已申请,2是管理员审核通过,3是管理员退款成功,4是管理员审核拒绝,5是用户已取消',`consignee` varchar(63) NOT NULL COMMENT '收货人名称',`mobile` varchar(63) NOT NULL COMMENT '收货人手机号',`address` varchar(127) NOT NULL COMMENT '收货具体地址',`message` varchar(512) NOT NULL DEFAULT '' COMMENT '用户订单留言',`goods_price` decimal(10,2) NOT NULL COMMENT '商品总费用',`freight_price` decimal(10,2) NOT NULL COMMENT '配送费用',`coupon_price` decimal(10,2) NOT NULL COMMENT '优惠券减免',`integral_price` decimal(10,2) NOT NULL COMMENT '用户积分减免',`groupon_price` decimal(10,2) NOT NULL COMMENT '团购优惠价减免',`order_price` decimal(10,2) NOT NULL COMMENT '订单费用, = goods_price + freight_price - coupon_price',`actual_price` decimal(10,2) NOT NULL COMMENT '实付费用, = order_price - integral_price',`pay_id` varchar(63) DEFAULT NULL COMMENT '微信付款编号',`pay_time` datetime DEFAULT NULL COMMENT '微信付款时间',`ship_sn` varchar(63) DEFAULT NULL COMMENT '发货编号',`ship_channel` varchar(63) DEFAULT NULL COMMENT '发货快递公司',`ship_time` datetime DEFAULT NULL COMMENT '发货开始时间',`refund_amount` decimal(10,2) DEFAULT NULL COMMENT '实际退款金额,(有可能退款金额小于实际支付金额)',`refund_type` varchar(63) DEFAULT NULL COMMENT '退款方式',`refund_content` varchar(127) DEFAULT NULL COMMENT '退款备注',`refund_time` datetime DEFAULT NULL COMMENT '退款时间',`confirm_time` datetime DEFAULT NULL COMMENT '用户确认收货时间',`comments` smallint(6) DEFAULT '0' COMMENT '待评价订单商品数量',`end_time` datetime DEFAULT NULL COMMENT '订单关闭时间',`add_time` datetime DEFAULT NULL COMMENT '创建时间',`update_time` datetime DEFAULT NULL COMMENT '更新时间',`deleted` tinyint(1) DEFAULT '0' COMMENT '逻辑删除',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=797 DEFAULT CHARSET=utf8mb4 COMMENT='订单表';

订单商品表

CREATE TABLE `litemall_order_goods` (`id` int(11) NOT NULL AUTO_INCREMENT,`order_id` int(11) NOT NULL DEFAULT '0' COMMENT '订单表的订单ID',`goods_id` int(11) NOT NULL DEFAULT '0' COMMENT '商品表的商品ID',`goods_name` varchar(127) NOT NULL DEFAULT '' COMMENT '商品名称',`goods_sn` varchar(63) NOT NULL DEFAULT '' COMMENT '商品编号',`product_id` int(11) NOT NULL DEFAULT '0' COMMENT '商品货品表的货品ID',`number` smallint(5) NOT NULL DEFAULT '0' COMMENT '商品货品的购买数量',`price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '商品货品的售价',`specifications` varchar(1023) NOT NULL COMMENT '商品货品的规格列表',`pic_url` varchar(255) NOT NULL DEFAULT '' COMMENT '商品货品图片或者商品图片',`comment` int(11) DEFAULT '0' COMMENT '订单商品评论,如果是-1,则超期不能评价;如果是0,则可以评价;如果其他值,则是comment表里面的评论ID。',`add_time` datetime DEFAULT NULL COMMENT '创建时间',`update_time` datetime DEFAULT NULL COMMENT '更新时间',`deleted` tinyint(1) DEFAULT '0' COMMENT '逻辑删除',PRIMARY KEY (`id`),KEY `order_id` (`order_id`),KEY `goods_id` (`goods_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1051 DEFAULT CHARSET=utf8mb4 COMMENT='订单商品表';



  /*** 订单取消* @param $userId* @param $orderId* @param  string  $role  支持:user/admin/system* @return bool* @throws BusinessException* @throws Throwable*/private function cancel($userId, $orderId, $role = 'user'){//通过用户id与orderid获取订单id$order = $this->getOrderByUserIdAndId($userId, $orderId);//如果订单为空说明是有问题的if (is_null($order)) {$this->throwBadArgumentValue();}//  if ($order->order_status != OrderEnums::ORDER_INVALID_OPERATION, '订单不能取消');//  }if (!$order->canCancelHandle()) {$this->throwBusinessException(CodeResponse::ORDER_INVALID_OPERATION, '订单不能取消');}}

    private function cancel($userId, $orderId, $role = 'user'){//通过用户id与orderid获取订单id$order = $this->getOrderByUserIdAndId($userId, $orderId);//如果订单为空说明是有问题的if (is_null($order)) {$this->throwBadArgumentValue();}if (!$order->canCancelHandle()) {$this->throwBusinessException(CodeResponse::ORDER_INVALID_OPERATION, '订单不能取消');}$order->order_status = OrderEnums::StATUS_CANCEL;}
    private function cancel($userId, $orderId, $role = 'user'){//通过用户id与orderid获取订单id$order = $this->getOrderByUserIdAndId($userId, $orderId);//如果订单为空说明是有问题的if (is_null($order)) {$this->throwBadArgumentValue();}if (!$order->canCancelHandle()) {$this->throwBusinessException(CodeResponse::ORDER_INVALID_OPERATION, '订单不能取消');}switch ($role) {case 'system':$order->order_status = OrderEnums::STATUS_AUTO_CANCEL;break;case 'admin':$order->order_status = OrderEnums::STATUS_ADMIN_CANCEL;break;default:$order->order_status = OrderEnums::STATUS_CANCEL;}Order::query()->where('update_time',$order->update_time)->where('id',$order->id)//原来的状态必须的是创建的状态->where('order_status', OrderEnums::STATUS_cancel]);->update([order_status] => orderEnums::STATUS_CANCEL]);//接下来判断保存更新是否正常
//  if (!$order->save()){//throwBusinessException(CodeResponse::UPDATED_FAIL);//}}

cas进行封装

    /*** 乐观锁更新 compare and save* @return int* @throws Throwable*/public function cas(){//获取被修改的订单状态$dirty = $this->getDirty();//获取对象的当前更新时间  $updateAt = $this->getUpdateAtColumn(); //update_time $this->update_time$query = self::query()->where($this->getKeyname(),$this->getKey())->where($updateAt,$this->($updateAt));foreach ($where as $key => $value) {//getOriginsl可以获取被修改之前的值$query -> where($key, $this->getOriginsl($key))}return $query->update($dirty);}

优化后的订单取消接口

/*** 订单取消* @param $userId* @param $orderId* @param  string  $role  支持:user/admin/system* @return bool* @throws BusinessException* @throws Throwable*/private function cancel($userId, $orderId, $role = 'user'){//通过用户id与orderid获取订单id$order = $this->getOrderByUserIdAndId($userId, $orderId);//如果订单为空说明是有问题的if (is_null($order)) {$this->throwBadArgumentValue();}if (!$order->canCancelHandle()) {$this->throwBusinessException(CodeResponse::ORDER_INVALID_OPERATION, '订单不能取消');}switch ($role) {case 'system':$order->order_status = OrderEnums::STATUS_AUTO_CANCEL;break;case 'admin':$order->order_status = OrderEnums::STATUS_ADMIN_CANCEL;break;default:$order->order_status = OrderEnums::STATUS_CANCEL;}// end_time视频中忘记更新了$order->end_time = now()->toDateTimeString();if ($order->cas() == 0) {$this->throwBusinessException(CodeResponse::UPDATED_FAIL);}//添加库存低配版本//获取订单列表$orderGoods = $this->getOrderGoodsList($orderId);foreach ($orderGoods as $goods) {$row = GoodsServices::getInstance()->addStock($goods->product_id, $goods->number);if ($row == 0) {$this->throwBusinessException(CodeResponse::UPDATED_FAIL);}}return true;}

添加库存未优化版本

    public function reduceStock($productId, $num){return GoodsProduct::query()->where('id', $productId)->where('product_id', $productId)->increment('number', $num);}

添加库存优化版本

    public function addStock($productId, $num){$product = $this->getGoodsProductById($productId);$product->number = $product->number + $num;return $product->cas();}

//这里是个提醒




创建邮件与短信通知







//订单流程接口




///任务调度

方案解决 可以通过延时解决 或者定时任务

    //编写定时任务public function getTimeoutUnConfirmOrders(){        //获取订单的天数$days = SystemServices::getInstance()->getOrderUnConfirmDays();//订单状态必须是已经发货的状态return Order::query()->where('order_status', OrderEnums::STATUS_SHIP)//小于等于时间减去当前天数当前天数  如发货30天   但是现在只发货10天->where('ship_time', '<=', now()->subDays($days))//只显示一个月的数据->where('ship_time', '>=', now()->subDays($days + 30))->get();}


该方法可以创建定时任务



每分钟执行一次调度任务

此命令可以观察日志

订单详情

    /*** 订单详情* @return JsonResponse* @throws BusinessException*/public function detail(){$orderId = $this->verifyId('orderId');$detail = OrderServices::getInstance()->detail($this->userId(), $orderId);return $this->success($detail);}
/*** 订单详情* @param $userId* @param $orderId* @return array* @throws BusinessException*/public function detail($userId, $orderId){//获取一下订单$order = $this->getOrderByUserIdAndId($userId, $orderId);if (empty($order)) {$this->throwBadArgumentValue();}//将订单转为数据     Arr::only可以获取数组的部分字段$detail = Arr::only($order->toArray(), ["id","orderSn","message","addTime","consignee","mobile","address","goodsPrice","couponPrice","freightPrice","actualPrice","aftersaleStatus",]);//获取订单的状态$detail['orderStatusText'] = OrderEnums::STATUS_TEXT_MAP[$order->order_status] ?? '';$detail['expCode'] = $order->ship_channel;$detail['expNo'] = $order->ship_sn;$detail['expName'] = ExpressServices::getInstance()->getExpressName($order->ship_channel);//获取物流公司的名字$express = ExpressServices::getInstance()->getOrderTraces($order->ship_channel, $order->ship_sn);$express = []; //to do  物流信息未封装return ['orderInfo' => $detail,'orderGoods' => $goodsList,'expressInfo' => $express];}

/*** 订单详情* @param $userId* @param $orderId* @return array* @throws BusinessException*/public function detail($userId, $orderId){//获取一下订单$order = $this->getOrderByUserIdAndId($userId, $orderId);if (empty($order)) {$this->throwBadArgumentValue();}//将订单转为数据     Arr::only可以获取数组的部分字段$detail = Arr::only($order->toArray(), ["id","orderSn","message","addTime","consignee","mobile","address","goodsPrice","couponPrice","freightPrice","actualPrice","aftersaleStatus",]);//获取订单的状态$detail['orderStatusText'] = OrderEnums::STATUS_TEXT_MAP[$order->order_status] ?? '';//获取动作代码块$detail['handleOption'] = $order->getCanHandelOptions();//获取订单商品记录$goodsList = $this->getOrderGoodsList($orderId);$express = [];//必须已发货的状态才付这三个值if ($order->isShipStatus()) {$detail['expCode'] = $order->ship_channel;$detail['expNo'] = $order->ship_sn;$detail['expName'] = ExpressServices::getInstance()->getExpressName($order->ship_channel);//获取物流公司的名字$express = ExpressServices::getInstance()->getOrderTraces($order->ship_channel, $order->ship_sn);}return ['orderInfo' => $detail,'orderGoods' => $goodsList,'expressInfo' => $express];}

//缺陷 物流处理的不好

优化前置状态

<?phpnamespace App\Models\Order;use App\Enums\OrderEnums;
use Exception;
use Illuminate\Support\Str;
use ReflectionClass;/*** Trait OrderStatusTrait* @package App\Models\Order* @method bool canCancelHandle()* @method bool canDeleteHandle()* @method bool canPayHandle()* @method bool canCommentHandle()* @method bool canConfirmHandle()* @method bool canRefundHandle()* @method bool canRebuyHandle()* @method bool canAftersaleHandle()* @method bool isCreateStatus()* @method bool isPayStatus()* @method bool isShipStatus()* @method bool isConfirmStatus()* @method bool isCancelStatus()* @method bool isAutoCancelStatus()* @method bool isRefundStatus()* @method bool isRefundConfirmStatus()* @method bool isAutoConfirmStatus()*/
trait OrderStatusTrait
{private $canHandleMap = [// 取消操作'cancel' => [OrderEnums::STATUS_CREATE],// 删除操作'delete' => [OrderEnums::STATUS_CANCEL,OrderEnums::STATUS_AUTO_CANCEL,OrderEnums::STATUS_ADMIN_CANCEL,OrderEnums::STATUS_REFUND_CONFIRM,OrderEnums::STATUS_CONFIRM,OrderEnums::STATUS_AUTO_CONFIRM],// 支付操作'pay' => [OrderEnums::STATUS_CREATE],// 发货'ship' => [OrderEnums::STATUS_PAY],// 评论操作'comment' => [OrderEnums::STATUS_CONFIRM,OrderEnums::STATUS_AUTO_CONFIRM],// 确认收货操作'confirm' => [OrderEnums::STATUS_SHIP],// 取消订单并退款操作'refund' => [OrderEnums::STATUS_PAY],// 再次购买'rebuy' => [OrderEnums::STATUS_CONFIRM,OrderEnums::STATUS_AUTO_CONFIRM],// 售后操作'aftersale' => [OrderEnums::STATUS_CONFIRM,OrderEnums::STATUS_AUTO_CONFIRM],// 同意退款'agreerefund' => [OrderEnums::STATUS_REFUND],];public function __call($name, $arguments){if (Str::is('can*Handle', $name)) {if (is_null($this->order_status)) {throw new Exception("order status is null when call method[$name]!");}//of可以链式调用$key = Str::of($name)->replaceFirst('can', '')->replaceLast('Handle', '')//将字母转成小写->lower();//判断订单的状态return in_array($this->order_status, $this->canHandleMap[(string) $key]);} elseif (Str::is('is*Status', $name)) {   //判断订单当前状态if (is_null($this->order_status)) {throw new Exception("order status is null when call method[$name]!");}$key = Str::of($name)->replaceFirst('is', '')//snake  下划线     upper  转换为大写  prepend追加状态->replaceLast('Status', '')->snake()->upper()->prepend('STATUS_');//ReflectionClass   反射的方法$status = (new ReflectionClass(OrderEnums::class))->getConstant($key);return $this->order_status == $status;}//将参数传进来__call是魔术方法可以将不存在方法存进来return parent::__call($name, $arguments);}public function getCanHandelOptions(){return ['cancel' => $this->canCancelHandle(),'delete' => $this->canDeleteHandle(),'pay' => $this->canPayHandle(),'comment' => $this->canCommentHandle(),'confirm' => $this->canConfirmHandle(),'refund' => $this->canRefundHandle(),'rebuy' => $this->canRebuyHandle(),'aftersale' => $this->canAfterSaleHandle(),];}public function isHadPaid(){return !in_array($this->order_status, [OrderEnums::STATUS_CREATE,OrderEnums::STATUS_ADMIN_CANCEL,OrderEnums::STATUS_AUTO_CANCEL,OrderEnums::STATUS_CANCEL]);}
}


划线的地方是我们需要开发的地方
这个支付的github扩展包地址
https://github.com/yansongda/pay



这里已经废弃


https://pay.yansongda.cn/docs/v3/quick-start/wechat.html#%E5%85%AC%E4%BC%97%E5%8F%B7%E6%94%AF%E4%BB%98

    /*** 微信支付* @return RedirectResponse* @throws BusinessException*/public function h5pay(){//获取订单id$orderId = $this->verifyId('orderId');$order = OrderServices::getInstance()->getWxPayOrder($this->userId(), $orderId);return Pay::wechat()->wap($order);}
    public function getWxPayOrder($userId, $orderId){//获取订单详情$order = $this->getPayOrderInfo($userId, $orderId);return ['out_trade_no' => $order->order_sn,'body' => '订单:'.$order->order_sn,'total_fee' => bcmul($order->actual_price, 100),];}
    private function getPayOrderInfo($userId, $orderId){$order = $this->getOrderByUserIdAndId($userId, $orderId);if (empty($order)) {$this->throwBadArgumentValue();}if (!$order->canPayHandle()) {$this->throwBusinessException(CodeResponse::ORDER_PAY_FAIL, '订单不能支付');}return $order;}

支付回调

    /*** 微信支付回调* @return Response* @throws Throwable* @throws InvalidArgumentException* @throws InvalidSignException*/public function wxNotify(){//verify是集合类型$data = Pay::wechat()->verify()->toArray();Log::info('wxNotify', $data);DB::transaction(function () use ($data) {OrderServices::getInstance()->wxNotify($data);});return Pay::wechat()->success();}
    /*** @param  array  $data* @return Order* @throws BusinessException* @throws Throwable*/public function wxNotify(array $data){$orderSn = $data['out_trade_no'] ?? '';$payId = $data['transaction_id'] ?? '';//这里的函数除以100$price = bcdiv($data['total_fee'], 100, 2);return $this->notify($orderSn, $payId, $price);}
    /*** @param $orderSn* @param $payId* @param $price* @return Order* @throws BusinessException* @throws Throwable*/private function notify($orderSn, $payId, $price){//获取订单编号$order = $this->getOrderBySn($orderSn);if (is_null($order)) {$this->throwBusinessException(CodeResponse::ORDER_UNKNOWN);}//判断是否已经支付  就将未支付的状态全部排除if ($order->isHadPaid()) {return $order;}//判断金额是否一致     左边是实际金额 $price是获取金额if (bccomp($order->actual_price, $price, 2) != 0) {$this->throwBusinessException(CodeResponse::FAIL,"支付回调,订单[{$order->id}]金额不一致,[total_amount={$price}],订单金额[actual_price={$order->actual_price}]");}return $this->payOrder($order, $payId);}




打开日志的方法

laravel之任务队列相关推荐

  1. laravel 任务队列_laravel队列-让守护进程处理耗时任务

    待解决的问题 最近在做一个服务器集群管理的web项目,需要处理一些极其耗时的操作,比如磁盘格式化分区.对于这个需求,最开始的想法是,为了让节点上的rpc(远程过程调用) service端尽可能简单(简 ...

  2. laravel 任务队列_Laravel 队列的简单使用例子

    php artisan make:job SynUser 4.在队列类里面的handle方法中写上业务逻辑(比如发送网络请求,发送邮件等等,这里简单写个日志代替) protected $message ...

  3. laravel 任务队列_Laravel5.5之事件监听、任务调度、队列

    流程: 1.1 创建event php artisan make:event UserLogin LoginController.php /*** The user has been authenti ...

  4. 关于 Laravel Redis 多个进程同时取队列问题详解

    这篇文章主要给大家介绍了关于 Laravel Redis 多个进程同时取队列问题的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或工作具有一定的参考学习价值,需要的朋友下面来一起学习学习吧. ...

  5. endwith php,辅助函数 | 进阶系列 | Laravel 7 中文文档

    辅助函数 由 学院君 创建于11个月前, 最后更新于 11个月前 版本号 #7 3845 views 0 likes 1 collects 简介 Laravel 自带了一系列 PHP 辅助函数,很多被 ...

  6. Laravel短信mysql_使用 Laravel 实现阿里云短信服务队列

    首先,基于 Laravel 5.2 实现一个任务队列,用于存储待发送短信的相关信息,及 seeder/worker 的处理逻辑 短信模板 ID 模板参数 短信签名 目标手机号码 创建存储任务的数据表 ...

  7. php 辅助函数,辅助函数 - Laravel 5.8 中文文档手册 - php中文网手册

    辅助函数 简介 Laravel 包含各种各样的「全局」PHP 辅助函数,框架本身也大量的使用了这些功能函数:如果你觉的方便,你可以在你的应用中任意使用这些函数 可用方法 数组 & 对象 路径 ...

  8. laravel5.1 基于redis实现任务队列

    laravel5.1 基于redis实现任务队列 1.服务器配置redis 以ubuntu为例: 1.安装redis $ sudo apt-get install redis-server 安装完成后 ...

  9. laravel开源版华登区块狗

    开源地址:https://github.com/tp5er/laravel-admin-block 介绍 华登区块狗每只的价钱在100至15000之间,分成5种狗: 普登是100至300之间, 勇登是 ...

最新文章

  1. 这家民办研究院太年轻,竟敢跟世界级选手“叫板”
  2. NanoPi NEO Air使用五:安装Xfce和xrdp,实现远程访问
  3. javaweb实现单点登录,防止重复登录,获取sessionid,对session及时销毁回收,只允许一个用户登录,结合struts2实现
  4. 使用python获取焦点窗口的进程名称
  5. ActiveMQ、RabbitMQ、RocketMQ、Kafka的介绍及优缺点说明
  6. [HNOI2007] 分裂游戏
  7. Css 基本的规则写法
  8. matlab答案1 8章,MATLAB第1-8章答案
  9. 再学C++之C++中的全部关键字
  10. akb48_原AKB48成员板野友美结婚了!闪嫁23岁职棒球员高桥奎二
  11. 代码生成器 Freemaker
  12. MATLAB最简单教程
  13. tree.js实现3D效果,官网demo
  14. rust执行cmd命令隐藏窗口
  15. solidity合约调用合约方法的方式
  16. 创业吧,兄弟--记者眼中的中关村创业大街创业热潮纪实
  17. 前端标注软件-pxcook像素大厨使用心得
  18. 2022年最新计算机专业毕业设计选题 - 选题推荐 毕设开题 简单易过 题目新颖
  19. excel自动求和_excel自动求和你会吗?更改姓名自动算出总分,三个函数轻松搞定...
  20. 暴风播酷云J3455局域网smb传输不稳定的另一种解决方案

热门文章

  1. 英国访问学者出国行李清单大盘点
  2. 新手必看——Python代码运行的方法都在这里了
  3. windows验证mysql是否安装成功
  4. mysql 数据表读锁机制详解
  5. 金仓数据库 KingbaseES 插件参考手册 O
  6. IDEA bootstrap.properties 绿叶图标设置
  7. 《Linux运维实战:使用mongodump和mongorestore备份与恢复Mongodb数据》
  8. 什么叫泛型?有什么作用?
  9. 关于河南xx公司对工作流引擎,表单引擎 jflow问题汇总以及相应的问题解决办法
  10. oracle11适配器错误,oracle11g登录出现协议适配器错误的解决办法(亲测)