header('platform', 'H5'); $ip = request()->ip(); // 生成父订单号 $parentOrderSn = 'P' . date("Ymdhis") . sprintf("%08d", $userId) . mt_rand(1000, 9999); $parentOrder = null; $childOrders = []; Db::startTrans(); try { // 先创建所有子订单 $firstOrder = true; foreach ($goodsList as $goodsItem) { // 创建子订单 $childOrder = self::createSingleChildOrder($goodsItem, $userId, $address, $firstOrder ? $userCouponId : 0, $remark, $orderTimeout, $platform, $ip, $profileId); $childOrders[] = $childOrder; $firstOrder = false; } // 计算父订单总金额 $totalAmountData = self::calculateTotalAmount($childOrders); // 创建父订单 $parentOrderInfo = [ 'parent_order_sn' => $parentOrderSn, 'user_id' => $userId, 'total_amount' => $totalAmountData['total_amount'], 'total_goods_price' => $totalAmountData['total_goods_price'], 'total_goods_num' => $totalAmountData['total_goods_num'], 'total_express_fee' => $totalAmountData['total_express_fee'], 'total_discount_fee' => $totalAmountData['total_discount_fee'], 'coupon_discount_fee' => $totalAmountData['coupon_discount_fee'], 'promo_discount_fee' => 0, 'total_order_amount' => $totalAmountData['total_order_amount'], 'pay_amount' => $totalAmountData['pay_amount'], 'pay_original_amount' => $totalAmountData['pay_amount'], 'pay_remain_amount' => $totalAmountData['pay_amount'], 'user_coupon_id' => $userCouponId ?: null, 'remark' => $remark, 'expire_time' => time() + $orderTimeout, 'order_status' => OrderEnum::STATUS_CREATE, 'pay_status' => 0, 'platform' => $platform, 'ip' => $ip, 'status' => 'normal', ]; $parentOrder = ParentOrder::create($parentOrderInfo, true); // 更新子订单的父订单ID foreach ($childOrders as $childOrder) { $childOrder->parent_order_id = $parentOrder->id; $childOrder->save(); } // 提交事务 Db::commit(); // 记录操作 OrderActionService::recordUserAction( $parentOrderSn, OrderActionEnum::ACTION_CREATE, $userId, '创建父订单', $userId ); } catch (Exception $e) { Db::rollback(); throw new BusinessException("创建父子订单失败: " . $e->getMessage()); } return $parentOrder; } /** * 创建单个子订单 * @param array $goodsItem 商品项 * @param int $userId 用户ID * @param object $address 地址对象 * @param int $userCouponId 优惠券ID * @param string $remark 备注 * @param int $orderTimeout 订单超时时间 * @param string $platform 平台 * @param string $ip IP地址 * @param int $profileId 档案ID * @return Order */ protected static function createSingleChildOrder($goodsItem, $userId, $address, $userCouponId, $remark, $orderTimeout, $platform, $ip, $profileId = 0) { // 构建单商品列表 $singleGoodsList = [$goodsItem]; // 生成子订单号 $orderSn = date("Ymdhis") . sprintf("%08d", $userId) . mt_rand(1000, 9999); // 子订单信息 $orderInfo = [ 'type' => 1, 'order_sn' => $orderSn, 'user_id' => $userId, 'amount' => 0, 'goods_price' => 0, 'goods_num' => 0, 'discount_fee' => 0, 'coupon_discount_fee' => 0, 'promo_discount_fee' => 0, 'order_amount' => 0, 'express_fee' => 0, 'expire_time' => time() + $orderTimeout, 'order_status' => OrderEnum::STATUS_CREATE, 'invoice_status' => 0, 'remark' => $remark, 'user_coupon_id' => $userCouponId > 0 ? $userCouponId : null, 'ip' => $ip, 'status' => 'normal', 'platform' => $platform, 'parent_order_id' => null, // 稍后更新 ]; // 使用OrderService创建订单 return OrderService::createOrder($address->id, $userId, $singleGoodsList, $userCouponId, $remark, 0, $profileId); } /** * 计算父订单总金额 * @param array $childOrders 子订单数组 * @return array */ protected static function calculateTotalAmount($childOrders) { $totalAmount = 0; $totalGoodsPrice = 0; $totalGoodsNum = 0; $totalExpressFee = 0; $totalDiscountFee = 0; $couponDiscountFee = 0; foreach ($childOrders as $childOrder) { $totalAmount = bcadd($totalAmount, $childOrder->amount, 2); $totalGoodsPrice = bcadd($totalGoodsPrice, $childOrder->goods_price, 2); $totalGoodsNum += $childOrder->goods_num; $totalExpressFee = bcadd($totalExpressFee, $childOrder->express_fee, 2); $totalDiscountFee = bcadd($totalDiscountFee, $childOrder->discount_fee, 2); $couponDiscountFee = bcadd($couponDiscountFee, $childOrder->coupon_discount_fee, 2); } return [ 'total_amount' => $totalAmount, 'total_goods_price' => $totalGoodsPrice, 'total_goods_num' => $totalGoodsNum, 'total_express_fee' => $totalExpressFee, 'total_discount_fee' => $totalDiscountFee, 'coupon_discount_fee' => $couponDiscountFee, 'total_order_amount' => bcadd($totalGoodsPrice, $totalExpressFee, 2), 'pay_amount' => $totalAmount ]; } /** * 获取父订单详情 * @param int $parentOrderId 父订单ID * @param int $userId 用户ID * @return ParentOrder|null */ public static function getParentOrderDetail($parentOrderId, $userId = 0) { $parentOrderModel = new ParentOrder(); $query = $parentOrderModel->with(['childOrders']); if ($userId > 0) { $query->where('user_id', $userId); } return $query->where('id', $parentOrderId)->find(); } /** * 根据父订单号获取详情 * @param string $parentOrderSn 父订单号 * @return ParentOrder|null */ public static function getParentOrderByOrderSn($parentOrderSn) { $parentOrderModel = new ParentOrder(); return $parentOrderModel->with(['childOrders']) ->where('parent_order_sn', $parentOrderSn) ->find(); } /** * 检查父订单是否可以支付 * @param ParentOrder $parentOrder 父订单对象 * @return bool */ public static function canPay($parentOrder) { return $parentOrder->order_status == OrderEnum::STATUS_CREATE && $parentOrder->pay_status == 0; } /** * 检查父订单是否已支付 * @param ParentOrder $parentOrder 父订单对象 * @return bool */ public static function isPaid($parentOrder) { return $parentOrder->pay_status == 1; } /** * 更新父订单支付状态 * @param ParentOrder $parentOrder 父订单对象 * @param int $payStatus 支付状态 * @param string $payType 支付方式 * @param string $transactionId 第三方交易号 * @return bool */ public static function updateParentOrderPayStatus($parentOrder, $payStatus, $payType = '', $transactionId = '') { $updateData = [ 'pay_status' => $payStatus, 'pay_type' => $payType, 'transaction_id' => $transactionId ]; if ($payStatus == 1) { $updateData['pay_time'] = time(); $updateData['order_status'] = OrderEnum::STATUS_PAY; } return $parentOrder->save($updateData); } /** * 更新子订单状态 * @param int $parentOrderId 父订单ID * @param int $status 订单状态 * @return bool */ public static function updateChildOrdersStatus($parentOrderId, $status) { $orderModel = new Order(); return $orderModel->where('parent_order_id', $parentOrderId)->update(['order_status' => $status]); } /** * 获取父订单的所有商品 * @param ParentOrder $parentOrder 父订单对象 * @return array */ public static function getAllOrderGoods($parentOrder) { $childOrderIds = []; foreach ($parentOrder->childOrders as $childOrder) { $childOrderIds[] = $childOrder->id; } if (empty($childOrderIds)) { return []; } $orderGoodsModel = new OrderGoods(); return $orderGoodsModel->where('order_id', 'in', $childOrderIds)->select(); } /** * 父订单支付成功后的处理 * @param string $parentOrderSn 父订单号 * @param string $payType 支付方式 * @param string $transactionId 第三方交易号 * @return bool */ public static function handleParentOrderPaySuccess($parentOrderSn, $payType = '', $transactionId = '') { $parentOrder = self::getParentOrderByOrderSn($parentOrderSn); if (!$parentOrder) { throw new BusinessException('父订单不存在'); } if (self::isPaid($parentOrder)) { throw new BusinessException('父订单已支付'); } Db::startTrans(); try { // 更新父订单支付状态 self::updateParentOrderPayStatus($parentOrder, 1, $payType, $transactionId); // 更新所有子订单状态为已支付 self::updateChildOrdersStatus($parentOrder->id, OrderEnum::STATUS_PAY); // 记录父订单支付操作 OrderActionService::recordUserAction( $parentOrderSn, OrderActionEnum::ACTION_PAY, $parentOrder->user_id, '父订单支付成功', $parentOrder->user_id ); // 记录子订单支付操作 foreach ($parentOrder->childOrders as $childOrder) { OrderActionService::recordUserAction( $childOrder->order_sn, OrderActionEnum::ACTION_PAY, $parentOrder->user_id, '子订单支付成功(通过父订单)', $parentOrder->user_id ); } Db::commit(); return true; } catch (Exception $e) { Db::rollback(); throw new BusinessException('处理父订单支付失败: ' . $e->getMessage()); } } /** * 取消父订单 * @param int $parentOrderId 父订单ID * @param int $userId 用户ID * @return bool */ public static function cancelParentOrder($parentOrderId, $userId) { $parentOrder = self::getParentOrderDetail($parentOrderId, $userId); if (!$parentOrder) { throw new BusinessException('父订单不存在'); } if (self::isPaid($parentOrder)) { throw new BusinessException('已支付的父订单无法取消'); } Db::startTrans(); try { // 更新父订单状态 $parentOrder->save(['order_status' => OrderEnum::STATUS_CANCEL]); // 更新所有子订单状态 self::updateChildOrdersStatus($parentOrder->id, OrderEnum::STATUS_CANCEL); // 恢复库存 foreach ($parentOrder->childOrders as $childOrder) { OrderGoods::setGoodsStocksInc($childOrder->order_sn); } // 恢复优惠券 if ($parentOrder->user_coupon_id) { $userCouponModel = new UserCoupon(); $userCouponModel->where('id', $parentOrder->user_coupon_id) ->update(['is_used' => 1]); } Db::commit(); return true; } catch (Exception $e) { Db::rollback(); throw new BusinessException('取消父订单失败: ' . $e->getMessage()); } } /** * 获取父订单列表 * @param int $userId 用户ID * @param array $param 查询参数 * @param array $status 状态筛选 * @return \think\Paginator */ public static function getParentOrderList($userId = 0, $param = [], $status = []) { $pageSize = $param['pageSize'] ?? 10; $parentOrderModel = new ParentOrder(); $query = $parentOrderModel->with(['childOrders']); if (!empty($userId)) { $query->where('user_id', $userId); } if (!empty($status)) { $query->whereIn('order_status', $status); } if (isset($param['keywords']) && $param['keywords'] != '') { $query->where('parent_order_sn', 'like', '%' . $param['keywords'] . '%'); } return $query->order('createtime desc') ->paginate($pageSize, false, ['query' => request()->get()]); } }