1952 lines
		
	
	
		
			73 KiB
		
	
	
	
		
			PHP
		
	
	
			
		
		
	
	
			1952 lines
		
	
	
		
			73 KiB
		
	
	
	
		
			PHP
		
	
	
| <?php
 | ||
| 
 | ||
| namespace app\api\logic;
 | ||
| 
 | ||
| use app\common\basics\Logic;
 | ||
| use app\common\enum\ClientEnum;
 | ||
| use app\common\enum\FootprintEnum;
 | ||
| use app\common\enum\GoodsEnum;
 | ||
| use app\common\enum\OrderEnum;
 | ||
| use app\common\enum\OrderGoodsEnum;
 | ||
| use app\common\enum\OrderInvoiceEnum;
 | ||
| use app\common\enum\OrderLogEnum;
 | ||
| use app\common\enum\PayEnum;
 | ||
| use app\common\enum\ShopEnum;
 | ||
| use app\common\enum\TeamEnum;
 | ||
| use app\common\logic\OrderLogLogic;
 | ||
| use app\common\logic\OrderRefundLogic;
 | ||
| use app\common\model\Cart;
 | ||
| use app\common\model\Freight;
 | ||
| use app\common\model\goods\Goods;
 | ||
| use app\common\model\Delivery;
 | ||
| use app\common\model\goods\GoodsItem;
 | ||
| use app\common\model\integral\IntegralOrder;
 | ||
| use app\common\model\order\Order;
 | ||
| use app\common\model\order\OrderGoods;
 | ||
| use app\common\model\order\OrderLog;
 | ||
| use app\common\model\order\OrderRefund;
 | ||
| use app\common\model\order\OrderTrade;
 | ||
| use app\common\model\Pay;
 | ||
| use app\common\model\RechargeOrder;
 | ||
| use app\common\model\shop\Shop;
 | ||
| use app\common\model\coupon\Coupon;
 | ||
| use app\common\model\coupon\CouponList;
 | ||
| use app\common\model\team\TeamFound;
 | ||
| use app\common\model\team\TeamJoin;
 | ||
| use app\common\model\user\User;
 | ||
| use app\common\model\user\UserLevel;
 | ||
| use app\common\server\UrlServer;
 | ||
| use app\common\model\seckill\SeckillGoods;
 | ||
| use app\common\model\bargain\BargainLaunch;
 | ||
| use app\common\model\user\UserAddress;
 | ||
| use app\common\server\AreaServer;
 | ||
| use app\common\server\ConfigServer;
 | ||
| use app\common\server\JsonServer;
 | ||
| use expressage\Kd100;
 | ||
| use expressage\Kdniao;
 | ||
| use think\Exception;
 | ||
| use think\facade\Db;
 | ||
| use think\facade\Env;
 | ||
| 
 | ||
| /**
 | ||
|  * Class OrderLogic
 | ||
|  * @package app\api\logic
 | ||
|  */
 | ||
| class OrderLogic extends Logic
 | ||
