getInfo([['order_id', '=', $order_id]], 'delivery_status'); if ($status['delivery_status'] == OrderGoodsDict::wait_delivery) { return [OrderRefundDict::ONLY_REFUNDS]; } else { return [OrderRefundDict::ONLY_REFUNDS, OrderRefundDict::A_REFUND_RETURN]; } } /** * 根据配送状态获取退款方式 * @param $order_goods_info * @return array */ public function getRefundType($order_goods_info) { if ($order_goods_info['is_virtual'] == 1) { return [OrderRefundDict::ONLY_REFUNDS]; } else { if ($order_goods_info['delivery_status'] == OrderGoodsDict::wait_delivery) { return [OrderRefundDict::ONLY_REFUNDS]; } else { return [OrderRefundDict::ONLY_REFUNDS, OrderRefundDict::A_REFUND_RETURN]; } } } /** * 获取退款金额 * @param $order_goods_ids * @return array */ public function getOrderRefundMoney($order_goods_ids) { //订单商品项 $order_goods_ids = (string)$order_goods_ids; $order_goods_lists = model('order_goods')->getList([[ 'order_goods_id', 'in', is_array($order_goods_ids) ? $order_goods_ids : (string)$order_goods_ids ]]); if (empty($order_goods_lists)) return $this->error(null, '未查询到订单商品!'); $order_id = $order_goods_lists[0]['order_id']; //退款状态检测 只有未申请的可以发起退款 foreach ($order_goods_lists as $val) { if (!in_array($val['refund_status'], [OrderRefundDict::REFUND_NOT_APPLY, OrderRefundDict::REFUND_DIEAGREE, OrderRefundDict::PARTIAL_REFUND])) { return $this->error(null, '订单商品退款状态有误!'); } } //剩余未申请退款的订单商品统计 $not_apply_count = model('order_goods')->getCount([ ['order_id', '=', $order_id], ['order_goods_id', 'not in', $order_goods_ids], ['refund_status', 'in', [OrderRefundDict::REFUND_NOT_APPLY, OrderRefundDict::REFUND_DIEAGREE]], ], 'order_goods_id'); //有退过运费的订单商品统计 $refund_delivery_count = model('order_goods')->getCount([ ['order_id', '=', $order_id], ['order_goods_id', 'not in', $order_goods_ids], ['refund_delivery_money', '>', 0], ], 'order_goods_id'); //如果还有未申请退款的商品就不退运费 发票 和发票运费 if ($not_apply_count > 0) { $delivery_money = 0; $invoice_delivery_money = 0; $invoice_money = 0; } else { $order_info = model('order')->getInfo([ ['order_id', '=', $order_id], ], '*'); if ($refund_delivery_count == 0) { $delivery_money = $order_info['delivery_money']; } else { $delivery_money = 0; } $invoice_delivery_money = $order_info['invoice_delivery_money']; $invoice_money = $order_info['invoice_money']; } //计算实际退款金额,商家主动退款金额部分不可再退 $refund_money = 0; foreach ($order_goods_lists as $item) { $refund_money += $item['real_goods_money'] - $item['shop_active_refund_money']; } $refund_money += $delivery_money + $invoice_delivery_money + $invoice_money; return [ 'refund_money' => round($refund_money, 2), 'refund_delivery_money' => round($delivery_money, 2) ]; } /************************************************************************* 操作事件 ***********************************************************/ /** * 退款操作检测 * @param $status * @param $role * @param $event * @return bool */ public function refundActionCheck($status, $role, $event) { $action_config = [ 'shop' => 'action', 'buyer' => 'member_action', ]; $action_key = $action_config[$role] ?? ''; $refund_status_data = OrderRefundDict::getStatus($status); $action_list = $refund_status_data[$action_key] ?? []; $exist = false; foreach ($action_list as $action_info) { if ($action_info['event'] == $event) { $exist = true; break; } } return $exist; } /** * 卖家确认收到退货 * @param array $data 退货信息 * @param $user_info * @return array */ public function orderRefundTakeDelivery($data, $user_info) { $order_goods_id = $data['order_goods_id']; $order_goods_info = model('order_goods')->getInfo(['order_goods_id' => $order_goods_id]); if (empty($order_goods_info)) return $this->error([], '订单项不存在!'); if (!$this->refundActionCheck($order_goods_info['refund_status'], 'shop', 'orderRefundTakeDelivery')) { return $this->error(null, '当前状态不可操作'); } model('order_goods')->startTrans(); try { $refund_status = OrderRefundDict::REFUND_TAKEDELIVERY; $refund_status_data = OrderRefundDict::getStatus($refund_status); $data['refund_status'] = $refund_status; $data['refund_status_name'] = $refund_status_data['name']; $data['refund_status_action'] = json_encode($refund_status_data, JSON_UNESCAPED_UNICODE); model('order_goods')->update($data, ['order_goods_id' => $order_goods_id]); model('order_goods')->commit(); $param = [ 'order_goods_info' => $order_goods_info, 'refund_status' => $refund_status, 'user_info' => $user_info ]; //收货后事件 TakeDelivery::after($param); return $this->success(); } catch (Exception $e) { model('order_goods')->rollback(); return $this->error('', $e->getMessage()); } } /** * 会员申请退款 * @param $data * @param $member_info * @param array $log_data * @return array */ public function apply($data, $member_info, $log_data = []) { $order_goods_id = $data['order_goods_id']; $order_goods_info = model('order_goods')->getInfo(['order_goods_id' => $order_goods_id], '*'); if (empty($order_goods_info)) return $this->error([], '订单项不存在!'); $event = 'orderRefundApply'; if ($order_goods_info['refund_status'] == OrderRefundDict::REFUND_DIEAGREE) { $event = 'orderRefundAsk'; } if (!$this->refundActionCheck($order_goods_info['refund_status'], 'buyer', $event)) { return $this->error([], '当前状态不可操作'); } $refund_type_list = $this->getRefundType($order_goods_info); //防止退款方式越权 if (!in_array($data['refund_type'], $refund_type_list)) return $this->error([], '退款方式不符合!'); $order_info = model('order')->getInfo(['order_id' => $order_goods_info['order_id']]); if (empty($order_info)) return $this->error([], '订单不存在!'); $param = [ 'order_info' => $order_info, 'order_goods_info' => $order_goods_info, 'member_info' => $member_info, 'log_data' => $log_data ]; //校验是否可以申请退款 Apply::check($param); $refund_status = OrderRefundDict::REFUND_APPLY; $refund_status_data = OrderRefundDict::getStatus($refund_status); $data['refund_status'] = $refund_status; $data['refund_status_name'] = $refund_status_data['name']; $data['refund_status_action'] = json_encode($refund_status_data, JSON_UNESCAPED_UNICODE); $data['refund_mode'] = $order_info['order_status'] == Order::ORDER_COMPLETE ? OrderRefundDict::after_sales : OrderRefundDict::refund; $pay_model = new Pay(); $data['refund_no'] = $pay_model->createRefundNo(); $data['refund_action_time'] = time(); $refund_apply_money_array = $this->getOrderRefundMoney($order_goods_id);//可退款金额 通过计算获得 $refund_apply_money = $refund_apply_money_array['refund_money']; $refund_delivery_money = $refund_apply_money_array['refund_delivery_money']; $data['refund_apply_money'] = $refund_apply_money;//申请的总退款 $data['refund_delivery_money'] = $refund_delivery_money;//退的运费 $data['is_refund_stock'] = 0;//初始化为不退库存 model('order_goods')->startTrans(); try { $res = model('order_goods')->update($data, ['order_goods_id' => $order_goods_id]); //退款需要操作的事件 Apply::event($param); model('order_goods')->commit(); //退款之后的事件 $param['refund_log_data'] = [ $order_goods_info['order_goods_id'], OrderRefundDict::REFUND_APPLY, '买家申请退款', 1, $member_info['member_id'], $member_info['nickname'] ]; // Queue::push('app\job\order_refund\OrderRefundApplyAfter', $param); Apply::after($param); return $this->success($res); } catch (Exception $e) { model('order_goods')->rollback(); return $this->error('', $e->getMessage()); } } /** * 用户撤销退款申请 * @param $data * @param $member_info * @param array $log_data * @return array */ public function cancel($data, $member_info, $log_data = []) { $order_goods_id = $data['order_goods_id']; $order_goods_info = model('order_goods')->getInfo(['order_goods_id' => $order_goods_id]); if (empty($order_goods_info)) return $this->error([], '订单项不存在!'); if (!$this->refundActionCheck($order_goods_info['refund_status'], 'buyer', 'orderRefundCancel')) { return $this->error([], '当前状态不可操作'); } $order_info = model('order')->getInfo(['order_id' => $order_goods_info['order_id']]); if (empty($order_info)) return $this->error([], '订单不存在!'); $param = [ 'order_info' => $order_info, 'order_goods_info' => $order_goods_info, 'log_data' => $log_data, 'member_info' => $member_info ]; model('order_goods')->startTrans(); try { //如果有主动退款撤销后是变为部分退款状态 if ($order_goods_info['shop_active_refund'] == 1) { $refund_status = OrderRefundDict::PARTIAL_REFUND; $refund_type = OrderRefundDict::ONLY_REFUNDS; } else { $refund_status = OrderRefundDict::REFUND_NOT_APPLY; $refund_type = 0; } $refund_status_data = OrderRefundDict::getStatus($refund_status); $data['refund_status'] = $refund_status; $data['refund_status_name'] = $refund_status_data['name']; $data['refund_status_action'] = json_encode($refund_status_data, JSON_UNESCAPED_UNICODE); $data['refund_type'] = $refund_type; //重置部分字段 $data['refund_apply_money'] = 0; $data['refund_address'] = ''; $data['refund_delivery_remark'] = ''; $data['refund_remark'] = ''; $data['refund_delivery_name'] = ''; $data['refund_delivery_no'] = ''; $data['refund_reason'] = ''; model('order_goods')->update($data, ['order_goods_id' => $order_goods_id]); //订单项退款取消的事件 Cancel::event($param); model('order_goods')->commit(); //订单取消后后续事件 // Queue::push('app\job\order_refund\OrderRefundCancelAfter', $param); Cancel::after($param); return $this->success(); } catch (Exception $e) { model('order_goods')->rollback(); return $this->error('', $e->getMessage()); } } /****************************************************************************订单退款相关操作(开始)**********************************/ /** * 卖家确认退款 * @param $data * @param $user_info * @return array */ public function orderRefundConfirm($data, $user_info) { $order_goods_id = $data['order_goods_id']; $order_goods_info = model('order_goods')->getInfo(['order_goods_id' => $order_goods_id]); if (empty($order_goods_info)) { return $this->error([], '订单项不存在!'); } if (!$this->refundActionCheck($order_goods_info['refund_status'], 'shop', 'orderRefundAgree')) { return $this->error([], '当前状态不可操作'); } $order_info = model('order')->getInfo(['order_id' => $order_goods_info['order_id']], '*'); if (empty($order_info)) return $this->error([], '订单不存在!'); model('order_goods')->startTrans(); try { if ($order_goods_info['refund_type'] == OrderRefundDict::ONLY_REFUNDS) { $data['refund_status'] = OrderRefundDict::REFUND_CONFIRM; //确认等待转账 } else { $data['refund_status'] = OrderRefundDict::REFUND_WAIT_DELIVERY; //确认等待买家发货 } $refund_status_data = OrderRefundDict::getStatus($data['refund_status']); $data['refund_status_name'] = $refund_status_data['name']; $data['refund_status_action'] = json_encode($refund_status_data, JSON_UNESCAPED_UNICODE); $res = model('order_goods')->update($data, ['order_goods_id' => $order_goods_id]); model('order_goods')->commit(); //订单退款同意后事件 $param = [ 'order_info' => $order_info, 'order_goods_info' => $order_goods_info, 'refund_status' => $data['refund_status'], 'user_info' => $user_info ]; // Queue::push('app\job\order_refund\OrderRefundConfirmAfter', $param); Confirm::after($param); return $this->success($res); } catch (Exception $e) { model('order_goods')->rollback(); return $this->error('', $e->getMessage()); } } /** * 卖家拒绝退款 * @param $data * @param $user_info * @param $refund_refuse_reason * @param array $log_data * @return array */ public function orderRefundRefuse($data, $user_info, $refund_refuse_reason, $log_data = []) { $order_goods_id = $data['order_goods_id']; $order_goods_info = model('order_goods')->getInfo([['order_goods_id', '=', $order_goods_id]]); if (empty($order_goods_info)) return $this->error([], '订单项不存在!'); if (!$this->refundActionCheck($order_goods_info['refund_status'], 'shop', 'orderRefundRefuse')) { return $this->error([], '当前状态不可操作'); } $order_info = model('order')->getInfo(['order_id' => $order_goods_info['order_id']], '*'); if (empty($order_info)) return $this->error([], '订单不存在!'); $refund_status = OrderRefundDict::REFUND_DIEAGREE; $refund_status_data = OrderRefundDict::getStatus($refund_status); $data['refund_status'] = $refund_status; $data['refund_status_name'] = $refund_status_data['name']; $data['refund_status_action'] = json_encode($refund_status_data, JSON_UNESCAPED_UNICODE); $data['refund_refuse_reason'] = $refund_refuse_reason; $data['refund_action_time'] = time(); $param = [ 'order_info' => $order_info, 'order_goods_info' => $order_goods_info, 'refund_status' => $refund_status, 'user_info' => $user_info ]; //校验定的那项是否可以退款 Refuse::check($param); model('order_goods')->startTrans(); try { model('order_goods')->update($data, ['order_goods_id' => $order_goods_id]); //拒绝的关联事件 Refuse::event($param); model('order_goods')->commit(); $param['refund_status'] = $data['refund_status']; $param['refund_refuse_reason'] = $refund_refuse_reason; $param['log_data'] = $log_data; //拒绝后事件 Refuse::after($param); return $this->success(); } catch (Exception $e) { model('order_goods')->rollback(); return $this->error('', $e->getMessage()); } } /** * 买家退货 * @param array $data 退货信息 * @param array $member_info 会员信息 */ public function orderRefundDelivery($data, $member_info) { $order_goods_id = $data['order_goods_id'] ?? 0; $order_goods_info = model('order_goods')->getInfo(['order_goods_id' => $order_goods_id]); if (empty($order_goods_info)) { return $this->error([], '订单项不存在!'); } if (!$this->refundActionCheck($order_goods_info['refund_status'], 'buyer', 'orderRefundDelivery')) { return $this->error([], '当前状态不可操作'); } model('order_goods')->startTrans(); try { $refund_status = OrderRefundDict::REFUND_WAIT_TAKEDELIVERY; $refund_status_data = OrderRefundDict::getStatus($refund_status); $data['refund_status'] = $refund_status; $data['refund_status_name'] = $refund_status_data['name']; $data['refund_status_action'] = json_encode($refund_status_data, JSON_UNESCAPED_UNICODE); $refund_address = $this->getRefundAddress($order_goods_info['site_id']); $data['refund_address'] = $refund_address['shop_address']; model('order_goods')->update($data, ['order_goods_id' => $order_goods_id]); model('order_goods')->commit(); $param = [ 'order_goods_info' => $order_goods_info, 'refund_status' => $data['refund_status'], 'member_info' => $member_info, 'refund_delivery_name' => $data['refund_delivery_name'], 'refund_delivery_no' => $data['refund_delivery_no'], ]; //退货后事件 Delivery::after($param); return $this->success(); } catch (Exception $e) { model('order_goods')->rollback(); return $this->error('', $e->getMessage()); } } /** * 查询退货地址 * @param $site_id * @param int $refund_address_id * @return array */ public function getRefundAddress($site_id, $refund_address_id = 0) { $address = []; $site_address_model = new SiteAddress(); $site_address_condition = [ ['site_id', '=', $site_id], ['is_return', '=', 1], ]; if ($refund_address_id > 0) { $site_address_condition[] = ['id', '=', $refund_address_id]; } else { $site_address_condition[] = ['is_return_default', '=', 1]; } $site_address_info = $site_address_model->getAddressInfo($site_address_condition)['data'] ?? []; if (empty($site_address_info)) { unset($site_address_condition[2]); $site_address_info = $site_address_model->getAddressInfo($site_address_condition)['data'] ?? []; } if (empty($site_address_info)) { $shop_model = new Shop(); $shop_info_result = $shop_model->getShopInfo([['site_id', '=', $site_id]], 'full_address,address,name,mobile'); $shop_info = $shop_info_result['data']; $address['shop_contacts'] = $shop_info['name']; $address['shop_mobile'] = $shop_info['mobile']; $address['shop_address'] = $shop_info['full_address'] . $shop_info['address']; } if (!empty($site_address_info)) { $address['shop_contacts'] = $site_address_info['contact_name']; $address['shop_mobile'] = $site_address_info['mobile']; $address['shop_address'] = $site_address_info['full_address']; } return $address; } /** * 关闭退款 * @param $order_goods_id * @param $site_id * @param $user_info * @return array */ public function orderRefundClose($order_goods_id, $site_id, $user_info) { $order_goods_info = model('order_goods')->getInfo(['order_goods_id' => $order_goods_id, 'site_id' => $site_id]); if (empty($order_goods_info)) return $this->error([], '订单项不存在!'); if (!$this->refundActionCheck($order_goods_info['refund_status'], 'shop', 'orderRefundClose')) { return $this->error([], '当前状态不可操作'); } $order_info = model('order')->getInfo(['order_id' => $order_goods_info['order_id']], '*'); if (empty($order_info)) return $this->error([], '订单不存在!'); model('order_goods')->startTrans(); try { //如果有主动退款撤销后是变为部分退款状态 if ($order_goods_info['shop_active_refund'] == 1) { $refund_status = OrderRefundDict::PARTIAL_REFUND; $refund_type = OrderRefundDict::ONLY_REFUNDS; } else { $refund_status = OrderRefundDict::REFUND_NOT_APPLY; $refund_type = 0; } $refund_status_data = OrderRefundDict::getStatus($refund_status); $data = [ 'order_goods_id' => $order_goods_id, 'refund_status' => $refund_status, 'refund_status_name' => $refund_status_data['name'], 'refund_status_action' => json_encode($refund_status_data, JSON_UNESCAPED_UNICODE), 'refund_apply_money' => 0, 'refund_type' => $refund_type, 'refund_address' => '', 'refund_delivery_remark' => '', 'refund_remark' => '', 'refund_delivery_name' => '', 'refund_delivery_no' => '', 'refund_reason' => '' ]; model('order_goods')->update($data, ['order_goods_id' => $order_goods_id]); //退款关闭相关事件 $param = [ 'order_goods_info' => $order_goods_info, 'order_info' => $order_info, 'user_info' => $user_info ]; Close::event($param); model('order_goods')->commit(); //退款关闭后事件 Close::after($param); return $this->success(); } catch (Exception $e) { model('order_goods')->rollback(); return $this->error('', $e->getMessage()); } } /** * 移除订单项退款操作 * @param $condition * @return array */ public function removeOrderGoodsRefundAction($condition) { //订单项增加可退款操作 $data = [ 'refund_status_action' => '' ]; $result = model('order_goods')->update($data, $condition); return $this->success($result); } /************************************************************************ 查询相关函数 *******************************************************************/ /** * 会员维权详情 * @param $order_goods_id * @param $member_id * @return array */ public function getMemberRefundDetail($order_goods_id, $member_id) { $condition = [ ['order_goods_id', '=', $order_goods_id] ]; $condition[] = ['member_id', '=', $member_id]; $order_common_model = new OrderCommon(); $info = $order_common_model->getOrderGoodsInfo($condition)['data']; //将售后日志引入 $refund_log_list = model('order_refund_log')->getList([['order_goods_id', '=', $order_goods_id]], '*', 'action_time desc'); $info['refund_log_list'] = $refund_log_list; return $this->success($info); } /** * 会员维权详情 * @param $order_goods_id * @param int $site_id * @param int $store_id * @return array */ public function getRefundDetail($order_goods_id, $site_id = 0, $store_id = 0) { $order_common_model = new OrderCommon(); $condition = [ ['order_goods_id', '=', $order_goods_id] ]; if ($site_id > 0) { $condition[] = ['site_id', '=', $site_id]; } if ($store_id > 0) { $condition[] = ['store_id', '=', $store_id]; } $info = $order_common_model->getOrderGoodsInfo($condition)['data']; if (empty($info)) return $this->error('', '订单项不存在!'); $order_id = $info['order_id']; $order_info = $order_common_model->getOrderDetail($info['order_id'])['data']; $info['pay_type'] = $order_info['pay_type']; $coupon_info = []; if ($order_info['coupon_id'] > 0) { $order_goods_count = model('order_goods')->getCount([['order_id', '=', $order_id]], 'order_goods_id'); $refund_count = model('order_goods')->getCount([['order_id', '=', $order_id], ['refund_status', '=', OrderRefundDict::REFUND_COMPLETE]], 'order_goods_id'); if (($order_goods_count - $refund_count) == 1) { //查询优惠劵信息 $coupon_model = new Coupon(); $coupon_info = $coupon_model->getCouponInfo([['coupon_id', '=', $order_info['coupon_id']]], 'coupon_id,coupon_name,type,at_least,money,discount,discount_limit')['data']; } } $info['coupon_info'] = $coupon_info; //添加会员昵称 $member = new Member(); $member_info = $member->getMemberInfo([['member_id', '=', $info['member_id']]], 'nickname')['data'] ?? []; $info['nickname'] = $member_info['nickname'] ?? ''; if ($info['refund_status'] == OrderRefundDict::REFUND_NOT_APPLY) { $refund_apply_arr = $this->getOrderRefundMoney($order_goods_id); $info['refund_apply_money'] = round($refund_apply_arr['refund_money'], 2); $info['refund_delivery_money'] = $refund_apply_arr['refund_delivery_money']; } $refund_action = empty($info['refund_status_action']) ? [] : json_decode($info['refund_status_action'], true); $refund_action = $refund_action['action'] ?? []; $info['refund_action'] = $refund_action; //将售后日志引入 $refund_log_list = model('order_refund_log')->getList([['order_goods_id', '=', $order_goods_id]], '*', 'action_time desc'); $info['refund_log_list'] = $refund_log_list; $info['num'] = numberFormat($info['num']); return $this->success($info); } /** * 获取退款维权订单列表 * @param array $condition * @param int $page * @param int $page_size * @param string $order * @param string $field * @return array */ public function getRefundOrderGoodsPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = 'nop.*,no.order_no,no.site_id,no.site_name,no.name,m.nickname') { $join = [ [ 'order no', 'nop.order_id = no.order_id', 'left' ], [ 'member m', 'm.member_id = no.member_id', 'left' ], ]; $list = model('order_goods')->pageList($condition, $field, $order, $page, $page_size, 'nop', $join); $order_common_model = new OrderCommon(); if (!empty($list['list'])) { foreach ($list['list'] as $k => $v) { $list['list'][$k] = $order_common_model->handleOrderGoodsInfo($v); } } return $this->success($list); } /** * 获取退款维权订单数量 * @param array $condition * @return array */ public function getRefundOrderGoodsCount($condition = []) { $count = model('order_goods')->getCount($condition); return $this->success($count); } /** * 获取订单项退款信息 * @param $order_goods_id * @param int $site_id * @param int $store_id * @return array */ public function getOrderGoodsRefundInfo($order_goods_id, $site_id = 0, $store_id = 0) { $order_goods_condition = [ ['order_goods_id', '=', $order_goods_id] ]; if ($site_id > 0) { $order_goods_condition[] = ['site_id', '=', $site_id]; } if ($store_id > 0) { $order_goods_condition[] = ['store_id', '=', $store_id]; } $order_goods_info = model('order_goods')->getInfo($order_goods_condition); if (empty($order_goods_info)) { return $this->error('', '该订单项不存在!'); } if ($order_goods_info['refund_status'] == OrderRefundDict::REFUND_COMPLETE) { return $this->error(null, '该订单项已维权结束!'); } $order_id = $order_goods_info['order_id']; $order_goods_info['num'] = numberFormat($order_goods_info['num']); if ($order_goods_info['refund_status'] == OrderRefundDict::REFUND_NOT_APPLY) { $refund_apply_arr = $this->getOrderRefundMoney($order_goods_id); $order_goods_info['refund_apply_money'] = round($refund_apply_arr['refund_money'], 2); $order_goods_info['refund_delivery_money'] = $refund_apply_arr['refund_delivery_money']; } //获取订单信息 $order_info = model('order')->getInfo([['order_id', '=', $order_goods_info['order_id']]]); $coupon_info = []; if ($order_info['coupon_id'] > 0) { $order_goods_count = model('order_goods')->getCount([['order_id', '=', $order_id]], 'order_goods_id'); $refund_count = model('order_goods')->getCount([['order_id', '=', $order_id], ['refund_status', '=', OrderRefundDict::REFUND_COMPLETE]], 'order_goods_id'); if (($order_goods_count - $refund_count) == 1) { //查询优惠劵信息 $coupon_model = new Coupon(); $coupon_info = $coupon_model->getCouponInfo([['coupon_id', '=', $order_info['coupon_id']]], 'coupon_id,coupon_name,type,at_least,money,discount,discount_limit')['data']; } } //补充订单商品信息 $goods_sku_info = model("goods_sku")->getInfo([['sku_id','=',$order_goods_info['sku_id']]],'pricing_type'); if(!empty($goods_sku_info)){ $order_goods_info = array_merge($order_goods_info, $goods_sku_info); } $data = [ 'order_goods_info' => $order_goods_info, 'order_info' => $order_info, 'coupon_info' => $coupon_info ]; //预售订单 if ($order_info['promotion_type'] == 'presale') { $presale_order_model = new PresaleOrder(); $presale_order_info = $presale_order_model->getPresaleOrderInfo([['order_no', '=', $order_info['order_no']]], 'presale_deposit_money,final_money'); $data['presale_order_info'] = $presale_order_info['data']; } return $this->success($data); } /** * 求和 * @param array $where * @param string $field * @param string $alias * @param null $join * @return array */ public function getRefundSum($where = [], $field = '', $alias = 'a', $join = null) { $data = model('order_goods')->getSum($where, $field, $alias, $join); return $this->success($data); } /********************************************************************** 主动退款 ********************************************************************/ /** * 主动完成退款流程 * @param $order_id * @param $remark * @param $refund_reason * @return array|mixed|void */ public function activeRefund($order_id, $remark, $refund_reason) { $order_info = model('order')->getInfo([['order_id', '=', $order_id]], '*'); if ($order_info['order_money'] > 0) { $pay_model = new Pay(); //遍历订单项 $order_goods_list = model('order_goods')->getList([['order_id', '=', $order_id]]); if (!empty($order_goods_list)) { $count = count($order_goods_list); foreach ($order_goods_list as $k => $v) { $item_refund_money = $v['real_goods_money']; if ($count == ($k + 1)) { $item_refund_money += $order_info['delivery_money']; } $item_result = $this->activeOrderGoodsRefund($v['order_goods_id'], $item_refund_money, $remark, $refund_reason); if ($item_result['code'] < 0) { return $item_result; } } } //订单整体退款 // $refund_result = $pay_model->refund($refund_no, $order_info['pay_money'], $order_info['out_trade_no'], '', $order_info['pay_money'], $order_info['site_id'], 1); } return $this->success(); } /** * 订单项主动退款 * @param $order_goods_id * @param $refund_money * @param string $remark * @param string $refund_reason * @return array|mixed|void */ public function activeOrderGoodsRefund($order_goods_id, $refund_money, $remark = '', $refund_reason = '') { //判断是否退款完毕 $order_goods_info = model('order_goods')->getInfo([['order_goods_id', '=', $order_goods_id]]); if ($order_goods_info['refund_status'] == OrderRefundDict::REFUND_COMPLETE) return $this->error('', '订单不能重复维权!'); $order_info = model('order')->getInfo(['order_id' => $order_goods_info['order_id']]); model('order_goods')->startTrans(); try { $pay_model = new Pay(); $refund_no = $pay_model->createRefundNo(); $update_data = [ 'refund_no' => $refund_no, 'refund_time' => time(), 'refund_reason' => $refund_reason, 'refund_apply_money' => $refund_money, 'refund_real_money' => $refund_money, 'refund_action_time' => time() ]; $refund_status = OrderRefundDict::REFUND_COMPLETE; $refund_status_data = OrderRefundDict::getStatus($refund_status); $update_data['refund_status'] = $refund_status; $update_data['refund_status_name'] = $refund_status_data['name']; $update_data['refund_status_action'] = json_encode($refund_status_data, JSON_UNESCAPED_UNICODE); $res = model('order_goods')->update($update_data, [['order_goods_id', '=', $order_goods_id]]); if ($res === false) { model('order_goods')->rollback(); return $this->error(); } $refund_result = $this->finishAction(array_merge($order_goods_info, $update_data), $order_info, [], 1, true); if ($refund_result['code'] < 0) { model('order_goods')->rollback(); return $refund_result; } //退货日志 $this->addOrderRefundLog($order_goods_id, OrderRefundDict::REFUND_COMPLETE, $remark . ',维权完成', 3, 0, '平台'); model('order_goods')->commit(); return $this->success(); } catch (Exception $e) { model('order_goods')->rollback(); return $this->error('', $e->getMessage()); } } /** * 商家主动退款 * @param $param * @return array */ public function shopActiveRefund($param) { try { $order_goods_id = $param['order_goods_id']; $shop_active_refund_money = $param['shop_active_refund_money']; $shop_active_refund_remark = $param['shop_active_refund_remark']; $shop_active_refund_money_type = $param['shop_active_refund_money_type']; $shop_active_refund_status = $param['refund_status'] ?? 'PARTIAL_REFUND'; $is_refund_stock = $param['is_refund_stock'] ?? 0; //检测 $check_res = ActiveRefund::check($param); if ($check_res['code'] < 0) return $check_res; $order_goods_info = $check_res['data']['order_goods_info']; $order_info = $check_res['data']['order_info']; $refund_apply_money = $check_res['data']['refund_apply_money']; if(empty($order_goods_info['goods_id'])){ $is_refund_stock = 0 ; //无码商品不退库存 } //退款编号 $pay_model = new Pay(); $shop_active_refund_no = $pay_model->createRefundNo(); //计算退款余额和现金部分 if ($order_info['balance_money'] > 0) { $balance_rate = $order_info['balance_money'] / $order_info['order_money']; $refund_balance_money = $shop_active_refund_money * $balance_rate; $refund_pay_money = $shop_active_refund_money - $refund_balance_money; } else { $refund_balance_money = 0; $refund_pay_money = $shop_active_refund_money; } //判断退款状态 if ($shop_active_refund_money == $refund_apply_money) { $refund_status = OrderRefundDict::REFUND_COMPLETE; } else { if ($shop_active_refund_status == 'PARTIAL_REFUND') { $refund_status = OrderRefundDict::PARTIAL_REFUND; } else { $refund_status = OrderRefundDict::REFUND_COMPLETE; } } $refund_status_data = OrderRefundDict::getStatus($refund_status); //更新数据 $update_data = [ 'shop_active_refund' => 1, 'shop_active_refund_no' => $shop_active_refund_no, 'shop_active_refund_remark' => $shop_active_refund_remark, 'shop_active_refund_money' => $shop_active_refund_money, 'shop_active_refund_money_type' => $shop_active_refund_money_type, 'refund_time' => time(), 'refund_action_time' => time(), 'refund_no' => $shop_active_refund_no, 'refund_type' => OrderRefundDict::ONLY_REFUNDS, 'refund_status' => $refund_status, 'refund_status_name' => $refund_status_data['name'], 'refund_status_action' => json_encode($refund_status_data, JSON_UNESCAPED_UNICODE), 'is_refund_stock' => $is_refund_stock,//初始化为不退库存 ]; } catch (Exception $e) { return $this->error(null, $e->getMessage()); } model('order_goods')->startTrans(); try { model('order_goods')->update($update_data, [['order_goods_id', '=', $order_goods_id]]); $order_goods_info = array_merge($order_goods_info, $update_data); //调用退款操作 $action_res = $this->refundMoneyAction([ 'order_goods_id' => $order_goods_id, 'refund_pay_money' => $refund_pay_money, 'refund_balance_money' => $refund_balance_money, 'refund_money_type' => $shop_active_refund_money_type, 'refund_no' => $shop_active_refund_no, 'order_info' => $order_info, ]); if ($action_res['code'] < 0) { model('order_goods')->rollback(); return $action_res; } event('OrderRefundMoneyFinish', ['order_goods_info' => $order_goods_info, 'order_info' => $order_info, 'refund_money' => $shop_active_refund_money]); //如果退款完成则调用完成操作 if ($refund_status == OrderRefundDict::REFUND_COMPLETE) { $action_res = $this->finishAction($order_goods_info, $order_info); if ($action_res['code'] < 0) { model('order_goods')->rollback(); return $action_res; } } $check_res['data']['order_goods_info'] = $order_goods_info; ActiveRefund::event(array_merge($param, $check_res['data'])); model('order_goods')->commit(); ActiveRefund::after(array_merge($param, $check_res['data'])); return $this->success(); } catch (Exception $e) { model('order_goods')->rollback(); return $this->error(null, $e->getMessage()); } } /********************************************************************** 退款公共事件 ********************************************************************/ /** * 添加退款操作日志 * @param $order_goods_id * @param $refund_status * @param $action * @param $action_way * @param $action_userid * @param $action_username * @param string $desc * @return int|string */ public function addOrderRefundLog($order_goods_id, $refund_status, $action, $action_way, $action_userid, $action_username, $desc = '') { $data = [ 'order_goods_id' => $order_goods_id, 'refund_status' => $refund_status, 'action' => $action, 'action_way' => $action_way, 'action_userid' => $action_userid, 'username' => $action_username, 'action_time' => time(), 'desc' => $desc ]; return model('order_refund_log')->add($data); } /** * 锁定订单 * @param $order_id * @return int */ public function verifyOrderLock($order_id) { $condition = [ ['order_id', '=', $order_id], ['refund_status', 'not in', [OrderRefundDict::REFUND_NOT_APPLY, OrderRefundDict::REFUND_COMPLETE, OrderRefundDict::PARTIAL_REFUND]], ]; $count = model('order_goods')->getCount($condition, 'order_goods_id'); $order_common_model = new OrderCommon(); if ($count > 0) { $res = $order_common_model->orderLock($order_id); } else { $res = $order_common_model->orderUnlock($order_id); } return $res; } /** * 退款完成操作 * @param $order_goods_info * @param $order_info * @param array $log_data * @param int $is_deposit_back * @param bool $is_active_refund * @return array|mixed|void */ public function finishAction($order_goods_info, $order_info, $log_data = [], $is_deposit_back = 1, $is_active_refund = false) { $order_goods_id = $order_goods_info['order_goods_id']; $order_id = $order_goods_info['order_id']; $order_no = $order_info['order_no']; //订单项总数 $order_goods_count = model('order_goods')->getCount([['order_id', '=', $order_id]], 'order_goods_id'); //退款订单项数 $refund_count = model('order_goods')->getCount([['order_id', '=', $order_id], ['refund_status', '=', OrderRefundDict::REFUND_COMPLETE]], 'order_goods_id'); //是否全部退款 $is_all_refund = false; $is_all_refund_money = false; if ($order_goods_count == $refund_count) { $is_all_refund = true; $is_all_refund_money = true; } $refund_total_real_money = model('order_goods')->getSum([['order_id', '=', $order_id], ['refund_status', '=', OrderRefundDict::REFUND_COMPLETE]], 'refund_real_money'); $refund_total_real_money += model('order_goods')->getSum([['order_id', '=', $order_id], ['shop_active_refund', '=', 1]], 'shop_active_refund_money'); if ($refund_total_real_money > $order_info['order_money']+$order_info['delivery_money']) { Log::write("订单退款异常,退款金额不能大于订单总金额:".json_encode(['refund_total_real_money'=>$refund_total_real_money,'order_info'=>$order_info])); return $this->error([], '退款金额不能大于订单总金额!'); } $refund_pay_money_sum = model('order_goods')->getSum([['order_id', '=', $order_id], ['refund_status', '=', OrderRefundDict::REFUND_COMPLETE], ['order_goods_id', '<>', $order_goods_id]], 'refund_pay_money'); $shop_active_refund_money_sum = model('order_goods')->getSum([['order_id', '=', $order_id], ['shop_active_refund', '=', 1], ['order_goods_id', '<>', $order_goods_id]], 'shop_active_refund_money'); $remain_pay_money = $order_info['pay_money'] - $refund_pay_money_sum - $shop_active_refund_money_sum; //todo 退还创建订单时使用的次卡 //实际执行转账 (存在余额支付的话 退款一部分余额 退还一部分实际金额) //订单退款退回余额积分等操作 if ($order_info['balance_money'] > 0 && $order_goods_info['refund_real_money'] > 0) { $balance_rate = $order_info['balance_money'] / $order_info['order_money']; $refund_balance_money = $order_goods_info['refund_real_money'] * $balance_rate; $refund_pay_money = $order_goods_info['refund_real_money'] - $refund_balance_money; } else { $refund_balance_money = 0; $refund_pay_money = $order_goods_info['refund_real_money']; } if ($refund_pay_money > 0 && $refund_pay_money > $remain_pay_money) { $refund_balance_money += $refund_pay_money - $remain_pay_money; $refund_pay_money = $remain_pay_money; } $param = [ 'order_info' => $order_info, 'order_goods_info' => $order_goods_info, 'is_all_refund' => $is_all_refund, 'refund_total_real_money' => $refund_total_real_money, 'log_data' => $log_data ]; model('order_goods')->startTrans(); try { model('order_goods')->update(['refund_pay_money' => $refund_pay_money], ['order_goods_id' => $order_goods_id]); $addon_result = event('AddonOrderRefund', ['order_no' => $order_no, 'promotion_type' => $order_info['promotion_type'], 'is_deposit_back' => $is_deposit_back, 'refund_money_type' => $order_goods_info['refund_money_type']], true); if (empty($addon_result)) { //根据选择的退款方式来退款 $action_res = $this->refundMoneyAction([ 'order_goods_id' => $order_goods_id, 'refund_pay_money' => $refund_pay_money, 'refund_balance_money' => $refund_balance_money, 'refund_money_type' => $order_goods_info['refund_money_type'], 'refund_no' => $order_goods_info['refund_no'], 'order_info' => $order_info, ]); if ($action_res['code'] < 0) { model('order_goods')->rollback(); return $action_res; } event('OrderRefundMoneyFinish', ['order_goods_info' => $order_goods_info, 'order_info' => $order_info, 'refund_money' => $order_goods_info['refund_real_money']]); } else { if ($addon_result['code'] < 0) { model('order_goods')->rollback(); return $addon_result; } } //退款完成操作关联事件 FinishAction::event($param); //验证订单是否全部退款完毕 订单如果全部退款完毕,订单关闭 if ($is_all_refund) { //将订单设置为不可退款 $order_common_model = new OrderCommon(); $order_common_model->orderUpdate(['is_enable_refund' => 0], [['order_id', '=', $order_id]]); //完成的订单不会关闭(收银台订单除外) if ($order_info['order_status'] != Order::ORDER_COMPLETE && $is_all_refund) { $param['is_all_refund_money'] = $is_all_refund_money; //订单完全退款事件(金额完全退) event('OrderRefundAllFinish', $param); $order_common_model = new OrderCommon(); //记录订单日志 start if (!empty($log_data)) { $log_data = array_merge($log_data, [ 'order_id' => $order_id, 'order_status' => OrderCommon::ORDER_CLOSE, 'order_status_name' => '已关闭' ]); // $order_common_model->addOrderLog($log_data); } $close_result = $order_common_model->orderClose($order_id, $log_data ?? [], $order_goods_info['refund_reason'] ?: '退款完成,订单关闭!'); if ($close_result['code'] < 0) { model('order_goods')->rollback(); return $close_result; } } } model('order_goods')->commit(); //退款完成操作后事件 $param['is_all_refund_money'] = $is_all_refund_money; FinishAction::after($param); return $this->success(); } catch (Exception $e) { model('order_goods')->rollback(); return $this->error('', $e->getMessage()); } } /** * 退款金额操作 * 1、用户申请同意后转账 * 2、商家主动退款 * @param $param * @return array|mixed|void */ public function refundMoneyAction($param) { $order_goods_id = $param['order_goods_id']; $refund_pay_money = $param['refund_pay_money']; $refund_balance_money = $param['refund_balance_money']; $refund_money_type = $param['refund_money_type']; $refund_no = $param['refund_no'] ?? ''; $order_info = $param['order_info']; //根据选择的退款方式来退款 $refund_stat_money = 0; switch ($refund_money_type) { case OrderRefundDict::back: //原路退回的时候退还余额 + 支付金额 //退还直接支付的金额 if ($refund_pay_money > 0) { $pay_model = new Pay(); if ($refund_no == '') { $refund_no = $pay_model->createRefundNo(); } $refund_result = $pay_model->refund($refund_no, $refund_pay_money, $order_info['out_trade_no'], '', $order_info['pay_money'], $order_info['site_id'], 1, $order_goods_id, $order_info['is_video_number']); if ($refund_result['code'] < 0) { return $refund_result; } } //余额部分 $balance_result = $this->refundBalanceMoneyAction($param); if ($balance_result['code'] < 0) return $balance_result; $refund_stat_money = $refund_pay_money; break; case OrderRefundDict::balance://退款到余额 $member_account_model = new MemberAccount(); $refund_result = $member_account_model->addMemberAccount($order_info['site_id'], $order_info['member_id'], AccountDict::balance, $refund_pay_money + $refund_balance_money, 'refund', $order_info['order_id'], '订单退款返还!'); if ($refund_result['code'] < 0) { return $refund_result; } break; case OrderRefundDict::offline://线下退款 //余额部分 $balance_result = $this->refundBalanceMoneyAction($param); if ($balance_result['code'] < 0) return $balance_result; $refund_stat_money = $refund_pay_money; break; } //退款统计金额 原路退款和线下退款中的现金部分需要统计 if ($refund_stat_money > 0) { $stat_model = new Stat(); $stat_model->switchStat(['type' => 'order_refund', 'data' => ['order_goods_id' => $order_goods_id, 'refund_pay_money' => $refund_stat_money, 'site_id' => $order_info['site_id']]]); } return $this->success(); } /** * 退余额操作 * @param $param * @return array */ public function refundBalanceMoneyAction($param) { $refund_balance_money = $param['refund_balance_money']; $order_info = $param['order_info']; //退款余额 if ($refund_balance_money > 0) { $member_account_model = new MemberAccount(); // 查询该订单使用的现金余额 $order_use_balance_money = abs($member_account_model->getMemberAccountSum([['account_type', '=', AccountDict::balance_money], ['type_tag', '=', $order_info['order_id']], ['from_type', '=', 'order']], 'account_data')['data']); // 查询该订单已退回的现金余额 $refunded_balance_money = $member_account_model->getMemberAccountSum([['account_type', '=', AccountDict::balance_money], ['type_tag', '=', $order_info['order_id']], ['from_type', '=', 'refund']], 'account_data')['data']; if ($order_use_balance_money > $refunded_balance_money) { $refundable_balance_money = $order_use_balance_money - $refunded_balance_money; $refundable_balance_money = min($refundable_balance_money, $refund_balance_money); $refund_balance_money -= $refundable_balance_money; $balance_result = $member_account_model->addMemberAccount($order_info['site_id'], $order_info['member_id'], AccountDict::balance_money, $refundable_balance_money, 'refund', $order_info['order_id'], '订单退款返还!'); if ($balance_result['code'] < 0) { return $balance_result; } } if ($refund_balance_money > 0) { $balance_result = $member_account_model->addMemberAccount($order_info['site_id'], $order_info['member_id'], AccountDict::balance, $refund_balance_money, 'refund', $order_info['order_id'], '订单退款返还!'); if ($balance_result['code'] < 0) { return $balance_result; } } } return $this->success(); } /** * 退货完成 * @param $data * @param $user_info * @param array $log_data * @return array */ public function orderRefundFinish($data, $user_info, $log_data = []) { $order_goods_id = $data['order_goods_id']; $order_goods_info = model('order_goods')->getInfo([['order_goods_id', '=', $order_goods_id]]); if (empty($order_goods_info)) return $this->error([], '订单项不存在!'); $order_id = $order_goods_info['order_id']; $order_info = model('order')->getInfo([['order_id', '=', $order_id]]); if (empty($order_info)) return $this->error([], '订单不存在!'); $refund_apply_money = $order_goods_info['refund_apply_money']; $update_data = [ 'refund_time' => time(), ]; if (!$this->refundActionCheck($order_goods_info['refund_status'], 'shop', 'orderRefundTransfer')) { return $this->error(null, '当前状态不可操作'); } if ($data['refund_real_money'] > $refund_apply_money) return $this->error('', '退款金额超出最大可退金额!'); model('order_goods')->startTrans(); try { $update_data['refund_apply_money'] = $refund_apply_money; $update_data['refund_money_type'] = $data['refund_money_type']; $update_data['refund_real_money'] = $data['refund_real_money']; $update_data['shop_refund_remark'] = $data['shop_refund_remark']; $update_data['refund_delivery_money'] = $data['refund_delivery_money'] ?? 0.00; $refund_status = OrderRefundDict::REFUND_COMPLETE; $refund_status_data = OrderRefundDict::getStatus($refund_status); $update_data['refund_status'] = $refund_status; $update_data['refund_status_name'] = $refund_status_data['name']; $update_data['refund_status_action'] = json_encode($refund_status_data, JSON_UNESCAPED_UNICODE); model('order_goods')->update($update_data, [['order_goods_id', '=', $order_goods_id]]); //订单日志 if(!empty($log_data)){ $order_common_model = new OrderCommon(); $log_data['action'] = '商品【'.$order_goods_info['sku_name'].'】'.$log_data['action']; $log_data = array_merge($log_data, [ 'order_id' => $order_goods_info['order_id'], 'order_status' => $order_info['order_status'], 'order_status_name' => $order_info['order_status_name'] ]); OrderLog::addOrderLog($log_data, $order_common_model); } //退款操作 $result = $this->finishAction(array_merge($order_goods_info, $update_data), $order_info, $log_data, $data['is_deposit_back'] ?? 0); if ($result['code'] < 0) { model('order_goods')->rollback(); return $result; } $param = [ 'refund_real_money' => $data['refund_real_money'], 'order_goods_info' => array_merge($order_goods_info, $update_data), 'order_info' => $order_info, 'user_info' => $user_info ]; //退款后相关事件 Finish::event($param); model('order_goods')->commit(); //退款完成后事件 Finish::after($param); return $this->success(); } catch (Exception $e) { model('order_goods')->rollback(); return $this->error('', $e->getMessage()); } } /** * 订单项退款 * @param $order_goods_info * @return mixed|void */ public function orderGoodsRefund($order_goods_info) { $order_info = model('order')->getInfo(['order_id' => $order_goods_info['order_id']]); if (!empty($order_info)) { $order_info['goods_num'] = numberFormat($order_info['goods_num']); } $order_goods_info['order_info'] = $order_info; $result = event('OrderGoodsRefund', $order_goods_info, true); if (empty($result)) { $order_common_model = new OrderCommon(); $order_model = $order_common_model->getOrderModel($order_info); $result = $order_model->refund($order_goods_info); } return $result; } /** * 未发货订单项主动退款 * @param $order_goods_id */ public function autoRefundOrder($order_goods_id){ $order_goods_info = model('order_goods')->getInfo([['order_goods_id', '=', $order_goods_id]]); if (empty($order_goods_info)) return $this->error([], '订单项不存在!'); if($order_goods_info['delivery_status'] != OrderGoodsDict::wait_delivery){ return $this->error([], '订单项已发货!'); } return $this->activeOrderGoodsRefund($order_goods_id,$order_goods_info['refund_apply_money'],'未发货订单自动退款'); } }