Jelajahi Sumber

Merge branch 'fixorder' into dev

joe 4 tahun lalu
induk
melakukan
667f9b0f15

+ 267 - 16
app/api/controller/order/StoreOrderController.php

@@ -15,6 +15,7 @@ use app\models\store\{
     StoreCouponIssue,
     StoreCouponIssue,
     StoreCouponUser,
     StoreCouponUser,
     StoreOrder,
     StoreOrder,
+    StoreOrderBatch,
     StoreOrderCartInfo,
     StoreOrderCartInfo,
     StoreOrderStatus,
     StoreOrderStatus,
     StorePink,
     StorePink,
@@ -50,8 +51,11 @@ class StoreOrderController
         // TODO: 运费模板只能选择 ID 为 1 的模板?
         // TODO: 运费模板只能选择 ID 为 1 的模板?
         $temp = ShippingTemplates::get(1);
         $temp = ShippingTemplates::get(1);
         if (!$temp) return app('json')->fail('默认模板未配置,无法下单');
         if (!$temp) return app('json')->fail('默认模板未配置,无法下单');
+
         list($cartId) = UtilService::postMore(['cartId'], $request, true);
         list($cartId) = UtilService::postMore(['cartId'], $request, true);
         if (!is_string($cartId) || !$cartId) return app('json')->fail('请提交购买的商品');
         if (!is_string($cartId) || !$cartId) return app('json')->fail('请提交购买的商品');
+
+        // 查询当前购物车有效的商品
         $uid = $request->uid();
         $uid = $request->uid();
         $cartGroup = StoreCart::getUserProductCartList($uid, $cartId, 1);
         $cartGroup = StoreCart::getUserProductCartList($uid, $cartId, 1);
         if (count($cartGroup['invalid'])) {
         if (count($cartGroup['invalid'])) {
@@ -60,15 +64,17 @@ class StoreOrderController
         if (!$cartGroup['valid']) {
         if (!$cartGroup['valid']) {
             return app('json')->fail('请提交购买的商品');
             return app('json')->fail('请提交购买的商品');
         }
         }
+        //
         $cartInfo = $cartGroup['valid'];
         $cartInfo = $cartGroup['valid'];
         $addr = UserAddress::getUserDefaultAddress($uid); //UserAddress::where('uid', $uid)->where('is_default', 1)->find();
         $addr = UserAddress::getUserDefaultAddress($uid); //UserAddress::where('uid', $uid)->where('is_default', 1)->find();
+        // 获取当前购物车中各项价格
         $priceGroup = StoreOrder::getOrderPriceGroup($cartInfo, $addr);
         $priceGroup = StoreOrder::getOrderPriceGroup($cartInfo, $addr);
         if ($priceGroup === false) {
         if ($priceGroup === false) {
             return app('json')->fail(StoreOrder::getErrorInfo('运费模板不存在'));
             return app('json')->fail(StoreOrder::getErrorInfo('运费模板不存在'));
         }
         }
         $other = [
         $other = [
-            'offlinePostage' => sys_config('offline_postage'),
-            'integralRatio' => sys_config('integral_ratio')
+            'offlinePostage' => sys_config('offline_postage'),  // 线下支付是否包邮
+            'integralRatio' => sys_config('integral_ratio')     // 积分抵用比例
         ];
         ];
         $usableCoupons = []; // TIP 屏蔽优惠券 StoreCouponUser::getUsableCouponList($uid, $cartGroup, $priceGroup['totalPrice']);
         $usableCoupons = []; // TIP 屏蔽优惠券 StoreCouponUser::getUsableCouponList($uid, $cartGroup, $priceGroup['totalPrice']);
         $usableCoupon = isset($usableCoupons[0]) ? $usableCoupons[0] : null;
         $usableCoupon = isset($usableCoupons[0]) ? $usableCoupons[0] : null;
@@ -103,7 +109,7 @@ class StoreOrderController
         }
         }
         $data['userInfo'] = $user;
         $data['userInfo'] = $user;
         $data['integralRatio'] = $other['integralRatio'];
         $data['integralRatio'] = $other['integralRatio'];
-        $data['offline_pay_status'] = (int)sys_config('offline_pay_status') ?? (int)2;
+        $data['offline_pay_status'] = (int)sys_config('offline_pay_status') ?? (int)2;  // 线下支付
         $data['store_self_mention'] = (int)sys_config('store_self_mention') ?? 0;//门店自提是否开启
         $data['store_self_mention'] = (int)sys_config('store_self_mention') ?? 0;//门店自提是否开启
         $data['system_store'] = []; // TIP: 屏蔽门店信息 ($res = SystemStore::getStoreDispose()) ? $res : [];//门店信息
         $data['system_store'] = []; // TIP: 屏蔽门店信息 ($res = SystemStore::getStoreDispose()) ? $res : [];//门店信息
         return app('json')->successful($data);
         return app('json')->successful($data);
@@ -121,9 +127,9 @@ class StoreOrderController
      */
      */
     public function computedOrder(Request $request, $key)
     public function computedOrder(Request $request, $key)
     {
     {
-
-//        $priceGroup = StoreOrder::getOrderPriceGroup($cartInfo);
+        // $key 就是 confirm 返回的 orderKey
         if (!$key) return app('json')->fail('参数错误!');
         if (!$key) return app('json')->fail('参数错误!');
+        // 是否已存在
         $uid = $request->uid();
         $uid = $request->uid();
         if (StoreOrder::be(['order_id|unique' => $key, 'uid' => $uid, 'is_del' => 0]))
         if (StoreOrder::be(['order_id|unique' => $key, 'uid' => $uid, 'is_del' => 0]))
             return app('json')->status('extend_order', '订单已生成', ['orderId' => $key, 'key' => $key]);
             return app('json')->status('extend_order', '订单已生成', ['orderId' => $key, 'key' => $key]);
@@ -141,6 +147,7 @@ class StoreOrderController
             ['bargainId', ''],
             ['bargainId', ''],
             ['shipping_type', 1],
             ['shipping_type', 1],
         ], $request, true);
         ], $request, true);
+        // weixin / yue
         $payType = strtolower($payType);
         $payType = strtolower($payType);
         if ($bargainId) {
         if ($bargainId) {
             $bargainUserTableId = StoreBargainUser::getBargainUserTableId($bargainId, $uid);//TODO 获取用户参与砍价表编号
             $bargainUserTableId = StoreBargainUser::getBargainUserTableId($bargainId, $uid);//TODO 获取用户参与砍价表编号
@@ -161,7 +168,8 @@ class StoreOrderController
             if (StoreOrder::getIsOrderPink($pinkId, $request->uid()))
             if (StoreOrder::getIsOrderPink($pinkId, $request->uid()))
                 return app('json')->status('ORDER_EXIST', '订单生成失败,你已经参加该团了,请先支付订单', ['orderId' => StoreOrder::getStoreIdPink($pinkId, $request->uid())]);
                 return app('json')->status('ORDER_EXIST', '订单生成失败,你已经参加该团了,请先支付订单', ['orderId' => StoreOrder::getStoreIdPink($pinkId, $request->uid())]);
         }
         }
-        $priceGroup = StoreOrder::cacheKeyCreateOrder($request->uid(), $key, $addressId, $payType, (int)$useIntegral, $couponId, $mark, $combinationId, $pinkId, $seckill_id, $bargainId, true, 0, $shipping_type);
+        $priceGroup = StoreOrder::cacheKeyCreateOrder($request->uid(), $key, $addressId, $payType, (int)$useIntegral, 
+            $couponId, $mark, $combinationId, $pinkId, $seckill_id, $bargainId, true, 0, $shipping_type);
         // return app('json')->fail(StoreOrder::getErrorInfo('计算失败'));
         // return app('json')->fail(StoreOrder::getErrorInfo('计算失败'));
         if ($priceGroup)
         if ($priceGroup)
             return app('json')->status('NONE', 'ok', $priceGroup);
             return app('json')->status('NONE', 'ok', $priceGroup);
