OrderController.php 14.3 KB
<?php
/**
 * Created by PhpStorm.
 * User: ruidiudiu
 * Date: 2018/11/24
 * Time: 8:54
 */

namespace app\portal\controller;


use cmf\controller\HomeBaseController;
use think\Db;
use think\Log;
use wxapp\pay\WeixinPay;

/**
 * @title 订单相关接口
 * @description 订单相关接口
 * @group 订单相关接口
 */
class OrderController extends HomeBaseController{

//    /**
//     * @title 生成订单
//     * @description 生成订单,加入开始时间和用户id
//     * @author 董瑞恩
//     * @url /portal/order/createOrder
//     * @method GET
//     *
//     * @param name:users_id type:String require:1 default:无 other: desc:用户id
//     * @param name:name type:String require:1 default:无 other: desc:设备名称
//     *
//     */
    public function createOrder($users_id,$name){
        $order=[
            'order_no' => cmf_get_order_sn(),
            'eq_name' => $name,
            'users_id' => $users_id,
            'start_time' => time(),
            'state' => 1
        ];
        try{
            Db::startTrans();
            Db::name('users')->where('id',$users_id)->update(['is_use'=>1]);
            Db::name('order')->insert($order);
        }catch (\Exception $exception){
            Db::rollback();
            $data=[
                'state'=>false,
                'message'=>$exception->getMessage()
            ];
            return $data;
        }
        Db::commit();
        $data=[
            'state'=>true,
            'order_no' => $order['order_no']
        ];
        return $data;
    }

//    /**
//     * @title 完成订单
//     * @description 订单完成,加入结束时间和结算费用,并调用微信统一下单
//     * @author 董瑞恩
//     * @url /portal/order/order
//     * @method GET
//     *
//     * @param name:users_id type:String require:1 default:无 other: desc:用户id
//     *
//     * @return data:返回用于调用支付的参数
//     */
    public function order($users_id,$name){
        $order= Db::name('order')->where(['users_id'=>$users_id,'state'=>1])->find();
        $end_time=time();
        $price=$this->getPrice($users_id,$order['start_time'],$end_time);
        $time=ceil(($end_time-$order['start_time'])/3600);
        $data=[
            'end_time'=>$end_time,
            'time' => $time,
            'price' => $price,
            'state' => 2
        ];
        try{
            Db::startTrans();
            Db::name('users')->where('id',$users_id)->update(['is_use'=>0]);
            Db::name('equipment')->where('name',$name)->update(['use'=>0]);
            Db::name('order')->where('order_no',$order['order_no'])->update($data);
        }catch (\Exception $exception){
            Db::rollback();
            $data=[
                'state'=>false,
                'message'=>'数据库操作失败',
                'error' =>$exception->getMessage()
            ];
            $this->apiResponse(200,'success',$data);
        }
        Db::commit();
        //调起支付
        if ($price==0){
            try{
                Db::name('order')->where(['order_no'=>$order['order_no']])->update(['state'=>3]);
            }catch (\Exception $exception){
                $this->apiResponse(301,'error:'.$exception->getMessage());
            }
            $data=[
                'state'=>2,
            ];
            $this->apiResponse(200,'success',$data);
        }
        $this->pay($order['order_no']);

    }