| {
 | ||
|     public static $order_type = OrderEnum::NORMAL_ORDER;
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 下单
 | ||
|      * @param $post
 | ||
|      * @return array|false
 | ||
|      * @throws Exception
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @throws \think\exception\PDOException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:19 下午
 | ||
|      */
 | ||
|     public static function add($post)
 | ||
|     {
 | ||
|         // 初始化支付方式
 | ||
|         $post['pay_way'] = 0;
 | ||
|         if (!empty($post['goods'])) {
 | ||
|             $goods = is_array($post['goods']) ?  $post['goods'] : json_decode($post['goods'], true);
 | ||
|             $post['goods'] = $goods;
 | ||
|         } else {
 | ||
|             $where = [[
 | ||
|                 'id', 'in', $post['cart_id']]
 | ||
|             ];
 | ||
|             $post['goods'] = $goods = Cart::where($where)
 | ||
|                 ->field(['goods_id', 'item_id', 'shop_id', 'goods_num as num'])
 | ||
|                 ->select()->toArray();
 | ||
|         }
 | ||
| 
 | ||
|         // 砍价订单验证
 | ||
|         if (isset($post['bargain_launch_id']) and $post['bargain_launch_id'] > 0) {
 | ||
|             self::$order_type = OrderEnum::BARGAIN_ORDER;
 | ||
|             $bargainLaunchModel = new BargainLaunch();
 | ||
|             $launch = $bargainLaunchModel->where(['id' => (int)$post['bargain_launch_id']])->find();
 | ||
|             if (!$launch) {
 | ||
|                 throw new Exception('砍价异常');
 | ||
|             }
 | ||
|             if ($launch['status'] == 2) {
 | ||
|                 throw new Exception('砍价失败,禁止下单');
 | ||
|             }
 | ||
|             if ($launch['payment_limit_time'] < time() and $launch['payment_limit_time'] > 0) {
 | ||
|                 throw new Exception('下单失败,超出限制时间');
 | ||
|             }
 | ||
|             if ($launch['order_id'] > 0) {
 | ||
|                 throw new Exception('您已下单了, 请勿重复操作');
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         //检查商品上架状态及库存
 | ||
|         $check_goods = self::checkGoods($goods);
 | ||
|         Db::startTrans();
 | ||
|         try {
 | ||
|             if (false === $check_goods) {
 | ||
|                 throw new Exception(self::$error);
 | ||
|             }
 | ||
|             $address = UserAddress::where('id', $post['address_id'])
 | ||
|                 ->field('contact,telephone,province_id,city_id,district_id,address')
 | ||
|                 ->find();
 | ||
|             if (empty($address)) {
 | ||
|                 throw new Exception('请选择地址');
 | ||
|             }
 | ||
| 
 | ||
|             // 校验发票信息 返回以店铺id为键,原发票参数为值的数组
 | ||
|             $invoice = OrderInvoiceLogic::checkOrderInvoice($post);
 | ||
|             if (false === $invoice) {
 | ||
|                 throw new Exception(OrderInvoiceLogic::getError());
 | ||
|             }
 | ||
| 
 | ||
|             $order_trade_add = self::addOrderTrade($post, $address);
 | ||
| 
 | ||
|             if (false === $order_trade_add) {
 | ||
|                 throw new Exception('父订单创建失败');
 | ||
|             }
 | ||
|             $shop_goods = [];
 | ||
|             $order_goods_datas_insert = [];
 | ||
|             $order_log_datas_insert = [];
 | ||
|             foreach ($post['goods'] as $key => $value) { //按店铺区分商品
 | ||
|                 $res = self::checkShop($value); //判断商家营业状态
 | ||
|                 if ($res !== true) {
 | ||
|                     throw new Exception($res);
 | ||
|                 }
 | ||
|                 $shop_goods[$value['shop_id']][] = $value;
 | ||
|             }
 | ||
| 
 | ||
|             foreach ($shop_goods as $key => $value) {
 | ||
|                 foreach ($value as $val) {
 | ||
|                     $seckill_goods_price = GoodsItem::isSeckill($val['item_id']);
 | ||
|                     if ($seckill_goods_price != 0) {//是秒杀商品
 | ||
|                         $sales_sum_res = self::setSeckillSaleSum($val['item_id'], $val['num']);
 | ||
|                         if ($sales_sum_res !== true) {
 | ||
|                             throw new Exception('秒杀商品销量设置失败');
 | ||
|                         }
 | ||
|                     }
 | ||
|                 }
 | ||
| 
 | ||
|                 $order_add = self::addOrder($order_trade_add, $value, $post, $key, $address);
 | ||
| 
 | ||
|                 if (false === $order_add) {
 | ||
|                     throw new Exception('订单生成失败');
 | ||
|                 }
 | ||
| 
 | ||
|                 // 增加发票
 | ||
|                 OrderInvoiceLogic::insertOrderInvoice($key, $post['user_id'], $order_add, $invoice);
 | ||
| 
 | ||
|                 $order_log_add_data = self::getOrderLogData($key, $post['user_id'], $key);
 | ||
|                 $order_log_datas_insert[] = $order_log_add_data;
 | ||
|                 $order_goods_data = self::getOrderGoodsData($order_add, $value,$post['user_id']);
 | ||
|                 $order_goods_datas_insert = array_merge($order_goods_datas_insert, $order_goods_data);
 | ||
|             }
 | ||
| 
 | ||
|             $order_log_insert = OrderLog::insertAll($order_log_datas_insert);
 | ||
| 
 | ||
|             if (false === $order_log_insert) {
 | ||
|                 throw new Exception('订单日志生成失败');
 | ||
|             }
 | ||
| 
 | ||
|             $order_goods_inster = OrderGoods::insertAll($order_goods_datas_insert);
 | ||
| 
 | ||
|             if (false === $order_goods_inster) {
 | ||
|                 throw new Exception('订单商品生成失败');
 | ||
|             }
 | ||
|             //商品库存减少
 | ||
|             $sub_goods_stock = self::subGoodsStock($post['goods']);
 | ||
|             if (false === $sub_goods_stock) {
 | ||
|                 throw new Exception('库存修改失败');
 | ||
|             }
 | ||
| 
 | ||
|             //购物车删除
 | ||
|             if (isset($post['cart_id']) && $post['cart_id'] != 0) {
 | ||
|                 $delCart = self::delCart($post['cart_id']);
 | ||
|                 if (false === $delCart) {
 | ||
|                     throw new Exception('购物车删除失败');
 | ||
|                 }
 | ||
|             }
 | ||
| 
 | ||
|             // 砍价订单处理
 | ||
|             if (isset($post['bargain_launch_id']) and $post['bargain_launch_id'] > 0) {
 | ||
|                 $bargainLaunchModel = new BargainLaunch();
 | ||
|                 $bargainLaunchModel->where(['id' => (int)$post['bargain_launch_id']])
 | ||
|                     ->update(['order_id' => $order_add, 'status' => 1]);
 | ||
|             }
 | ||
| 
 | ||
|             // 检测包邮活动
 | ||
|             $orders = Db::name('order')->where('trade_id', $order_trade_add)->select()->toArray();
 | ||
|             foreach($orders as $item) {
 | ||
|                 $address = [
 | ||
|                     'province_id' => $item['province'],
 | ||
|                     'city_id' => $item['city'],
 | ||
|                     'district_id' => $item['district'],
 | ||
|                 ];
 | ||
|                 if(self::isFreeShipping($item['shop_id'], ($item['goods_price'] - $item['discount_amount']), $address)) {
 | ||
|                     // 符合包邮条件,去邮费
 | ||
|                     Db::name('order')->where('id', $item['id'])->update([
 | ||
|                         'order_amount' => $item['order_amount'] - $item['shipping_price'],
 | ||
|                         'total_amount' => $item['total_amount'] - $item['shipping_price'],
 | ||
|                         'shipping_price' => 0,
 | ||
|                     ]);
 | ||
|                 }
 | ||
|             }
 | ||
|             // 更新主订单金额
 | ||
|             $newOrderAmount = Db::name('order')->where('trade_id', $order_trade_add)->sum('order_amount');
 | ||
|             $newTotalAmount = Db::name('order')->where('trade_id', $order_trade_add)->sum('total_amount');
 | ||
|             Db::name('order_trade')->where('id', $order_trade_add)->update([
 | ||
|                 'order_amount' => $newOrderAmount,
 | ||
|                 'total_amount' => $newTotalAmount,
 | ||
|             ]);
 | ||
| 
 | ||
|             Db::commit();
 | ||
|             return ['trade_id' => $order_trade_add, 'order_id' => $order_add, 'type' => 'trade'];
 | ||
|         } catch (Exception $e) {
 | ||
|             Db::rollback();
 | ||
|             self::$error = $e->getMessage();
 | ||
|             return false;
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 结算页数据
 | ||
|      * @param $post
 | ||
|      * @return array|false
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:19 下午
 | ||
|      */
 | ||
|     public static function settlement($post)
 | ||
|     {
 | ||
|         if (!empty($post['goods'])) {
 | ||
|             $goods = json_decode($post['goods'], true);
 | ||
|             $post['goods'] = $goods;
 | ||
|         } else {
 | ||
|             $where = [[
 | ||
|                 'id', 'in', $post['cart_id']]
 | ||
|             ];
 | ||
|             $post['goods'] = $goods = Cart::where($where)
 | ||
|                 ->field(['goods_id', 'item_id', 'shop_id', 'goods_num as num'])
 | ||
|                 ->select()->toArray();
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         // 检查店铺营业状态
 | ||
|         foreach($post['goods'] as $good) {
 | ||
|             $shop = Shop::field('name,expire_time,is_run,is_freeze')->where(['del' => 0, 'id' => $good['shop_id']])->findOrEmpty();
 | ||
|             if($shop->isEmpty()) {
 | ||
|                 self::$error = '部分商品所属店铺不存在';
 | ||
|                 return false;
 | ||
|             }
 | ||
|             // 获取原始数据(不经获取器)
 | ||
|             $shop = $shop->getData();
 | ||
|             if(!empty($shop['expire_time']) && ($shop['expire_time'] <= time())) {
 | ||
|                 self::$error = '部分商品所属店铺已到期';
 | ||
|                 return false;
 | ||
|             }
 | ||
|             if($shop['is_freeze']) {
 | ||
|                 self::$error = '部分商品所属店铺已被冻结';
 | ||
|                 return false;
 | ||
|             }
 | ||
|             if(!$shop['is_run']) {
 | ||
|                 self::$error = '部分商品所属店铺暂停营业中';
 | ||
|                 return false;
 | ||
|             }
 | ||
|         }
 | ||
|         $Goods = new Goods();
 | ||
|         $GoodsItem = new GoodsItem();
 | ||
|         $Shop = new Shop();
 | ||
|         if (isset($post['address_id']) && !empty($post['address_id'])) {
 | ||
|             $where = [
 | ||
|                 'id' => $post['address_id'],
 | ||
|                 'del' => 0,
 | ||
|             ];
 | ||
|             $address = UserAddress::where($where)
 | ||
|                 ->field('id,contact,telephone,province_id,city_id,district_id,address')
 | ||
|                 ->find()->toArray();
 | ||
|         } else {
 | ||
|             $address = UserAddress::where(['user_id' => $post['user_id'], 'is_default' => 1,'del' => 0])
 | ||
|                 ->field('id,contact,telephone,province_id,city_id,district_id,address')
 | ||
|                 ->find();
 | ||
|         }
 | ||
|         if (!empty($address)) {
 | ||
|             $address['province'] = AreaServer::getAddress($address['province_id']);
 | ||
|             $address['city'] = AreaServer::getAddress($address['city_id']);
 | ||
|             $address['district'] = AreaServer::getAddress($address['district_id']);
 | ||
|         } else {
 | ||
|             $address = [];
 | ||
|         }
 | ||
| 
 | ||
|         // 校验发票信息 返回以店铺id为键,原发票参数为值的数组
 | ||
|         $invoice = OrderInvoiceLogic::checkOrderInvoice($post);
 | ||
|         if (false === $invoice) {
 | ||
|             self::$error = OrderInvoiceLogic::getError();
 | ||
|             return false;
 | ||
|         }
 | ||
| 
 | ||
|         foreach ($goods as &$good) {
 | ||
|             $goods_item = $GoodsItem->alias('gi')
 | ||
|                 ->join('goods g', 'g.id = gi.goods_id')
 | ||
|                 ->where(['gi.id' => $good['item_id'], 'gi.goods_id' => $good['goods_id']])
 | ||
|                 ->field('gi.price,gi.spec_value_str,gi.image,g.image,g.name as goods_name, g.type as goods_type')
 | ||
|                 ->find()
 | ||
|                 ->toArray();
 | ||
|             $good['type'] = $goods_item['goods_type'];
 | ||
|             $good['name'] = $goods_item['goods_name'];
 | ||
|             $good['price'] = $goods_item['price'];
 | ||
|             $good['spec_value'] = $goods_item['spec_value_str'];
 | ||
|             $good['image'] = empty($goods_item['image']) ? $goods_item['image'] : $goods_item['image'];
 | ||
|             $good['image'] = UrlServer::getFileUrl($good['image']);
 | ||
|         }
 | ||
| 
 | ||
|         $shop = [];
 | ||
| 
 | ||
|         foreach ($goods as $key => $value) { //按店铺区分商品
 | ||
|             $shop_data = $Shop->where('id', $value['shop_id'])->find();
 | ||
|             $shop[$value['shop_id']]['shop_id'] = $value['shop_id'];
 | ||
|             $shop[$value['shop_id']]['shop_name'] = $shop_data['name'];
 | ||
|             $shop[$value['shop_id']]['open_invoice'] = $shop_data['open_invoice']; // 发票开关
 | ||
|             $shop[$value['shop_id']]['spec_invoice'] = $shop_data['spec_invoice']; // 是否支持专票
 | ||
|             $shop[$value['shop_id']]['delivery_type_text'] = Order::getDeliveryType(OrderEnum::DELIVERY_TYPE_EXPRESS);
 | ||
|             $shop[$value['shop_id']]['delivery_type'] = OrderEnum::DELIVERY_TYPE_EXPRESS;
 | ||
| 
 | ||
|             // 虚拟商品, 配送方式为 虚拟发货
 | ||
|             if ($value['type'] == GoodsEnum::TYPE_VIRTUAL) {
 | ||
|                 $shop[$value['shop_id']]['delivery_type_text'] = Order::getDeliveryType(OrderEnum::DELIVERY_TYPE_VIRTUAL);
 | ||
|                 $shop[$value['shop_id']]['delivery_type'] = OrderEnum::DELIVERY_TYPE_VIRTUAL;
 | ||
|             }
 | ||
| 
 | ||
|             $array = $post;
 | ||
|             $array['shop_id'] = $value['shop_id'];
 | ||
|             $shop_coupon_list = CouponLogic::getShopCouponList($array);
 | ||
|             $shop[$value['shop_id']]['coupon_list'] = $shop_coupon_list['suit'];
 | ||
|             //是否为秒杀
 | ||
|             $seckill_goods_price = GoodsItem::isSeckill($value['item_id']);
 | ||
|             if ($seckill_goods_price != 0) {
 | ||
|                 $value['price'] = $seckill_goods_price;
 | ||
|                 self::$order_type = OrderEnum::SECKILL_ORDER;  //秒杀订单
 | ||
|             }
 | ||
| 
 | ||
|             // 如果是砍价的商品,则替换信息
 | ||
|             if (isset($post['bargain_launch_id']) and $post['bargain_launch_id'] > 0) {
 | ||
|                 $bargainLaunchModel = new BargainLaunch();
 | ||
|                 $launch = $bargainLaunchModel->field(true)
 | ||
|                     ->where(['id' => (int)$post['bargain_launch_id']])
 | ||
|                     ->find();
 | ||
| 
 | ||
|                 $bargainImage = $launch['goods_snap']['image'] == '' ? $launch['goods_snap']['goods_iamge'] : $launch['goods_snap']['image'];
 | ||
|                 $value['goods_name'] = $launch['goods_snap']['name'];
 | ||
|                 $value['image_str'] = UrlServer::getFileUrl($bargainImage);
 | ||
|                 $value['price'] = $launch['current_price'];
 | ||
|                 $value['spec_value_str'] = $launch['goods_snap']['spec_value_str'];
 | ||
|                 self::$order_type = OrderEnum::BARGAIN_ORDER;//砍价订单
 | ||
|             }
 | ||
| 
 | ||
|             $shop[$value['shop_id']]['goods'][] = $value;
 | ||
|             $shop[$value['shop_id']]['shipping_price'] = self::calculateFreight($shop[$value['shop_id']]['goods'], $address);
 | ||
| 
 | ||
|             $user = User::where('id', $post['user_id'])->find();
 | ||
|             $discount = UserLevel::where(['id' => $user['level'],'del' => 0])->value('discount');
 | ||
| 
 | ||
|             // 普通订单才参与会员价
 | ||
|             if (self::$order_type == OrderEnum::NORMAL_ORDER) {
 | ||
|                 if($discount == 0){
 | ||
|                     $discount = 10;
 | ||
|                 }
 | ||
|                 $shop[$value['shop_id']]['total_amount'] = round(self::calculateGoodsPrice($shop[$value['shop_id']]['goods'],$discount) + $shop[$value['shop_id']]['shipping_price'], 2);
 | ||
|             } else {
 | ||
|                 $shop[$value['shop_id']]['total_amount'] = round(round($value['price'] * $value['num'], 2) + $shop[$value['shop_id']]['shipping_price'], 2);
 | ||
|             }
 | ||
| 
 | ||
|             //优惠券
 | ||
|             $discount_amount = 0;
 | ||
|             if (isset($post['coupon_id']) && !empty($post['coupon_id'])) {
 | ||
|                 $result = self::checkCoupon($post['coupon_id'], $value['shop_id']);
 | ||
|                 if ($result) {
 | ||
|                     $discount_amount = self::getDiscountAmount($post['coupon_id'], $value['shop_id'])['money'] ?? 0;
 | ||
|                 }
 | ||
|             }
 | ||
|             $shop[$value['shop_id']]['discount_amount'] = $discount_amount;
 | ||
|             if ($shop[$value['shop_id']]['total_amount'] > $discount_amount) {
 | ||
|                 $shop[$value['shop_id']]['total_amount'] = round($shop[$value['shop_id']]['total_amount'] - $discount_amount, 2);
 | ||
|             } else { //优惠金额大于当前商品总价,总价为0
 | ||
|                 $shop[$value['shop_id']]['total_amount'] = 0;
 | ||
|             }
 | ||
| 
 | ||
|             $num = 0;
 | ||
|             foreach ($shop[$value['shop_id']]['goods'] as &$item) {
 | ||
|                 $is_member = Goods::where('id',$item['goods_id'])->value('is_member');
 | ||
|                 $price_sum = round($item['price'] * $item['num'],2);
 | ||
| 
 | ||
|                 // 商品参与会员价 并且订单是 普通订单
 | ||
|                 if ($is_member && self::$order_type == OrderEnum::NORMAL_ORDER) {
 | ||
|                     $item['is_member'] = 1;
 | ||
|                 } else {
 | ||
|                     $item['is_member'] = 0;
 | ||
|                 }
 | ||
| 
 | ||
|                 if($item['is_member']) {
 | ||
|                     $member_amount = round($item['price']*$discount/10,2);
 | ||
|                     $item['member_amount'] = $member_amount;
 | ||
|                     $price_sum = round($member_amount * $item['num'],2);
 | ||
|                 }
 | ||
|                 $item['sum_price'] = $price_sum;
 | ||
|                 $num += $item['num'];
 | ||
|             }
 | ||
|             $shop[$value['shop_id']]['total_num'] = $num;
 | ||
|         }
 | ||
| 
 | ||
|         $shop = array_values($shop);
 | ||
|         $total_amount = array_sum(array_column($shop, 'total_amount'));
 | ||
|         $orders['address'] = $address;
 | ||
|         $orders['shop'] = $shop;
 | ||
|         $orders['order_type'] = self::$order_type;
 | ||
|         $orders['total_amount'] = $total_amount;
 | ||
|         $orders['pay_way_text'] = "微信支付";
 | ||
|         $orders['pay_way'] = OrderEnum::PAY_WAY_WECHAT;
 | ||
| 
 | ||
|         // 检验是否参与包邮活动,若参与去除邮费
 | ||
|         $orders = self::checkFreeShipping($orders);
 | ||
|         // 重新算总价
 | ||
|         $orders['total_amount'] = array_sum(array_column($orders['shop'], 'total_amount'));
 | ||
| 
 | ||
|         $orders['invoice'] = array_values($invoice);
 | ||
| 
 | ||
|         return $orders;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 校验是否符合包邮条件
 | ||
|      * @param $orders
 | ||
|      * @author Tab
 | ||
|      * @date 2021/8/31 15:11
 | ||
|      */
 | ||
|     public static function checkFreeShipping($orders)
 | ||
|     {
 | ||
|         if (empty($orders['address'])) {
 | ||
|             return $orders;
 | ||
|         }
 | ||
|         $address = $orders['address'];
 | ||
|         foreach($orders['shop'] as &$item) {
 | ||
|             if (self::isFreeShipping($item['shop_id'], ($item['total_amount'] - $item['shipping_price']), $address)) {
 | ||
|                 // 原总价格已算上邮费需减掉
 | ||
|                 $item['total_amount'] = $item['total_amount'] - $item['shipping_price'];
 | ||
|                 // 符合包邮条件,去邮费
 | ||
|                 $item['shipping_price'] = 0;
 | ||
|             }
 | ||
|         }
 | ||
|         return $orders;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 是否满足包邮条件
 | ||
|      * @param $shopId 店铺ID
 | ||
|      * @param $orderAmount 订单金额
 | ||
|      * @param $address 地址
 | ||
|      * @return bool
 | ||
|      * @author Tab
 | ||
|      * @date 2021/8/31 15:42
 | ||
|      */
 | ||
|     public static function isFreeShipping($shopId, $orderAmount, $address)
 | ||
|     {
 | ||
|         $config = Db::name('free_shipping_config')->where([
 | ||
|             'shop_id' => $shopId,
 | ||
|             'del' => 0
 | ||
|         ])->findOrEmpty();
 | ||
|         if (empty($config) || $config['status'] == 0) {
 | ||
|             // 未设置 或 未开启包邮活动
 | ||
|             return false;
 | ||
|         }
 | ||
|         // 校验区级设置
 | ||
|         $district = Db::name('free_shipping_region')->where([
 | ||
|             'shop_id' => $shopId,
 | ||
|             'del' => 0
 | ||
|         ])->whereFindInSet('region', $address['district_id'])->findOrEmpty();
 | ||
|         if (!empty($district) && $orderAmount >= $district['order_amount']) {
 | ||
|             // 符合包邮条件
 | ||
|             return true;
 | ||
|         }
 | ||
|         if (!empty($district) && $orderAmount < $district['order_amount']) {
 | ||
|             // 不符合条件,不再校验市级
 | ||
|             return false;
 | ||
|         }
 | ||
|         // 校验市级设置
 | ||
|         $city = Db::name('free_shipping_region')->where([
 | ||
|             'shop_id' => $shopId,
 | ||
|             'del' => 0
 | ||
|         ])->whereFindInSet('region', $address['city_id'])->findOrEmpty();
 | ||
|         if (!empty($city) && $orderAmount >= $city['order_amount']) {
 | ||
|             // 符合包邮条件
 | ||
|             return true;
 | ||
|         }
 | ||
|         if (!empty($city) && $orderAmount < $city['order_amount']) {
 | ||
|             // 不符合条件,不再校验省级
 | ||
|             return false;
 | ||
|         }
 | ||
| 
 | ||
|         // 校验省级设置
 | ||
|         $province = Db::name('free_shipping_region')->where([
 | ||
|             'shop_id' => $shopId,
 | ||
|             'del' => 0
 | ||
|         ])->whereFindInSet('region', $address['province_id'])->findOrEmpty();
 | ||
|         if (!empty($province) && $orderAmount >= $province['order_amount']) {
 | ||
|             // 符合包邮条件
 | ||
|             return true;
 | ||
|         }
 | ||
|         if (!empty($province) && $orderAmount < $province['order_amount']) {
 | ||
|             // 不符合条件,不再校验全国设置
 | ||
|             return false;
 | ||
|         }
 | ||
| 
 | ||
|         // 校验全国设置
 | ||
|         $all = Db::name('free_shipping_region')->where([
 | ||
|             'shop_id' => $shopId,
 | ||
|             'del' => 0,
 | ||
|             'region' => 'all'
 | ||
|         ])->findOrEmpty();
 | ||
|         if (!empty($all) && $orderAmount >= $all['order_amount']) {
 | ||
|             // 符合包邮条件
 | ||
|             return true;
 | ||
|         }
 | ||
|         return false;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 获取优惠金额
 | ||
|      * @param $coupon_id
 | ||
|      * @return int|mixed
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:19 下午
 | ||
|      */
 | ||
|     public static function getDiscountAmount($coupon_id, $shopId = null)
 | ||
|     {
 | ||
|         $result = [
 | ||
|             'money' => 0,
 | ||
|             'shop_id' => $shopId,
 | ||
|             'coupon_list_id' => 0,
 | ||
|         ];
 | ||
| 
 | ||
|         if (!isset($coupon_id) || empty($coupon_id)) {
 | ||
|             return $result;
 | ||
|         }
 | ||
| 
 | ||
|         //优惠金额
 | ||
|         foreach ($coupon_id as $item) {
 | ||
|             $Coupon_list = CouponList::where('id', $item)->find();
 | ||
|             if (is_null($shopId)) {
 | ||
|                 $where = ['id' => $Coupon_list['coupon_id'], 'del' => 0];
 | ||
|             } else {
 | ||
|                 $where = ['id' => $Coupon_list['coupon_id'], 'del' => 0, 'shop_id' => $shopId];
 | ||
|             }
 | ||
|             $coupon = Coupon::where($where)
 | ||
|                 ->find();
 | ||
|             if (!empty($coupon)) {
 | ||
|                 $result['money'] = $coupon['money'];
 | ||
|                 $result['shop_id'] = $shopId;
 | ||
|                 $result['coupon_list_id'] = $item;
 | ||
|             }
 | ||
|         }
 | ||
|         return $result;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes shop优惠券
 | ||
|      * @param $coupon_ids
 | ||
|      * @param $shop_id
 | ||
|      * @return bool
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:20 下午
 | ||
|      */
 | ||
|     public static function checkCoupon($coupon_ids, $shop_id)
 | ||
|     {
 | ||
| 
 | ||
|         $coupons = CouponList::where([['id', 'in', $coupon_ids]])->select()->toArray();
 | ||
| 
 | ||
|         if ($coupons) {
 | ||
|             foreach ($coupons as $item) {
 | ||
|                 $coupon_id = $item['coupon_id'];
 | ||
|                 $where = [
 | ||
|                     'id' => $coupon_id
 | ||
|                 ];
 | ||
|                 $result = Coupon::where($where)->value('shop_id');
 | ||
|                 if ($shop_id == $result) {
 | ||
|                     return true;
 | ||
|                 }
 | ||
|             }
 | ||
|         } else {
 | ||
|             return false;
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 检查商品库存
 | ||
|      * @param $goods
 | ||
|      * @return bool
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:20 下午
 | ||
|      */
 | ||
|     public static function checkGoods($goods)
 | ||
|     {
 | ||
| 
 | ||
|         if (!is_array($goods)) {
 | ||
|             self::$error = '商品数据格式不正确';
 | ||
|             return false;
 | ||
|         }
 | ||
|         $goods_item = new GoodsItem();
 | ||
|         $Good = new Goods();
 | ||
|         foreach ($goods as $key => $value) {
 | ||
|             $check_static = $Good->checkStatusById($value['goods_id']);
 | ||
|             $goods_name = $Good->where('id', $value['goods_id'])->value('name');
 | ||
|             if (false === $check_static) {
 | ||
|                 self::$error = $goods_name . '商品不存在/未上架';
 | ||
|                 return false;
 | ||
|             }
 | ||
|             $check_stock = $goods_item
 | ||
|                 ->where([
 | ||
|                     ['goods_id', '=', $value['goods_id']],
 | ||
|                     ['id', '=', $value['item_id']],
 | ||
|                     ['stock', '<', $value['num']],
 | ||
|                 ])
 | ||
|                 ->find();
 | ||
|             if ($check_stock) {
 | ||
|                 self::$error = '商品库存不足';
 | ||
|                 return false;
 | ||
|             }
 | ||
|         }
 | ||
|         return true;
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 计算商品总价格
 | ||
|      * @param $goods
 | ||
|      * @return false|float|int
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:20 下午
 | ||
|      */
 | ||
|     public static function calculateGoodsPrice($goods,$discount)
 | ||
|     {
 | ||
| 
 | ||
| 
 | ||
|         if (!is_array($goods)) {
 | ||
|             return false;
 | ||
|         }
 | ||
|         $GoodsItem = new GoodsItem();
 | ||
|         $all_goods_price = 0;
 | ||
|         foreach ($goods as $key => $value) {
 | ||
|             $goods_price = $GoodsItem->sumGoodsPrice($value['goods_id'], $value['item_id'], $value['num'],$discount);
 | ||
|             $all_goods_price = round($goods_price + $all_goods_price, 2);
 | ||
|         }
 | ||
|         return $all_goods_price;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 计算会员折扣金额
 | ||
|      * @param $goods
 | ||
|      * @param $discount
 | ||
|      * @return false|float|int
 | ||
|      * @author suny
 | ||
|      * @date 2021/9/7 4:42 下午
 | ||
|      */
 | ||
|     public static function memberGoodsPrice($goods,$discount)
 | ||
|     {
 | ||
| 
 | ||
|         if (!is_array($goods)) {
 | ||
|             return false;
 | ||
|         }
 | ||
|         $GoodsItem = new GoodsItem();
 | ||
|         $all_goods_price = 0;
 | ||
|         foreach ($goods as $key => $value) {
 | ||
|             $goods_price = $GoodsItem->sumMemberPrice($value['goods_id'], $value['item_id'], $value['num'],$discount);
 | ||
|             $all_goods_price = round($goods_price + $all_goods_price, 2);
 | ||
|         }
 | ||
|         return $all_goods_price;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 根据goods计算商品总运费
 | ||
|      * @param $goods
 | ||
|      * @param $address
 | ||
|      * @return false|int|string
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:20 下午
 | ||
|      */
 | ||
|     public static function calculateFreight($goods, $address)
 | ||
|     {
 | ||
|         if (!is_array($goods)) {
 | ||
|             return 0;
 | ||
|         }
 | ||
| 
 | ||
|         $Goods = new Goods();
 | ||
|         $GoodsItem = new GoodsItem();
 | ||
|         $Freight = new Freight();
 | ||
|         $freight = 0;
 | ||
|         if (empty($address)) {
 | ||
|             return $freight;
 | ||
|         }
 | ||
| 
 | ||
|         foreach ($goods as $key => $value) {
 | ||
|             $express = $Goods->getExpressType($value['goods_id']);
 | ||
|             if ($express['express_type'] == 2) { //统一运费
 | ||
|                 $price = $express['express_money'] * $value['num'];
 | ||
| //                $freight = bcadd($freight, $price, 2);
 | ||
|                 $freight = round(($freight + $price), 2);
 | ||
|             }
 | ||
|             if ($express['express_type'] == 3) { //运费模板
 | ||
|                 $goods_item = $GoodsItem->where([
 | ||
|                     ['goods_id', '=', $value['goods_id']],
 | ||
|                     ['id', '=', $value['item_id']]
 | ||
|                 ])->field('stock,volume,weight')
 | ||
|                     ->find()
 | ||
|                     ->toArray();
 | ||
|                 $price = $Freight->sumFreight($address, $goods_item, $express['express_template_id'], $value['num']);
 | ||
| //                $freight = bcadd($freight, $price, 2);
 | ||
|                 $freight = round(($freight + $price), 2);
 | ||
|             }
 | ||
|         }
 | ||
|         return $freight;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 添加父订单
 | ||
|      * @param $post
 | ||
|      * @param $address
 | ||
|      * @return false|mixed
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @throws \think\exception\DbException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:20 下午
 | ||
|      */
 | ||
|     public static function addOrderTrade($post, $address)
 | ||
|     {
 | ||
| 
 | ||
|         $OrderTrade = new OrderTrade();
 | ||
|         $order_amount = 0;
 | ||
|         $total_amount = 0;
 | ||
|         //计算商品总价格
 | ||
|         $user = User::where('id', $post['user_id'])->find();
 | ||
|         $discount = UserLevel::where('id', $user['level'])->value('discount');
 | ||
|         if($discount == 0 || self::$order_type != OrderEnum::NORMAL_ORDER){
 | ||
|             $discount = 10;
 | ||
|         }
 | ||
|         $all_goods_price = self::calculateGoodsPrice($post['goods'],$discount);
 | ||
|         //计算商品运费
 | ||
|         $all_freight = self::calculateFreight($post['goods'], $address);
 | ||
|         $total_amount = $all_goods_price + $all_freight;
 | ||
| 
 | ||
|         //计算优惠券优惠的金额
 | ||
|         $discount_amount = 0;
 | ||
|         if (isset($post['coupon_id'])) {
 | ||
|             foreach ($post['goods'] as $value) {
 | ||
|                 $discount_amount += self::getDiscountAmount($post['coupon_id'], $value['shop_id'])['money'] ?? 0;
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         if ($total_amount > $discount_amount) {
 | ||
|             $total_amount = round(($total_amount - $discount_amount), 2);
 | ||
|         } else { //优惠金额大于当前商品总价,总价为0
 | ||
|             $total_amount = 0;
 | ||
|         }
 | ||
| 
 | ||
| 
 | ||
|         // 砍价订单
 | ||
|         if (isset($post['bargain_launch_id']) and $post['bargain_launch_id'] > 0) {
 | ||
|             foreach ($post['goods'] as $goods) {
 | ||
|                 $bargainLaunchModel = new BargainLaunch();
 | ||
|                 $launch = $bargainLaunchModel->field(true)
 | ||
|                     ->where(['id' => (int)$post['bargain_launch_id']])
 | ||
|                     ->find();
 | ||
|                 $total_amount = round($launch['current_price'] * $goods['num'], 2);
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         // 记录访问足迹
 | ||
|         event('Footprint', [
 | ||
|             'type' => FootprintEnum::PLACE_ORDER,
 | ||
|             'user_id' => $post['user_id'],
 | ||
|             'total_money' => $total_amount
 | ||
|         ]);
 | ||
|         $trade_order_data = [];
 | ||
|         $trade_order_data['t_sn'] = createSn('order_trade', 't_sn');
 | ||
| 
 | ||
|         // 拿shop_id,连接成字符串存入order_trade表shop_id中
 | ||
|         $shop_id = '';
 | ||
|         foreach ($post['goods'] as $key => $value) {
 | ||
|             $shop_id .= ',' . $value['shop_id'];
 | ||
|         }
 | ||
|         $shop_id = substr($shop_id, 1);
 | ||
|         $trade_order_data['shop_id'] = $shop_id;
 | ||
|         $trade_order_data['user_id'] = $post['user_id'];
 | ||
|         $trade_order_data['goods_price'] = $all_goods_price;
 | ||
|         $trade_order_data['order_amount'] = $total_amount;
 | ||
|         $trade_order_data['total_amount'] = $total_amount;
 | ||
|         $trade_order_data['discount_amount'] = $discount_amount;
 | ||
|         $trade_order_data['create_time'] = time();
 | ||
|         $order_trade_create = $OrderTrade->create($trade_order_data);
 | ||
|         if (false === $order_trade_create) {
 | ||
|             return false;
 | ||
|         }
 | ||
|         return $order_trade_create->id;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 添加子订单
 | ||
|      * @param $order_id
 | ||
|      * @param $goods
 | ||
|      * @param $post
 | ||
|      * @param $shop_id
 | ||
|      * @param $address
 | ||
|      * @return false|mixed
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @throws \think\exception\DbException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:21 下午
 | ||
|      */
 | ||
|     public static function addOrder($order_id, $goods, $post, $shop_id, $address)
 | ||
|     {
 | ||
|         $Order = new Order();
 | ||
| 
 | ||
|         $remarks = isset($post['remark']) ? json_decode($post['remark'], true) : '';
 | ||
|         if ($remarks != '') {
 | ||
|             foreach ($remarks as $key => $value) {
 | ||
|                 $user_remark[$value['shop_id']] = $value['remark'];
 | ||
|             }
 | ||
|             if (array_key_exists($shop_id, $user_remark)) {
 | ||
|                 $remark = $user_remark[$shop_id];
 | ||
|             } else $remark = '';
 | ||
|         } else {
 | ||
|             $remark = $remarks;
 | ||
|         }
 | ||
|         $user = User::where('id', $post['user_id'])->find();
 | ||
|         $discount = UserLevel::where('id', $user['level'])->value('discount');
 | ||
|         if($discount == 0 || self::$order_type != OrderEnum::NORMAL_ORDER){
 | ||
|             $discount = 10;
 | ||
|         }
 | ||
|         $goods_price = self::calculateGoodsPrice($goods,$discount); //商品价格
 | ||
|         $member_amount = self::memberGoodsPrice($goods,$discount); //会员优惠价格
 | ||
|         $shipping_price = self::calculateFreight($goods, $address);
 | ||
| 
 | ||
|         //计算优惠券优惠的金额
 | ||
|         $coupon_list_id = 0;
 | ||
|         $discount_amount = 0;
 | ||
|         if (isset($post['coupon_id'])) {
 | ||
|             $discount = self::getDiscountAmount($post['coupon_id'], $shop_id);
 | ||
|             $discount_amount = $discount['money'];
 | ||
|             $coupon_list_id = $discount['coupon_list_id'];
 | ||
|         }
 | ||
| 
 | ||
|         if($goods_price + $shipping_price <= $discount_amount){
 | ||
|             $total_amount = $order_amount = 0;
 | ||
|         }else{
 | ||
|             $total_amount = $order_amount = $goods_price + $shipping_price - $discount_amount;
 | ||
|         }
 | ||
| 
 | ||
|         // 砍价订单
 | ||
|         if (isset($post['bargain_launch_id']) and $post['bargain_launch_id'] > 0) {
 | ||
|             foreach ($post['goods'] as $post_goods) {
 | ||
|                 $bargainLaunchModel = new BargainLaunch();
 | ||
|                 $launch = $bargainLaunchModel->field(true)
 | ||
|                     ->where(['id' => (int)$post['bargain_launch_id']])
 | ||
|                     ->find();
 | ||
|                 $order_amount = $total_amount = round($launch['current_price'] * $post_goods['num'], 2);
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         $order_data = [];
 | ||
|         $order_data['trade_id'] = $order_id;
 | ||
|         $order_data['shop_id'] = $shop_id;
 | ||
|         $order_data['user_id'] = $post['user_id'];
 | ||
|         $order_data['order_sn'] = createSn('order_trade', 't_sn');
 | ||
|         $order_data['order_type'] = self::$order_type;
 | ||
|         $order_data['order_source'] = $post['client'];
 | ||
|         $order_data['order_status'] = OrderEnum::ORDER_STATUS_NO_PAID;
 | ||
|         $order_data['pay_status'] = OrderEnum::PAY_STATUS_NO_PAID;
 | ||
|         $order_data['pay_way'] = $post['pay_way'];
 | ||
|         $order_data['delivery_type'] = $post['delivery_type'] ?? 0;
 | ||
|         $order_data['aftersale_status'] = OrderEnum::AFTERSALE_STATUS_NO_SALE;
 | ||
|         $order_data['consignee'] = $address['contact'];
 | ||
|         $order_data['province'] = $address['province_id'];
 | ||
|         $order_data['city'] = $address['city_id'];
 | ||
|         $order_data['district'] = $address['district_id'];
 | ||
|         $order_data['address'] = $address['address'];
 | ||
|         $order_data['mobile'] = $address['telephone'];
 | ||
|         $order_data['goods_price'] = $goods_price;
 | ||
|         $order_data['shipping_price'] = $shipping_price;
 | ||
|         $order_data['order_amount'] = $order_amount;
 | ||
|         $order_data['discount_amount'] = $discount_amount;
 | ||
|         $order_data['member_amount'] = $member_amount;
 | ||
|         $order_data['total_amount'] = $total_amount;
 | ||
|         $order_data['total_num'] = array_sum(array_column($goods, 'num'));
 | ||
|         $order_data['user_remark'] = $remark;
 | ||
|         $order_data['distribution_money'] = 0;
 | ||
|         $order_data['coupon_list_id'] = $coupon_list_id;
 | ||
|         $order_data['create_time'] = time();
 | ||
|         
 | ||
|         $order_create = $Order->create($order_data);
 | ||
| 
 | ||
|         if (false === $order_create) {
 | ||
|             return false;
 | ||
|         }
 | ||
| 
 | ||
|         if (!empty($coupon_list_id)) {
 | ||
|             self::editCoupon($coupon_list_id, $order_create->id);
 | ||
|         }
 | ||
| 
 | ||
|         return $order_create->id;
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 添加订单商品
 | ||
|      * @param $order_id
 | ||
|      * @param $goods
 | ||
|      * @return array
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:21 下午
 | ||
|      */
 | ||
|     public static function getOrderGoodsData($order_id, $goods,$user_id)
 | ||
|     {
 | ||
|         $user = User::where('id', $user_id)->find();
 | ||
|         $discount = UserLevel::where('id', $user['level'])->value('discount');
 | ||
|         if($discount == 0 || self::$order_type != OrderEnum::NORMAL_ORDER){
 | ||
|             $discount = 10;
 | ||
|         }
 | ||
|         $goods_data = [];
 | ||
|         foreach ($goods as $key => $value) {
 | ||
|             $Goods = Goods::where('id', $value['goods_id'])->field('name,image,shop_id')->find();
 | ||
|             $GoodsItem = GoodsItem::where([
 | ||
|                 ['id', '=', $value['item_id']],
 | ||
|                 ['goods_id', '=', $value['goods_id']],
 | ||
|             ])->field('price,image,spec_value_ids,spec_value_str')
 | ||
|                 ->find();
 | ||
|             $goods_data[$key]['order_id'] = $order_id;
 | ||
|             $goods_data[$key]['shop_id'] = $Goods['shop_id'];
 | ||
|             $goods_data[$key]['goods_id'] = $value['goods_id'];
 | ||
|             $goods_data[$key]['item_id'] = $value['item_id'];
 | ||
|             $goods_data[$key]['goods_num'] = $value['num'];
 | ||
|             $goods_data[$key]['goods_name'] = $Goods['name'];
 | ||
|             $goods_data[$key]['goods_price'] = $GoodsItem['price'];
 | ||
|             $goods_data[$key]['total_price'] = round($GoodsItem['price'] * $value['num'],2);
 | ||
|             $goods_data[$key]['total_pay_price'] = self::calculateGoodsPrice([$value],$discount);
 | ||
|             $goods_data[$key]['spec_value'] = $GoodsItem['spec_value_str'];
 | ||
|             $goods_data[$key]['spec_value_ids'] = $GoodsItem['spec_value_ids'];
 | ||
|             $goods_data[$key]['image'] = !empty($Goods['image']) ? UrlServer::setFileUrl($Goods['image']) : '';
 | ||
|             $goods_data[$key]['create_time'] = time();
 | ||
|         }
 | ||
|         $goods_data = self::shareDiscount($goods_data, $order_id);
 | ||
| 
 | ||
|         return $goods_data;
 | ||
|     }
 | ||
| 
 | ||
|     public static function shareDiscount($goodsData, $orderId)
 | ||
|     {
 | ||
|         // 获取订单优惠价格
 | ||
|         $orderDiscount = Order::where('id', $orderId)->value('discount_amount');
 | ||
|         if ($orderDiscount <= 0) {
 | ||
|             // 未使用优惠
 | ||
|             foreach ($goodsData as $key => &$item) {
 | ||
|                 $item['discount_price'] = 0;
 | ||
|             }
 | ||
|             return $goodsData;
 | ||
|         }
 | ||
|         // 累计应付总金额
 | ||
|         $sumPayPrice = 0;
 | ||
|         foreach ($goodsData as $item) {
 | ||
|             $sumPayPrice += $item['total_pay_price'];
 | ||
|         }
 | ||
|         // 根据比例分摊优惠金额
 | ||
|         $sumDiscount = 0;
 | ||
|         foreach ($goodsData as $key => &$item) {
 | ||
|             if ($key == (count($goodsData) - 1)) {
 | ||
|                 // 最后一条记录
 | ||
|                 $item['discount_price'] = $orderDiscount - $sumDiscount;
 | ||
|             }
 | ||
|             $item['discount_price'] = round($item['total_pay_price'] / $sumPayPrice * $orderDiscount, 2);
 | ||
|             $item['total_pay_price'] -=  $item['discount_price'];
 | ||
|             $sumDiscount .+ $item['discount_price'];
 | ||
|         }
 | ||
| 
 | ||
|         return $goodsData;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 扣除商品库存
 | ||
|      * @param $goods
 | ||
|      * @return bool
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:21 下午
 | ||
|      */
 | ||
|     public static function subGoodsStock($goods)
 | ||
|     {
 | ||
|         $goods_ids = [];
 | ||
| 
 | ||
|         foreach ($goods as $key => $value) {
 | ||
|             $goods_item_stock_dec = GoodsItem::where([
 | ||
|                 ['id', '=', $value['item_id']],
 | ||
|                 ['goods_id', '=', $value['goods_id']],
 | ||
|             ])->dec('stock', $value['num'])
 | ||
|                 ->update();
 | ||
|             $goods_stock_dec = Goods::where('id', $value['goods_id'])
 | ||
|                 ->dec('stock', $value['num'])
 | ||
|                 ->update();
 | ||
|             if (false === $goods_item_stock_dec) {
 | ||
|                 return false;
 | ||
|             }
 | ||
|             if (false === $goods_stock_dec) {
 | ||
|                 return false;
 | ||
|             }
 | ||
| 
 | ||
|             $goods_ids[] = $value['goods_id'];
 | ||
|         }
 | ||
| 
 | ||
|         // 下架总库存为0商品
 | ||
|         self::outGoods($goods_ids);
 | ||
| 
 | ||
|         return true;
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 下架总库存为0商品
 | ||
|      * @param $goods_ids
 | ||
|      * @return bool|void
 | ||
|      * @author 段誉
 | ||
|      * @date 2021/12/21 14:46
 | ||
|      */
 | ||
|     public static function outGoods($goods_ids)
 | ||
|     {
 | ||
|         try{
 | ||
|             $goods = Goods::where('id', 'in', $goods_ids)
 | ||
|                 ->field('id, stock')
 | ||
|                 ->select();
 | ||
| 
 | ||
|             if (empty($goods)) {
 | ||
|                 return true;
 | ||
|             }
 | ||
| 
 | ||
|             $need_handle_ids = [];
 | ||
|             foreach ($goods as $good) {
 | ||
|                 if ($good['stock'] <= 0) {
 | ||
|                     $need_handle_ids[] =  $good['id'];
 | ||
|                 }
 | ||
|             }
 | ||
| 
 | ||
|             if (empty($need_handle_ids)){
 | ||
|                 return true;
 | ||
|             }
 | ||
|             //下架订单商品中 商品总库存已为0的商品
 | ||
|             Goods::where('id', 'in', $need_handle_ids)->update(['status' => 0]);
 | ||
| 
 | ||
|             // 下架或删除商品更新收藏状态
 | ||
|             event('UpdateCollect', ['goods_id' => $need_handle_ids]);
 | ||
| 
 | ||
|         } catch (\Exception $e) {}
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 添加订单日志表
 | ||
|      * @param $order_id
 | ||
|      * @param $user_id
 | ||
|      * @param $shop_id
 | ||
|      * @return array
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:21 下午
 | ||
|      */
 | ||
|     public static function getOrderLogData($order_id, $user_id, $shop_id)
 | ||
|     {
 | ||
| 
 | ||
|         $order_log_data = [];
 | ||
|         $order_log_data['type'] = OrderLogEnum::TYPE_USER;
 | ||
|         $order_log_data['channel'] = OrderLogEnum::USER_ADD_ORDER;
 | ||
|         $order_log_data['order_id'] = $order_id;
 | ||
|         $order_log_data['handle_id'] = $user_id;
 | ||
|         $order_log_data['shop_id'] = $shop_id;
 | ||
|         $order_log_data['content'] = OrderLogEnum::USER_ADD_ORDER;
 | ||
|         $order_log_data['create_time'] = time();
 | ||
| 
 | ||
|         return $order_log_data;
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 删除购物车
 | ||
|      * @param $cart_id
 | ||
|      * @return bool
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:21 下午
 | ||
|      */
 | ||
|     public static function delCart($cart_id)
 | ||
|     {
 | ||
| 
 | ||
|         $delCart = Cart::where([
 | ||
|             ['id', 'in', $cart_id],
 | ||
|             ['selected', '=', 1]
 | ||
|         ])
 | ||
|             ->delete();
 | ||
|         if (false === $delCart) {
 | ||
|             return false;
 | ||
|         }
 | ||
|         return true;
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 订单列表
 | ||
|      * @param $user_id
 | ||
|      * @param $type
 | ||
|      * @param $page
 | ||
|      * @param $size
 | ||
|      * @return array
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:21 下午
 | ||
|      */
 | ||
|     public static function getOrderList($user_id, $type, $page, $size)
 | ||
|     {
 | ||
| 
 | ||
|         $order = new Order();
 | ||
|         $where[] = ['del', '=', 0];
 | ||
|         $where[] = ['user_id', '=', $user_id];
 | ||
| 
 | ||
|         switch ($type) {
 | ||
|             case 'pay':
 | ||
|                 $where[] = ['order_status', '=', OrderEnum::ORDER_STATUS_NO_PAID];
 | ||
|                 break;
 | ||
|             case 'delivery':
 | ||
|                 $where[] = ['order_status', 'in', [OrderEnum::ORDER_STATUS_DELIVERY, OrderEnum::ORDER_STATUS_GOODS]];
 | ||
|                 break;
 | ||
|             case 'finish':
 | ||
|                 $where[] = ['order_status', '=', OrderEnum::ORDER_STATUS_COMPLETE];
 | ||
|                 break;
 | ||
|             case 'close':
 | ||
|                 $where[] = ['order_status', '=', OrderEnum::ORDER_STATUS_DOWN];
 | ||
|                 break;
 | ||
|         }
 | ||
| 
 | ||
|         $count = $order->where(['del' => 0, 'user_id' => $user_id])
 | ||
|             ->where($where)
 | ||
|             ->count();
 | ||
| 
 | ||
|         $lists = $order->where(['del' => 0, 'user_id' => $user_id])
 | ||
|             ->where($where)
 | ||
|             ->with(['order_goods', 'shop'])
 | ||
|             ->field('id,order_sn,order_status,pay_status,order_amount,order_status,order_type,shipping_status,create_time,shop_id,delivery_type')
 | ||
|             ->page($page, $size)
 | ||
|             ->order('id desc')
 | ||
|             ->select();
 | ||
| 
 | ||
|         $lists->append(['goods_count', 'pay_btn', 'cancel_btn', 'delivery_btn', 'take_btn', 'del_btn', 'comment_btn', 'content_btn','order_cancel_time']);
 | ||
| 
 | ||
|         foreach ($lists as $list) {
 | ||
|             if ($list['order_type'] == OrderEnum::SECKILL_ORDER) {//如果是秒杀
 | ||
|                 foreach ($list['order_goods'] as $item) {
 | ||
|                     $seckill_price = GoodsItem::isSeckill($item['item_id']);
 | ||
|                     if ($seckill_price != 0) {
 | ||
|                         $item['goods_price'] = $seckill_price;
 | ||
|                     }
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
|         $data = [
 | ||
|             'list' => $lists,
 | ||
|             'page' => $page,
 | ||
|             'size' => $size,
 | ||
|             'count' => $count,
 | ||
|             'more' => is_more($count, $page, $size)
 | ||
|         ];
 | ||
|         return $data;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 通过规格id查询秒杀价格
 | ||
|      * @param $item_id
 | ||
|      * @return int|mixed
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:21 下午
 | ||
|      */
 | ||
|     public static function getSekillPriceByItemId($item_id)
 | ||
|     {
 | ||
| 
 | ||
|         $where = [
 | ||
|             'item_id' => $item_id,
 | ||
|             'del' => 0,
 | ||
|             'review_status' => 1
 | ||
|         ];
 | ||
|         $seckill = SeckillGoods::where($where)->find();
 | ||
|         return isset($seckill['price']) ? $seckill['price'] : 0;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 订单详情
 | ||
|      * @param $order_id
 | ||
|      * @return array|\think\Model|null
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:22 下午
 | ||
|      */
 | ||
|     public static function getOrderDetail($order_id)
 | ||
|     {
 | ||
| 
 | ||
|         $order = Order::with(['order_goods', 'shop'])->where(['del' => 0, 'id' => $order_id])->find();
 | ||
|         if ($order) {
 | ||
|             $order->append(['delivery_address', 'pay_btn', 'cancel_btn', 'delivery_btn', 'take_btn', 'del_btn','view_invoice_btn','save_invoice_btn', 'order_cancel_time'])
 | ||
|                 ->hidden(['user_id', 'order_source',
 | ||
|                     'city', 'district', 'address', 'shipping_status', 'shipping_code',
 | ||
|                     'pay_status', 'transaction_id', 'del', 'province']);
 | ||
| 
 | ||
|             $refund_days = ConfigServer::get('after_sale', 'refund_days', 7 * 86400, 0) * 86400;
 | ||
|             $now = time();
 | ||
|             foreach ($order->order_goods as $order_good) {
 | ||
|                 if ($order['order_type'] == OrderEnum::SECKILL_ORDER) { // 是秒杀商品
 | ||
|                     $seckill_price = GoodsItem::isSeckill($order_good['item_id']);
 | ||
|                     if ($seckill_price != 0) {
 | ||
|                         $order_good['goods_price'] = $seckill_price;
 | ||
|                     }
 | ||
|                 }$order_good['sum_price'] = $order_good['goods_price'] * $order_good['goods_num'];
 | ||
|                 $order_good['comment_btn'] = 0;
 | ||
|                 if ($order['pay_status'] == PayEnum::ISPAID && $order['order_status'] == OrderEnum::ORDER_STATUS_COMPLETE && $order_good['is_comment'] == 0) {
 | ||
|                     $order_good['comment_btn'] = 1;
 | ||
|                 }
 | ||
|                 $order_good['refund_btn'] = 0;
 | ||
| 
 | ||
|                 $confirm_take_time = strtotime($order['confirm_take_time']) ?: 0;
 | ||
|                 $refund_time = $confirm_take_time + $refund_days;
 | ||
|                 if ($order['order_status'] == OrderEnum::ORDER_STATUS_COMPLETE && $order_good['refund_status'] == OrderGoodsEnum::REFUND_STATUS_NO) {
 | ||
|                     $order_good['refund_btn'] = 1;
 | ||
|                 }
 | ||
|                 $order_good['sum_price'] = $order_good['goods_price'] * $order_good['goods_num'];
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         // 如果是拼团的订单
 | ||
|         if ($order['order_type'] == OrderEnum::TEAM_ORDER) {
 | ||
|             $teamJoin = (new TeamJoin())->where(['order_id' => $order['id']])->findOrEmpty()->toArray();
 | ||
|             $teamJoin['team_snap'] = json_decode($teamJoin['team_snap'], true);
 | ||
|             $order['team'] = [
 | ||
|                 'team_activity_id' => $teamJoin['team_activity_id'],
 | ||
|                 'team_id' => $teamJoin['team_id'],
 | ||
|                 'identity' => $teamJoin['identity'] == 1 ? '团长' : '团员',
 | ||
|                 'people_num' => $teamJoin['team_snap']['people_num'],
 | ||
|                 'status' => $teamJoin['status'],
 | ||
|                 'status_text' => TeamEnum::getStatusDesc($teamJoin['status'])
 | ||
|             ];
 | ||
|         }
 | ||
| 
 | ||
|         $order['order_type'] = Order::getOrderType($order['order_type']);
 | ||
|         $order['pay_way'] = PayEnum::getPayWay($order['pay_way']);
 | ||
|         $order['create_time'] = $order['create_time'] == 0 ? '' : $order['create_time'];
 | ||
|         $order['update_time'] = $order['update_time'] == 0 ? '' : $order['update_time'];
 | ||
|         $order['confirm_take_time'] = $order['confirm_take_time'] == 0 ? '' : date('Y-m-d H:i:s', $order['confirm_take_time']);;
 | ||
|         $order['shipping_time'] = $order['shipping_time'] == 0 ? '' : date('Y-m-d H:i:s', $order['shipping_time']);
 | ||
|         $order['pay_time'] = $order['pay_time'] == 0 ? '' : date('Y-m-d H:i:s', $order['pay_time']);
 | ||
|         $order['cancel_time'] = $order['cancel_time'] == 0 ? '' : date('Y-m-d H:i:s', $order['cancel_time']);
 | ||
| 
 | ||
|         // 虚拟商品 发货内容
 | ||
|         if ($order['delivery_type'] != OrderEnum::DELIVERY_TYPE_VIRTUAL || $order['shipping_status'] != OrderEnum::SHIPPING_FINISH) {
 | ||
|             $order['delivery_content'] = '';
 | ||
|         }
 | ||
| 
 | ||
|         return $order->toArray();
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 取消订单
 | ||
|      * @param $order_id
 | ||
|      * @param $user_id
 | ||
|      * @return \think\response\Json
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @throws \think\exception\PDOException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:22 下午
 | ||
|      */
 | ||
|     public static function cancel($order_id, $user_id)
 | ||
|     {
 | ||
|         $time = time();
 | ||
|         $order = Order::with(['orderGoods'])->where(['del' => 0, 'user_id' => $user_id, 'id' => $order_id])->find();
 | ||
| 
 | ||
|         if (!$order || (int)$order['order_status'] > OrderEnum::ORDER_STATUS_DELIVERY) {
 | ||
|             return JsonServer::error('很抱歉!订单无法取消');
 | ||
|         }
 | ||
| 
 | ||
|         $cancel_limit = ConfigServer::get('transaction', 'paid_order_cancel_time', 0);
 | ||
|         $limit_time = strtotime($order['create_time']) + $cancel_limit * 60;
 | ||
|         if ($limit_time < time()) {
 | ||
|             return JsonServer::error('很抱歉!订单已不可取消');
 | ||
|         }
 | ||
| 
 | ||
|         Db::startTrans();
 | ||
|         try {
 | ||
|             // 如果是拼团的订单
 | ||
|             if ($order['order_type'] == OrderEnum::TEAM_ORDER) {
 | ||
| 
 | ||
|                 $team_id = (new TeamJoin())->where(['order_id' => $order['id']])->value('team_id');
 | ||
|                 $teamJoin = (new TeamJoin())->alias('TJ')
 | ||
|                     ->field(['TJ.*,O.order_sn,O.order_status,O.pay_status,O.refund_status,O.order_amount'])
 | ||
|                     ->where(['team_id' => $team_id])
 | ||
|                     ->join('order O', 'O.id=TJ.order_id')
 | ||
|                     ->select()->toArray();
 | ||
| 
 | ||
|                 TeamFound::update(['status' => TeamEnum::TEAM_STATUS_FAIL, 'team_end_time' => $time], ['id' => $team_id]);
 | ||
|                 foreach ($teamJoin as $item) {
 | ||
|                     TeamJoin::update(['status' => TeamEnum::TEAM_STATUS_FAIL, 'update_time' => $time], ['id' => $item['id']]);
 | ||
|                     OrderRefundLogic::cancelOrder($item['order_id'], OrderLogEnum::TYPE_USER, $user_id);  //取消订单
 | ||
| 
 | ||
|                     if ($item['pay_status'] == PayEnum::ISPAID) {
 | ||
|                         $order = (new Order())->findOrEmpty($item['order_id'])->toArray();
 | ||
|                         OrderRefundLogic::cancelOrderRefundUpdate($order); //更新订单状态
 | ||
|                         OrderRefundLogic::refund($order, $order['order_amount'], $order['order_amount']); //订单退款
 | ||
|                     }
 | ||
|                 }
 | ||
| 
 | ||
| 
 | ||
|             } else {
 | ||
|                 //取消订单
 | ||
|                 OrderRefundLogic::cancelOrder($order_id, OrderLogEnum::TYPE_USER, $user_id);
 | ||
|                 //已支付的订单,取消,退款
 | ||
|                 if ($order['pay_status'] == PayEnum::ISPAID) {
 | ||
|                     //更新订单状态
 | ||
|                     OrderRefundLogic::cancelOrderRefundUpdate($order);
 | ||
|                     //订单退款
 | ||
|                     OrderRefundLogic::refund($order, $order['order_amount'], $order['order_amount']);
 | ||
|                 }
 | ||
| 
 | ||
|             }
 | ||
| 
 | ||
|             Db::commit();
 | ||
|             return JsonServer::success('取消成功');
 | ||
|         } catch (Exception $e) {
 | ||
|             Db::rollback();
 | ||
|             self::addErrorRefund($order, $e->getMessage());
 | ||
|             return JsonServer::error($e->getMessage());
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 回退商品库存
 | ||
|      * @param $goods
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:22 下午
 | ||
|      */
 | ||
|     public static function backStock($goods)
 | ||
|     {
 | ||
| 
 | ||
|         foreach ($goods as $good) {
 | ||
|             //回退库存,回退规格库存,减少商品销量
 | ||
|             Goods::where('id', $good['goods_id'])
 | ||
|                 ->update([
 | ||
|                     'stock' => Db::raw('stock+' . $good['goods_num'])
 | ||
|                 ]);
 | ||
| 
 | ||
|             //补充规格表库存
 | ||
|             GoodsItem::where('id', $good['item_id'])
 | ||
|                 ->inc('stock', $good['goods_num'])
 | ||
|                 ->update();
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 增加退款失败记录
 | ||
|      * @param $order
 | ||
|      * @param $err_msg
 | ||
|      * @return int|string
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @throws \think\exception\DbException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:22 下午
 | ||
|      */
 | ||
|     public static function addErrorRefund($order, $err_msg)
 | ||
|     {
 | ||
| 
 | ||
|         $orderRefund = new OrderRefund();
 | ||
|         $refund_data = [
 | ||
|             'order_id' => $order['id'],
 | ||
|             'user_id' => $order['user_id'],
 | ||
|             'refund_sn' => createSn('order_refund', 'refund_sn'),
 | ||
|             'order_amount' => $order['order_amount'],//订单应付金额
 | ||
|             'refund_amount' => $order['order_amount'],//订单退款金额
 | ||
|             'transaction_id' => $order['transaction_id'],
 | ||
|             'create_time' => time(),
 | ||
|             'refund_status' => 2,
 | ||
|             'refund_msg' => json_encode($err_msg, JSON_UNESCAPED_UNICODE),
 | ||
|         ];
 | ||
|         return $orderRefund->insertGetId($refund_data);
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 获取退款订单的应付金额
 | ||
|      * @param $order
 | ||
|      * @return mixed
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:22 下午
 | ||
|      */
 | ||
|     public static function getOrderTotalFee($order)
 | ||
|     {
 | ||
| 
 | ||
|         $OrderTrade = new OrderTrade();
 | ||
|         $trade = $OrderTrade
 | ||
|             ->where('transaction_id', $order['transaction_id'])
 | ||
|             ->find();
 | ||
| 
 | ||
|         $total_fee = $order['order_amount'];
 | ||
|         if ($trade) {
 | ||
|             $total_fee = $trade['order_amount'];
 | ||
|         }
 | ||
|         return $total_fee;
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 确认订单
 | ||
|      * @param $order_id
 | ||
|      * @param $user_id
 | ||
|      * @return \think\response\Json
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:22 下午
 | ||
|      */
 | ||
|     public static function confirm($order_id, $user_id)
 | ||
|     {
 | ||
| 
 | ||
|         $order = Order::where(['del' => 0, 'id' => $order_id])->find();
 | ||
|         if ($order['order_status'] == OrderEnum::ORDER_STATUS_COMPLETE) {
 | ||
|             return JsonServer::error('订单已完成');
 | ||
|         }
 | ||
|         if ($order['shipping_status'] == 0) {
 | ||
|             return JsonServer::error('订单未发货');
 | ||
|         }
 | ||
|         $order->order_status = OrderEnum::ORDER_STATUS_COMPLETE;
 | ||
|         $order->update_time = time();
 | ||
|         $order->confirm_take_time = time();
 | ||
|         $order->save();
 | ||
| 
 | ||
|         //订单日志
 | ||
|         OrderLogLogic::record(
 | ||
|             OrderLogEnum::TYPE_USER,
 | ||
|             OrderLogEnum::USER_CONFIRM_ORDER,
 | ||
|             $order_id,
 | ||
|             $user_id,
 | ||
|             OrderLogEnum::USER_CONFIRM_ORDER
 | ||
|         );
 | ||
| 
 | ||
|         return JsonServer::success('确认成功');
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 删除订单
 | ||
|      * @param $order_id
 | ||
|      * @param $user_id
 | ||
|      * @return \think\response\Json
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:23 下午
 | ||
|      */
 | ||
|     public static function del($order_id, $user_id)
 | ||
|     {
 | ||
| 
 | ||
|         $where = [
 | ||
|             'order_status' => OrderEnum::ORDER_STATUS_DOWN,
 | ||
|             'user_id' => $user_id,
 | ||
|             'id' => $order_id,
 | ||
|             'del' => 0,
 | ||
|         ];
 | ||
|         $order = Order::where($where)->find();
 | ||
| 
 | ||
|         if (!$order) {
 | ||
|             return JsonServer::error('订单无法删除');
 | ||
|         }
 | ||
| 
 | ||
| //        $res = $order->save(['del' => 1, 'update_time' => time()]);
 | ||
|         $data = ['del' => 1, 'update_time' => time(), 'pat_status' => OrderEnum::ORDER_STATUS_DOWN];
 | ||
|         $res = Order::update($data, ['id' => $order['id']]);
 | ||
|         OrderLogLogic::record(
 | ||
|             OrderLogEnum::TYPE_USER,
 | ||
|             OrderLogEnum::USER_DEL_ORDER,
 | ||
|             $order_id,
 | ||
|             $user_id,
 | ||
|             OrderLogEnum::USER_DEL_ORDER
 | ||
|         );
 | ||
|         return JsonServer::success('删除成功', ['res' => $res]);
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 获取订单支付结果
 | ||
|      * @param $trade_id
 | ||
|      * @return array|false
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:23 下午
 | ||
|      */
 | ||
|     public static function pay_result($id,$from)
 | ||
|     {
 | ||
|         switch ($from) {
 | ||
|             case 'trade' : //如果是父订单类型下单,$id为父订单id
 | ||
|                 $result = OrderTrade::alias('ot')
 | ||
|                     ->where(['ot.id' => $id,'o.pay_status' => 1])
 | ||
|                     ->join('order o','o.trade_id = ot.id')
 | ||
|                     ->field(['ot.id', 'ot.t_sn as order_sn', 'o.pay_time', 'o.pay_way', 'ot.total_amount'])
 | ||
|                     ->findOrEmpty()
 | ||
|                     ->toArray();
 | ||
|                 $result['total_amount'] = '¥' . $result['total_amount'];
 | ||
|                 break;
 | ||
| 
 | ||
|             case 'order' : //如果是子订单类型下单,$id为子订单id
 | ||
|                 $result = Order::where(['id' => $id])
 | ||
|                     ->field(['id', 'order_sn', 'pay_time', 'pay_way', 'total_amount'])
 | ||
|                     ->findOrEmpty()
 | ||
|                     ->toArray();
 | ||
|                 $result['total_amount'] = '¥' . $result['total_amount'];
 | ||
|                 break;
 | ||
| 
 | ||
|             case 'integral':
 | ||
|                 $result = IntegralOrder::where(['id' => $id])
 | ||
|                     ->field(['id', 'order_sn', 'pay_time', 'pay_way', 'order_amount', 'order_integral', 'exchange_way'])
 | ||
|                     ->findOrEmpty()->toArray();
 | ||
|                 $order_integral = $result['order_integral'] > 0 ? $result['order_integral'] . '积分' : '';
 | ||
|                 $order_amount = $result['order_amount'] > 0 ? '+ ¥' . $result['order_amount'] . '元' : '';
 | ||
|                 $result['total_amount'] = $order_integral . $order_amount;
 | ||
|                 break;
 | ||
|             default :
 | ||
|                 return false;
 | ||
|         }
 | ||
|         if ($result) {
 | ||
|             $result['pay_time'] = date('Y-m-d H:i:s', $result['pay_time']);
 | ||
|             $result['pay_way'] = PayEnum::getPayWay($result['pay_way']);
 | ||
|             return $result;
 | ||
|         }
 | ||
|         return false;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 获取支付方式
 | ||
|      * @param $user_id
 | ||
|      * @return array|array[]|\array[][]|\array[][][]
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:23 下午
 | ||
|      */
 | ||
|     public static function getPayWay($user_id, $client, $params)
 | ||
|     {
 | ||
| 
 | ||
|         $payModel = new Pay();
 | ||
|         $payway = $payModel->where(['status' => 1])->order('sort')->hidden(['config'])->select()->toArray();
 | ||
|         foreach ($payway as $k => &$item) {
 | ||
|             if ($item['code'] == 'wechat') {
 | ||
|                 $item['extra'] = '微信快捷支付';
 | ||
|                 $item['pay_way'] = PayEnum::WECHAT_PAY;
 | ||
|             }
 | ||
| 
 | ||
|             if ($item['code'] == 'balance') {
 | ||
|                 $user_money = Db::name('user')->where(['id' => $user_id])->value('user_money');
 | ||
|                 $item['extra'] = '可用余额:' . $user_money;
 | ||
|                 $item['pay_way'] = PayEnum::BALANCE_PAY;
 | ||
|                 if($params['from'] == 'recharge') {
 | ||
|                     unset($payway[$k]);
 | ||
|                 }
 | ||
|             }
 | ||
| 
 | ||
|             if ($item['code'] == 'alipay') {
 | ||
|                 $item['extra'] = '';
 | ||
|                 $item['pay_way'] = PayEnum::ALI_PAY;
 | ||
|                 if (in_array($client, [ClientEnum::mnp, ClientEnum::oa])) {
 | ||
|                     unset($payway[$k]);
 | ||
|                 }
 | ||
|             }
 | ||
|         }
 | ||
| 
 | ||
|         if($params['from'] == 'order') {
 | ||
|             $order = Order::findOrEmpty($params['order_id']);
 | ||
|         } else if($params['from'] == 'trade') {
 | ||
|             $order = OrderTrade::findOrEmpty($params['order_id']);
 | ||
|         } else if($params['from'] == 'integral') {
 | ||
|             $order = IntegralOrder::findOrEmpty($params['order_id']);
 | ||
|         } else {
 | ||
|             $order = RechargeOrder::findOrEmpty($params['order_id']);
 | ||
|         }
 | ||
|         $cancelTime = ConfigServer::get('transaction', 'unpaid_order_cancel_time', '');
 | ||
|         if(empty($cancelTime) || $params['from'] == 'integral') {
 | ||
|             $cancelTime = 0;
 | ||
|         } else {
 | ||
|             $cancelTime = strtotime($order['create_time']) + intval($cancelTime) * 60;
 | ||
|         }
 | ||
|         return [
 | ||
|             'pay_way' => $payway,
 | ||
|             'order_amount' => $order['order_amount'],
 | ||
|             'cancel_time' => $cancelTime,
 | ||
|         ];
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 查询物流
 | ||
|      * @param $id
 | ||
|      * @param $user_id
 | ||
|      * @return array|false
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @throws \think\exception\DbException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:23 下午
 | ||
|      */
 | ||
|     public static function orderTraces($id, $user_id)
 | ||
|     {
 | ||
| 
 | ||
|         $order = new Order();
 | ||
|         $order = $order->alias('o')
 | ||
|             ->join('order_goods og', 'o.id = og.order_id')
 | ||
|             ->join('goods g', 'g.id = og.goods_id')
 | ||
|             ->where(['o.id' => $id, 'o.user_id' => $user_id, 'pay_status' => OrderEnum::ORDER_STATUS_DELIVERY, 'o.del' => 0])
 | ||
|             ->field('o.id,order_status,total_num,og.image,o.consignee,o.mobile,o.province,o.city,o.district,o.address,pay_time,confirm_take_time,o.shipping_status,shipping_time')
 | ||
|             ->append(['delivery_address'])
 | ||
|             ->find();
 | ||
|         if (!self::checkDelivery($order['delivery_id'])) {
 | ||
|             return false;
 | ||
|         }
 | ||
|         //初始化数据
 | ||
|         $order_tips = '已下单';
 | ||
|         $order_traces = [];
 | ||
|         $traces = [];//物流轨迹
 | ||
|         $shipment = [//发货
 | ||
|             'title' => '已发货',
 | ||
|             'tips' => '',
 | ||
|             'time' => '',
 | ||
|         ];
 | ||
|         $finish = [//交易完成
 | ||
|             'title' => '交易完成',
 | ||
|             'tips' => '',
 | ||
|             'time' => '',
 | ||
|         ];
 | ||
| 
 | ||
|         if ($order) {
 | ||
|             $order_delivery = Delivery::where(['order_id' => $id])->field('invoice_no,shipping_name,shipping_id,mobile')->find();
 | ||
| 
 | ||
|             $express = ConfigServer::get('express', 'way', '', '');
 | ||
|             //已发货
 | ||
|             if ($express && $order['shipping_status']) {
 | ||
|                 $key = ConfigServer::get($express, 'appkey');
 | ||
|                 $app = ConfigServer::get($express, 'appsecret');
 | ||
|                 //获取物流配置
 | ||
|                 if ($app && $key) {
 | ||
|                     //快递配置设置为快递鸟时
 | ||
|                     if ($express === 'kdniao') {
 | ||
|                         $expressage = (new Kdniao($app, $key, Env::get('app.app_debug', 'true')));
 | ||
|                         $shipping_field = 'codebird';
 | ||
|                     } else {
 | ||
|                         $expressage = (new Kd100($app, $key, Env::get('app.app_debug', 'true')));
 | ||
|                         $shipping_field = 'code100';
 | ||
|                     }
 | ||
|                     //快递编码
 | ||
|                     $shipping_code = Db::name('express')->where(['id' => $order_delivery['shipping_id']])->value($shipping_field);
 | ||
|                     //获取物流轨迹
 | ||
|                     if ($shipping_code === 'SF' && $express === 'kdniao') {
 | ||
|                         $expressage->logistics($shipping_code, $order_delivery['invoice_no'], substr($order_delivery['mobile'],-4));
 | ||
|                     }else {
 | ||
|                         $expressage->logistics($shipping_code, $order_delivery['invoice_no']);
 | ||
|                     }
 | ||
|                     $traces = $expressage->logisticsFormat();
 | ||
|                     //获取不到物流轨迹时
 | ||
|                     if ($traces == false) {
 | ||
|                         $error = $expressage->getError();
 | ||
|                         $error = json_decode($error,true);
 | ||
|                         if ($express === 'kdniao') {
 | ||
|                             if($error['Success'] == false){
 | ||
|                                 $traces[] = [$error['Reason']];
 | ||
|                             }
 | ||
|                         } else {
 | ||
|                             if($error['result'] == false){
 | ||
|                                 $traces[] = [$error['message']];
 | ||
|                             }
 | ||
|                         }
 | ||
| 
 | ||
|                     } else {
 | ||
|                         foreach ($traces as &$item) {
 | ||
|                             $item = array_values(array_unique($item));
 | ||
|                         }
 | ||
|                     }
 | ||
| 
 | ||
|                 }
 | ||
|             }
 | ||
|             //待收货
 | ||
|             if ($order['order_status'] == 2) {
 | ||
|                 $shipment['tips'] = '商品已出库';
 | ||
|                 $shipment['time'] = date('Y-m-d H:i:s', $order['shipping_time']);
 | ||
|             }
 | ||
|             //确认收货
 | ||
|             if ($order['order_status'] == 3) {
 | ||
|                 $order_tips = '交易完成';
 | ||
|                 $finish['tips'] = '订单交易完成';
 | ||
|                 $finish['time'] = $order['confirm_take_time'] ? date('Y-m-d H:i:s', $order['confirm_take_time']) : $order['confirm_take_time'];
 | ||
|             }
 | ||
|             //数据合并
 | ||
|             $order_traces = [
 | ||
|                 'order' => [
 | ||
|                     'tips' => $order_tips,
 | ||
|                     'image' => UrlServer::getFileUrl($order['image']),
 | ||
|                     'count' => $order['total_num'],
 | ||
|                     'invoice_no' => $order_delivery['invoice_no'],
 | ||
|                     'shipping_name' => empty($order_delivery['shipping_name']) ? '-' : $order_delivery['shipping_name'],
 | ||
|                 ],
 | ||
|                 'take' => [
 | ||
|                     'contacts' => $order['consignee'],
 | ||
|                     'mobile' => $order['mobile'],
 | ||
|                     'address' => $order['delivery_address'],
 | ||
|                 ],
 | ||
|                 'finish' => $finish,
 | ||
|                 'delivery' => [
 | ||
|                     'title' => '运输中',
 | ||
|                     'traces' => $traces
 | ||
|                 ],
 | ||
|                 'shipment' => $shipment,
 | ||
|                 'buy' => [
 | ||
|                     'title' => '已下单',
 | ||
|                     'tips' => '订单提交成功',
 | ||
|                     'time' => date('Y-m-d H:i:s', $order['pay_time'])
 | ||
|                 ],
 | ||
|             ];
 | ||
|             return $order_traces;
 | ||
|         }
 | ||
| 
 | ||
|         return $order_traces;
 | ||
| 
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 配送方式无需快递的
 | ||
|      * @param $delivery_id
 | ||
|      * @return bool
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:23 下午
 | ||
|      */
 | ||
|     public static function checkDelivery($delivery_id)
 | ||
|     {
 | ||
| 
 | ||
|         $delivery = Delivery::where(['id' => $delivery_id])
 | ||
|             ->find();
 | ||
|         if ($delivery['send_type'] == 2) {
 | ||
|             return false;
 | ||
|         }
 | ||
|         return true;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 判断商家营业状态
 | ||
|      * @param $value
 | ||
|      * @return bool|string
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:23 下午
 | ||
|      */
 | ||
|     public static function checkShop($value)
 | ||
|     {
 | ||
|         $shop = Shop::where('id', $value['shop_id'])->field('is_run, is_pay')->findOrEmpty();
 | ||
|         if (!$shop['is_run']) {
 | ||
|             return '该商家已暂停营业';
 | ||
|         }
 | ||
| 
 | ||
|         if (!$shop['is_pay']) {
 | ||
|             return '该商家支付功能已关闭';
 | ||
|         }
 | ||
|         return true;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 修改优惠券状态
 | ||
|      * @param $coupon_id
 | ||
|      * @param $order_id
 | ||
|      * @return CouponList|false
 | ||
|      * @throws \think\db\exception\DataNotFoundException
 | ||
|      * @throws \think\db\exception\DbException
 | ||
|      * @throws \think\db\exception\ModelNotFoundException
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:23 下午
 | ||
|      */
 | ||
|     public static function editCoupon($coupon_id, $order_id)
 | ||
|     {
 | ||
| 
 | ||
|         $status = CouponList::where(['id' => $coupon_id, 'status' => 0])->find();
 | ||
|         if (!$status) {
 | ||
|             return false;
 | ||
|         }
 | ||
|         $time = time();
 | ||
|         $data = [
 | ||
|             'status' => 1,
 | ||
|             'use_time' => $time,
 | ||
|             'update_time' => $time,
 | ||
|             'order_id' => $order_id
 | ||
|         ];
 | ||
|         $res = CouponList::where('id', $status->id)
 | ||
|             ->update($data);
 | ||
|         return $res;
 | ||
|     }
 | ||
| 
 | ||
|     /**
 | ||
|      * @notes 设置秒杀商品销量
 | ||
|      * @param $item_id
 | ||
|      * @param $num
 | ||
|      * @return bool
 | ||
|      * @author suny
 | ||
|      * @date 2021/7/13 6:23 下午
 | ||
|      */
 | ||
|     public static function setSeckillSaleSum($item_id, $num)
 | ||
|     {
 | ||
| 
 | ||
|         $result = SeckillGoods::where('item_id', $item_id)
 | ||
|             ->inc('sales_sum', $num)
 | ||
|             ->save();
 | ||
|         if ($result) {
 | ||
|             return true;
 | ||
|         } else {
 | ||
|             return false;
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     public static function getPayStatus($id,$from)
 | ||
|     {
 | ||
| 
 | ||
|         switch ($from){
 | ||
|             case 'trade' : //如果是父订单类型下单,$id为父订单id
 | ||
|                 $order_trade = OrderTrade::alias('ot')
 | ||
|                     ->where(['ot.id' => $id])
 | ||
|                     ->join('order o','o.trade_id = ot.id')
 | ||
|                     ->field(['ot.id','o.id as order_id', 'ot.t_sn as order_sn', 'o.pay_time', 'o.pay_way', 'ot.total_amount','o.pay_status','o.order_status'])
 | ||
|                     ->select()
 | ||
|                     ->toArray();
 | ||
|                 foreach ($order_trade as $item) {
 | ||
|                     if($item['pay_time']){
 | ||
|                         $item['pay_time'] = date('Y-m-d H:i:s', $item['pay_time']);
 | ||
|                     }
 | ||
|                     $create_time = Db::name('order')->where(['id' => $item['order_id']])->value('create_time');
 | ||
|                     $unpaid_order_cancel_time = ConfigServer::get('transaction','unpaid_order_cancel_time','30');
 | ||
|                     $cancel_time = $create_time + $unpaid_order_cancel_time * 60;
 | ||
|                     $item['pay_status_text'] = PayEnum::getPayStatus($item['pay_status']);
 | ||
|                     $result = $item;
 | ||
|                     $goods_lists = Db::name('order_goods')
 | ||
|                         ->where(['order_id' => $item['order_id']])
 | ||
|                         ->field('id,goods_name')
 | ||
|                         ->order('shop_id desc')
 | ||
|                         ->select()
 | ||
|                         ->toArray();
 | ||
|                     foreach ($goods_lists as $goods_list) {
 | ||
|                         $order_goods[] = $goods_list;
 | ||
|                     }
 | ||
|                     $order = Order::where(['id' => $item['order_id']])
 | ||
|                         ->find()
 | ||
|                         ->append(['pc_address'])
 | ||
|                         ->toArray();
 | ||
|                     $contact = $order['consignee'];
 | ||
|                     $mobile = $order['mobile'];
 | ||
|                     $address = [
 | ||
|                         'contact' => $contact,
 | ||
|                         'mobile' => $mobile,
 | ||
|                         'delivery_address' => $order['pc_address'],
 | ||
|                     ];
 | ||
| 
 | ||
|                     $pay_way_text = PayEnum::getPayWay($item['pay_way']);
 | ||
|                     $result['pay_way'] = $pay_way_text;
 | ||
|                     $result['cancel_time'] = $cancel_time;
 | ||
|                 }
 | ||
|                 $result['order_goods'] = $order_goods;
 | ||
|                 $result['address'] = $address;
 | ||
|                 break;
 | ||
| 
 | ||
|             case 'order' : //如果是子订单类型下单,$id为子订单id
 | ||
|                 $result = Order::where(['id' => $id])
 | ||
|                     ->field(['id', 'order_sn', 'pay_time', 'pay_way', 'total_amount','consignee','mobile','province','city','district','address','pay_status','order_status'])
 | ||
|                     ->findOrEmpty()
 | ||
|                     ->append(['pc_address'])
 | ||
|                     ->toArray();
 | ||
|                 $create_time = Db::name('order')->where(['id' => $id])->value('create_time');
 | ||
|                 $unpaid_order_cancel_time = ConfigServer::get('transaction','unpaid_order_cancel_time','30');
 | ||
|                 $cancel_time = $create_time + $unpaid_order_cancel_time * 60;
 | ||
|                 $order_goods = Db::name('order_goods')
 | ||
|                     ->where(['order_id' => $result['id']])
 | ||
|                     ->field('id,goods_name')
 | ||
|                     ->order('shop_id desc')
 | ||
|                     ->select()
 | ||
|                     ->toArray();
 | ||
|                 $contact = $result['consignee'];
 | ||
|                 $mobile = $result['mobile'];
 | ||
|                 $address = [
 | ||
|                     'contact' => $contact,
 | ||
|                     'mobile' => $mobile,
 | ||
|                     'delivery_address' => $result['pc_address'],
 | ||
|                 ];
 | ||
|                 $result['order_goods'] = $order_goods;
 | ||
|                 $result['address'] = $address;
 | ||
|                 $result['cancel_time'] = $cancel_time;
 | ||
|                 if($result['pay_time']){
 | ||
|                     $result['pay_time'] = date('Y-m-d H:i:s', $result['pay_time']);
 | ||
|                 }
 | ||
|                 break;
 | ||
|             default :
 | ||
|                 return false;
 | ||
|         }
 | ||
|         return $result;
 | ||
|     }
 | ||
| }
 |