@@ -181,14 +189,24 @@ class StoreOrderController
      */
      */
     public function create(Request $request, $key)
     public function create(Request $request, $key)
     {
     {
+        // 还是那个 $orderKey
         if (!$key) return app('json')->fail('参数错误!');
         if (!$key) return app('json')->fail('参数错误!');
+        // 订单是否已存在
         $uid = $request->uid();
         $uid = $request->uid();
         if (StoreOrder::be(['order_id|unique' => $key, 'uid' => $uid, 'is_del' => 0]))
         if (StoreOrder::be(['order_id|unique' => $key, 'uid' => $uid, 'is_del' => 0]))
             return app('json')->status('extend_order', '订单已生成', ['orderId' => $key, 'key' => $key]);
             return app('json')->status('extend_order', '订单已生成', ['orderId' => $key, 'key' => $key]);
+        // 获得参数
         list($addressId, $couponId, $payType, $useIntegral, $mark, $combinationId, $pinkId, $seckill_id, $formId, $bargainId, $from, $shipping_type, $real_name, $phone, $storeId) = UtilService::postMore([
         list($addressId, $couponId, $payType, $useIntegral, $mark, $combinationId, $pinkId, $seckill_id, $formId, $bargainId, $from, $shipping_type, $real_name, $phone, $storeId) = UtilService::postMore([
-            'addressId', 'couponId', 'payType', ['useIntegral', 0], 'mark', ['combinationId', 0], ['pinkId', 0], ['seckill_id', 0], ['formId', ''], ['bargainId', ''], ['from', 'weixin'],
+            'addressId', 
+            'couponId', 
+            'payType', 
+            ['useIntegral', 0], 
+            'mark', 
+            ['combinationId', 0], ['pinkId', 0], ['seckill_id', 0], ['formId', ''], ['bargainId', ''], 
+            ['from', 'weixin'],
             ['shipping_type', 1], ['real_name', ''], ['phone', ''], ['store_id', 0]
             ['shipping_type', 1], ['real_name', ''], ['phone', ''], ['store_id', 0]
         ], $request, true);
         ], $request, true);
+        // weixin / yue
         $payType = strtolower($payType);
         $payType = strtolower($payType);
         if ($bargainId) {
         if ($bargainId) {
             $bargainUserTableId = StoreBargainUser::getBargainUserTableId($bargainId, $uid);//TODO 获取用户参与砍价表编号
             $bargainUserTableId = StoreBargainUser::getBargainUserTableId($bargainId, $uid);//TODO 获取用户参与砍价表编号
@@ -209,18 +227,22 @@ class StoreOrderController
             if (StoreOrder::getIsOrderPink($pinkId, $request->uid()))
             if (StoreOrder::getIsOrderPink($pinkId, $request->uid()))
                 return app('json')->status('ORDER_EXIST', '订单生成失败,你已经参加该团了,请先支付订单', ['orderId' => StoreOrder::getStoreIdPink($pinkId, $request->uid())]);
                 return app('json')->status('ORDER_EXIST', '订单生成失败,你已经参加该团了,请先支付订单', ['orderId' => StoreOrder::getStoreIdPink($pinkId, $request->uid())]);
         }
         }
-        $isChannel = 1;
+        $isChannel = 1;         // 'routine'
         if ($from == 'weixin')
         if ($from == 'weixin')
             $isChannel = 0;
             $isChannel = 0;
         elseif ($from == 'weixinh5')
         elseif ($from == 'weixinh5')
             $isChannel = 2;
             $isChannel = 2;
-        $order = StoreOrder::cacheKeyCreateOrder($request->uid(), $key, $addressId, $payType, (int)$useIntegral, $couponId, $mark, $combinationId, $pinkId, $seckill_id, $bargainId, false, $isChannel, $shipping_type, $real_name, $phone, $storeId);
-        if ($order === false) return app('json')->fail(StoreOrder::getErrorInfo('订单生成失败'));
+        $order = StoreOrder::cacheKeyCreateOrder($request->uid(), $key, $addressId, $payType, (int)$useIntegral, 
+            $couponId, $mark, $combinationId, $pinkId, $seckill_id, $bargainId, false, $isChannel, 
+            $shipping_type, $real_name, $phone, $storeId);
+        if ($order === false) {
+            return app('json')->fail(StoreOrder::getErrorInfo('订单生成失败'));
+        }
         $orderId = $order['order_id'];
         $orderId = $order['order_id'];
         $info = compact('orderId', 'key');
         $info = compact('orderId', 'key');
         if ($orderId) {
         if ($orderId) {
             event('OrderCreated', [$order]); //订单创建成功事件
             event('OrderCreated', [$order]); //订单创建成功事件
-//            event('ShortMssageSend', [$orderId, 'AdminPlaceAnOrder']);//发送管理员通知
+            // event('ShortMssageSend', [$orderId, 'AdminPlaceAnOrder']);//发送管理员通知
             switch ($payType) {
             switch ($payType) {
                 case "weixin":
                 case "weixin":
                     $orderInfo = StoreOrder::where('order_id', $orderId)->find();
                     $orderInfo = StoreOrder::where('order_id', $orderId)->find();
@@ -270,7 +292,195 @@ class StoreOrderController
                     return app('json')->status('success', '订单创建成功', $info);
                     return app('json')->status('success', '订单创建成功', $info);
                     break;
                     break;
             }
             }
-        } else return app('json')->fail(StoreOrder::getErrorInfo('订单生成失败!'));
+        } else { // !$orderId
+            return app('json')->fail(StoreOrder::getErrorInfo('订单生成失败!'));
+        }
+    }
+
+        /**
+     * 计算订单金额
+     * @param Request $request
+     * @param $key
+     * @return mixed
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function computedOrder_v2(Request $request, $key)
+    {
+        // $key 就是 confirm 返回的 orderKey
+        if (!$key) return app('json')->fail('参数错误!');
+        // 是否已存在
+        $uid = $request->uid();
+        if (StoreOrderBatch::be(['unique' => $key, 'uid' => $uid]))
+            return app('json')->status('extend_order', '订单已生成', ['orderId' => $key, 'key' => $key]);
+        list($addressId, $couponId, $payType, $useIntegral, $mark, 
+            $combinationId, $pinkId, $seckill_id, $formId, $bargainId, $shipping_type) = UtilService::postMore([
+            'addressId', 
+            'couponId', 
+            ['payType', 'yue'], 
+            ['useIntegral', 0], 
+            'mark', 
+            ['combinationId', 0], 
+            ['pinkId', 0], 
+            ['seckill_id', 0], 
+            ['formId', ''], 
+            ['bargainId', ''],
+            ['shipping_type', 1],
+        ], $request, true);
+        // weixin / yue
+        $payType = strtolower($payType);
+        if ($bargainId) {
+            $bargainUserTableId = StoreBargainUser::getBargainUserTableId($bargainId, $uid);//TODO 获取用户参与砍价表编号
+            if (!$bargainUserTableId)
+                return app('json')->fail('砍价失败');
+            $status = StoreBargainUser::getBargainUserStatusEnd($bargainUserTableId);
+            if ($status == 3)
+                return app('json')->fail('砍价已支付');
+            StoreBargainUser::setBargainUserStatus($bargainId, $uid); //修改砍价状态
+        }
+        if ($pinkId) {
+            $cache_pink = Cache::get(md5('store_pink_' . $pinkId));
+            if ($cache_pink && bcsub($cache_pink['people'], $cache_pink['now_people'], 0) <= 0) {
+                return app('json')->status('ORDER_EXIST', '订单生成失败,该团人员已满', ['orderId' => StoreOrder::getStoreIdPink($pinkId, $request->uid())]);
+            }
+            if (StorePink::getIsPinkUid($pinkId, $request->uid()))
+                return app('json')->status('ORDER_EXIST', '订单生成失败,你已经在该团内不能再参加了', ['orderId' => StoreOrder::getStoreIdPink($pinkId, $request->uid())]);
+            if (StoreOrder::getIsOrderPink($pinkId, $request->uid()))
+                return app('json')->status('ORDER_EXIST', '订单生成失败,你已经参加该团了,请先支付订单', ['orderId' => StoreOrder::getStoreIdPink($pinkId, $request->uid())]);
+        }
+        $priceGroup = StoreOrderBatch::cacheKeyCreateOrderBatch($request->uid(), $key, $addressId, $payType, (int)$useIntegral, 
+            $couponId, $mark, $combinationId, $pinkId, $seckill_id, $bargainId, true, 0, $shipping_type);
+        // return app('json')->fail(StoreOrder::getErrorInfo('计算失败'));
+        if ($priceGroup)
+            return app('json')->status('NONE', 'ok', $priceGroup);
+        else
+            return app('json')->fail(StoreOrder::getErrorInfo('计算失败'));
+    }
+
+    /**
+     * 订单创建, 支持子订单版本
+     * @param Request $request
+     * @param $key
+     * @return mixed
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public function create_v2(Request $request, $key)
+    {
+        // 还是那个 $orderKey
+        if (!$key) {
+            return app('json')->fail('参数错误!');
+        }
+        // 订单是否已存在
+        $uid = $request->uid();
+        if (StoreOrderBatch::be(['unique' => $key, 'uid' => $uid]))
+            return app('json')->status('extend_order', '订单已生成', ['orderId' => $key, 'key' => $key]);
+        // 获得参数
+        list($addressId, $couponId, $payType, $useIntegral, $mark, $combinationId, $pinkId, $seckill_id, $formId, $bargainId, $from, $shipping_type, $real_name, $phone, $storeId) = UtilService::postMore([
+            'addressId', 
+            'couponId', 
+            'payType', 
+            ['useIntegral', 0], 
+            'mark', 
+            ['combinationId', 0], ['pinkId', 0], ['seckill_id', 0], ['formId', ''], ['bargainId', ''], 
+            ['from', 'weixin'],
+            ['shipping_type', 1], ['real_name', ''], ['phone', ''], ['store_id', 0]
+        ], $request, true);
+        // weixin / yue
+        $payType = strtolower($payType);
+        if ($bargainId) {
+            $bargainUserTableId = StoreBargainUser::getBargainUserTableId($bargainId, $uid);//TODO 获取用户参与砍价表编号
+            if (!$bargainUserTableId)
+                return app('json')->fail('砍价失败');
+            $status = StoreBargainUser::getBargainUserStatusEnd($bargainUserTableId);
+            if ($status == 3)
+                return app('json')->fail('砍价已支付');
+            StoreBargainUser::setBargainUserStatus($bargainId, $uid); //修改砍价状态
+        }
+        if ($pinkId) {
+            $cache_pink = Cache::get(md5('store_pink_' . $pinkId));
+            if ($cache_pink && bcsub($cache_pink['people'], $cache_pink['now_people'], 0) <= 0) {
+                return app('json')->status('ORDER_EXIST', '订单生成失败,该团人员已满', ['orderId' => StoreOrder::getStoreIdPink($pinkId, $request->uid())]);
+            }
+            if (StorePink::getIsPinkUid($pinkId, $request->uid()))
+                return app('json')->status('ORDER_EXIST', '订单生成失败,你已经在该团内不能再参加了', ['orderId' => StoreOrder::getStoreIdPink($pinkId, $request->uid())]);
+            if (StoreOrder::getIsOrderPink($pinkId, $request->uid()))
+                return app('json')->status('ORDER_EXIST', '订单生成失败,你已经参加该团了,请先支付订单', ['orderId' => StoreOrder::getStoreIdPink($pinkId, $request->uid())]);
+        }
+        $isChannel = 1;         // 'routine'
+        if ($from == 'weixin')
+            $isChannel = 0;
+        elseif ($from == 'weixinh5')
+            $isChannel = 2;
+        $porderId = StoreOrderBatch::cacheKeyCreateOrderBatch($request->uid(), $key, $addressId, $payType, (int)$useIntegral, 
+            $couponId, $mark, $combinationId, $pinkId, $seckill_id, $bargainId, false, $isChannel, 
+            $shipping_type, $real_name, $phone, $storeId);
+        if ($porderId === false) {
+            return app('json')->fail(StoreOrderBatch::getErrorInfo('订单生成失败'));
+        }
+        $orderId = $porderId;       // for compact
+        $info = compact('orderId', 'key');
+        if ($porderId) {
+            event('BatchOrderCreated', [$porderId]); //订单创建成功事件
+            // event('ShortMssageSend', [$orderId, 'AdminPlaceAnOrder']);//发送管理员通知
+            switch ($payType) {
+                case "weixin":
+                    $subOrders = StoreOrderBatch::getAllSubOrders($porderId);
+                    if (!$subOrders) return app('json')->fail('支付订单不存在!');
+                    $fieldValues = StoreOrderBatch::sumFields($subOrders, ['paid','pay_price']);
+                    if ($fieldValues['paid']) {
+                        return app('json')->fail('支付已支付!');
+                    }
+                    //支付金额为0
+                    if (bcsub($fieldValues['pay_price'], 0, 2) <= 0) {
+                        //创建订单jspay支付
+                        $payPriceStatus = StoreOrderBatch::jsPayPriceBatch($porderId, $uid, $formId);
+                        if ($payPriceStatus)//0元支付成功
+                            return app('json')->status('success', '微信支付成功', $info);
+                        else
+                            return app('json')->status('pay_error', StoreOrderBatch::getErrorInfo());
+                    } else {
+                        try {
+                            if ($from == 'routine') {
+                                $jsConfig = OrderRepository::jsPayBatch($porderId); //创建订单jspay
+                            } else if ($from == 'weixinh5') {
+                                $jsConfig = OrderRepository::h5PayBatch($porderId);
+                            } else {
+                                $jsConfig = OrderRepository::wxPayBatch($porderId);
+                            }
+                        } catch (\Exception $e) {
+                            return app('json')->status('pay_error', $e->getMessage(), $info);
+                        }
+                        $info['jsConfig'] = $jsConfig;
+                        if ($from == 'weixinh5') {
+                            return app('json')->status('wechat_h5_pay', '订单创建成功', $info);
+                        } else {
+                            return app('json')->status('wechat_pay', '订单创建成功', $info);
+                        }
+                    }
+                    break;
+                case 'yue':
+                    if (StoreOrderBatch::yuePayBatch($porderId, $request->uid(), $formId))
+                        return app('json')->status('success', '余额支付成功', $info);
+                    else {
+                        $errorinfo = StoreOrderBatch::getErrorInfo();
+                        if (is_array($errorinfo))
+                            return app('json')->status($errorinfo['status'], $errorinfo['msg'], $info);
+                        else
+                            return app('json')->status('pay_error', $errorinfo);
+                    }
+                    break;
+                case 'offline':
+                    return app('json')->status('success', '订单创建成功', $info);
+                    break;
+            }
+        } else { // !$orderId
+            return app('json')->fail(StoreOrderBatch::getErrorInfo('订单生成失败!'));
+        }
     }
     }
 
 
     /**
     /**
@@ -396,6 +606,37 @@ class StoreOrderController
         return app('json')->successful(StoreOrder::getUserOrderSearchList($request->uid(), $type, $page, $limit, $search));
         return app('json')->successful(StoreOrder::getUserOrderSearchList($request->uid(), $type, $page, $limit, $search));
     }
     }
 
 
+    /**
+     * 订单详情 v2 
+     * 订单支持子订单之后,订单详情协议传过来的 $uni 有可能是子订单的,也有可能是主订单的
+     */
+    public function detail_v2(Request $request, $uni)
+    {
+        if (!strlen(trim($uni))) return app('json')->fail('参数错误');
+        $uid = $request->uid();
+        $first4 = mb_substr($uni, 0, 4);
+        if ($first4 == 'wxcn') {
+            $porder = StoreOrderBatch::where('porder_id', $uni)->where('uid', $uid)->find();
+            if (!$porder) {
+                return app('json')->fail('订单不存在');
+            }
+            $porder = $porder->toArray();
+            $subOrders = StoreOrderBatch::getAllSubOrders($porder['porder_id']);
+            if (!$subOrders) {
+                return app('json')->fail('订单不存在');
+            }
+            $order = $this->__get_order_details($uid, $subOrders[0]['order_id']);
+            if (!$order) {
+                return app('json')->fail('订单不存在');
+            }
+            $order['order_id'] = $porder['porder_id'];
+            $order['pay_price'] = $porder['total_price'];
+            return app('json')->successful('ok', $order);
+        } else {
+            return $this->detail($request, $uni);
+        }
+    }
+
     /**
     /**
      * 订单详情
      * 订单详情
      * @param Request $request
      * @param Request $request
@@ -404,9 +645,19 @@ class StoreOrderController
      */
      */
     public function detail(Request $request, $uni)
     public function detail(Request $request, $uni)
     {
     {
-        if (!strlen(trim($uni))) return app('json')->fail('参数错误');
-        $order = StoreOrder::getUserOrderDetail($request->uid(), $uni);
-        if (!$order) return app('json')->fail('订单不存在');
+        $order = $this->__get_order_details($request->uid(), $uni);
+        if (!$order) {
+            return app('json')->fail('订单不存在');
+        }
+        return app('json')->successful('ok', $order);
+    }
+
+    public function __get_order_details($uid, $uni)
+    {
+        $order = StoreOrder::getUserOrderDetail($uid, $uni);
+        if (!$order) {
+            return false;
+        }
         $order = $order->toArray();
         $order = $order->toArray();
         //是否开启门店自提
         //是否开启门店自提
         $store_self_mention = sys_config('store_self_mention');
         $store_self_mention = sys_config('store_self_mention');
@@ -438,7 +689,7 @@ class StoreOrderController
             $order['code'] = $url;
             $order['code'] = $url;
         }
         }
         $order['mapKey'] = sys_config('tengxun_map_key');
         $order['mapKey'] = sys_config('tengxun_map_key');
-        return app('json')->successful('ok', StoreOrder::tidyOrder($order, true, true));
+        return StoreOrder::tidyOrder($order, true, true);
     }
     }
 
 
     /**
     /**

+ 7 - 3
app/models/store/StoreCart.php

@@ -135,7 +135,7 @@ class StoreCart extends BaseModel
      * 
      * 
      * @uid
      * @uid
      * @cartIds: string
      * @cartIds: string
-     * @status: 1/0 是否为立即购买
+     * @status: 1/0 是否为立即购买, 如果传入1,则不过滤 is_new 字段
      */
      */
     public static function getUserProductCartList($uid, $cartIds = '', $status = 0)
     public static function getUserProductCartList($uid, $cartIds = '', $status = 0)
     {
     {
@@ -155,9 +155,11 @@ class StoreCart extends BaseModel
         $model = $model->order('c.add_time DESC');
         $model = $model->order('c.add_time DESC');
         $list = $model->select()->toArray();
         $list = $model->select()->toArray();
         if (!count($list)) return compact('valid', 'invalid');
         if (!count($list)) return compact('valid', 'invalid');
+
         $now = time();
         $now = time();
         // TODO: for 里调 sql
         // TODO: for 里调 sql
         foreach ($list as $k => $cart) {
         foreach ($list as $k => $cart) {
+            // 根据购物车中每一件商品ID 找到商品信息
             if ($cart['seckill_id']) {
             if ($cart['seckill_id']) {
                 $product = StoreSeckill::field($seckillInfoField)
                 $product = StoreSeckill::field($seckillInfoField)
                     ->find($cart['seckill_id'])->toArray();
                     ->find($cart['seckill_id'])->toArray();
@@ -210,7 +212,8 @@ class StoreCart extends BaseModel
                     }
                     }
 
 
                 }
                 }
-                if ($cart['product_attr_unique']) {
+                if ($cart['product_attr_unique']) { // 大部分走这个分支
+                    // 从 product_attr_value 表中根据 unique 找到 sku 详情
                     $attrInfo = StoreProductAttr::uniqueByAttrInfo($cart['product_attr_unique']);
                     $attrInfo = StoreProductAttr::uniqueByAttrInfo($cart['product_attr_unique']);
                     //商品没有对应的属性
                     //商品没有对应的属性
                     if (!$attrInfo || !$attrInfo['stock'])
                     if (!$attrInfo || !$attrInfo['stock'])
@@ -251,7 +254,8 @@ class StoreCart extends BaseModel
                     $valid[] = $cart;
                     $valid[] = $cart;
                 }
                 }
             }
             }