    public function getPrice($users_id,$start_time,$end_time){
        $cost=Db::name('cost')->where('id',1)->find();
        $interval = Db::name('interval')->where('id',1)->find();
        $is_free=Db::name('users')->where('id',$users_id)->find()['is_free'];
        //一小时免费状态
        $free=$cost['free'];

        //获取整天的价格
        $dayPrice=$this->getDayPrice();

        //用了多少天
        $day=floor(($end_time-$start_time)/86400);
        $dayPrice=$day*$dayPrice;
        //去掉整天的金额
        $new_start_time=$start_time+$day*86400;//时间戳
        $new_end_time= $end_time;//时间戳
        $hours_start_time=date('His',$new_start_time);
        $hours_end_time=date('His',$new_end_time);

        $stateTime=strtotime($interval['start_time']);
        $endTime=strtotime($interval['end_time']);
        //判断预设时间段是否跨天
        $price=0;
        if ($endTime < $stateTime){
            //设备使用时间段是否跨天(不跨天)
            if ($hours_end_time > $hours_start_time){
//                dump(date('Y-m-d H:i:s',$new_start_time));
//                dump(date('Y-m-d H:i:s',$new_end_time));
//                dump(date('Y-m-d H:i:s',$stateTime));
//                dump(date('Y-m-d H:i:s',$endTime));
                //在预设时间段左边并不与之重合
                if (($new_start_time > strtotime('00:00:00') && $new_start_time < $endTime) && ($new_end_time > $new_start_time && $new_end_time < $endTime)){
                    $price +=(ceil(($new_end_time-$new_start_time)/3600) * $interval['price']);
                }
                //与预设时间段的尾部重合
                if (($new_start_time > strtotime('00:00:00') && $new_start_time < $endTime) && ($new_end_time > $endTime && $new_end_time < $stateTime)){
                    $price +=(ceil(($endTime-$new_start_time)/3600) * $interval['price'] +  ceil(($new_end_time-$endTime)/3600) * $cost['cost']);
                }
                //与预设时间段的头尾都重合
                if (($new_start_time > strtotime('00:00:00') && $new_start_time < $endTime) && $new_end_time > $stateTime){
                    $price +=(ceil(($endTime-$new_start_time)/3600) * $interval['price'] +  ceil(($new_end_time-$stateTime)/3600) * $interval['price'] + ceil(($stateTime-$endTime)/3600) * $cost['cost']);
                }
                //不与预设时间段重合
                if (($new_start_time > $endTime && $new_start_time < $stateTime) && ($new_end_time > $new_start_time && $new_end_time < $stateTime)){
                    //存在首小时免费
                    $price +=(ceil(($new_end_time-$new_start_time)/3600) * $cost['cost']);
                    if ($free==1 && $is_free==0){
                        $price-=$cost['cost'];
                        Db::name('users')->where('id',$users_id)->update(['is_free'=>2]);
                        Log::init([
                            'type'  =>  'File',
                            'path'  =>  APP_PATH.'logs/'
                        ]);
                        Log::write($price);
                    }
                }
                //与预设时间段的头部重合
                if (($new_start_time > $endTime && $new_start_time < $stateTime) && ($new_end_time > $stateTime && $new_end_time < strtotime('24:00:00'))){
                    //存在首小时免费
                    $price += (ceil(($stateTime-$new_start_time)/3600) * $cost['cost'] + ceil(($new_end_time-$stateTime)/3600) * $interval['price']);
                    if ($free==1 && $is_free==0){
                        $price-=$cost['cost'];
                        Db::name('users')->where('id',$users_id)->update(['is_free'=>1]);
                    }
                }
                //在预设时间段右边并不与之重合
                if (($new_start_time > $stateTime && $new_start_time < strtotime('24:00:00')) && ($new_end_time > $new_start_time && $new_end_time < strtotime('24:00:00'))){
                    $price +=(ceil(($new_end_time-$new_start_time)/3600) * $interval['price']);
                }
            //设备使用时间段是否跨天(跨天:开始时间在昨天,结束时间在今天)
            }else{
                $YesterdayStateTime=$stateTime-86400;
                $YesterdayEndTime=$endTime-86400;
                //昨天预设结束前使用,今天预设结束前停止
                if(($new_start_time > (strtotime('00:00:00')-86400) && $new_start_time < $YesterdayEndTime) && ($new_end_time > strtotime('00:00:00') && $new_end_time < $endTime)){

                    $price+= ceil(($YesterdayEndTime-$new_start_time)/3600) * $interval['price']
                            +ceil(($YesterdayStateTime-$YesterdayEndTime)/3600) * $cost['cost']
                            +ceil(($new_end_time-$YesterdayStateTime)/3600) * $interval['price'];
                }
                //昨天预设开始前使用,今天预设结束前停止
                if(($new_start_time > $YesterdayEndTime && $new_start_time < $YesterdayStateTime) && ($new_end_time > strtotime('00:00:00') && $new_end_time < $endTime)){
                    //存在首小时免费

                    $price+= ceil(($YesterdayStateTime-$new_start_time)/3600) *  $cost['cost']
                            +ceil(($new_end_time-$YesterdayStateTime)/3600) * $interval['price'];
                    if ($free==1 && $is_free==0){
                        $price-=$cost['cost'];
                        Db::name('users')->where('id',$users_id)->update(['is_free'=>1]);
                    }
                }
                //昨天预设开始前使用,今天预设结束后停止
                if(($new_start_time > $YesterdayEndTime && $new_start_time < $YesterdayStateTime) && ($new_end_time > $endTime && $new_end_time < $stateTime)){
                    //存在首小时免费

                    $price+= ceil(($YesterdayStateTime-$new_start_time)/3600) *  $cost['cost']
                            +ceil(($endTime-$YesterdayStateTime)/3600) *  $interval['price']
                            +ceil(($new_end_time-$endTime)/3600) * $cost['cost'];
                    if ($free==1 && $is_free==0){
                        $price-=$cost['cost'];
                        Db::name('users')->where('id',$users_id)->update(['is_free'=>1]);
                    }
                }
                //昨天预设开始后使用,今天预设结束前停止
                if(($new_start_time > $YesterdayStateTime && $new_start_time < strtotime('00:00:00')) && ($new_end_time > strtotime('00:00:00') && $new_end_time < $endTime)){

                    $price+= ceil(($new_end_time-$new_start_time)/3600) *  $interval['price'];
                }
                //昨天预设开始后使用,今天预设结束后停止
                if(($new_start_time > $YesterdayStateTime && $new_start_time < strtotime('00:00:00')) && ($new_end_time > $endTime && $new_end_time < $stateTime)){

                    $price+= ceil(($endTime-$new_start_time)/3600) *  $interval['price']
                            +ceil(($new_end_time-$endTime)/3600) * $cost['cost'];
                }
                //昨天预设开始后使用,今天预设开始前停止
                if(($new_start_time > $YesterdayStateTime && $new_start_time < strtotime('00:00:00')) && ($new_end_time > $stateTime && $new_end_time < ($new_start_time+86400))){

                    $price+= ceil(($endTime-$new_start_time)/3600) *  $interval['price']
                            +ceil(($stateTime-$endTime)/3600) * $cost['cost']
                            +ceil(($new_end_time-$stateTime)/3600) * $interval['price'];
                }
            }
        }
        if ($price > $cost['ceiling']){
            $price = $cost['ceiling'];
        }
        $numPrice = $dayPrice+$price;
        log::write($numPrice);
        return $numPrice;
    }

