auth->id; $orderinfo = Db::name('order')->where('id',$orderid)->where('user_id',$uid)->find(); //创建订单 $data['user_id'] = $uid; $data['out_trade_no'] = createUniqueNo('P',$uid); // 数据库订单号加密 $data['order_amount'] = $orderinfo['pay_fee']; $data['createtime'] = time(); $data['pay_type'] = $pay_type; $data['order_status'] = 0; $data['table_name'] = 'order'; $data['table_id'] = $orderid; $orderid = Db::name('pay_order')->insertGetId($data); $openid = $this->auth->mini_openid; //下单 $params = [ 'type' => $pay_type, 'orderid' => $data['out_trade_no'], 'title' => '支付订单', 'amount' => $data['order_amount'], 'method' => $platform, 'openid' => $openid, 'notifyurl' => config('pay_notify_url').'/api/pay/order_notify_base/paytype/'.$pay_type, 'returnurl' => '', ]; $res = Service::submitOrder($params); if($pay_type == 'wechat'){ $this->success('success',json_decode($res,true)); }else{ $this->success('success',$res); } } //异步回调对外方法 public function order_notify_base(){ //验签 $paytype = input('paytype','wechat'); $func = input('func','order_notify_do'); $out_trade_no = 'O230606102813244205462'; $rs = $this->$func($out_trade_no);echo '
';var_dump($rs);exit;
        $notify_file = $this->notify_log_start($paytype);
        $pay = Service::checkNotify($paytype);
        if (!$pay) {
            echo '签名错误';
            exit;
        }

        //验证,拿订单号等信息
        $data = $pay->verify();
        $out_trade_no = $data['out_trade_no'];
        //订单查询
        $info = Db::name('pay_order')->where('out_trade_no',$out_trade_no)->find();

        if(empty($info)){
            return $pay->success()->send();
            exit;
        }

        if($info['order_status'] != 0)
        {
            return $pay->success()->send();
            exit;
        }
        //你可以在此编写订单逻辑
        $rs = $this->$func($out_trade_no);
        if($rs === false){
            //不论结果都应返回success
            return $pay->success()->send();
            exit;
        }else{
            //不论结果都应返回success
            return $pay->success()->send();
            exit;
        }

        //默认
        return $pay->success()->send();
        exit;
    }

    //异步逻辑
    private function order_notify_do($out_trade_no){

        Db::startTrans();
        $orderInfo = Db::name('pay_order')->where(['out_trade_no' => $out_trade_no])->lock(true)->find();
        if (empty($orderInfo)) {
            Db::rollback();
            return false;
        }

        if($orderInfo['order_status'] != 0){
            Db::rollback();
            return false;
        }

        //逻辑开始
        $update = [
            'status'=>10,
            'paytime'=>time(),
            'pay_type'=>$orderInfo['pay_type'],
            'pay_out_trade_no'=>$out_trade_no,
        ];
        $rs_order = Db::name('order')->where('id',$orderInfo['table_id'])->update($update);
        if($rs_order === false){
            Db::rollback();
            return false;
        }
        //逻辑结束

        //状态
        $ros = Db::name('pay_order')->where(['out_trade_no' => $out_trade_no])->update(['order_status'=>1,'notifytime'=>time()]);
        if($ros === false) {
            Db::rollback();
            return false;
        }

        //默认提交
        Db::commit();
        return true;


    }



    //异步日志
    private function notify_log_start($paytype = 'wechat'){
        //记录支付回调数据
        ignore_user_abort(); // run script in background
        set_time_limit(30);
        // 日志文件 start
        $log_base_dir = '../paylog/'.$paytype.'/';
        if (!is_dir($log_base_dir))
        {
            mkdir($log_base_dir, 0770, true);
            @chmod($log_base_dir, 0770);
        }
        $notify_file = $log_base_dir.'notify.txt';
        if(!file_exists($notify_file)) {
            @touch($notify_file);
            @chmod($notify_file, 0770);
        }
        if(filesize($notify_file)>5242880)//大于5M自动切换
        {
            rename($notify_file, $log_base_dir.'notify_'.date('Y_m_d_H_i_s').'.txt');
        }
        if(!file_exists($notify_file)) {
            @touch($notify_file);
            @chmod($notify_file, 0770);
        }
        // 日志文件 end
        //开始写入
        $_REQUEST = isset($_REQUEST) ? $_REQUEST : array();
        if($_REQUEST && $paytype == 'alipay') {
            file_put_contents($notify_file, "\r\n\r\n".date('Y-m-d H:i:s')." [notify][入口接收request]".json_encode($_REQUEST), FILE_APPEND);
        } else {
            $xml = file_get_contents("php://input");
            file_put_contents($notify_file, "\r\n\r\n".date('Y-m-d H:i:s')." [notify][入口接收php://input流原始数据] \n".$xml, FILE_APPEND);
            $xmlObj = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
            file_put_contents($notify_file, "\r\n\r\n".date('Y-m-d H:i:s')." [notify][入口接收php://input流] ".json_encode($xmlObj), FILE_APPEND);
        }

        ini_set('display_errors','On');

        return $notify_file;

    }

    //////////////



    //微信小程序充值
    public function pay_recharge()
    {
        Db::startTrans();
        try {
            $pay_type = input('pay_type','wechat');
            $platform = input('platform','miniapp');
            $id = input('id','0');
            $amounts = input('amounts','0.00');
            $uid = $this->auth->id;
            $companyId = $this->auth->company_id;
            if (empty($id) && empty($amounts)) {
                throw new Exception('参数错误');
            }
            $gift_amount = 0.00;
            if (!empty($id)) {//验证充值配置
                $where['status'] = 1;//上架
                $orderinfo = Db::name('recharge_config')->where('id',$id)->where($where)->find();
                if (empty($orderinfo)) {
                    throw new Exception('未获取到充值套餐信息');
                }
                $order_amount = $orderinfo['price'];
                $gift_amount = $orderinfo['giftprice'];
            } else {
                $isInt = is_int($amounts);
                if (!$isInt) {
                    throw new Exception('请输入整数');
                }
                if ($amounts < 1) {
                    throw new Exception('充值金额有误');
                }
                $order_amount = $amounts;
            }

            //创建订单
            $data['company_id'] = $companyId;
            $data['user_id'] = $uid;
            $data['out_trade_no'] = createUniqueNo('R',$uid); // 数据库订单号加密
            $data['order_amount'] = $order_amount;
            $data['gift_amount'] = $gift_amount;
            $data['createtime'] = time();
            $data['pay_type'] = $pay_type;
            $data['order_status'] = 0;
            $data['table_name'] = 'recharge_config';
            $data['table_id'] = $id;

            $orderid = Db::name('pay_order')->insertGetId($data);

            $openid = $this->auth->mini_openid;
            $httpStr = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'];
            //下单
            $params = [
                'type'         => $pay_type,
                'orderid'      => $data['out_trade_no'],
                'title'        => '余额充值',
                'amount'       => $data['order_amount'],
                'method'       => $platform,
                'openid'       => $openid,
                'notifyurl' => $httpStr.'/api/pay/order_notify_base/paytype/'.$pay_type.'/func/recharge',
                'returnurl' => '',
            ];

            $res = Service::submitOrder($params);
            Db::commit();
            if($pay_type == 'wechat'){
                $this->success('success',json_decode($res,true));
            }else{
                $this->success('success',$res);
            }
        } catch (Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
    }

    /**
     * 充值到账
     * @param $out_trade_no
     * @return bool
     */
    private function recharge($out_trade_no)
    {
        Db::startTrans();
        $orderInfo = Db::name('pay_order')->where(['out_trade_no' => $out_trade_no])->lock(true)->find();
        if (empty($orderInfo)) {
            Db::rollback();
            return false;
        }

        if($orderInfo['order_status'] != 0){
            Db::rollback();
            return false;
        }
        //赠送优惠券
        $rg = 'recharge_gift';
        $c = 'coupons';
        $field = $rg.'.*,'.$c.'.name,'.$c.'.info,'.$c.'.days';
        $rechargeGiftWhere['config_id'] = $orderInfo['table_id'];
        $rechargeGiftWhere[$c.'.status'] = 1;
        $rechargeGift = Db::name($rg)->alias($rg)->field($field)
            ->join($c,$c.'.id = '.$rg.'.coupon_id','LEFT')->where($rechargeGiftWhere)->select();
        if (!empty($rechargeGift)) {
            $time = time();
            foreach ($rechargeGift as $key => $value) {
                $endtime = $time + 86400 * $value['days'];
                $userCouponsData[] = [
                    'user_id' => $orderInfo['user_id'],
                    'company_id' => $orderInfo['company_id'],
                    'coupons_id' => $value['coupon_id'],
                    'coupon_name' => $value['name'],
                    'coupon_info' => $value['info'],
                    'createtime' => $time,
                    'endtime' => $endtime,
                    'number' => $value['number'],
                    'remain' => $value['number'],
                    'payorder_id' => $orderInfo['id'],
                    'getfrom' => '充值赠送',
                ];
            }
            $userCouponsRes = Db::name('user_coupons')->insertAll($userCouponsData);
            if (!$userCouponsRes) {
                throw new Exception('赠送优惠失败');
            }
        }
        $userWalletWhere['user_id'] = $orderInfo['user_id'];
        $userWalletWhere['company_id'] = $orderInfo['company_id'];
        $userWalletData = Db::name('user_wallet')->where($userWalletWhere)->find();
        $before = isset($userWalletData['money']) ? $userWalletData['money'] : 0.00;
        $changeValue = bcadd($orderInfo['order_amount'],$orderInfo['gift_amount'],2);
        $remain = bcadd($before,$changeValue,2);
        $time = time();
        //逻辑开始 记录充值明细
        $userMoneyLogData = [
            'user_id'      => $orderInfo['user_id'],
            'company_id'   => $orderInfo['company_id'],
            'log_type'     => 104, //日志类型 104
            'before'       => $before, //之前余额
            'change_value' => $changeValue, //变动金额
            'remain'       => $remain, //剩余金额
            'table'        => 'pay_order', //数据来源
            'table_id'     => $orderInfo['id'], //数据来源ID
            'remark'       => '余额充值', //remark
            'createtime'   => $time,
        ];
        $userMoneyLogRes = Db::name('user_money_log')->insertGetId($userMoneyLogData);
        if (!$userMoneyLogRes) {
            throw new Exception('充值记录失败');
        }
        //更新钱包余额
        $update = [
            'money' => $remain,
            'updatetime' => $time,
        ];
        $rs_order = Db::name('user_wallet')->where($userWalletWhere)->update($update);
        if(!$rs_order){
            Db::rollback();
            return false;
        }
        //逻辑结束

        //状态
        $ros = Db::name('pay_order')->where(['out_trade_no' => $out_trade_no])->update(['order_status'=>1,'notifytime'=>time()]);
        if($ros === false) {
            Db::rollback();
            return false;
        }
        //默认提交
        Db::commit();
        return true;
    }

    /**
     * 购买套餐
     * @return void
     * @throws \Exception
     */
    public function package()
    {
        Db::startTrans();
        try {
            $pay_type = input('pay_type','wechat');//支付类型:wallet=余额,wechat=微信
            $platform = input('platform','miniapp');
            $id = input('package_id','0');
            $carId = input('car_id','0');
            $uid = $this->auth->id;
            $companyId = $this->auth->company_id;
            $time = time();
            if (empty($id)) {
                throw new Exception('请选择套餐');
            }
            if (empty($carId)) {
                throw new Exception('请选择车辆');
            }
            $userCarWhere['user_id'] = $uid;
            $userCarWhere['id'] = $carId;
            $userCar = Db::name('user_car')->where($userCarWhere)->find();
            if (empty($userCar)) {
                throw new Exception('未找到车辆信息');
            }
            $packageWhere['id'] = $id;
            $packageWhere['status'] = 1;
            $package = Db::name('package')->where($packageWhere)->find();
            if (empty($package)) {
                throw new Exception('未找到套餐信息');
            }
            if ($package['company_id'] != $companyId) {
                throw new Exception('您绑定的门店和购买套餐门店不一致');
            }
            if ($pay_type == 'wallet') {//验证余额
                $userWalletWhere['user_id'] = $uid;
                $userWalletWhere['company_id'] = $companyId;
                $userWallet = Db::name('user_wallet')->where($userWalletWhere)->find();
                if (empty($userWallet)) {
                    throw new Exception('钱包异常');
                }
                if ($userWallet['money'] < $package['price']) {
                    throw new Exception('您的余额不足,请充值。');
                }
            }
            $gift_amount = 0.00;
            $order_amount = $package['price'];
            $extData = ['car_id'=>$carId];
            //创建订单
            $data['company_id'] = $companyId;
            $data['user_id'] = $uid;
            $data['out_trade_no'] = createUniqueNo('O',$uid); // 数据库订单号加密
            $data['order_amount'] = $order_amount;
            $data['gift_amount'] = $gift_amount;
            $data['createtime'] = time();
            $data['pay_type'] = $pay_type;
            $data['order_status'] = 0;
            $data['table_name'] = 'package';
            $data['table_id'] = $id;
            $data['ext_data'] = json_encode($extData);

            $orderid = Db::name('pay_order')->insertGetId($data);
            if ($pay_type == 'wechat') {//微信支付
                $openid = $this->auth->mini_openid;
                $httpStr = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'];
                //下单
                $params = [
                    'type'         => $pay_type,
                    'orderid'      => $data['out_trade_no'],
                    'title'        => '购买套餐',
                    'amount'       => $data['order_amount'],
                    'method'       => $platform,
                    'openid'       => $openid,
                    'notifyurl' => $httpStr.'/api/pay/order_notify_base/paytype/'.$pay_type.'/func/package_do',
                    'returnurl' => '',
                ];

                $res = Service::submitOrder($params);
            } else {//余额支付
                //扣除钱包
                $oldMoney = $userWallet['money'];
                $newMoney = bcsub($oldMoney,$package['price'],2);
                $userWalletData['money'] = $newMoney;
                $userWalletData['updatetime'] = $time;

                $userWalletWhere['user_id'] = $uid;
                $userWalletWhere['company_id'] = $companyId;
                $userWalletRes = Db::name('user_wallet')->where($userWalletWhere)->update($userWalletData);
                if (!$userWalletRes) {
                    throw new Exception('支付失败');
                }
                //余额明细记录
                $userMoneyLogData = [
                    'company_id' => $companyId,
                    'user_id' => $uid,
                    'log_type' => 103,//购买套餐
                    'before' => $oldMoney,
                    'change_value' => $package['price'],
                    'remain' => $newMoney,
                    'table' => 'pay_order',
                    'table_id' => $orderid,
                    'remark' => '订单消费',
                    'createtime' => $time,
                ];
                $userMoneyLogRes = Db::name('user_money_log')->insertGetId($userMoneyLogData);
                if (!$userMoneyLogRes) {
                    throw new Exception('余额明细记录失败');
                }
                //生成订单
                $time = time();
                $packageWhere['id'] = $id;
                $package = Db::name('package')->where($packageWhere)->find();
                $days = isset($package['days']) ? $package['days'] : 0;
                $packageEndtime = $time + 86400 * $days;
                $userId = $uid;
                $userWhere['id'] = $userId;
                $user = Db::name('user')->where($userWhere)->find();
                $userCarWhere['id'] = $carId;
                $userCar = Db::name('user_car')->where($userCarWhere)->find();
                //生成订单
                $orderData = [
                    'orderno'         => createUniqueNo('O', $userId),//订单号
                    'ordertype'       => 3,//类型:1=预约下单,2=在线下单,3=套餐订单
                    'company_id'      => $companyId,//门店ID
                    'user_id'         => $userId,//用户ID
                    'user_name'       => isset($user['nickname']) ? $user['nickname'] : '',//用户姓名
                    'user_car_id'     => isset($userCar['id']) ? $userCar['id'] : 0,//车辆ID
                    'user_car_number' => isset($userCar['car_number']) ? $userCar['car_number'] : '',//用户车牌
                    'user_mobile'     => isset($user['mobile']) ? $user['mobile'] : '',//用户手机
                    'pre_order_id'    => 0,//预约单ID
                    'package_id'      => isset($package['id']) ? $package['id'] : 0,//套餐ID
                    'server_info'     => isset($package['info']) ? $package['info'] : '',//套餐内容
                    'server_images'   => isset($package['images']) ? $package['images'] : '',//套餐图片
                    'pay_fee'         => isset($package['price']) ? $package['price'] : 0,//套餐价格
                    'package_endtime' => $packageEndtime,//套餐到期时间
                    'status'          => 2,//状态:1=待支付,2=待处理,3=已完成,4=已取消
                    'pay_time'        => $time,
                    'paytype'         => 2,//支付方式:1=线下,2=余额,3=微信
                    'pay_fee'         => $order_amount,//支付总额
                    'createtime'      => $time,//下单时间
                    'pay_order_id'    => $orderid,//支付ID
                ];
                $orderRes = Db::name('order')->insertGetId($orderData);
                $payOrderData['order_status'] = 1;
                $payOrderWhere['id'] = $orderid;
                $payOrderRes = Db::name('pay_order')->where($payOrderWhere)->update($payOrderData);
                if (!$payOrderRes) {
                    throw new Exception('支付失败');
                }
            }
            $res['order_id'] = isset($orderRes) ? $orderRes : 0;
            $res['pay_order_id'] = $orderid;
            Db::commit();
            if($pay_type == 'wechat'){
                $this->success('操作成功',json_decode($res,true));
            }else{
                $this->success('操作成功',$res);
            }
        } catch (Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }
    }

    /**
     * 购买套餐回调
     * @param $out_trade_no
     * @return bool
     */
    private function package_do($out_trade_no)
    {
        Db::startTrans();
        $orderInfo = Db::name('pay_order')->where(['out_trade_no' => $out_trade_no])->lock(true)->find();
        if (empty($orderInfo)) {
            Db::rollback();
            return false;
        }
        if($orderInfo['order_status'] != 0){
            Db::rollback();
            return false;
        }
        $time = time();
        $packageWhere['id'] = $orderInfo['table_id'];
        $package = Db::name('package')->where($packageWhere)->find();
        $days = isset($package['days']) ? $package['days'] : 0;
        $packageEndtime = $time + 86400 * $days;
        $userId = $orderInfo['user_id'];
        $userWhere['id'] = $userId;
        $user = Db::name('user')->where($userWhere)->find();
        $extData = json_decode($orderInfo['ext_data'], true);
        $userCarWhere['id'] = isset($extData['car_id']) ? $extData['car_id'] : 0;
        $userCar = Db::name('user_car')->where($userCarWhere)->find();
        //生成订单
        $orderData = [
            'orderno'         => createUniqueNo('O', $userId),//订单号
            'ordertype'       => 3,//类型:1=预约下单,2=在线下单,3=套餐订单
            'company_id'      => $orderInfo['company_id'],//门店ID
            'user_id'         => $userId,//用户ID
            'user_name'       => isset($user['nickname']) ? $user['nickname'] : '',//用户姓名
            'user_car_id'     => isset($userCar['id']) ? $userCar['id'] : 0,//车辆ID
            'user_car_number' => isset($userCar['car_number']) ? $userCar['car_number'] : '',//用户车牌
            'user_mobile'     => isset($user['mobile']) ? $user['mobile'] : '',//用户手机
            'pre_order_id'    => 0,//预约单ID
            'package_id'      => isset($package['id']) ? $package['id'] : 0,//套餐ID
            'server_info'     => isset($package['info']) ? $package['info'] : '',//套餐内容
            'server_images'   => isset($package['images']) ? $package['images'] : '',//套餐图片
            'pay_fee'         => isset($package['price']) ? $package['price'] : 0,//套餐价格
            'package_endtime' => $packageEndtime,//套餐到期时间
            'status'          => 2,//状态:1=待支付,2=待处理,3=已完成,4=已取消
            'pay_time'        => $time,
            'paytype'         => 3,//支付方式:1=线下,2=余额,3=微信
            'pay_fee'         => $orderInfo['order_amount'],//支付总额
            'createtime'      => $time,//下单时间
            'pay_order_id'    => $orderInfo['id'],//支付ID
        ];
        $orderRes = Db::name('order')->insertGetId($orderData);
        if (!$orderRes) {
            Db::rollback();
            return false;
        }

        //状态
        $ros = Db::name('pay_order')->where(['out_trade_no' => $out_trade_no])->update(['order_status'=>1,'notifytime'=>time()]);
        if($ros === false) {
            Db::rollback();
            return false;
        }
        //默认提交
        Db::commit();
        return true;
    }

}