<?php namespace app\order\controller; use app\coupons\model\CouponModel; use app\order\model\OrderModel; use cmf\controller\HomeBaseController; use think\Db; /** * @title 订单模块 */ class OrderController extends HomeBaseController { function _initialize() { require_once EXTEND_PATH . '/Payment.php'; } /** * @title 下单页面 * @description 默认访问接口 * @author sᴏᴜʟ ᴏғ ᴄɪɴᴅᴇʀ * @url /order/Order/confirm * @method POST * * @param name:activity_id type:int require:1 default:19 desc:上一页选中的活动id * @param name:schedule_id type:int require:1 default:68 desc:上一页选中的批次id * @param name:num type:int require:1 default:2 desc:上一页选中的购买数量 */ public function confirm() { $request = request(); $post = $request->param(); $coupons = new CouponModel; $post['num'] = (request()->param('num') == null) ? 1 : request()->param('num'); $couponsList = $coupons->orderCoupon($post['activity_id'], $post['schedule_id'], $post['num'], session('user.id')); $schedule = Db::name('activity_schedule') ->field('id as schedule_id,start_time,end_time,maximum,real_join_num,addition_join_num,price') ->where(['activity_id' => $post['activity_id']]) ->select(); $total = 0; $choose = []; foreach ($schedule as $k => $v) { $v['start_time'] = date('Y.m.d', $v['start_time']); $v['end_time'] = date('Y.m.d', $v['end_time']); if ($v['schedule_id'] == $post['schedule_id']) { $allowMaximum = $v['maximum'] - ($v['real_join_num'] + $v['addition_join_num']); $total = $v['price'] * $post['num']; $choose = [ 'schedule_id' => $post['schedule_id'], 'time_text' => $v['start_time'] . ' 至 ' . $v['end_time'], 'num' => $post['num'], 'allowMaximum' => $allowMaximum ]; } unset($v['real_join_num']); unset($v['addition_join_num']); unset($v['maximum']); $schedule[$k] = $v; } $result = [ 'is_first' => Db::name('user')->where(['id' => session('user.id')])->value('is_first'), 'activity' => Db::name('activity')->field('id as activity_id,name, is_down_payment as type')->where(['id' => $post['activity_id']])->find(), 'schedule' => $schedule, 'choose' => $choose, 'coupons' => $couponsList, 'down_price' => Db::name('activity')->where(['id' => $post['activity_id']])->value('down_price') * $post['num'], 'total' => $total ]; if (request()->isPost()) { echo json_encode(['data' => $result, 'code' => 20000]); exit(); } else { require_once EXTEND_PATH . '/WeChatCommon.php'; $wx = new \WeChatCommon(); return $this->fetch(':confirm', [ 'data' => $result, 'js_sdk' => $wx->js_sdk() ]); } } /** * @title 提交订单 * @description 默认访问接口 * @author sᴏᴜʟ ᴏғ ᴄɪɴᴅᴇʀ * @url /order/Order/done * @method POST * * @param name:activity_id type:int require:1 default:19 desc:活动id * @param name:schedule_id type:int require:1 default:68 desc:批次id * @param name:num type:int require:1 default:2 desc:购买数量 * @param name:escort type:char require:1 default:同行人id字符串(逗号分隔) desc:1,2,3 * @param name:payment type:int require:1 default:支付方式 desc:0余额,1微信,2支付宝 * @param name:discount_coupon_id type:int require:0 default:112 desc:优惠券id * @param name:room type:char require:1 default:1 desc:房间信息 * @param name:desc type:text require:1 default:0 desc:商家备注 */ public function done() { $request = request(); if ($request->isPost()) { $post = $request->param(); $data['user_id'] = session('user.id'); $data['order_sn'] = date('YmdHis') . rand(0, 9999); $data['activity_id'] = $post['activity_id']; $data['schedule_id'] = $post['schedule_id']; $data['add_time'] = time(); $activity = Db::name('activity')->field('is_down_payment,down_price')->where(['id' => $post['activity_id']])->find(); $data['order_type'] = $activity['is_down_payment']; $data['is_use_discount_coupon'] = (empty($post['discount_coupon_id'])) ? 0 : 1; $data['discount_coupon_id'] = $post['discount_coupon_id']; $data['payment'] = $post['payment']; $data['status'] = 1; $data['room'] = $post['room']; $data['desc'] = $post['desc']; $final_price = $this->getFinalPrice($data['activity_id'], $data['schedule_id'], $post['num'], $data['discount_coupon_id']); $post['escort'] = substr($post['escort'], 0, strlen($post['escort']) - 1); if (empty($post['escort'])) { echo json_encode(['msg' => '请选择出行人', 'code' => 40000]); exit(); } $this->checkOrder($data['schedule_id'], $data['payment'], $post['escort'], $post['num'], $final_price); Db::startTrans(); if (Db::name('order_info')->insert($data)) { $oid = Db::name('order_info')->getLastInsID(); $detail = []; $explode_escort = explode(',', $post['escort']); for ($i = 0; $i < $post['num']; $i++) { $detail[$i] = [ 'oid' => $oid, 'escort_id' => $explode_escort[$i], 'status' => 0 ]; } if (Db::name('order_detail')->insertAll($detail)) { //☆在这就要将优惠券变为已使用☆ if ($data['is_use_discount_coupon'] == 1 && !empty($data['discount_coupon_id'])) { $coupons = [ 'id' => $post['discount_coupon_id'], 'use_time' => time(), 'status' => 2 ]; if (!(Db::name('discount_coupon')->update($coupons))) { Db::rollback(); } } //插入订单记录表(包含订单总价) $log = [ 'oid' => $oid, 'order_amount' => $final_price, 'type' => $data['order_type'] ]; if (Db::name('order_log')->insert($log)) { Db::commit(); //首次下单状态改变 Db::name('user')->update(['id' => session('user.id'), 'is_first' => 0]); //微信支付 if ($data['payment'] == 1) { $info = [ 'attach' => $oid, 'openid' => session('user.openid'), 'body' => '萨米户外', 'total_fee' => $final_price ]; $this->success('微信支付', url('user/Center/orderDetail', ['oid' => $oid]), $this->wxPay($info)); } //支付宝支付 elseif ($data['payment'] == 2) { } //余额支付 elseif ($data['payment'] == 0) { $model = new OrderModel; if ($model->orderCallBack($oid)) { echo json_encode(['msg' => '下单成功', 'code' => 20000, 'url' => url('user/Center/orderDetail', ['oid' => $oid])]); exit(); } else { echo json_encode(['msg' => '下单失败', 'code' => 40000]); exit(); } } else { echo json_encode(['msg' => '未知错误', 'code' => 40000]); exit(); } } } } else { Db::rollback(); echo json_encode(['msg' => '下单失败', 'code' => 40000]); exit(); } } else { echo json_encode(['msg' => '非法操作', 'code' => 40000]); exit(); } } //个人中心继续付款 public function done2() { $request = request(); if ($request->isPost()) { $oid = $request->param('oid'); $info = Db::name('order_info')->alias('o') ->field('status,order_type,a.down_price,s.price') ->join('activity a', 'o.activity_id=a.id') ->join('activity_schedule s ', 'o.schedule_id=s.id') ->where(['o.id' => $oid])->find(); $num = Db::name('order_detail')->where(['oid' => $oid, 'status' => ['neq', 2]])->count(); if ($info['status'] == 1) { if ($info['order_type'] == 0) { $order_amount = $num * $info['price']; } elseif ($info['order_type'] == 1) { $order_amount = $num * $info['down_price']; } else { echo json_encode(['msg' => '未知错误', 'code' => 40000]); exit(); } } elseif ($info['status'] == 3) { $order_amount = $num * $info['price']; } else { echo json_encode(['msg' => '未知错误', 'code' => 40000]); exit(); } //再次支付的支付方式,先更新支付方式 $payment = $request->param('payment'); Db::name('order_info')->update(['id' => $oid, 'payment' => $payment]); if ($payment == 0) { $model = new OrderModel; $balance = Db::name('user')->where(['id'=>session('user.id')])->value('balance'); if($balance < $order_amount) { echo json_encode(['msg' => '您的余额不足', 'code' => 40000]); exit(); } if ($model->orderCallBack($oid, $order_amount)) { //如果是有定金订单,则需要更新order_log if ($info['order_type'] == 1) { Db::name('order_log')->where(['oid' => $oid])->update(['order_amount' => $order_amount]); } echo json_encode(['msg' => '支付成功', 'code' => 20000, 'url' => url('user/Center/orderDetail', ['oid' => $oid])]); exit(); } else { echo json_encode(['msg' => '支付失败', 'code' => 40000]); exit(); } } elseif ($payment == 1) { $data = [ 'attach' => $oid, 'openid' => session('user.openid'), 'body' => '萨米户外', 'total_fee' => $order_amount ]; echo json_encode(['msg' => '微信支付', 'data' => $this->wxPay($data), 'code' => 20000, 'url' => url('user/Center/orderDetail', ['oid' => $oid])]); exit(); } elseif ($payment == 2) { echo json_encode(['msg' => '支付宝支付', 'code' => 20000]); } else { echo json_encode(['msg' => '未知错误', 'code' => 40000]); exit(); } } else { echo json_encode(['msg' => '非法操作', 'code' => 40000]); exit(); } } /** * 计算订单最终价格 * @param $activityId * @param $scheduleId * @param $num * @param null $discountCouponId * @return float|int|mixed * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\ModelNotFoundException * @throws \think\exception\DbException */ private function getFinalPrice($activityId, $scheduleId, $num, $discountCouponId = null) { $info = Db::name('activity')->field('is_down_payment,down_price')->where(['id' => $activityId])->find(); //如果有定金则支付定金*数量 if ($info['is_down_payment'] == 1) { $sum = $info['down_price'] * $num; } //如果没有定金则支付批次金额*数量 else { $price = Db::name('activity_schedule')->where(['activity_id' => $activityId, 'id' => $scheduleId])->value('price'); $sum = $price * $num; } //如果有使用优惠券 if (!empty($discountCouponId)) { //判断该优惠券是否已使用 $coupons = Db::name('discount_coupon')->field('status,reduce,overflow')->where(['id' => $discountCouponId])->find(); if ($coupons['status'] == 1) { //是否符合满减 if ($sum >= $coupons['overflow']) { $sum -= $coupons['reduce']; } } } return $sum; } /** * 订单校验 * @param $scheduleId * @param int $payment * @param $escort * @param $num * @param $finalPrice */ private function checkOrder($scheduleId, $payment = 0, $escort, $num, $finalPrice) { if ($scheduleId == null) { echo json_encode(['msg' => '请选择活动批次', 'code' => 40000]); exit(); } //判断活动是否过期 if (Db::name('activity_schedule')->where(['id' => $scheduleId])->value('deadline') < time()) { echo json_encode(['msg' => '本次活动已过期,请重新选择', 'code' => 40000]); exit(); } //判断出行人与购买数量是否匹配 $escortNum = (strlen($escort) == 1) ? 1 : count(explode(',', $escort)); if ($escortNum != $num) { echo json_encode(['msg' => '购买数量需与出行人数量一致', 'code' => 40000]); exit(); } //判断支付方式 if (($payment != 0 && $payment != 1 && $payment != 2 && $payment) || $payment == null) { echo json_encode(['msg' => '请选择支付方式', 'code' => 40000]); exit(); } //判断用户余额能否支持余额支付 if ($payment == 0) { if (Db::name('user')->where(['id' => session('user.id')])->value('balance') < $finalPrice) { echo json_encode(['msg' => '您的余额不足,请选择其他支付方式', 'code' => 40000]); exit(); } } } //微信支付 private function wxPay($info) { $pay = new \Payment($info['attach'], $info['openid'], $info['body'], 1/*$info['total_fee'] * 100*/); return $pay->pay(); } public function notify() { $pay = new \Payment(); $return = $pay->handleNotify(); if(!empty($return)) { $order = new OrderModel; $order->orderCallBack($return['attach'], $return['total_fee']); } } }