-        }
+        } // foreach
+
         // TODO: for 里 sql
         // TODO: for 里 sql
         foreach ($valid as $k => $cart) {
         foreach ($valid as $k => $cart) {
             if ($cart['trueStock'] < $cart['cart_num']) {
             if ($cart['trueStock'] < $cart['cart_num']) {

+ 17 - 10
app/models/store/StoreOrder.php

@@ -50,7 +50,7 @@ class StoreOrder extends BaseModel
 
 
     protected $insert = ['add_time'];
     protected $insert = ['add_time'];
 
 
-    protected static $payType = ['weixin' => '微信支付', 'yue' => '余额支付', 'offline' => '线下支付'];
+    public static $payType = ['weixin' => '微信支付', 'yue' => '余额支付', 'offline' => '线下支付'];
 
 
     protected static $deliveryType = ['send' => '商家配送', 'express' => '快递配送'];
     protected static $deliveryType = ['send' => '商家配送', 'express' => '快递配送'];
 
 
@@ -208,13 +208,14 @@ class StoreOrder extends BaseModel
     }
     }
 
 
     /**
     /**
-     * 缓存订单信息
+     * 缓存大订单信息
+     * 
      * @param $uid
      * @param $uid
      * @param $cartInfo
      * @param $cartInfo
      * @param $priceGroup
      * @param $priceGroup
      * @param array $other
      * @param array $other
      * @param int $cacheTime
      * @param int $cacheTime
-     * @return string
+     * @return string 
      * @throws \Psr\SimpleCache\InvalidArgumentException
      * @throws \Psr\SimpleCache\InvalidArgumentException
      */
      */
     public static function cacheOrderInfo($uid, $cartInfo, $priceGroup, $other = [], $cacheTime = 600)
     public static function cacheOrderInfo($uid, $cartInfo, $priceGroup, $other = [], $cacheTime = 600)
@@ -251,21 +252,22 @@ class StoreOrder extends BaseModel
     /**
     /**
      * 生成订单
      * 生成订单
      * @param $uid
      * @param $uid
-     * @param $key
+     * @param $key      orderKey 由客户端传入
      * @param $addressId
      * @param $addressId
-     * @param $payType
-     * @param bool $useIntegral
+     * @param $payType  weixin / yue
+     * @param bool $useIntegral: 是否使用积分
      * @param int $couponId
      * @param int $couponId
-     * @param string $mark
+     * @param string $mark: 订单留言
      * @param int $combinationId
      * @param int $combinationId
      * @param int $pinkId
      * @param int $pinkId
      * @param int $seckill_id
      * @param int $seckill_id
      * @param int $bargain_id
      * @param int $bargain_id
      * @param bool $test
      * @param bool $test
-     * @param int $isChannel
+     * @param int $isChannel 0, 1, 2 : routine, weixin, weixinh5
      * @param int $shipping_type
      * @param int $shipping_type
      * @param string $real_name
      * @param string $real_name
      * @param string $phone
      * @param string $phone
+     * @param int $storeId: 门店ID
      * @return StoreOrder|bool|\think\Model
      * @return StoreOrder|bool|\think\Model
      * @throws \think\Exception
      * @throws \think\Exception
      * @throws \think\db\exception\DataNotFoundException
      * @throws \think\db\exception\DataNotFoundException
@@ -273,7 +275,9 @@ class StoreOrder extends BaseModel
      * @throws \think\exception\DbException
      * @throws \think\exception\DbException
      */
      */
 
 
-    public static function cacheKeyCreateOrder($uid, $key, $addressId, $payType, $useIntegral = false, $couponId = 0, $mark = '', $combinationId = 0, $pinkId = 0, $seckill_id = 0, $bargain_id = 0, $test = false, $isChannel = 0, $shipping_type = 1, $real_name = '', $phone = '', $storeId = 0)
+    public static function cacheKeyCreateOrder($uid, $key, $addressId, $payType, $useIntegral = false, $couponId = 0, 
+        $mark = '', $combinationId = 0, $pinkId = 0, $seckill_id = 0, $bargain_id = 0, $test = false, $isChannel = 0, 
+        $shipping_type = 1, $real_name = '', $phone = '', $storeId = 0)
     {
     {
         self::beginTrans();
         self::beginTrans();
         try {
         try {
@@ -282,14 +286,17 @@ class StoreOrder extends BaseModel
             if ($offlinePayStatus == 2) unset(self::$payType['offline']);
             if ($offlinePayStatus == 2) unset(self::$payType['offline']);
             if (!array_key_exists($payType, self::$payType)) return self::setErrorInfo('选择支付方式有误!', true);
             if (!array_key_exists($payType, self::$payType)) return self::setErrorInfo('选择支付方式有误!', true);
             if (self::be(['unique' => $key, 'uid' => $uid])) return self::setErrorInfo('请勿重复提交订单', true);
             if (self::be(['unique' => $key, 'uid' => $uid])) return self::setErrorInfo('请勿重复提交订单', true);
+            // 用户
             $userInfo = User::getUserInfo($uid);
             $userInfo = User::getUserInfo($uid);
             if (!$userInfo) return self::setErrorInfo('用户不存在!', true);
             if (!$userInfo) return self::setErrorInfo('用户不存在!', true);
+            // 取订单缓存
             $cartGroup = self::getCacheOrderInfo($uid, $key);
             $cartGroup = self::getCacheOrderInfo($uid, $key);
             if (!$cartGroup) return self::setErrorInfo('订单已过期,请刷新当前页面!', true);
             if (!$cartGroup) return self::setErrorInfo('订单已过期,请刷新当前页面!', true);
             $cartInfo = $cartGroup['cartInfo'];
             $cartInfo = $cartGroup['cartInfo'];
             $priceGroup = $cartGroup['priceGroup'];
             $priceGroup = $cartGroup['priceGroup'];
             $other = $cartGroup['other'];
             $other = $cartGroup['other'];
             $payPrice = (float)$priceGroup['totalPrice'];
             $payPrice = (float)$priceGroup['totalPrice'];
+            // 收货地址
             $addr = UserAddress::where('uid', $uid)->where('id', $addressId)->find();
             $addr = UserAddress::where('uid', $uid)->where('id', $addressId)->find();
             if ($payType == 'offline' && sys_config('offline_postage') == 1) {
             if ($payType == 'offline' && sys_config('offline_postage') == 1) {
                 $payPostage = 0;
                 $payPostage = 0;
@@ -1449,7 +1456,7 @@ class StoreOrder extends BaseModel
             if (!$res) throw new \Exception('更新错误');
             if (!$res) throw new \Exception('更新错误');
             unset($orderList, $res, $pages);
             unset($orderList, $res, $pages);
             return null;
             return null;
-        } catch (PDOException $e) {
+        } catch (\PDOException $e) {
             Log::error('未支付自动取消时发生数据库查询错误,错误原因为:' . $e->getMessage());
             Log::error('未支付自动取消时发生数据库查询错误,错误原因为:' . $e->getMessage());
             throw new \Exception($e->getMessage());
             throw new \Exception($e->getMessage());
         } catch (\think\Exception $e) {
         } catch (\think\Exception $e) {

+ 593 - 0
app/models/store/StoreOrderBatch.php

@@ -0,0 +1,593 @@
+<?php
+/**
+ *
+ * @author: xaboy<365615158@qq.com>
+ * @day: 2017/12/20
+ */
+
+namespace app\models\store;
+
+use crmeb\basic\BaseModel;
+use think\facade\Cache;
+use crmeb\traits\ModelTrait;
+use app\models\system\SystemStore;
+use app\models\user\{
+    User, UserAddress, UserBill, WechatUser
+};
+use crmeb\repositories\{
+    GoodsRepository, PaymentRepositories, OrderRepository, ShortLetterRepositories, UserRepository
+};
+use EasyWeChat\Store\Store;
+
+/**
+ *  正常情況, 一次性下單購物車中多個商品,只產生一個訂單。 支付,積分,發貨,退貨,等等都是基於這一個訂單操作。
+ * 一個明顯的問題是:當此訂單中多個商品不能在一個快遞中發貨時,訂單就變得不易管理
+ * 
+ *  這個類的目的就是。已最小的侵入性來實現:一個訂單中包含多個商品時,自動按照一定的邏輯把這個訂單拆分爲若幹個訂單
+ * 每個訂單中的商品可在同一個快遞中發貨。
+ * 
+ *  有點類似一個電商平臺多個商家的情況,肯定是各個商家派發購物車中屬於自己家的商品。
+ * 
+ *  實現:
+ * 
+ *  單獨建一個表,此表只記錄一個大訂單號(用於支付接口傳遞訂單參數)和關聯的所有子訂單
+ *  支付接口按大訂單號走,發貨等訂單管理按子訂單走。
+ *  這樣有一個問題:子訂單退貨沒法執行三方支付退款(暫定)
+ */
+class StoreOrderBatch extends BaseModel {
+    /**
+     * 数据表主键
+     * @var string
+     */
+    protected $pk = 'id';
+
+    /**
+     * 模型名称
+     * @var string
+     */
+    protected $name = 'store_order_batch';
+
+    use ModelTrait;
+
+    /**
+     * 获取订单各项金额
+     * 
+     */
+    public static function getOrderPriceGroup($cartInfo, $addr)
+    {
+        return StoreOrder::getOrderPriceGroup($cartInfo, $addr);
+    }
+
+    /**
+     * 缓存订单信息
+     * @param $uid
+     * @param $cartInfo
+     * @param $priceGroup
+     * @param array $other
+     * @param int $cacheTime
+     * @return string 总订单ID
+     * @throws \Psr\SimpleCache\InvalidArgumentException
+     */
+    public static function cacheOrderInfo($uid, $cartInfo, $priceGroup, $other = [], $cacheTime = 600)
+    {
+        $key = md5(time() . $uid);
+        Cache::set('user_order_' . $uid . $key, compact('cartInfo', 'priceGroup', 'other'), $cacheTime);
+        return $key;
+    }
+
+    /**
+     * 获取订单缓存信息
+     * @param $uid
+     * @param $key
+     * @return mixed|null
+     * @throws \Psr\SimpleCache\InvalidArgumentException
+     */
+    public static function getCacheOrderInfo($uid, $key)
+    {
+        $cacheName = 'user_order_' . $uid . $key;
+        if (!Cache::has($cacheName)) return null;
+        return Cache::get($cacheName);
+    }
+
+    /**
+     * 生成总订单唯一id
+     * @param $uid 用户uid
+     * @return string
+     */
+    public static function getNewPOrderId()
+    {
+        $prefix = 'wxcn';
+        list($msec, $sec) = explode(' ', microtime());
+        $msectime = number_format((floatval($msec) + floatval($sec)) * 1000, 0, '', '');
+        $porderId = $prefix . $msectime . mt_rand(10000, 99999);
+        if (self::be(['porder_id' => $porderId])) {
+            $porderId = $prefix . $msectime . mt_rand(10000, 99999);
+        }
+        return $porderId;
+    }
+
+    /**
+     * 获取所有子订单
+     * @param string $porderId: porder_id
+     */
+    public static function getAllSubOrders(string $porderId): Array
+    {
+        $subOrders = self::alias('b')->join('StoreOrder o', 'o.id=b.oid')
+            ->where('b.porder_id', $porderId)->select()->toArray();
+        foreach($subOrders as &$subOrder) {
+            $subOrder['cart_id'] = json_decode($subOrder['cart_id'], true);
+        }
+        return $subOrders;
+    }
+
+    /**
+     * 字段累加
+     * @param Array $subOrders
+     * @param Array $field_name_list
+     * @return Array
+     */
+    public static function sumFields(Array $marr, Array $field_name_list): Array
+    {
+        $sums = [];
+        foreach($marr as $row) {
+            foreach($field_name_list as $fname) {
+                $fv = $row[$fname] ?? 0;    // field value
+                $sums[$fname] = (float)bcadd($sums[$fname] ?? 0, $fv, 2);
+            }
+        }
+        return $sums;
+    }
+
+     /**
+     * 微信支付 为 0元时
+     * @param $order_id
+     * @param $uid
+     * @param string $formId
+     * @return bool
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public static function jsPayPriceBatch($porder_id, $uid, $formId = '')
+    {
+        $subOrders = self::getAllSubOrders($porder_id);
+        if (!$subOrders) return self::setErrorInfo('订单不存在!');
+        $fieldValues = self::sumFields($subOrders, ['paid']);
+        if ($fieldValues['paid']) return self::setErrorInfo('该订单已支付!');
+        $userInfo = User::getUserInfo($uid);
+        self::beginTrans();
+        $res1 = $res2 = true;
+        foreach($subOrders as $orderInfo) {
+            $res1 = $res1 && UserBill::expend('购买商品', $uid, 'now_money', 'pay_product', $orderInfo['pay_price'], $orderInfo['id'], $userInfo['now_money'], '微信支付' . floatval($orderInfo['pay_price']) . '元购买商品');
+            $res2 = $res2 && StoreOrder::paySuccess($orderInfo['order_id'], 'weixin', $formId);//微信支付为0时
+        }
+        $res = $res1 && $res2;
+        self::checkTrans($res);
+        return $res;
+    }
+
+    /**
+     * 查找购物车里的所有产品标题
+     * @param $cartId 购物车id
+     * @return bool|string
+     */
+    public static function getProductTitleBatch($subOrders)
+    {
+        $title = '';
+        $cartId = [];
+        foreach($subOrders as $order) {
+            $cartId = array_merge($cartId, $order['cart_id']);
+        }
+        try {
+            $orderCart = StoreOrderCartInfo::where('cart_id', 'in', $cartId)->field('cart_info')->select();
+            foreach ($orderCart as $item) {
+                if (isset($item['cart_info']['productInfo']['store_name'])) {
+                    $title .= $item['cart_info']['productInfo']['store_name'] . '|';
+                }
+            }
+            unset($item);
+            if (!$title) {
+                $productIds = StoreCart::where('id', 'in', $cartId)->column('product_id');
+                $productlist = ($productlist = StoreProduct::getProductField($productIds, 'store_name')) ? $productlist->toArray() : [];
+                foreach ($productlist as $item) {
+                    if (isset($item['store_name'])) $title .= $item['store_name'] . '|';
+                }
+            }
+            if ($title) $title = substr($title, 0, strlen($title) - 1);
+            unset($item);
+        } catch (\Exception $e) {
+        }
+        return $title;
+    }
+
+    /**
+     * 余额支付
+     * @param $order_id
+     * @param $uid
+     * @param string $formId
+     * @return bool
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public static function yuePayBatch($porder_id, $uid, $formId = '')
+    {
+        $porderInfo = self::where('uid', $uid)->where('porder_id', $porder_id)->find();
+        if (!$porderInfo) {
+            return self::setErrorInfo('订单不存在!');
+        }
+        $subOrders = self::getAllSubOrders($porder_id);
+        if (!$subOrders) {
+            return self::setErrorInfo('订单不存在!');
+        }
+        $fieldValues = self::sumFields($subOrders, ['paid']);
+        if ($fieldValues['paid']) {
+            return self::setErrorInfo('该订单已支付!');
+        }
+        $userInfo = User::getUserInfo($uid);
+        if ($userInfo['now_money'] < $porderInfo['total_price'])
+            return self::setErrorInfo(['status' => 'pay_deficiency', 'msg' => '余额不足' . floatval($porderInfo['total_price'])]);
+
+        self::beginTrans();
+        $res1 = $res2 = $res3 = true;
+        foreach($subOrders as $orderInfo) {
+            $res1 = $res1 && (false !== User::bcDec($uid, 'now_money', $orderInfo['pay_price'], 'uid'));
+            $res2 = $res2 && UserBill::expend('购买商品', $uid, 'now_money', 'pay_product', $orderInfo['pay_price'], $orderInfo['id'], $userInfo['now_money'], '余额支付' . floatval($orderInfo['pay_price']) . '元购买商品');
+            $res3 = $res3 && StoreOrder::paySuccess($orderInfo['order_id'], 'yue', $formId);//余额支付成功
+            try {
+                PaymentRepositories::yuePayProduct($userInfo, $orderInfo);
+            } catch (\Exception $e) {
+                self::rollbackTrans();
+                return self::setErrorInfo($e->getMessage());
+            }
+        }
+       
+        $res = $res1 && $res2 && $res3;
+        self::checkTrans($res);
+        return $res;
+    }
+
+    public static function paySuccessBatch($porderId, $paytype = 'weixin', $formId = '')
+    {
+        $subOrders = self::getAllSubOrders($porderId);
+        $res = true;
+        foreach($subOrders as $order) {
+            $res = $res && StoreOrder::paySuccess($order['order_id'], $paytype, $formId);
+        }
+        return $res;
+    }
+
+    /**
+     * 生成订单
+     * @param $uid
+     * @param $key  orderKey 由客户端传入,总订单ID
+     * @param $addressId
+     * @param $payType  weixin / yue
+     * @param bool $useIntegral: 是否使用积分
+     * @param int $couponId
+     * @param string $mark: 订单留言
+     * @param int $combinationId
+     * @param int $pinkId
+     * @param int $seckill_id
+     * @param int $bargain_id
+     * @param bool $test
+     * @param int $isChannel 0, 1, 2 : routine, weixin, weixinh5
+     * @param int $shipping_type
+     * @param string $real_name
+     * @param string $phone
+     * @param int $storeId: 门店ID
+     * @return StoreOrder|bool|\think\Model
+     * @throws \think\Exception
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public static function cacheKeyCreateOrderBatch($uid, $key, $addressId, $payType, $useIntegral = false, $couponId = 0, 
+        $mark = '', $combinationId = 0, $pinkId = 0, $seckill_id = 0, $bargain_id = 0, $test = false, $isChannel = 0, 
+        $shipping_type = 1, $real_name = '', $phone = '', $storeId = 0)
+    {
+        StoreOrder::beginTrans();
+        try {
+            $shipping_type = (int)$shipping_type;
+            // 支付方式判断
+            $offlinePayStatus = (int)sys_config('offline_pay_status') ?? (int)2;    //线下支付状态 2 关闭
+            if ($offlinePayStatus == 2) {
+                unset(StoreOrder::$payType['offline']);
+            }
+            if (!array_key_exists($payType, StoreOrder::$payType)) {
+                return self::setErrorInfo('选择支付方式有误!', true);
+            }
+            // 查总订单 sql-1
+            if (self::be(['unique' => $key, 'uid' => $uid])) {
+                return self::setErrorInfo('请勿重复提交订单', true);
+            }
+
+            // 用户信息 sql-2
+            $userInfo = User::getUserInfo($uid);
+            if (!$userInfo) return self::setErrorInfo('用户不存在!', true);
+            // 取订单缓存
+            $cartGroup = self::getCacheOrderInfo($uid, $key);
+            if (!$cartGroup) return self::setErrorInfo('订单已过期,请刷新当前页面!', true);
+            $cartInfo = $cartGroup['cartInfo'];
+            $priceGroup = $cartGroup['priceGroup'];
+            $other = $cartGroup['other'];
+            // $payPrice = (float)$priceGroup['totalPrice'];
+            // 收货地址 sql-3
+            $addr = UserAddress::where('uid', $uid)->where('id', $addressId)->find();
+            // if ($payType == 'offline' && sys_config('offline_postage') == 1) {
+            //     $payPostage = 0;
+            // } else {
+            //     $payPostage = $priceGroup['storePostage'];
+            // }
+            if ($shipping_type === 1) {
+                if (!$test && !$addressId) {
+                    return self::setErrorInfo('请选择收货地址!', true);
+                }
+                // sql-4,5
+                if (!$test && (!UserAddress::be(['uid' => $uid, 'id' => $addressId, 'is_del' => 0]) || !($addressInfo = UserAddress::find($addressId))))
+                    return self::setErrorInfo('地址选择有误!', true);
+            } else {
+                if ((!$real_name || !$phone) && !$test) {
+                    return self::setErrorInfo('请填写姓名和电话', true);
+                }
+                $addressInfo['real_name'] = $real_name;
+                $addressInfo['phone'] = $phone;
+                $addressInfo['province'] = '';
+                $addressInfo['city'] = '';
+                $addressInfo['district'] = '';
+                $addressInfo['detail'] = '';
+            }
+
+            $totalPrice = 0.0;
+            $totalPayPrice = 0.0;
+            $SurplusIntegral = 0;
+            $totalPostage = 0.0;
+            $totalDeductionPrice = 0.0;
+            $totalCouponPrice = 0.0;
+            $counter = 0;
+            $subOrders = [];
+            // 子订单逐个处理
+            foreach ($cartInfo as $ci) {
+                $counter += 1;
+
+                // 一个订单的购物车
+                $subOrderCart = [$ci];
+                
+                $subOrderId = StoreOrder::getNewOrderId();
+                $subPriceGroup = StoreOrder::getOrderPriceGroup($subOrderCart, $addr);
+                if (!$subPriceGroup) {
+                    return false;
+                }
+                $payPrice = (float)$subPriceGroup['totalPrice'];
+                $totalPrice = (float)bcadd($totalPrice, $payPrice, 2);
+
+                $cartIds = [];      // 子订单购物车ID
+                $totalNum = 0;      // 总数量
+                $gainIntegral = 0;  // 总可得积分
+                foreach ($subOrderCart as $cart){
+                    // sql-6 x n
+                    if (!$test && !StoreOrder::checkProductStock($uid, $cart['product_id'], $cart['cart_num'], $cart['product_attr_unique'], $cart['combination_id'], $cart['seckill_id'], $cart['bargain_id'])) {
+                        return false;
+                    }
+                    $cartIds[] = $cart['id'];
+                    $totalNum += $cart['cart_num'];
+                    if (!$seckill_id) $seckill_id = $cart['seckill_id'];
+                    if (!$bargain_id) $bargain_id = $cart['bargain_id'];
+                    if (!$combinationId) $combinationId = $cart['combination_id'];
+                    // 可赚积分
+                    $cartInfoGainIntegral = isset($cart['productInfo']['give_integral']) ? bcmul($cart['cart_num'], $cart['productInfo']['give_integral'], 2) : 0;
+                    // 汇总
+                    $gainIntegral = bcadd($gainIntegral, $cartInfoGainIntegral, 2);
+                } // foreach
+                
+                // 活动
+                $deduction = $seckill_id || $bargain_id || $combinationId;
+                if ($deduction) {
+                    $couponId = 0;
+                    $useIntegral = false;
+                    if (!$test) {
+                        unset(StoreOrder::$payType['offline']);
+                        if (!array_key_exists($payType, StoreOrder::$payType)) {
+                            return self::setErrorInfo('营销产品不能使用线下支付!', true);
+                        } 
+                    }
+                }// 
+
+                //使用优惠劵
+                $res1 = true;
+                if ($couponId) {
+                    $couponInfo = StoreCouponUser::validAddressWhere()->where('id', $couponId)->where('uid', $uid)->find();
+                    if (!$couponInfo) return self::setErrorInfo('选择的优惠劵无效!', true);
+                    $coupons = StoreCouponUser::getUsableCouponList($uid, ['valid' => $subOrderCart], $payPrice);
+                    $flag = false;
+                    foreach ($coupons as $coupon) {
+                        if ($coupon['id'] == $couponId) {
+                            $flag = true;
+                            continue;
+                        }
+                    }
+                    if (!$flag)
+                        return self::setErrorInfo('不满足优惠劵的使用条件!', true);
+                    $payPrice = (float)bcsub($payPrice, $couponInfo['coupon_price'], 2);
+                    $res1 = StoreCouponUser::useCoupon($couponId);
+                    $couponPrice = $couponInfo['coupon_price'];
+                } else {
+                    $couponId = 0;
+                    $couponPrice = 0;
+                }
+                if (!$res1) {
+                    return self::setErrorInfo('使用优惠劵失败!', true);
+                }
+                $totalCouponPrice = (float)bcadd($totalCouponPrice, $couponPrice, 2);
+
+                //$shipping_type = 1 快递发货 $shipping_type = 2 门店自提
+                $store_self_mention = sys_config('store_self_mention') ?? 0;
+                if (!$store_self_mention) $shipping_type = 1;
+                $payPostage = 0;
+                if ($shipping_type === 1) {
+                    //是否包邮
+                    if ((isset($other['offlinePostage']) && $other['offlinePostage'] && $payType == 'offline')) {
+                        $payPostage = 0;
+                    }
+                    $payPrice = (float)bcadd($payPrice, $payPostage, 2);
+                } else if ($shipping_type === 2) {
+                    //门店自提没有邮费支付
+                    $subPriceGroup['storePostage'] = 0;
+                    $payPostage = 0;
+                    if (!$storeId && !$test) {
+                        return self::setErrorInfo('请选择门店', true);
+                    }
+                }
+                $totalPostage = (float)bcadd($totalPostage, $payPostage, 2);
+
+                //积分抵扣
+                $res2 = true;
+                $usedIntegral = 0.0;
+                if ($useIntegral && $userInfo['integral'] > 0) {
+                    $deductionPrice = (float)bcmul($userInfo['integral'], $other['integralRatio'], 2);
+                    if ($deductionPrice < $payPrice) {
+                        $payPrice = bcsub($payPrice, $deductionPrice, 2);
+                        $usedIntegral = $userInfo['integral'];
+                        $SurplusIntegral = 0;
+                        // sql
+                        $res2 = false !== User::edit(['integral' => 0], $userInfo['uid'], 'uid');
+                    } else {
+                        $deductionPrice = $payPrice;
+                        $usedIntegral = (float)bcdiv($payPrice, $other['integralRatio'], 2);
+                        $SurplusIntegral = bcsub($userInfo['integral'], $usedIntegral, 2);
+                        $res2 = false !== User::bcDec($userInfo['uid'], 'integral', $usedIntegral, 'uid');
+                        $payPrice = 0;
+                    }
+                    $res2 = $res2 && false != UserBill::expend('积分抵扣', $uid, 'integral', 'deduction', $usedIntegral, $subOrderId, $userInfo['integral'], '购买商品使用' . floatval($usedIntegral) . '积分抵扣' . floatval($deductionPrice) . '元');
+                } else {
+                    $deductionPrice = 0;
+                    $usedIntegral = 0;
+                }
+                if (!$res2) {
+                    return self::setErrorInfo('使用积分抵扣失败!', true);
+                }
+                // fix at runtime
+                $userInfo['integral'] = (float)bcsub($userInfo['integral'], $usedIntegral, 2);
+                if ($userInfo['integral'] < 0) {
+                    $userInfo['integral'] = 0;
+                }
+                
+                $totalDeductionPrice = (float)bcadd($totalDeductionPrice, $deductionPrice, 2);
+                $totalPayPrice = (float)bcadd($totalPayPrice, $payPrice, 2);
+
+                if ($test) {
+                    continue;
+                }
+
+                $unique = mb_substr($key, 0, mb_strlen($key)-3) . $counter;
+                // 增加子订单
+                $orderInfo = [
+                    'uid' => $uid,
+                    'order_id' => $test ? 0 : $subOrderId,
+                    'real_name' => $addressInfo['real_name'],
+                    'user_phone' => $addressInfo['phone'],
+                    'user_address' => $addressInfo['province'] . ' ' . $addressInfo['city'] . ' ' . $addressInfo['district'] . ' ' . $addressInfo['detail'],
+                    'cart_id' => $cartIds,
+                    'total_num' => $totalNum,
+                    'total_price' => $subPriceGroup['totalPrice'],
+                    'total_postage' => $subPriceGroup['storePostage'],
+                    'coupon_id' => $couponId,
+                    'coupon_price' => $couponPrice,
+                    'pay_price' => $payPrice,
+                    'pay_postage' => $payPostage,
+                    'deduction_price' => $deductionPrice,
+                    'paid' => 0,
+                    'pay_type' => $payType,
+                    'use_integral' => $usedIntegral,
+                    'gain_integral' => $gainIntegral,
+                    'mark' => htmlspecialchars($mark),
+                    'combination_id' => $combinationId,
+                    'pink_id' => $pinkId,
+                    'seckill_id' => $seckill_id,
+                    'bargain_id' => $bargain_id,
+                    'cost' => $subPriceGroup['costPrice'],
+                    'is_channel' => $isChannel,
+                    'add_time' => time(),
+                    'unique' => $unique,
+                    'shipping_type' => $shipping_type,
+                ];
+                if ($shipping_type === 2) {
+                    $orderInfo['verify_code'] = StoreOrder::getStoreCode();
+                    $orderInfo['store_id'] = SystemStore::getStoreDispose($storeId, 'id');
+                    if (!$orderInfo['store_id']) return self::setErrorInfo('暂无门店无法选择门店自提!', true);
+                }
+                $order = StoreOrder::create($orderInfo);
+                if (!$order) {
+                    return self::setErrorInfo('订单生成失败!', true);
+                }
+                $res5 = true;
+                foreach ($subOrderCart as $cart) {
+                    //减库存加销量
+                    if ($combinationId) {
+                        $res5 = $res5 && StoreCombination::decCombinationStock($cart['cart_num'], $combinationId, isset($cart['productInfo']['attrInfo']) ? $cart['productInfo']['attrInfo']['unique'] : '');
+                    } else if ($seckill_id) {
+                        $res5 = $res5 && StoreSeckill::decSeckillStock($cart['cart_num'], $seckill_id, isset($cart['productInfo']['attrInfo']) ? $cart['productInfo']['attrInfo']['unique'] : '');
+                    } else if ($bargain_id) {
+                        $res5 = $res5 && StoreBargain::decBargainStock($cart['cart_num'], $bargain_id, isset($cart['productInfo']['attrInfo']) ? $cart['productInfo']['attrInfo']['unique'] : '');
+                    } else {
+                        $res5 = $res5 && StoreProduct::decProductStock($cart['cart_num'], $cart['productInfo']['id'], isset($cart['productInfo']['attrInfo']) ? $cart['productInfo']['attrInfo']['unique'] : '');
+                    }
+                }
+                //保存购物车商品信息
+                $res4 = false !== StoreOrderCartInfo::setCartInfo($order['id'], $subOrderCart);
+                //购物车状态修改
+                $res6 = false !== StoreCart::where('id', 'IN', $cartIds)->update(['is_pay' => 1]);
+                if (!$res4 || !$res5 || !$res6) {
+                    return self::setErrorInfo('订单生成失败!', true);
+                }
+                StoreOrderStatus::status($order['id'], 'cache_key_create_order', '订单生成');
+                $subOrders[] = $order;
+            } // foreach 
+            
+            if ($totalPayPrice <= 0) $totalPayPrice = 0;
+
+            if ($test) {
+                StoreOrder::rollbackTrans();
+                return [
+                    'total_price' => $totalPrice,
+                    'pay_price' => $totalPayPrice,
+                    'pay_postage' => $totalPostage,
+                    'coupon_price' => $totalCouponPrice,
+                    'deduction_price' => $totalDeductionPrice,
+                    'SurplusIntegral' => $SurplusIntegral,
+                ];
+            }
+
+            $pOrderId = self::getNewPOrderId();
+            foreach($subOrders as $subOrder) {
+                $porderInfo = [
+                    'porder_id' => $pOrderId,
+                    'oid' => $subOrder['id'],
+                    'total_price' => $totalPayPrice,
+                    'unique' => $key,
+                    'uid' => $uid,
+                ];
+                $porder = self::create($porderInfo);
+                if(!$porder) {
+                    return self::setErrorInfo('订单生成失败!', true);
+                }
+            }
+            //自动设置默认地址
+            if (count($subOrders)) {
+                UserRepository::storeProductOrderCreateEbApi($subOrders[0], compact('cartInfo', 'addressId'));
+            }
+            StoreOrder::clearCacheOrderInfo($uid, $key);
+            StoreOrder::commitTrans();
+            return $pOrderId;
+        } catch (\PDOException $e) {
+            StoreOrder::rollbackTrans();
+            return self::setErrorInfo('生成订单时SQL执行错误错误原因:' . $e->getMessage());
+        } catch (\Exception $e) {
+            StoreOrder::rollbackTrans();
+            throw $e;
+            return self::setErrorInfo('生成订单时系统错误错误原因:' . $e->getMessage());
+        }
+    }
+}

+ 82 - 1
crmeb/repositories/OrderRepository.php

@@ -7,6 +7,7 @@ use app\models\user\User;
 use app\models\user\UserBill;
 use app\models\user\UserBill;
 use app\models\user\WechatUser;
 use app\models\user\WechatUser;
 use app\admin\model\order\StoreOrder as AdminStoreOrder;
 use app\admin\model\order\StoreOrder as AdminStoreOrder;
+use app\models\store\StoreOrderBatch;
 use crmeb\services\MiniProgramService;
 use crmeb\services\MiniProgramService;
 use crmeb\services\WechatService;
 use crmeb\services\WechatService;
 
 
@@ -42,6 +43,33 @@ class OrderRepository
         return MiniProgramService::jsPay($openid, $orderInfo['order_id'], $orderInfo['pay_price'], 'product', StoreOrder::getSubstrUTf8($site_name . ' - ' . $bodyContent, 30));
         return MiniProgramService::jsPay($openid, $orderInfo['order_id'], $orderInfo['pay_price'], 'product', StoreOrder::getSubstrUTf8($site_name . ' - ' . $bodyContent, 30));
     }
     }
 
 
+        /**
+     * TODO 小程序JS支付
+     * @param $orderId
+     * @param string $field
+     * @return array|string
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public static function jsPayBatch($porderId, $field = 'porder_id')
+    {
+        if (is_string($porderId))
+            $porderInfo = StoreOrderBatch::where($field, $porderId)->find();
+        else
+            $porderInfo = $porderId;
+        $subOrders = StoreOrderBatch::getAllSubOrders($porderId);
+        if (!$subOrders) exception('支付订单不存在!');
+        $fieldValues = StoreOrderBatch::sumFields($subOrders, ['paid', 'pay_price']);
+        if ($fieldValues['paid']) exception('支付已支付!');
+        if ($fieldValues['pay_price'] <= 0) exception('该支付无需支付!');
+        $openid = WechatUser::getOpenId($porderInfo['uid']);
+        $bodyContent = StoreOrderBatch::getProductTitleBatch($subOrders);
+        $site_name = sys_config('site_name');
+        if (!$bodyContent && !$site_name) exception('支付参数缺少:请前往后台设置->系统设置-> 填写 网站名称');
+        return MiniProgramService::jsPay($openid, $porderInfo['porder_id'], $fieldValues['pay_price'], 'product', StoreOrder::getSubstrUTf8($site_name . ' - ' . $bodyContent, 30));
+    }
+
     /**
     /**
      * 微信公众号JS支付
      * 微信公众号JS支付
      * @param $orderId
      * @param $orderId
@@ -64,7 +92,35 @@ class OrderRepository
         $bodyContent = StoreOrder::getProductTitle($orderInfo['cart_id']);
         $bodyContent = StoreOrder::getProductTitle($orderInfo['cart_id']);
         $site_name = sys_config('site_name');
         $site_name = sys_config('site_name');
         if (!$bodyContent && !$site_name) exception('支付参数缺少:请前往后台设置->系统设置-> 填写 网站名称');
         if (!$bodyContent && !$site_name) exception('支付参数缺少:请前往后台设置->系统设置-> 填写 网站名称');
-        return WechatService::jsPay($openid, $orderInfo['order_id'], $orderInfo['pay_price'], 'product', StoreOrder::getSubstrUTf8($site_name . ' - ' . $bodyContent, 30));
+        return WechatService::jsPay($openid, $orderInfo['porder_id'], $orderInfo['total_price'], 'product', StoreOrder::getSubstrUTf8($site_name . ' - ' . $bodyContent, 30));
+    }
+
+    /**
+     * 微信公众号JS支付
+     * @param $orderId
+     * @param string $field
+     * @return array|string
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public static function wxPayBatch($porderId, $field = 'porder_id')
+    {
+        if (is_string($porderId))
+            $porderInfo = StoreOrderBatch::where($field, $porderId)->find();
+        else
+            $porderInfo = $porderId;
+        
+        $subOrders = StoreOrderBatch::getAllSubOrders($porderId);
+        if (!$subOrders) exception('支付订单不存在!');
+        $fieldValues = StoreOrderBatch::sumFields($subOrders, ['paid', 'pay_price']);
+        if ($fieldValues['paid']) exception('支付已支付!');
+        if ($fieldValues['pay_price'] <= 0) exception('该支付无需支付!');
+        $openid = WechatUser::uidToOpenid($porderInfo['uid'], 'openid');
+        $bodyContent = StoreOrderBatch::getProductTitleBatch($subOrders);
+        $site_name = sys_config('site_name');
+        if (!$bodyContent && !$site_name) exception('支付参数缺少:请前往后台设置->系统设置-> 填写 网站名称');
+        return WechatService::jsPay($openid, $porderInfo['porder_id'], $porderInfo['total_price'], 'product', StoreOrder::getSubstrUTf8($site_name . ' - ' . $bodyContent, 30));
     }
     }
 
 
     /**
     /**
@@ -91,6 +147,31 @@ class OrderRepository
         return WechatService::paymentPrepare(null, $orderInfo['order_id'], $orderInfo['pay_price'], 'product', StoreOrder::getSubstrUTf8($site_name . ' - ' . $bodyContent, 30), '', 'MWEB');
         return WechatService::paymentPrepare(null, $orderInfo['order_id'], $orderInfo['pay_price'], 'product', StoreOrder::getSubstrUTf8($site_name . ' - ' . $bodyContent, 30), '', 'MWEB');
     }
     }
 
 
+    /**
+     * 微信h5支付
+     * @param $orderId
+     * @param string $field
+     * @return array|string
+     * @throws \think\db\exception\DataNotFoundException
+     * @throws \think\db\exception\ModelNotFoundException
+     * @throws \think\exception\DbException
+     */
+    public static function h5PayBatch($porderId, $field = 'order_id')
+    {
+        if (is_string($porderId))
+            $porderInfo = StoreOrderBatch::where($field, $porderId)->find();
+        else
+            $porderInfo = $porderId;
+        $subOrders = StoreOrderBatch::getAllSubOrders($porderId);
+        if (!$subOrders) exception('支付订单不存在!');
+        $fieldValues = StoreOrderBatch::sumFields($subOrders, ['paid', 'pay_price']);
+        if ($fieldValues['paid']) exception('支付已支付!');
+        if ($fieldValues['pay_price'] <= 0) exception('该支付无需支付!');
+        $bodyContent = StoreOrderBatch::getProductTitleBatch($subOrders);
+        $site_name = sys_config('site_name');
+        if (!$bodyContent && !$site_name) exception('支付参数缺少:请前往后台设置->系统设置-> 填写 网站名称');
+        return WechatService::paymentPrepare(null, $porderInfo['porder_id'], $porderInfo['total_price'], 'product', StoreOrder::getSubstrUTf8($site_name . ' - ' . $bodyContent, 30), '', 'MWEB');
+    }
     /**
     /**
      * 用户确认收货
      * 用户确认收货
      * @param $order
      * @param $order

+ 9 - 2
crmeb/repositories/PaymentRepositories.php

@@ -3,6 +3,7 @@
 namespace crmeb\repositories;
 namespace crmeb\repositories;
 
 
 use app\models\store\StoreOrder;
 use app\models\store\StoreOrder;
+use app\models\store\StoreOrderBatch;
 use app\models\user\UserRecharge;
 use app\models\user\UserRecharge;
 
 
 /**
 /**
@@ -51,8 +52,14 @@ class PaymentRepositories
     public static function wechatProduct(string $order_id = null)
     public static function wechatProduct(string $order_id = null)
     {
     {
         try {
         try {
-            if (StoreOrder::be(['order_id' => $order_id, 'paid' => 1])) return true;
-            return StoreOrder::paySuccess($order_id);
+            $first4 = mb_substr($order_id, 0, 4);
+            if ($first4 == 'wxcn') {
+                return StoreOrderBatch::paySuccessBatch($order_id);
+            } else {
+                // single version commented
+                if (StoreOrder::be(['order_id' => $order_id, 'paid' => 1])) return true;
+                return StoreOrder::paySuccess($order_id);
+            }
         } catch (\Exception $e) {
         } catch (\Exception $e) {
             return false;
             return false;
         }
         }

+ 0 - 0
docs/scripts/mt/funcs/__init__.py


TEMPAT SAMPAH
docs/scripts/mt/funcs/__pycache__/config.cpython-39.pyc


+ 9 - 32
docs/scripts/mt/funcs/products.py

@@ -4,12 +4,14 @@ import json
 import time
 import time
 import pymysql
 import pymysql
 
 
+from tw.config import conn, table
 from datetime import datetime
 from datetime import datetime
 from random import randint
 from random import randint
 from collections import namedtuple
 from collections import namedtuple
 from openpyxl import Workbook
 from openpyxl import Workbook
 from openpyxl.styles import PatternFill, colors
 from openpyxl.styles import PatternFill, colors
 
 
+
 '''
 '''
 twong 辅助工具,扫描商品表,及其关联表
 twong 辅助工具,扫描商品表,及其关联表
 
 
@@ -22,19 +24,6 @@ twong 辅助工具,扫描商品表,及其关联表
 
 
 SHOW_MAX_DAYS = 800  # 超过天数自动下架
 SHOW_MAX_DAYS = 800  # 超过天数自动下架
 
 
-# database config type
-DbConf = namedtuple('DbConf', 'type, host, port, username, password, database, prefix, charset')
-
-conf = DbConf('mysql', '127.0.0.1', 3306, 'toor', '123456', 'twong', 'eb_', 'utf8mb4')
-
-conn = pymysql.connect(
-    host=conf.host,
-    port=conf.port,
-    user=conf.username,
-    password=conf.password,
-    database=conf.database,
-    charset=conf.charset,
-)
 
 
 NOW = int(time.time())      # 当前时间戳
 NOW = int(time.time())      # 当前时间戳
 
 
@@ -62,18 +51,6 @@ for cols in sheet.iter_cols(min_col=1,max_col=8,min_row=1,max_row=1):
         cell.fill = PatternFill('solid', fgColor='C5C1AA')
         cell.fill = PatternFill('solid', fgColor='C5C1AA')
 sheet['A1'].fill = PatternFill('solid', fgColor='C5C1AA')
 sheet['A1'].fill = PatternFill('solid', fgColor='C5C1AA')
 
 
-# 初始化表名
-tables = {
-    'product': 'store_product',
-    'product_attr_result': 'store_product_attr_result',
-    'product_attr_value': 'store_product_attr_value',
-    'user': 'user',
-    'order': 'store_order',
-}
-
-for k, v in tables.items():
-    tables[k] = conf.prefix + v
-
 
 
 def updateResult(productId, result, skuName, stock=0, price=0, otPrice=0, brokerage=0, brokerage2=0):
 def updateResult(productId, result, skuName, stock=0, price=0, otPrice=0, brokerage=0, brokerage2=0):
     '''
     '''
@@ -160,7 +137,7 @@ with conn:
     with conn.cursor() as cursor:
     with conn.cursor() as cursor:
         sql = '''SELECT id, store_name, image, slider_image, spec_type, price, cost, stock, ficti, add_time
         sql = '''SELECT id, store_name, image, slider_image, spec_type, price, cost, stock, ficti, add_time
             FROM {} 
             FROM {} 
-            WHERE is_show=1 AND is_del=0 '''.format(tables['product'])
+            WHERE is_show=1 AND is_del=0 '''.format(table('store_product'))
         cursor.execute(sql)
         cursor.execute(sql)
         products = cursor.fetchall()
         products = cursor.fetchall()
         errors = {}
         errors = {}
@@ -181,7 +158,7 @@ with conn:
 
 
             sq2 = '''SELECT result 
             sq2 = '''SELECT result 
                 FROM {}
                 FROM {}
-                WHERE product_id={}'''.format(tables['product_attr_result'], productId)
+                WHERE product_id={}'''.format(table('store_product_attr_result'), productId)
             cursor.execute(sq2)
             cursor.execute(sq2)
             result = cursor.fetchone()
             result = cursor.fetchone()
             if not result or len(result) <= 0:
             if not result or len(result) <= 0:
@@ -194,7 +171,7 @@ with conn:
 
 
             sq3 = '''SELECT suk, stock, sales, price, cost, ot_price, brokerage, brokerage_two, `unique`
             sq3 = '''SELECT suk, stock, sales, price, cost, ot_price, brokerage, brokerage_two, `unique`
                 FROM {}
                 FROM {}
-                WHERE product_id={}'''.format(tables['product_attr_value'], productId)
+                WHERE product_id={}'''.format(table('store_product_attr_value'), productId)
             cursor.execute(sq3)
             cursor.execute(sq3)
             values = cursor.fetchall()
             values = cursor.fetchall()
 
 
@@ -209,7 +186,7 @@ with conn:
             # 上架超过一定时间自动下架,并将 add_time 改为当前日期
             # 上架超过一定时间自动下架,并将 add_time 改为当前日期
             days = int( (NOW - addTime) / 86400 )
             days = int( (NOW - addTime) / 86400 )
             if days > SHOW_MAX_DAYS:
             if days > SHOW_MAX_DAYS:
-                sql = '''UPDATE {} SET is_show=0, add_time={} WHERE id={}'''.format(tables['product'], NOW, productId)
+                sql = '''UPDATE {} SET is_show=0, add_time={} WHERE id={}'''.format(table('store_product'), NOW, productId)
                 with conn.cursor() as cs:
                 with conn.cursor() as cs:
                     cs.execute(sql)
                     cs.execute(sql)
                     print('{}-{} 过期{}天 已启动下架'.format(productId, productName, days))
                     print('{}-{} 过期{}天 已启动下架'.format(productId, productName, days))
@@ -292,7 +269,7 @@ with conn:
                     sparts = ','.join(parts)
                     sparts = ','.join(parts)
                     sql = ''' UPDATE {} 
                     sql = ''' UPDATE {} 
                         SET {}, brokerage=0, brokerage_two=0
                         SET {}, brokerage=0, brokerage_two=0
-                        WHERE `unique`='{}' '''.format(tables['product_attr_value'], sparts, unique)
+                        WHERE `unique`='{}' '''.format(table('store_product_attr_value'), sparts, unique)
                     with conn.cursor() as cs:
                     with conn.cursor() as cs:
                         cs.execute(sql)
                         cs.execute(sql)
                         print('{}-{}-{} 自动修改库存名称等: sql={}'.format(productId, productName, skuName, sql))
                         print('{}-{}-{} 自动修改库存名称等: sql={}'.format(productId, productName, skuName, sql))
@@ -303,7 +280,7 @@ with conn:
             if chResult:
             if chResult:
                 sql = '''UPDATE {}
                 sql = '''UPDATE {}
                     SET result='{}'
                     SET result='{}'
-                    WHERE product_id={}'''.format(tables['product_attr_result'], json.dumps(result, ensure_ascii=False), productId)
+                    WHERE product_id={}'''.format(table('store_product_attr_result'), json.dumps(result, ensure_ascii=False), productId)
 
 
                 with conn.cursor() as cs:
                 with conn.cursor() as cs:
                     cs.execute(sql)
                     cs.execute(sql)
@@ -320,7 +297,7 @@ with conn:
                 sparts = ','.join(parts)
                 sparts = ','.join(parts)
                 sql = '''UPDATE {} 
                 sql = '''UPDATE {} 
                 SET {}
                 SET {}
-                WHERE id={}'''.format(tables['product'], sparts, productId)
+                WHERE id={}'''.format(table('store_product'), sparts, productId)
                 with conn.cursor() as cs:
                 with conn.cursor() as cs:
                     cs.execute(sql)
                     cs.execute(sql)
                     print('{}-{} 更改虚拟销量和库存 {}'.format(productId, productName, sparts))
                     print('{}-{} 更改虚拟销量和库存 {}'.format(productId, productName, sparts))

+ 35 - 0
docs/scripts/mt/funcs/remove_order.py

@@ -0,0 +1,35 @@
+from tw.config import conn, table
+
+
+def clear_orders():
+    sqls = [
+        'DELETE FROM {}'.format(table('store_order_batch')),
+        'DELETE FROM {}'.format(table('store_order')),
+        'DELETE FROM {}'.format(table('store_order_cart_info')),
+        'DELETE FROM {}'.format(table('store_order_status')),
+        'DELETE FROM {}'.format(table('user_bill')),
+    ]
+    with conn:
+        with conn.cursor() as cs:
+            try:
+                for sql in sqls:
+                    print(sql)
+                    cs.execute(sql)
+                conn.commit()
+            except Exception as e:
+                print(e)
+
+
+def remove_order(orderId:list) -> bool:
+    sql1 = ''' DELETE FROM {} WHERE id={}'''.format(table('store_order'), orderId)
+    sql2 = ''' DELETE FROM {} WHERE oid={}'''.format(table('store_order_cart_info'), orderId)
+    sql3 = ''' DELETE FROM {} WHERE oid={}'''.format(table('store_status'), orderId)
+
+
+
+def remove_porder(porder):
+    pass
+
+
+if __name__ == '__main__':
+    clear_orders()

+ 0 - 0
docs/scripts/mt/funcs/tw/__init__.py


TEMPAT SAMPAH
docs/scripts/mt/funcs/tw/__pycache__/__init__.cpython-39.pyc


TEMPAT SAMPAH
docs/scripts/mt/funcs/tw/__pycache__/config.cpython-39.pyc


+ 22 - 0
docs/scripts/mt/funcs/tw/config.py

@@ -0,0 +1,22 @@
+import pymysql
+
+from collections import namedtuple
+
+
+# database config type
+DbConf = namedtuple('DbConf', 'type, host, port, username, password, database, prefix, charset')
+
+conf = DbConf('mysql', '127.0.0.1', 3306, 'toor', '123456', 'twong', 'eb_', 'utf8mb4')
+
+conn = pymysql.connect(
+    host=conf.host,
+    port=conf.port,
+    user=conf.username,
+    password=conf.password,
+    database=conf.database,
+    charset=conf.charset,
+)
+
+# 表名
+def table(name:str) -> str:
+    return conf.prefix + name

+ 42 - 0
docs/已有协议分析/address.md

@@ -0,0 +1,42 @@
+# address
+
+## GET address/default
+
+returns
+```json
+{
+  "status": 200,
+  "msg": "ok",
+  "data": {
+    "id": 2,
+    "real_name": "fd",
+    "phone": "13222224444",
+    "province": "北京市",
+    "city": "北京市",
+    "district": "东城区",
+    "detail": "dfdf",
+    "is_default": 1
+  }
+}
+```
+## GET address/list?page=1&limit=5
+
+returns
+```json
+{
+  "status": 200,
+  "msg": "ok",
+  "data": [
+    {
+      "id": 2,
+      "real_name": "fd",
+      "phone": "13222224444",
+      "province": "北京市",
+      "city": "北京市",
+      "district": "东城区",
+      "detail": "dfdf",
+      "is_default": 1
+    }
+  ]
+}
+```

+ 24 - 0
docs/已有协议分析/cart.md

@@ -0,0 +1,24 @@
+# 购物车
+
+## POST cart/add
+
+params
+```json
+{
+    "cartNum": 1,
+    "new": 1,
+    "productId": "807",
+    "uniqueId": "cfd3efef"
+}
+```
+
+returns
+```json
+{
+  "status": 200,
+  "msg": "ok",
+  "data": {
+    "cartId": "38"
+  }
+}
+```

+ 18 - 0
public/install/crmeb.sql

@@ -1014,6 +1014,24 @@ CREATE TABLE IF NOT EXISTS `eb_store_coupon_user` (
 
 
 -- --------------------------------------------------------
 -- --------------------------------------------------------
 
 
+--
+-- eb_store_order_batch
+--
+
+CREATE TABLE `eb_store_order_batch` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '总订单ID',
+  `porder_id` varchar(32) NOT NULL COMMENT '总订单号 主要用于关联和支付',
+  `oid` int(11) unsigned NOT NULL COMMENT '子订单号,关联到 store_order 表',
+  `total_price` decimal(8,2) unsigned NOT NULL DEFAULT 0.00 COMMENT '订单总价',
+  `unique` char(32) NOT NULL COMMENT '唯一id(md5加密)类似id',
+  `uid` int(11) unsigned NOT NULL COMMENT '用户id,主要用于过滤',
+  PRIMARY KEY (`id`) USING BTREE,
+  UNIQUE KEY `poid` (`porder_id`,`oid`) USING BTREE,
+  KEY `unique` (`unique`) USING BTREE,
+  KEY `uid` (`uid`) USING BTREE
+) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='父级订单表' AUTO_INCREMENT=1;
+
+-- --------------------------------------------------------
 --
 --
 -- 表的结构 `eb_store_order`
 -- 表的结构 `eb_store_order`
 --
 --

+ 3 - 0
route/api/route.php

@@ -116,10 +116,13 @@ Route::group(function () {
     //订单类
     //订单类
     Route::post('order/confirm', 'order.StoreOrderController/confirm')->name('orderConfirm'); //订单确认
     Route::post('order/confirm', 'order.StoreOrderController/confirm')->name('orderConfirm'); //订单确认
     Route::post('order/computed/:key', 'order.StoreOrderController/computedOrder')->name('computedOrder'); //计算订单金额
     Route::post('order/computed/:key', 'order.StoreOrderController/computedOrder')->name('computedOrder'); //计算订单金额
+    Route::post('order/v2/computed/:key', 'order.StoreOrderController/computedOrder_v2')->name('computedOrder'); //计算订单金额
     Route::post('order/create/:key', 'order.StoreOrderController/create')->name('orderCreate'); //订单创建
     Route::post('order/create/:key', 'order.StoreOrderController/create')->name('orderCreate'); //订单创建
+    Route::post('order/v2/create/:key', 'order.StoreOrderController/create_v2')->name('orderCreate'); //订单创建
     Route::get('order/data', 'order.StoreOrderController/data')->name('orderData'); //订单统计数据
     Route::get('order/data', 'order.StoreOrderController/data')->name('orderData'); //订单统计数据
     Route::get('order/list', 'order.StoreOrderController/lst')->name('orderList'); //订单列表
     Route::get('order/list', 'order.StoreOrderController/lst')->name('orderList'); //订单列表
     Route::get('order/detail/:uni', 'order.StoreOrderController/detail')->name('orderDetail'); //订单详情
     Route::get('order/detail/:uni', 'order.StoreOrderController/detail')->name('orderDetail'); //订单详情
+    Route::get('order/v2/detail/:uni', 'order.StoreOrderController/detail_v2')->name('orderDetail'); //订单详情
     Route::get('order/refund/reason', 'order.StoreOrderController/refund_reason')->name('orderRefundReason'); //订单退款理由
     Route::get('order/refund/reason', 'order.StoreOrderController/refund_reason')->name('orderRefundReason'); //订单退款理由
     Route::post('order/refund/verify', 'order.StoreOrderController/refund_verify')->name('orderRefundVerify'); //订单退款审核
     Route::post('order/refund/verify', 'order.StoreOrderController/refund_verify')->name('orderRefundVerify'); //订单退款审核
     Route::post('order/take', 'order.StoreOrderController/take')->name('orderTake'); //订单收货
     Route::post('order/take', 'order.StoreOrderController/take')->name('orderTake'); //订单收货