    //获取整天的价格
    public function getDayPrice(){
        $cost=Db::name('cost')->where('id',1)->find();
        $interval = Db::name('interval')->where('id',1)->find();
        $stateTime=strtotime($interval['start_time']);
        $endTime=strtotime($interval['end_time']);
        //预设时间长度
        $time=($stateTime-$endTime)/3600;
        if ($endTime < $stateTime){
            $price=($time *  $cost['cost']) + ((24-$time) *  $interval['price']);
        }else{
            $price=($time *  $interval['price']) + ((24-$time) *  $cost['cost']);
        }

        if ($price > $cost['ceiling']){
            $price = $cost['ceiling'];
        }
        return $price;
    }


    /**
     * @title 统一下单
     * @description 微信统一下单
     * @author 董瑞恩
     * @url /portal/order/pay
     * @method GET
     *
     * @param name:order_no type:String require:1 default:无 other: desc:订单号
     *
     * @return data:返回用于调用支付的参数
     */
    public function pay($order_no){
        $order=Db::name('order')->where(['order_no'=>$order_no,'state'=>2])->find();
        $openId=Db::name('users')->where('id',$order['users_id'])->find()['open_id'];
        $body='支付';
        $price=$order['price']*100;//订单价格
        $notify_url=url('order/notify','','',true);//回调地址
        $out_trade_no=$order_no.$this->create_noncestr(4);
        $wxPay=new WeixinPay($openId,$out_trade_no,$body,$price,$notify_url);
        $pay=$wxPay->pay();
        if (isset($pay['package'])){
            $data=[
                'state'=>1,
                'pay'=>$pay
            ];
            $this->apiResponse(200,'success',$data);
        }else{
            $data=[
                'state'=>0,
                'message'=>'统一下单失败',
                'error' => $pay
            ];
            $this->apiResponse(200,'success',$data);
        }

    }

    //支付回调接口
    public function notify(){
        $param = $this->request->param();
        if ($param == null) {
            $param = file_get_contents("php://input");
            if ($param == null) {
                $param = $GLOBALS['HTTP_RAW_POST_DATA'];
            }
        }
        $wxPay=new WeixinPay();
        $data = $wxPay->xmlToArray($param);
        $Sign = $data['sign'];
        //支付成功回调后变更订单状态
        $mySign = $wxPay->getSign($data);
        $order_no =substr($data['out_trade_no'], 0, -4);
        if ($Sign===$mySign && $data['return_code'] == 'SUCCESS') {
            try{
                Db::name('order')->where(['order_no'=>$order_no])->update(['state'=>3]);
            }catch (\Exception $exception){
                $this->apiResponse(301,'error:'.$exception->getMessage());
            }
            return "<xml>
                      <return_code><![CDATA[SUCCESS]]></return_code>
                      <return_msg><![CDATA[OK]]></return_msg>
                    </xml>";

        }
    }

    function create_noncestr($length = 4){
        $chars = "0123456789";
        $str = "";
        for($i=0;$i<$length;$i++){
            $str.= substr($chars,mt_rand(0,strlen($chars)-1),1);
        }
        return $str;
    }

}