getOrderProduct($buy_type, $product_id, $product_sku, $number); if (empty($order_product)) { return sendErrorArray(3001, '无有效商品'); } // 判断商品类型是否一致 // 订单类型 1--实物 2--虚拟 $order_type = $order_product[0]['product_type']; foreach ($order_product as $k => $v) { if ($v['product_type'] != $order_type) { return sendErrorArray(3002, '下单商品类型不一致'); } } // 虚拟物品不需要配送 if ($order_type == 2) { $delivery_type = ''; } else { if(empty($delivery_type)){ // 获取配送方式 $config = $config_model->getOneData([ ['uid', '=', $this->mid] ], 'id,delivery_type'); $config['delivery_type'] = explode(',', $config['delivery_type']); // 默认到货方式 1--邮寄 2--自提 $delivery_type = ''; if (in_array(2, $config['delivery_type'])) { $delivery_type = 2; } if (in_array(1, $config['delivery_type'])) { $delivery_type = 1; } } } $my_address = []; if($delivery_type == 1){ // 获取我的地址 如果前台传了地址ID,则获取选中地址;否则,获取默认地址 if (!empty($my_address_id)) { // 获取指定地址 $my_address = $address_model->getAddress($my_address_id); } else { // 获取默认地址 $my_address = $address_model->getDefaultAddress(); } } // 商品总积分 $total_integral = 0; // 商品总价钱 $total_price = 0; // 运费 $freight = 0; foreach ($order_product as $k => $v) { // 总价钱 = 总价钱 + 产品价钱 * 数量 $total_price += $v['product_price'] * $v['number']; // 总积分 = 总积分 + 产品积分 * 数量 $total_integral += $v['product_integral'] * $v['number']; // 如果有地址,计算运费 if (!empty($my_address) && $delivery_type == 1) { // 运费类型 1--统一运费 2--运费模板 if ($v['freight_type'] == 2) { $freight += $freight_logic->getFreight($v['freight_id'], $v['weight'], $v['number'], $v['product_price'], isset($my_address['province_id']) ? $my_address['province_id'] : '', isset($my_address['city_id']) ? $my_address['city_id'] : '', isset($my_address['area_id']) ? $my_address['area_id'] : ''); } else { $freight += $v['freight_money'] * $v['number']; } } unset($order_product[$k]['product_stock']); unset($order_product[$k]['freight_type']); unset($order_product[$k]['freight_id']); unset($order_product[$k]['freight_money']); unset($order_product[$k]['weight']); } // 是否满足整单免运费,满足运费置0 if ($delivery_type == 1) { $free_freight_limit = $config_model->getField('free_freight_limit'); if ($total_price >= $free_freight_limit) { $freight = 0; } } else { $freight = 0; } // 支付价钱 $pay_money = $total_price + $freight; $r_data = [ // 选中地址 'my_address' => $my_address, // 购买产品 'order_product' => $order_product, // 总积分 'total_integral' => $total_integral, // 总价钱 'total_price' => $total_price, // 运费 'freight' => $freight, // 实际付款 'pay_money' => round($pay_money, 2), // 实际付积分 'pay_integral' => $total_integral, // 订单类型 1--实物 2--虚拟 'order_type' => $order_type ]; return sendSuccessArray($r_data); } /** * 提交订单 * @param int $buy_type 购买类型 1--购物车 2--立即购买 * @param int $delivery_type 到货类型 1--邮寄 2--自提 * @param int $my_address_id 我的地址ID * @param int $store_id 门店ID * @param int $product_id buy_type=2时,产品ID * @param string $product_sku buy_type=2时,产品SKU * @param int $number buy_type=2时,购买数量 * @param int $pay_type 支付方式 0--不用支付 1--微信支付 2--支付宝支付 3--余额支付 * @param string $remark 备注 * @date 2022-11-18 */ public function insertOrder($buy_type, $delivery_type, $my_address_id, $store_id, $product_id, $product_sku, $number, $pay_type, $remark) { $order_model = new IntegralOrder(); $order_product_model = new IntegralOrderProduct(); $cart_model = new IntegralCart(); $address_model = new UserAddress(); $product_model = new IntegralProduct(); $freight_logic = new Freight(); $config_model = new IntegralConfig(); $store_model = new IntegralStore(); $my_model = new IntegralMy(); $order_service = new \app\integral\service\Order(); $snow_flake_class = new Snowflake(); // 获取购买的商品 $order_product = $order_service->getOrderProduct($buy_type, $product_id, $product_sku, $number); if (empty($order_product)) { return sendErrorArray(3001, '无有效商品'); } // 订单类型 1--实物 2--虚拟 $order_type = $order_product[0]['product_type']; foreach ($order_product as $k => $v) { // 判断商品类型是否一致 if ($v['product_type'] != $order_type) { return sendErrorArray(3002, '下单商品类型不一致'); } } if ($order_type == 2) { $delivery_type = ''; } // 邮寄 if ($delivery_type == 1) { // 获取指定地址 $my_address = $address_model->getAddress($my_address_id); } else if ($delivery_type == 2) { $store = $store_model->getOneData([ ['id', '=', $store_id] ], 'id,name,address,lat,lng'); } // 商品总积分 $total_integral = 0; // 商品总价钱 $total_price = 0; // 总数量 $total_number = 0; // 运费 $freight = 0; foreach ($order_product as $k => $v) { if ($v['number'] > $v['product_stock']) { return sendErrorArray(3003, $v['product_name'] . '商品' . $v['product_sku_name'] . '库存不足'); } // 商品快照 $product_snapshot = $product_model->getOneData([ ['id', '=', $v['product_id']] ])->toArray(); $order_product_data[] = [ 'id' => $snow_flake_class->id(), 'uid' => $this->mid, 'product_id' => $v['product_id'], 'product_type' => $v['product_type'], 'product_name' => $v['product_name'], 'product_cover_img' => $v['product_cover_img'], 'is_product_spec_open' => $v['is_product_spec_open'], 'product_sku' => $v['product_sku'], 'product_sku_name' => $v['product_sku_name'], 'product_integral' => $v['product_integral'], 'product_price' => $v['product_price'], 'number' => $v['number'], 'total_integral' => $v['number'] * $v['product_integral'], 'total_price' => $v['number'] * $v['product_price'], 'product_snapshot' => serialize($product_snapshot) ]; // 总积分 = 总积分 + 产品积分 * 数量 $total_integral += $v['product_integral'] * $v['number']; // 总价钱 = 总价钱 + 产品价钱 * 数量 $total_price += $v['product_price'] * $v['number']; // 总数量 = 总数量 + 数量 $total_number += $v['number']; // 邮寄时,计算运费 if ($delivery_type == 1) { // 运费类型 1--统一运费 2--运费模板 if ($v['freight_type'] == 2) { $freight += $freight_logic->getFreight($v['freight_id'], $v['weight'], $v['number'], $v['product_price'], $my_address['province_id'], $my_address['city_id'], $my_address['area_id']); } else { $freight += $v['freight_money'] * $v['number']; } } } // 邮寄时,是否满足整单免运费,满足运费置0 if ($delivery_type == 1) { $free_freight_limit = $config_model->getField('free_freight_limit'); if ($total_price >= $free_freight_limit) { $freight = 0; } } else { $freight = 0; } // 积分是否足够 $my_integral = $my_model->getMyIntegral($this->userId); if ($my_integral['integral'] < $total_integral) { return sendErrorArray(3004, '您的积分不足'); } // 生成订单数据 $data = [ 'uid' => $this->mid, 'user_agent' => $this->userAgent, 'user_id' => $this->userId, 'delivery_type' => $delivery_type, 'product_type' => $order_type, 'order_number' => $order_model->createOrderNumber('I'), 'total_integral' => $total_integral, 'total_price' => $total_price, 'total_number' => $total_number, 'freight' => $freight, //自提运费为0 'pay_integral' => $total_integral, 'pay_money' => $total_price + $freight, 'remark' => $remark, 'pay_type' => $pay_type, 'linkman' => $delivery_type == 1 ? $my_address['linkman'] : '', 'mobile_phone' => $delivery_type == 1 ? $my_address['mobile_phone'] : '', 'province' => $delivery_type == 1 ? $my_address['province'] : '', 'city' => $delivery_type == 1 ? $my_address['city'] : '', 'area' => $delivery_type == 1 ? $my_address['area'] : '', 'address' => $delivery_type == 1 ? $my_address['address'] : '', 'store_id' => $delivery_type == 2 ? $store['id'] : '', 'store_name' => $delivery_type == 2 ? $store['name'] : '', 'store_address' => $delivery_type == 2 ? $store['address'] : '', 'store_lat' => $delivery_type == 2 ? $store['lat'] : '', 'store_lng' => $delivery_type == 2 ? $store['lng'] : '', 'is_pay' => 0, 'status' => 1 ]; // 特殊情况支付金额小于0时修改为0 if ($data['pay_money'] < 0) { $data['pay_money'] = 0; } Db::startTrans(); // 存入订单总表 $order_id = $order_model->dataUpdate($data); if (!$order_id) { Db::rollback(); return sendErrorArray(3005, '生成总订单失败'); } // 批量存入订单商品表 foreach ($order_product_data as $k => $v) { $order_product_data[$k]['order_id'] = $order_id; $order_product_data[$k]['create_time'] = time(); $order_product_data[$k]['update_time'] = time(); } $res = $order_product_model->insertAll($order_product_data); if (!$res) { Db::rollback(); return sendErrorArray(3006, '生成订单商品失败'); } // 购物车方式清空购物车 if ($buy_type == 1) { $res = $cart_model->deleteCartSelectedProduct($this->userId); if (!$res) { Db::rollback(); return sendErrorArray(3007, '清空兑换车失败'); } } // 下单减少库存 foreach ($order_product as $k => $v) { $res = $order_service->productStockChange($v['product_id'], $v['product_sku'], -$v['number']); if ($res['code'] != 0) { Db::rollback(); return $res; } } Db::commit(); // 订单支付金额为0,即不用支付 if ($data['pay_money'] == 0) { Db::startTrans(); $res = $order_service->afterOrderPaySuccess($order_id); if ($res['code'] != 0) { Db::rollback(); return $res; } Db::commit(); return sendSuccessArray([ // 是否需要支付 'need_pay' => 0 ]); } // 调起支付 $res = $order_service->createPayOrder($order_id); if ($res['code'] != 0) { return $res; } return $res; } /** * 我的订单列表 * @param int $last_id 列表最后一条数据ID * @param int $index 订单状态 0--所有 1--待支付 2--待发货 3--待收货 4--已完成 * @date 2022-11-20 */ public function listMyOrder($last_id, $index) { $order_model = new IntegralOrder(); $where = [ ['uid', '=', $this->mid], ['user_id', '=', $this->userId], // 用户未删除 ['is_user_delete', '=', 0] ]; // 在最后一条数据ID之前的订单 if (!empty($last_id)) { $where[] = ['id', '<', $last_id]; } // 订单状态 0--所有 1--待支付 2--待发货 3--待收货 4--已完成 if (!empty($index)) { if ($index == 4) { $where[] = ['status', '=', 5]; } else { $where[] = ['status', '=', $index]; } } $filed = 'id,delivery_type,order_number,status,pay_money,pay_integral,delivery_code,store_name,store_address,store_lat,store_lng,total_number'; $list = $order_model->listMyOrderByLastId($where, $filed); return sendSuccessArray([ 'list' => $list ]); } /** * 我的订单详情 * @param int $order_id 订单ID * @param int $is_check_user 是否检查是不是用户自己的单,0--不检查(订单核销时) 1--检查 * @date 2022-11-20 */ public function getMyOrder($order_id, $is_check_user = 1) { $config_model = new IntegralConfig(); $order_model = new IntegralOrder(); $where = [ ['id', '=', $order_id], ['uid', '=', $this->mid], ['is_user_delete', '=', 0] ]; if ($is_check_user == 1) { $where[] = ['user_id', '=', $this->userId]; } $field = 'id,order_number,delivery_type,delivery_code,product_type,status,pay_type,total_integral,total_price,freight,pay_integral,pay_money,remark ,create_time,pay_time,express_time,confirm_time,cancel_time ,linkman,mobile_phone,province,city,area,address,store_id,store_name,store_address,store_lat,store_lng'; $order = $order_model->getMyOrder($where, $field); if (empty($order)) { return sendErrorArray(3001, '订单不存在'); } $order = $order->toArray(); $order['create_time'] = date("Y-m-d H:i", strtotime($order['create_time'])); if ($order['pay_time']) { $order['pay_time'] = date("Y-m-d H:i", strtotime($order['pay_time'])); } if ($order['express_time']) { $order['express_time'] = date("Y-m-d H:i", strtotime($order['express_time'])); } if ($order['confirm_time']) { $order['confirm_time'] = date("Y-m-d H:i", strtotime($order['confirm_time'])); } if ($order['cancel_time']) { $order['cancel_time'] = date("Y-m-d H:i", strtotime($order['cancel_time'])); } // 未付款状态下,获取自动取消订单倒计时 $order['cancel_rest_second'] = 0; if ($order['status'] == 1) { // 获取商城配置-X分钟自动取消订单 $order_cancel_minute = $config_model->getOneData([ ['uid', '=', $this->mid] ], 'order_cancel_minute'); // 剩余X秒自动取消订单 $order['cancel_rest_second'] = strtotime($order['create_time']) + $order_cancel_minute * 60 - time(); } return sendSuccessArray([ // 订单详情 'order' => $order ]); } /** * 订单再支付 * @param int $order_id 订单ID * @param int $pay_type 支付方式 1--微信支付 2--支付宝支付 3--余额支付 * @date 2022-11-21 */ public function rePayOrder($order_id, $pay_type) { $order_model = new IntegralOrder(); $order_service = new \app\integral\service\Order(); $order = $order_model->getOneData([ ['id', '=', $order_id] ], 'id,user_agent,status,order_number'); // 非待支付状态 if ($order['status'] != 1) { return sendErrorArray(3001, '订单状态不支持支付'); } // 查询单号是否支付 if ($pay_type == 1) { $wxpay_param = get_wxpay_config_with_weixin($order['user_agent']); $wxpay_class = new \tencent\wechat\pay\Wxpay($wxpay_param); // 查询订单 $result = $wxpay_class->queryByOutTradeNumber($order['order_number']); if ($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS') { if ($result['trade_state'] == 'SUCCESS') { return sendErrorArray(3002, '订单已支付'); } } } Db::startTrans(); // 更新订单总表 $data_update = [ 'id' => $order_id, 'pay_type' => $pay_type, ]; $order_id = $order_model->dataUpdate($data_update); if (!$order_id) { Db::rollback(); return sendErrorArray(4001, '生成总订单失败'); } Db::commit(); // 调起支付 $res = $order_service->createPayOrder($order_id); if ($res['code'] != 0) { return $res; } return $res; } /** * 订单取消 * @param int $order_id 订单ID * @param int $type 1--用户操作 2--后台操作 3--定时 * @date 2022-11-21 */ public function cancelOrder($order_id, $type = 1) { $order_model = new IntegralOrder(); $order_product_model = new IntegralOrderProduct(); $order_service = new \app\integral\service\Order(); // 获取订单信息 $order = $order_model->getOneData([ ['id', '=', $order_id] ], 'id,user_id,status'); if (empty($order)) { return sendErrorArray(3001, '订单不存在'); } if ($type == 1 && $order['user_id'] != $this->userId) { return sendErrorArray(3002, '非本人操作'); } if ($order['status'] != 1) { return sendErrorArray(3003, '订单状态有变化,请刷新后查看'); } Db::startTrans(); // 更改订单状态 $data_update = [ 'status' => 8, 'cancel_time' => time() ]; $res = $order_model->dataUpdate($data_update, [ ['id', '=', $order_id] ]); if (!$res) { Db::rollback(); return sendErrorArray(3004, '取消失败'); } // 查找订单产品 $order_product = $order_product_model->getAllData([ ['order_id', '=', $order_id] ], 'id,product_id,product_sku,number')->toArray(); // 取消订单,产品增加库存 foreach ($order_product as $k => $v) { $res = $order_service->productStockChange($v['product_id'], $v['product_sku'], $v['number']); if ($res['code'] != 0) { Db::rollback(); return $res; } } Db::commit(); return sendSuccessArray([], '取消成功'); } /** * 订单提醒发货 * @param integer $order_id 订单ID * @date 2022-11-21 */ public function remindOrder($order_id) { $order_model = new IntegralOrder(); // 获取订单信息 $order = $order_model->getOneData([ ['id', '=', $order_id] ], 'id,user_id,status'); if (empty($order)) { return sendErrorArray(3001, '订单不存在'); } if ($order['user_id'] != $this->userId) { return sendErrorArray(3002, '非本人操作'); } if ($order['status'] != 2) { return sendErrorArray(3003, '订单状态不支持提醒发货'); } // 更改订单状态 $data_update = [ 'remind_time' => time() ]; $res = $order_model->dataUpdate($data_update, [ ['id', '=', $order_id] ]); if (!$res) { return sendErrorArray(3004, '提醒发货失败'); } return sendSuccessArray([], '已提醒店家尽快发货'); } /** * 订单确认收货 * @param integer $user_id $oprate_type==1时为用户ID $oprate_type==2时为后台登录账号ID * @param integer $type 操作类型 1--用户操作 2--后台操作 3--定时操作 * @date 2022-11-20 */ public function finishOrder($order_id, $type = 1) { $order_model = new IntegralOrder(); // 获取订单信息 $order = $order_model->getOneData([ ['id', '=', $order_id] ], 'id,user_id,status'); if (empty($order)) { return sendErrorArray(3001, '订单不存在'); } if ($type == 1 && $order['user_id'] != $this->userId) { return sendErrorArray(3002, '非本人操作'); } if ($order['status'] != 3) { return sendErrorArray(3003, '订单状态不支持确认收货'); } Db::startTrans(); // 更改订单状态 $data_update = [ // 直接为已完成 暂时没有待评价状态 'status' => 5, 'confirm_time' => time() ]; $res = $order_model->dataUpdate($data_update, [ ['id', '=', $order_id] ]); if (!$res) { Db::rollback(); return sendErrorArray(3004, '确认收货失败'); } Db::commit(); return sendSuccessArray([], '确认收货成功'); } /** * 订单删除 * @param int $order_id 订单ID * @param int $type 1--用户操作 2--后台操作 * @date 2022-11-21 */ public function deleteOrder($order_id, $type = 1) { $order_model = new IntegralOrder(); // 获取订单信息 $order = $order_model->getOneData([ ['id', '=', $order_id] ], 'id,user_id,status'); if (empty($order)) { return sendErrorArray(3001, '订单不存在'); } if ($type == 1 && $order['user_id'] != $this->userId) { return sendErrorArray(3002, '非本人操作'); } if (!($order['status'] == 8 || $order['status'] == 5)) { return sendErrorArray(3003, '订单状态不支持删除'); } // 更改订单状态 $data_update = [ 'is_user_delete' => 1, 'user_delete_time' => time() ]; $res = $order_model->dataUpdate($data_update, [ ['id', '=', $order_id] ]); if (!$res) { return sendErrorArray(3004, '删除失败'); } return sendSuccessArray([], '删除成功'); } /** * 订单物流 * @date 2022-11-22 */ public function getLogistics($order_id) { $order_model = new IntegralOrder(); $kdniao_param = get_kdniao_config(); $logistic_class = new Logistics($kdniao_param); $where = [ ['uid', '=', $this->mid], ['user_id', '=', $this->userId], ['is_user_delete', '=', 0], ['id', '=', $order_id] ]; // 查找订单 $field = 'id,order_number,total_number,express_name,express_number,express_code,province,city,area,address'; $order = $order_model->getMyOrder($where, $field); if (empty($order)) { return sendErrorArray(3001, '订单不存在'); } $order = $order->toArray(); foreach ($order['integralOrderProduct'] as $k => $v) { unset($order['integralOrderProduct'][$k]['is_product_spec_open']); unset($order['integralOrderProduct'][$k]['product_type']); unset($order['integralOrderProduct'][$k]['product_sku_name']); } // 查看物流 $result = $logistic_class->getLogistics($order['express_number'], $order['express_code']); // 有错误 if ($result['Success'] != 'true') { // 物流状态 $logistics['logistics_status'] = 0; // 物流状态显示文本 $logistics['logistics_text'] = $result['Reason']; // 物流轨迹 $logistics['logistics'] = [ [ 'accept_date' => '', 'accept_time' => '', 'content' => '该订单编号暂时无法获取物流轨迹' ] ]; } else { // 物流状态 $logistics['logistics_status'] = $result['State']; // 物流状态显示文本 $logistics['logistics_text'] = $result['logistics_text']; // 物流轨迹 $result['Traces'] = array_reverse($result['Traces']); foreach ($result['Traces'] as $k => $v) { $logistics['logistics'][$k]['accept_date'] = date('Y-m-d', strtotime($v['AcceptTime'])); $logistics['logistics'][$k]['accept_time'] = date('H:i:s', strtotime($v['AcceptTime'])); $logistics['logistics'][$k]['content'] = $v['AcceptStation']; } } return sendSuccessArray([ // 订单信息 'order' => $order, // 物流信息 'logistics' => $logistics ]); } /** * 是否有核销权限 * @param int $order_id 订单ID * @date 2022-11-20 */ public function isCanWriteOffOrder($order_id) { $order_model = new IntegralOrder(); $checker_model = new IntegralStoreChecker(); // 获取订单信息 $order = $order_model->getOneData([ ['id', '=', $order_id] ], 'id,store_id'); $checker = $checker_model->getOneData([ ['store_id', '=', $order['store_id']], ['user_id', '=', $this->userId], ], 'id'); return sendSuccessArray([ // 是否有核销权限 'is_can_write_off' => empty($checker) ? 0 : 1 ]); } /** * 订单确认收货 * @param int $order_id 订单ID * @param int $type 1--小程序 2--后台 * @date 2022-11-20 */ public function writeOffOrder($order_id, $type = 1) { $order_model = new IntegralOrder(); $checker_model = new IntegralStoreChecker(); $check_model = new IntegralOrderCheck(); // 获取订单信息 $order = $order_model->getOneData([ ['id', '=', $order_id] ], 'id,user_id,store_id,delivery_type,status'); if (empty($order)) { return sendErrorArray(3001, '订单不存在'); } if ($order['status'] != 3 || $order['delivery_type'] != 2) { return sendErrorArray(3002, '订单状态不支持核销'); } // 是否是该门店核销员 $checker = $checker_model->getOneData([ ['store_id', '=', $order['store_id']], ['user_id', '=', $this->userId], ], 'id'); if (empty($checker)) { return sendErrorArray(3003, '您没有权限操作该订单'); } Db::startTrans(); // 更改订单状态 $data_update = [ // 直接为已完成 暂时没有待评价状态 'status' => 5, 'confirm_time' => time() ]; $res = $order_model->dataUpdate($data_update, [ ['id', '=', $order_id] ]); if (!$res) { Db::rollback(); return sendErrorArray(3004, '确认收货失败'); } $check_data = [ 'uid' => $this->mid, 'user_id' => $type == 1 ? $this->userId : '', 'store_id' => $order['store_id'], 'order_id' => $order_id, 'type' => $type, 'system_loginer_id' => $type == 2 ? LID : '' ]; $res = $check_model->dataUpdate($check_data); if (!$res) { Db::rollback(); return sendErrorArray(3005, '核销失败'); } Db::commit(); return sendSuccessArray([], '核销成功'); } /** * 获取自提地址列表 * @param string $lat 纬度 * @param string $lng 经度 * @param int $is_location 是否定位 0--没有 1--有 * @date 2022-11-17 */ public function listStore($lat, $lng, $is_location) { $store_model = new IntegralStore(); // 门店列表 $where = [ ['uid', '=', $this->mid], ['is_publish', '=', 1] ]; if ($is_location == 1) { $field = 'id,name,address,ROUND(2 * asin(sqrt(pow(sin((lat * pi() / 180 - ' . $lat . ' * pi() / 180) / 2),2) + cos(lat * pi() / 180) * cos( ' . $lat . ' * pi() / 180) * pow(sin((lng * pi() / 180 - ' . $lng . ' * pi() / 180) / 2),2))) * 6378.137,1) as distance'; $order = 'distance'; } else { $field = 'id,name,address'; $order = 'id desc'; } $store_list = $store_model->getAllData($where, $field, $order); return sendSuccessArray([ // 门店列表 'store_list' => $store_list, ]); } }