'现金', '3' => '微信', '4' => '支付宝', '5' => '会员余额', '6' => '小程序微信', '7' => '其他支付', '8' => '组合', '9' => '德育币', ); } /** * 获取订单支付类型描述 * @param $pay_type 支付类型值 * @param $bill_id 支付类型值 * @return mixed */ public function getPayType($pay_type, $bill_id) { switch ($pay_type) { case 0: //赊账 if (in_array('Credit', C('MODULE_ALLOW_LIST'))) { $CreditRecord = new \Credit\Business\CreditRecord(); $pay_type_name = $CreditRecord->getPayTypeName($bill_id); } else { $pay_type_name = '其他支付'; } break; case 8: $pay_type_name = '组合支付'; break; case 7: //其他支付 $PayOrder = new PayOrder(); $PayList = $PayOrder->getFindPayList('', '', $bill_id); $pay_type_name = $PayList[0]['name']; break; default: $pay_type_name = $this->payType()[$pay_type]; } return $pay_type_name; } /** * 根据pay_order表获取bill_order表的支付类型 * @param $pay_pay_type * @return mixed */ public function getBillPayType($pay_pay_type) { //bill 1现金 3微信支付 4支付宝支付 5会员卡余额支付 6小程序商城微信支付 7其他支付方式 8组合支付 9德育币 //pay 1微信 2支付宝 3现金 4小程序微信 5其他支付方式 6会员余额 8德育币 $array = [ '1' => '3', '2' => '4', '3' => '1', '4' => '6', '5' => '7', '6' => '5', '8' => '9', ]; return $array[$pay_pay_type]; } /** * 根据bill_order表获取pay_order表的支付类型 * @param $bill_pay_type * @return mixed */ public function getPayOrderPayType($bill_pay_type) { //bill 1现金 3微信支付 4支付宝支付 5会员卡余额支付 6小程序商城微信支付 7其他支付方式 8组合支付 9德育币 //pay 1微信 2支付宝 3现金 4小程序微信 5其他支付方式 6会员余额 8德育币 $array = [ '1' => '3', '3' => '1', '4' => '2', '5' => '6', '6' => '4', '7' => '5', '8' => '', '9' => '8', ]; return $array[$bill_pay_type]; } /** * 处理线下退款订单的查询条件 * @param $param * $param['merchant_id'] 商户ID * $param['store_id'] 门店ID * $param['time'] 时间范围 * $param['order_no'] 订单号/原订单号 * $param['pay_type'] 订单支付类型 * $param['status'] 订单退款状态 * $param['vip_phone'] 会员手机号/卡号/实体卡号 * @return array */ private function handleLineRefundMap($param) { $map = [ 'b.merchant_id' => $param['merchant_id'], 'b.store_id' => $param['store_id'], 'b.order_type' => 2, 'b.type' => 2, 'b.pay_state' => ['in', '0,1'], 'b.refund_status' => ['in', '-1,2'], ]; if (!empty($param['time'])) { $map['b.add_time'] = ['between', [strtotime($param['time'][0]), strtotime($param['time'][1])]]; } if (!empty($param['order_no'])) { $map['b.order_no|b.refund_no'] = ['like', "%" . trim($param['order_no']) . "%"]; } if (!empty($param['pay_type'])) { $map['b.pay_type'] = $param['pay_type']; } if (!empty($param['status'])) { switch ($param['status']) { case 1: //退款成功 $map['b.refund_status'] = 2; $map['b.pay_state'] = 1; break; case -1: //退款失败 $map['b.pay_state'] = 0; $map['b.refund_status'] = -1; break; } } //会员搜索 if (!empty($param['vip_phone'])) { $map['v.mobile_phone|v.cardnum|v.card_key'] = ['like', '%' . $param['vip_phone'] . '%']; $map['v.merchantid'] = $param['merchant_id']; $map['v.status'] = 1; } return $map; } /** * 获取线下退款订单的列表 * @param $param * $param['merchant_id'] 商户ID * $param['store_id'] 门店ID * $param['time'] 时间范围 * $param['order_no'] 订单号/原订单号 * $param['pay_type'] 订单支付类型 * $param['status'] 订单退款状态 * $param['vip_phone'] 会员手机号/卡号/实体卡号 * $param['page'] 页码 * $param['limit'] 每页数量 * $param['is_export'] 是否为导出 * @return mixed * @throws \think\Exception * @throws \think\db\exception\DbException */ public function getLineRefundOrderList($param) { $map = $this->handleLineRefundMap($param); if ($param['is_export']) { //导出 $orderList = M('retail_bill_order as b') ->join('ls_retail_bill_discount as d ON b.id=d.bill_id') ->join('ls_retail_vip as v ON b.vid=v.id', 'LEFT') ->field('b.*,d.*,v.mobile_phone as vip_phone,v.name as vip_name,v.nickname as vip_nickname') ->where($map) ->order('b.id desc') ->select(); } else { $orderList = M('retail_bill_order as b') ->join('ls_retail_bill_discount as d ON b.id=d.bill_id') ->join('ls_retail_vip as v ON b.vid=v.id', 'LEFT') ->page($param['page'], $param['limit']) ->field('b.*,d.*,v.mobile_phone as vip_phone,v.name as vip_name,v.nickname as vip_nickname') ->where($map) ->order('b.id desc') ->select(); } $count = 0; if (!empty($orderList)) { if (!$param['is_export']) { $count = M('retail_bill_order as b') ->join('ls_retail_bill_discount as d on b.id=d.bill_id') ->join('ls_retail_vip as v on b.vid=v.id', 'LEFT') ->where($map) ->count(); } $PayOrderModel = new RetailPayOrderModel(); foreach ($orderList as $key => &$val) { $val['index'] = $key + 1; $val['add_time'] = newDate("Y-m-d H:i:s", $val['add_time']); if (!empty($val['vid'])) { $val['identity'] = "会员"; } else { $val['identity'] = "散客"; } switch ($val['refund_status']) { case '2': $val['status_name'] = "退款成功"; $val['refund_money'] = $val['all_money']; $val['wait_refund_money'] = 0; break; case '-1': $val['status_name'] = "退款失败"; $pMap = [ 'bill_id' => $val['id'], 'order_state' => 'REFUND', ]; $refund_money = $PayOrderModel->getSum($pMap, 'trade_amount'); $val['refund_money'] = $refund_money; $val['wait_refund_money'] = bcsub($val['all_money'], $refund_money, 2) * 1; if ($val['refund_money'] == 0) { $val['status_name'] = "退款失败"; } break; } $val['need_refund_state'] = $val['refund_money'] > 0 && $val['wait_refund_money'] > 0 ? 1 : 0; $val['pay_type_name'] = $this->getPayType($val['pay_type']); } } return callBack(statusCode()['success'], empty($orderList) ? '暂无数据' : '获取成功', [ 'list' => $orderList, 'count' => intval($count), ]); } /** * 获取线下退款订单的统计数据 * @param $param * $param['merchant_id'] 商户ID * $param['store_id'] 门店ID * $param['time'] 时间范围 * $param['order_no'] 订单号/原订单号 * $param['pay_type'] 订单支付类型 * $param['status'] 订单退款状态 * $param['vip_phone'] 会员手机号/卡号/实体卡号 * @return mixed 退款失败订单数\退款失败金额\已退金额 * @throws \think\Exception */ public function getLineRefundOrderSumData($param) { $map = $this->handleLineRefundMap($param); $refund_status = $map['b.refund_status']; //退款订单的总金额 $refund_all_money = M('retail_bill_order as b') ->join('ls_retail_bill_discount as d on b.id=d.bill_id') ->join('ls_retail_vip as v on b.vid=v.id', 'LEFT') ->where($map) ->sum('all_money'); $refund_all_money = $refund_all_money ? intval($refund_all_money) : 0; //退款失败总条数 $map['b.refund_status'] = -1; $refund_fail_count = M('retail_bill_order as b') ->join('ls_retail_bill_discount as d on b.id=d.bill_id') ->join('ls_retail_vip as v on b.vid=v.id', 'LEFT') ->where($map) ->count(); //退款成功的金额 $map['b.refund_status'] = $refund_status; $map['p.order_state'] = 'REFUND'; $refund_money = M('retail_bill_order as b') ->join('ls_retail_bill_discount as d on b.id=d.bill_id') ->join('ls_retail_pay_order as p on b.id=p.bill_id') ->join('ls_retail_vip as v on b.vid=v.id', 'LEFT') ->where($map) ->sum('trade_amount'); $refund_money = $refund_money ? intval($refund_money) : 0; //退款失败的金额 $refund_fail_money = bcsub($refund_all_money, $refund_money, 2); return callBack(statusCode()['success'], '获取成功', [ 'refund_fail_count' => $refund_fail_count, 'refund_fail_money' => $refund_fail_money, 'refund_money' => $refund_money, ]); } /** * 部分退款失败订单继续退款 * @param $param * $param['merchant_id'] *商户ID * $param['store_id'] *门店ID * $param['order_no'] *退款订单号 * $param['operate_id'] 操作者ID(修改收银员登录接口后记录) * $param['cashier_id'] 收银员ID * @return mixed */ public function failOrderRefund($param) { $BillOrderModel = new RetailBillOrderModel(); //查询退款订单 $oMap = [ 'merchant_id' => $param['merchant_id'], 'store_id' => $param['store_id'], 'order_no' => strval($param['order_no']), 'refund_status' => -1, 'pay_state' => 0, 'order_type' => 2, ]; $param['refund_order'] = $BillOrderModel->getFind($oMap); if (empty($param['refund_order'])) { return callBack(statusCode()['error'], '订单不存在或已退款成功'); } //查询原购买订单ID $param['buy_bill_id'] = $BillOrderModel->getFindField(['order_no' => strval($param['refund_order']['refund_no'])], 'id'); //查询已退款金额 $PayOrderModel = new RetailPayOrderModel(); $param['refund_all_money'] = $PayOrderModel->getSum(['bill_id' => $param['refund_order']['id'], 'order_state' => 'SUCCESS'], 'trade_amount'); return $this->orderRefund($param); } /** * 订单退款 * @param $param * $param['merchant_id'] *商户ID * $param['store_id'] *门店ID * $param['order_no'] *退款订单号 * $param['operate_id'] 操作者ID(修改收银员登录接口后记录) * $param['cashier_id'] 收银员ID * $param['refund_order'] 退款订单信息 * $param['buy_bill_id'] 原购买订单ID * $param['refund_all_money']已退款金额 * @return mixed */ public function orderRefund($param) { $BillOrderModel = new RetailBillOrderModel(); $PayOrderModel = new RetailPayOrderModel(); if (empty($param['refund_order'])) { //查询退款订单 $oMap = [ 'merchant_id' => $param['merchant_id'], 'store_id' => $param['store_id'], 'order_no' => strval($param['order_no']), 'refund_status' => -1, 'pay_state' => 0, 'order_type' => 2, ]; $refund_order = $BillOrderModel->getFind($oMap); if (empty($refund_order)) { return callBack(statusCode()['error'], '订单不存在或已退款成功'); } } else { $refund_order = $param['refund_order']; } if (empty($param['buy_bill_id'])) { //查询原购买订单ID $param['buy_bill_id'] = $BillOrderModel->getFindField(['order_no' => strval($refund_order['refund_no'])], 'id'); } if (isset($param['refund_all_money'])) { //查询已退款金额 $param['refund_all_money'] = $PayOrderModel->getSum(['bill_id' => $refund_order['id'], 'order_state' => 'SUCCESS'], 'trade_amount'); } //计算待退款金额 $wait_refund_money = bcsub($refund_order['all_money'], $param['refund_all_money'], 2); if ($wait_refund_money <= 0) { return callBack(statusCode()['error'], '该订单已退款完毕,请勿重复操作'); } //获取退款顺序 $RefundOrderModel = new RefundOrderModel(); $refundOrder = $RefundOrderModel->getFindOrderAsc($refund_order['merchant_id']); $refundRes = []; //存储所有退款结果 foreach ($refundOrder as $key => $value) { if ($refund_order['type'] == 1 && !in_array($key, ['wx_refund_order', 'vip_refund_order'])) continue; $map = [ 'bill_id' => $param['buy_bill_id'], 'order_state' => 'SUCCESS', 'order_type' => 1, ]; switch ($key) { case 'cash_refund_order': //现金 $map['pay_type'] = 3; break; case 'vip_refund_order': //会员余额 $map['pay_type'] = 6; break; case 'other_refund_order': //其他支付 $map['pay_type'] = 5; break; case 'al_refund_order': //支付宝 $map['pay_type'] = 2; break; case 'wx_refund_order': //微信 $map['pay_type'] = $refund_order['type'] == 1 ? 4 : 1; break; default: if ($param['refund_all_money'] > 0) { $BillOrderModel->updateOrder(['id' => $refund_order['id']], ['refund_status' => -1]); } return callBack(statusCode()['error'], '系统发生错误'); } $payOrderList = $PayOrderModel->getSelect($map); if (!empty($payOrderList)) { foreach ($payOrderList as $val) { $tempMoney = bcsub($val['trade_amount'], $val['refund_money'], 2); if ($tempMoney && bcadd($param['refund_all_money'], $tempMoney, 2) > $wait_refund_money) { $tempMoney = bcsub($wait_refund_money, $param['refund_all_money'], 2); } $tempMoney = floatval($tempMoney);//钱数转换类型 if (!empty($tempMoney)) { //去退款 $refundRes[] = $this->refundBillOrderPrice([ 'buy_bill_id' => $param['buy_bill_id'], 'new_bill_id' => $refund_order['id'], 'type' => $refund_order['type'] == 1 ? 4 : 1, 'pay_order' => $val, 'refund_money' => $tempMoney, 'cashier_id' => $param['cashier_id'], ]); } $param['refund_all_money'] = bcadd($param['refund_all_money'], $tempMoney, 2); } } if (round($refund_order['all_money'] - $param['refund_all_money'], 2) <= 0) { break; } } if (empty($refundRes)) { return callBack(statusCode()['error'], '退款失败'); } //已退款金额 $refund_success_money = round($refund_order['all_money'] - $wait_refund_money, 2); $message = []; $is_fail = false; //判断是否有失败的退款 $is_success = false; //判断是否有成功的退款 foreach ($refundRes as $v) { if ($v['status'] === 0) { //退款失败 $is_fail = true; $message[] = $v['message']; } else if ($v['status'] == 1) { $refund_success_money = round($refund_success_money + $v['data']['actual_refund_money'], 2); $is_success = true; } } if (count($refundRes) == 1 && $is_fail) { //退款失败 return callBack(statusCode()['error'], '退款失败:' . implode(',', $message)); } else if ($is_fail && $is_success) { //存储为退款失败订单 $save = [ 'refund_status' => -1, ]; $BillOrderModel->updateOrder(['id' => $refund_order['id']], $save); return callBack(statusCode()['error'], '部分退款成功:' . implode(',', $message)); } else { //全部退款成功 if (bcsub($refund_order['all_money'], $wait_refund_money, 2) > 0 || count($refundRes) > 1) { //组合退款 $pay_type = 8; } else { $pay_type = $this->getBillPayType($payOrderList[0]['pay_type']); } $save = [ 'refund_status' => 2, 'pay_type' => $pay_type, ]; $BillOrderModel->updateOrder(['id' => $refund_order['id']], $save); $Sell = new Sell(); $result = $Sell->refundGoods([ 'refund_order' => $refund_order, 'pay_type' => $pay_type, 'buy_bill_id' => $param['buy_bill_id'], ]); return callBack(statusCode()['success'], '退款成功', $result['data']); } } /** * 去退款 * @param $param * $param['buy_bill_id'] 原购买订单ID * $param['new_bill_id'] 退款订单ID * $param['type'] 订单场景 1收银机 2商户后台 3门店后台 4小程序 5公众号 6快捷收款 * $param['pay_order'] 支付流水订单 * $param['refund_money'] 退款金额 * $param['cashier_id'] 收银员ID * @return array */ private function refundBillOrderPrice($param) { $Refund = new Pay(); $res = $Refund->refund([ 'pay_order' => $param['pay_order'], 'vip_scene_type' => $param['type'], 'bill_id' => $param['new_bill_id'], 'cashier_id' => $param['cashier_id'], 'refund_money' => $param['refund_money'], ]); if ($res['status'] == 1) { //支付流水修改 $BillModel = new RetailBillOrderModel(); //增加bill_order表的退款金额 $BillModel->toSetInc(['id' => $param['buy_bill_id']], 'refund_money', $res['data']['actual_refund_money']); if (isset($res['data']['pay_coupon'])) { //减去代金券的金额 $BillModel->toSetDec(['id' => $param['new_bill_id']], 'all_money', $res['data']['pay_coupon']['pay_coupon_fee']); $BillModel->toSetDec(['id' => $param['new_bill_id']], 'refund_money', $res['data']['pay_coupon']['pay_coupon_fee']); $DisCountModel = new RetailBillDiscountModel(); $DisCountModel->updateOrder(['bill_id' => $param['new_bill_id']], [ 'pay_coupon_id_str' => $res['data']['pay_coupon']['pay_coupon_id_str'], 'pay_coupon_fee' => $res['data']['pay_coupon']['pay_coupon_fee'] ]); } return callBack(statusCode()['success'], '退款成功', $res); } else { return callBack(statusCode()['error'], '退款失败', $res); } } }