/** * 提前还款 - 全部(可人工指定还款金额) * * @param string $order_id 订单编号 * @param int $money 还款金额 * @param int $pay_type 还款类型:0(默认)管理员手工;1系统自动-来自支付宝;2系统自动-来自桂林银行 * @param string $pay_trade_no 支付交易单号 */ public function repayAllCustom($order_id, $money, $pay_type = 0, $pay_trade_no = '') { if ($money <= 0) { return $this->_error('暂不支持还款金额<=0!'); } $user = $pay_type > 0 ? ['uid' => 0, 'uname' => '系统'] : get_user(); if (!$user) { return $this->_error('无法读取当前操作人信息!'); } // 获取订单并判断状态 $orderModel = new \Loan\Model\OrderModel(); $order = $orderModel->find($order_id); if (!$order) { return $this->_error('订单不存在!'); } if (!in_array($order['status'], $orderModel->allowRepayStatus($pay_type == 0))) { return $this->_error('当前订单状态不允许执行还款!'); } if ($order['is_allow_prepayment'] < 1) { return $this->_error('此订单不允许提前还款!'); } $time_limit = strtotime(date('Y-m-d 00:00:00')); // 开启事务,逐个账单进行处理 $this->startTrans(); $now = time(); // 获取所有未还的账单 $bills = $this->where(['order_id' => $order_id, 'status' => ['in', '0,1']])->order('issue')->select(); if (!$bills) { return $this->_error('找不到待还款账单信息!'); } // 获取缺少的本金 $total_money_principal_remain = 0; foreach ($bills as $bill) { $total_money_principal_remain += max(0, $bill['money_principal'] - $bill['return_money']); } // 判断本金 if (bccomp($money, $total_money_principal_remain, 2) < 0) { $this->rollback(); return $this->_error('还款金额不足以支付本金!'); } // 新增订单日志 M('loan_order_log')->add(['order_id' => $order_id, 'created' => $now, 'uid' => $user['uid'], 'uname' => $user['uname'], 'status' => $order['status'], 'action' => '提前全部还款', 'remark' => $this->_payTypeName($pay_type) . '自定义金额还款:' . number_format($money, 2, '.', '')]); // 处理每一个账单 $money_remain = $money; $total_money_principal = 0; foreach ($bills as $pos => $bill) { // 验证统计字段 if (bccomp($bill['money_total'], $bill['money_principal'] + $bill['money_fee'] + $bill['money_delay'], 2) != 0) { $this->rollback(); system_warn('检测到账单money_total字段异常!'); return $this->_error('检测money_total字段存在异常,请检查!'); } // 填满本金 $bill_repay_money = max(0, $bill['money_principal'] - $bill['return_money']); // 计算实际还款金额(最后一期的还款金额是把剩余可用金额) if ($pos == count($bills) - 1) { $real_repay_money = $money_remain; } else { $real_repay_money = bccomp($money_remain, $bill_repay_money, 2) >= 0 ? $bill_repay_money : $money_remain; } $total_money_principal += $bill['money_principal']; if ($this->where(['order_id' => $order_id, 'issue' => $bill['issue'], 'return_money' => $bill['return_money'], 'status' => $bill['status']])->save(['status' => 2, 'return_time' => $now, 'return_money' => $bill['return_money'] + $real_repay_money]) != 1) { $this->rollback(); return $this->_error('更新账单操作失败,请稍后重试!'); } // 新增支付日志 M('loan_bill_pay')->add(['order_id' => $order_id, 'issue' => $bill['issue'], 'created' => $now, 'type' => $pay_type, 'trade_no' => $pay_trade_no, 'money' => $real_repay_money]); // 更新剩余金额 $money_remain -= $real_repay_money; } // 更新用户已归还金额(仅限本金) M('loan_user')->where('uid=' . $order['uid'])->setInc('total_money_return', $total_money_principal); M('loan_user')->where('uid=' . $order['uid'])->setInc('total_money_remain', $total_money_principal); // 更新 - 订单最后还款期号和已还款金额 if (!$orderModel->where(['id' => $order_id, 'status' => $order['status']])->save(['status' => $orderModel::STATUS_FINISH_SUCCESS, 'last_bill_issue' => 0, 'loan_money_return' => ['exp', 'loan_money_return+' . $total_money_principal]])) { $this->rollback(); return $this->_error('更新账单状态失败,请刷新后重试!'); } // 新增日志 M('loan_order_log')->add(['order_id' => $order_id, 'created' => time(), 'uid' => $user['uid'], 'uname' => $user['uname'], 'status' => $order['status'], 'action' => '还款全部完成']); // 更新资金流 $orderModel->moneyFlow(3, $order_id, 0, $money, $user, $pay_trade_no); // 提交事务 $this->commit(); // 提醒短信 if ($pay_type == 0) { $this->_sms($order['uid'], $money); } // 还款完成后处理 $this->_after_success($order); return true; }