json_encode($json) ); $condition = array( ['out_trade_no', '=', $out_trade_no] ); $pay_model->edit($data, $condition); //写入单据表 // Cache::set('cashier_cache_' . $out_trade_no, $json); return $this->success(); } public function getCache($out_trade_no) { $pay_model = new Pay(); $pay_info = $pay_model->getPayInfo($out_trade_no)['data'] ?? []; $cache = !empty($pay_info['pay_json']) ? json_decode($pay_info['pay_json'], true) : []; // $cache = Cache::get('cashier_cache_' . $out_trade_no); return $this->success($cache); } /** * 创建支付单据 * @param $params * @return array */ public function createPay($params) { $out_trade_no = $params['out_trade_no']; $cache = $this->getCache($out_trade_no)['data'] ?? []; $promotion = $cache['promotion'] ?? []; $member_id = $cache['member_id'] ?? 0; $site_id = $params['site_id']; $params['member_id'] = $member_id; $params['promotion'] = $promotion; $calculate_model = new CashierOrderCalculate(); $calculate_result = $calculate_model->calculate($params); if ($calculate_result['code'] < 0) { return $calculate_result; } $calculate = $calculate_result['data']; $pay_model = new Pay(); $pay_info = $pay_model->getPayInfo($out_trade_no)['data'] ?? []; $pay_money = $pay_info['pay_money']; $surplus_money = $calculate['surplus_money']; if ($pay_money != $surplus_money) { $pay_model->deletePay($out_trade_no); //如果金额与上次一样的话就不需要生成新的支付 // 生成整体付费支付单据 $pay_model->addPay($site_id, $out_trade_no, 'ONLINE_PAY', $calculate['order_name'], $calculate['order_name'], $surplus_money, '', 'CashierOrderPayNotify', ''); $this->setCache($out_trade_no, ['promotion' => $promotion, 'member_id' => $this->params['member_id'] ?? 0]); } return $this->success(); } /** * 去支付 * @param $params * @return array */ public function doPay($params) { $out_trade_no = $params['out_trade_no']; $cache = $this->getCache($out_trade_no)['data'] ?? []; $promotion = $cache['promotion'] ?? []; $member_id = $cache['member_id'] ?? 0; $condition = array( ['out_trade_no', '=', $out_trade_no] ); $info = model('order')->getInfo($condition); $pay_type = $params['pay_type']; $calculate_params = array( 'site_id' => $info['site_id'],//站点id 'out_trade_no' => $out_trade_no, 'store_id' => $info['store_id'], 'online_type' => $params['online_type'] ?? $pay_type, 'pay_type' => $pay_type, 'member_id' => $member_id, ); if (!empty($promotion)) { $calculate_params['promotion'] = $promotion; } $result = $this->confirm($calculate_params); return $result; } /** * 确认支付,生成订单 * @param $params * @return array */ public function confirm($params) { try { $calculate_model = new CashierOrderCalculate(); $result = $calculate_model->calculate($params); if ($result['code'] < 0) return $result; $calculate = $result['data']; $surplus_money = $calculate['surplus_money']; if ($surplus_money <= 0) { $result = $this->orderPay($calculate); if ($result['code'] < 0) return $result; } else { return $this->error([], '当前收银订单未支付'); } return $this->success(); } catch (\Exception $e) { return $this->error('', $e->getMessage() . $e->getLine() . $e->getFile()); } } /** * 订单线上支付 * @param unknown $out_trade_no */ public function orderPay($calculate) { model('order')->startTrans(); try { $out_trade_no = $calculate['out_trade_no']; $cashier_condition = array( ['out_trade_no', '=', $out_trade_no], ); $cashier_order_info = model('order')->getInfo($cashier_condition, '*'); if ($cashier_order_info['order_status'] != 0) { model('order')->rollback(); return $this->error([], '订单未处于待支付状态!'); } $cashier_order_info['goods_num'] = numberFormat($cashier_order_info['goods_num']); $pay_type = empty($calculate['pay_type']) ? 'ONLINE_PAY' : $calculate['pay_type']; $cashier_order_model = new CashierOrder(); $order_common_model = new OrderCommon(); $pat_type_list = $order_common_model->getPayType(['order_type' => $cashier_order_info['order_type']]); $pay_model = new Pay(); $pay_model->edit(['pay_type' => $pay_type, 'pay_time' => time(), 'pay_status' => 2], [['out_trade_no', '=', $out_trade_no]]); $cashier_order_type = $cashier_order_info['cashier_order_type']; switch ($cashier_order_type) { case 'goods': $is_enable_refund = 1; break; case 'recharge': $is_enable_refund = 0; break; case 'card': $is_enable_refund = 1; break; } $data = array( 'pay_money' => $calculate['pay_money'], 'pay_type' => $pay_type, 'pay_type_name' => $pat_type_list[$pay_type] ?? '', 'pay_status' => 1, 'pay_time' => time(), 'reduction' => $calculate['reduction'] ?? 0, 'round_money' => $calculate['round_money'], 'order_money' => $calculate['order_money'], 'promotion_money' => $calculate['promotion_money'] ?? 0, 'balance_money' => $calculate['total_balance'],//总余额 todo 暂时先不区分可提现和不可提现余额 'coupon_id' => $calculate['coupon_id'], 'coupon_money' => $calculate['coupon_money'] ?? 0, 'is_enable_refund' => $is_enable_refund, 'point_money' => $calculate['point_money'] ?? 0, 'point' => $calculate['point'] ?? 0 ); $member_id = $params['member_id'] ?? 0; if ($member_id > 0) { $data['member_id'] = $member_id; } $out_trade_no = $calculate['out_trade_no']; $condition = array( ['out_trade_no', '=', $out_trade_no], ); model('order')->update($data, $condition); //扣除抵扣项 $offset_result = $this->deductOffset($calculate); if ($offset_result['code'] < 0) { model('order')->rollback(); return $offset_result; } // 用户线上支付 if (in_array($pay_type, ['cywechatpay', 'cyalipay', 'cyunionpay', 'wechatpay', 'alipay', 'BALANCE', 'ONLINE_PAY'])) { $log_data = array( 'order_id' => $cashier_order_info['order_id'], 'action' => 'pay', 'site_id' => $cashier_order_info['site_id'], 'member_id' => $cashier_order_info['member_id'], ); (new OrderLog())->addLog($log_data); } else { // 收银员收款 $log_data = array( 'order_id' => $cashier_order_info['order_id'], 'action' => 'pay', 'site_id' => $cashier_order_info['site_id'], 'member_id' => $cashier_order_info['member_id'], 'operater' => [ 'uid' => $cashier_order_info['cashier_operator_id'] ] ); (new OrderLog())->addLog($log_data); } //模拟订单支付后操作钩子 if (addon_is_exit('memberconsume')) { $consume_model = new Consume(); $consume_model->memberConsume(['out_trade_no' => $calculate['out_trade_no'], 'status' => 'pay']); } $complete_result = $cashier_order_model->complete($cashier_order_info); if ($complete_result['code'] < 0) { model('order')->rollback(); return $complete_result; } $create_result = $this->create($cashier_order_info); if ($create_result['code'] < 0) { model('order')->rollback(); return $create_result; } //添加支付验证任务 $cron_model = new Cron(); $cron_model->addCron(1, 1, '支付回调执行', 'OrderPayChangeEvent', time(), $cashier_order_info['order_id']); model('order')->commit(); return $this->success(); } catch (\Exception $e) { model('order')->rollback(); return $this->error('', $e->getMessage() . $e->getFile() . $e->getLine()); } } /** * 订的创建 * @param $params * @return array */ public function create($params) { // Log::write('收银订单创建' . json_encode($params)); $out_trade_no = $params['out_trade_no']; $cashier_condition = array( ['out_trade_no', '=', $out_trade_no], ); $cashier_order_info = model('order')->getInfo($cashier_condition, '*'); model('order')->startTrans(); try { $cashier_order_info['goods_num'] = numberFormat($cashier_order_info['goods_num']); $cashier_order_id = $cashier_order_info['order_id']; $store_id = $cashier_order_info['store_id']; //拆分订单 $order_goods_condition = array( ['order_id', '=', $cashier_order_id], ); $order_goods_list = model('order_goods')->getList($order_goods_condition); foreach ($order_goods_list as $k => $v) { $order_goods_list[$k]['num'] = numberFormat($order_goods_list[$k]['num']); } $site_id = $cashier_order_info['site_id']; $cashier_order_data = $cashier_order_info; $cashier_order_data['goods_list'] = $order_goods_list; $member_id = $cashier_order_info['member_id']; $cashier_order_type = $cashier_order_info['cashier_order_type']; //根据商品类型合并订单组 $cashier_order_refund_model = new CashierOrderRefund(); $order_refund_model = new OrderRefund(); $store_stat = new Stat(); $stat_data = []; switch ($cashier_order_type) { case 'goods': $cashier_trade_model = new CashierTrade(); $item_list = []; foreach ($order_goods_list as $k => $v) { $card_item_id = $v['card_item_id']; if ($card_item_id > 0) { $num = $v['num']; $order_goods_id = $v['order_goods_id']; $type = 'order'; //订单使用此卡 $item_params = array( 'item_id' => $card_item_id, 'num' => $num, 'type' => $type, 'relation_id' => $order_goods_id, 'store_id' => $store_id ); $item_list[] = $item_params; } } if(addon_is_exit('cardservice')){ $member_card_model = new MemberCard(); if (!empty($item_list)) { $user_card_result = $member_card_model->cardUse($item_list); // Log::write('使用此卡错误' . json_encode($user_card_result)); if ($user_card_result['code'] < 0) { $cashier_order_data['refund_reason'] = $user_card_result['message']; $refund_result = $order_refund_model->activeRefund($cashier_order_id, '', '订单退款'); //todo 理论上退款转账不会导致退失败 if ($refund_result['code'] < 0) { model('order')->rollback(); return $refund_result; } model('order')->commit(); return $user_card_result; } } } foreach ($order_goods_list as $k => $v) { $cashier_result = $cashier_trade_model->toSend($v, $cashier_order_info); if ($cashier_result['code'] < 0) { $cashier_order_data['refund_reason'] = $cashier_result['message']; $refund_result = $order_refund_model->activeRefund($cashier_order_id, '', '订单退款'); //todo 理论上退款转账不会导致退失败 if ($refund_result['code'] < 0) { model('order')->rollback(); return $refund_result; } model('order')->commit(); return $cashier_result; } } // 统计数据 $stat_data['billing_count'] = 1; $stat_data['billing_money'] = $cashier_order_info['pay_money']; break; case 'recharge': // Log::write('收银订单创建'); $recharge_order_create_model = new MemberrechargeOrderCreate(); $recharge_order_model = new MemberrechargeOrder(); foreach ($order_goods_list as $k => $v) { $item_sku_id = $v['sku_id']; $goods_money = $v['goods_money']; $data = [ 'recharge_id' => $item_sku_id,//套餐id 'face_value' => $goods_money,//自定义充值面额 'member_id' => $member_id, 'order_from' => $cashier_order_info['order_from'], 'order_from_name' => $cashier_order_info['order_from_name'], 'site_id' => $site_id, 'relate_id' => $cashier_order_id, 'relate_type' => 'order' ]; $recharge_order_result = $recharge_order_create_model->create($data); //todo 这儿也应该退款的 if ($recharge_order_result['code'] < 0) { model('order')->rollback(); // Log::write('充值订单错误' . json_encode($recharge_order_result)); return $recharge_order_result; } $recharge_order_out_trade_no = $recharge_order_result['data']; //todo 支付方式兼容(因为充值订单不一定有) $result = $recharge_order_model->orderPay([ 'out_trade_no' => $recharge_order_out_trade_no, 'pay_type' => $cashier_order_info['pay_type'] ]); if ($result['code'] < 0) { model('order')->rollback(); return $result; } } // 统计数据 $stat_data['recharge_count'] = 1; $stat_data['recharge_money'] = $cashier_order_info['pay_money']; break; case 'card': $cashier_trade_model = new CashierTrade(); foreach ($order_goods_list as $k => $v) { $cashier_result = $cashier_trade_model->toSend($v, $cashier_order_info); if ($cashier_result['code'] < 0) { // $refund_res = $cashier_order_refund_model->orderRefund(['order_id' => $order_id]); // model('order')->commit(); // return $refund_res; $refund_result = $order_refund_model->activeRefund($cashier_order_id, '', '订单退款'); //todo 理论上退款转账不会导致退失败 if ($refund_result['code'] < 0) { model('order')->rollback(); return $refund_result; } model('order')->commit(); return $cashier_result; } } // 统计数据 $stat_data['buycard_count'] = 1; $stat_data['buycard_money'] = $cashier_order_info['pay_money']; break; } $order_stock_model = new OrderStock(); $stock_params = array( 'store_id' => $store_id, 'goods_sku_list' => $order_goods_list, 'site_id' => $cashier_order_info['site_id'], 'user_info' => [ 'uid' => $cashier_order_info['cashier_operator_id'], 'username' => $cashier_order_info['cashier_operator_name'], ] ); $result = $order_stock_model->decOrderStock($stock_params); if ($result['code'] < 0) { $refund_result = $order_refund_model->activeRefund($cashier_order_id, '', '订单退款'); //todo 理论上退款转账不会导致退失败 if ($refund_result['code'] < 0) { model('order')->rollback(); return $refund_result; } model('order')->commit(); return $result; } // 统计下单人数 if ($member_id) { $count = model('order')->getCount([['member_id', '=', $member_id], ['pay_status', '=', 1], ['store_id', '=', $store_id]]); if ($count == 1) $stat_data['order_member_count'] = 1; if ($cashier_order_info['balance_money']) $stat_data['balance_money'] = $cashier_order_info['balance_money']; } // 添加统计数据 if (!empty($stat_data)) { $stat_data['site_id'] = $site_id; $stat_data['store_id'] = $store_id; $store_stat->addStoreStat($stat_data); } model('order')->commit(); return $this->success(); } catch (\Exception $e) { model('order')->rollback(); // Log::write('收银单支付完成错误' . $e->getMessage() . $e->getFile() . $e->getLine()); return $this->error('', $e->getMessage() . $e->getFile() . $e->getLine()); } } /** * 抵扣扣除 * @param $calculate_data */ public function deductOffset($calculate_data) { //使用优惠券 $coupon_result = $this->useCoupon($calculate_data); if ($coupon_result['code'] < 0) { return $coupon_result; } //扣除积分 $point_result = $this->deductPoint($calculate_data); if ($point_result['code'] < 0) { return $point_result; } //抵扣余额 $balance_result = $this->deductBalance($calculate_data); if ($balance_result['code'] < 0) { return $balance_result; } return $this->success(); } /** * 扣除余额 * @param $calacalc_data */ public function deductBalance($calculate_data) { $member_id = $calculate_data['member_id']; $site_id = $calculate_data['site_id']; $cashier_order_type = $calculate_data['cashier_order_type']; $order_id = $calculate_data['order_id'] ?? 0; $is_use_balance = $calculate_data['is_use_balance'] ?? 0; if (in_array($cashier_order_type, ['goods', 'card'])) { //判断是否已经扣除过余额 if ($is_use_balance > 0) { $balance_money = $calculate_data['total_balance'] ?? 0; if ($balance_money > 0) { $member_model = new Member(); $member_account_model = new MemberAccount(); $member_condition = array( ['member_id', '=', $member_id], ['site_id', '=', $site_id] ); $member_info = $member_model->getMemberInfo($member_condition)['data'] ?? []; $member_balance = $member_info['balance'];//储值余额 $member_balance_money = $member_info['balance_money'];//现金余额 if ($balance_money > 0) { $order_data = array(); //优先扣除可不提现余额 $surplus = $balance_money; $temp_balance = $member_balance; if ($member_balance > $surplus) { $temp_balance = $surplus; } $surplus -= $temp_balance; $from_type = 'order'; $relate_tag = '余额抵扣'; $remark = '订单名称:' . $calculate_data['order_name'] . ',订单编号:' . $calculate_data['out_trade_no'] ?? '' . ',订单金额:' . $calculate_data['order_money'] . ',订单余额抵扣,扣除储值余额:' . $temp_balance; $remark = '收银订单余额抵扣'; if ($temp_balance > 0) { $result = $member_account_model->addMemberAccount($site_id, $member_id, 'balance', -$temp_balance, $from_type, $relate_tag, $remark, $order_id); if ($result['code'] < 0) { return $result; } $order_data['balance'] = $temp_balance; } //扣除现金余额 $temp_balance = $member_balance_money; if ($member_balance_money > $surplus) { $temp_balance = $surplus; } $from_type = 'order'; $relate_tag = '余额抵扣'; $remark = '订单名称:' . $calculate_data['order_name'] . ',订单编号:' . $calculate_data['out_trade_no'] . ',订单金额:' . $calculate_data['order_money'] . ',订单余额抵扣,扣除储值余额:' . $temp_balance; $remark = '收银订单余额抵扣'; if ($temp_balance > 0) { $result = $member_account_model->addMemberAccount($site_id, $member_id, 'balance_money', -$temp_balance, $from_type, $relate_tag, $remark, $order_id); if ($result['code'] < 0) { return $result; } $order_data['balance_money'] = $temp_balance; } if (!empty($order_data)) { $order_condition = array( ['order_id', '=', $order_id] ); model('order')->update($order_data, $order_condition); } } } } } return $this->success(); } public function useCoupon($calculate_data) { $coupon_id = $calculate_data['coupon_id'] ?? 0; //只有开单和卡项可以用优惠券 $cashier_order_type = $calculate_data['cashier_order_type']; if (in_array($cashier_order_type, ['goods', 'card'])) { if (!empty($coupon_id)) { $order_id = $calculate_data['order_id']; $member_coupon_model = new MemberCoupon(); //扣除优惠券 $result = $member_coupon_model->useMemberCoupon($coupon_id, $calculate_data['member_id'], $order_id); if ($result['code'] < 0) { return $result; } } } return $this->success(); } /** * 扣除积分 * @param $calacalc_data */ public function deductPoint($calculate_data) { $member_account_model = new MemberAccount(); $member_id = $calculate_data['member_id']; $site_id = $calculate_data['site_id']; $point = $calculate_data['point'] ?? 0; $order_id = $calculate_data['order_id'] ?? 0; $point_money = $calculate_data['point_money'] ?? 0; $order_type = $calculate_data['cashier_order_type']; if (in_array($order_type, ['goods', 'card'])) { if ($point > 0) { $is_use_point = $calculate_data['is_use_point'] ?? 0; if ($is_use_point > 0) { $member_account_model = new MemberAccount(); $from_type = 'order'; $relate_tag = '积分抵扣'; $remark = '收银订单积分抵扣,扣除积分:' . $point; $remark = '收银订单积分抵扣'; $result = $member_account_model->addMemberAccount($site_id, $member_id, 'point', -$point, $from_type, $relate_tag, $remark, $order_id); if ($result['code'] < 0) { return $result; } } } } return $this->success(); } }