<?php
/*
* Api 提供小程序前端使用
*/
namespace app\index\controller;
use think\Controller;
use think\Request;
use app\index\controller\Common;
use wechat\wxBizDataCrypt;

class Api extends Common {

    public $memid; //会员ID
    public $token; //token
    public function __construct() {
        parent::__construct();
        header('Content-Type: text/html;charset=utf-8');
        header('Access-Control-Allow-Origin:*'); // *代表允许任何网址请求
        header('Access-Control-Allow-Methods:POST,GET,OPTIONS,DELETE'); // 允许请求的类型
        header('Access-Control-Allow-Credentials: true'); // 设置是否允许发送 cookies
        header('Access-Control-Allow-Headers: token, memid'); // 设置允许自定义请求头的字段
        
    }

    //检测是否登录
    public function checkLogin() {
        $memid = Request::instance()->header('Memid');
        $token = Request::instance()->header('Token');
        $flag = false;
        if ($memid == "" || $token == "") {
            result(RE_NO_LOGIN, "暂无操作权限，请先登录");
        } else {
            $this->memid = $memid;
            $this->token = $token;
            $res = db('member')->where(['id' => $memid, 'token' => $token])->find();
            if (empty($res)) {
                result(RE_LOGIN_INVALID, "登录已失效，请重新登录");
            }
        }
    } 

    /* 获取单篇文章 
    *  参数：id 文章ID field 获取字段
    */  
    public function getOne() {
        $id = input('id', '', 'intval');
        $field = input('field');
        if ($id != "") {
            $one = db('article')->field($field)->where(['id' => $id])->find();
            $url = substr(config('weburl') , 0, -1);
            if ($one) {
                $one['imgurl'] = $url . $one['img'];
                if ($one['imgs'] != "") {
                    $one['image'] = explode('|', $one['imgs']);
                    foreach ($one['image'] as $key => $v) {
                        $one['image'][$key] = $url . $v;
                    }
                }
                $one['content'] = replaceContentImgUrl($one['content']);
                $one['datetime'] = date('Y-m-d', $one['datetime']);
            }
            result(RE_SUCCESS, "获取成功", $one);
        } else {
            result(RE_ERROR, "ID不能为空");
        }
    }
    public function getCate() {
        $nid = input('nid', '', 'intval');
        if ($nid != "") {
            $cate = webtreelist('cate', 'title,img,id,entitle,content', ['nid' => $nid]);
        }
        return json(['code' => RE_SUCCESS, 'msg' => '获取成功', 'data' => $cate]);
    }

    /* 获取列表 
    *  参数：nid 栏目ID cid 分类ID at 【isvouch推荐 ishome首页 istop置顶】 field 查询字段 current 当前页 size 每页显示
    */    
    public function getList() {
        $nid = input('nid', '0', 'intval');
        $cid = input('cid', '0', 'intval');
        $at = input('at');
        $field = input('field');
        $current = input('current', '1', 'intval');
        $size = input('size', '10', 'intval');
        if ($nid != 0) {
            $where['nid'] = $nid;
        }
        if ($cid != 0) {
            $where['cid'] = webtreecatewhere($cid);
        }
        if ($at != "") {
            $where[$at] = 1;
        }
        if ($where) {
            $total = db('article')->where($where)->count();
            $sort = "istop desc,sort desc,datetime desc,id desc";
            $list = db('article')->field($field)->where($where)->order($sort)->limit(($current - 1) * $size, $size)->select();
            if ($list) {
                $url = substr(config('weburl') , 0, -1);
                foreach ($list as $key => $v) {
                    $list[$key]['img'] = $url . $v['img'];
                    $list[$key]['datetime'] = date('Y-m-d', $v['datetime']);
                }
            }
        }
        exit(json_encode(['code' => RE_SUCCESS, 'msg' => '获取成功', 'data' => $list, 'total' => $total]));
    }

    //获取openid
    public function getOpenid() {
        $appid = config('appid');
        $appsecret = config('appsecret');
        $jscode = input('jscode');
        if ($jscode == "") {
            result(1, "jscode不能为空");
        }
        $url = 'https://api.weixin.qq.com/sns/jscode2session?appid=' . $appid . '&secret=' . $appsecret . '&js_code=' . $jscode . '&grant_type=authorization_code';
        $result = curl_get($url);
        $result = json_decode($result, true);
        if ($result['openid'] != "") {
            result(RE_SUCCESS, "获取openid和unionid成功", $result);
        } else {
            if ($result['errcode'] == - 1) {
                $msg = "系统繁忙，此时请开发者稍候再试";
            }
            if ($result['errcode'] == 40029) {
                $msg = "code 无效";
            }
            if ($result['errcode'] == 45011) {
                $msg = "频率限制，每个用户每分钟100次";
            }
            result(RE_ERROR, "获取openid失败：" . $msg);
        }
    }

    //获取头像
    public function getheadimg($src){
        $url = substr(config('weburl') , 0, -1);
        if(strpos($src,'http') !== false){
            return $src; 
        }else{
            return $url.$src;
        }
    }

    //处理小程序登录
    public function xcxLogin() {
        if ($_POST) {
            $openid = input('openid');
            $unionid = input('unionid');
            if ($openid == "" || $unionid == "") {
                result(RE_ERROR, "openid或unionid不能为空");
            }
            $w['unionid'] = $unionid;
            $data['openid'] = $openid;
            $data['unionid'] = $unionid;
            $data['token'] = getRandomString(18);
            $data['name'] = input('name');
            $data['head'] = input('head');
            $data['gender'] = input('gender');
            $res = db('member')->where($w)->find();
            if ($res) {
                if ($res['status'] == 1) {
                    result(RE_ERROR, "登录失败，账号已锁定，请联系管理员");
                }
                $data['logintime'] = date('Y-m-d H:i:s', time());
                db('member')->where($w)->update($data);
                $info = db('member')->where($w)->find();
                $info['head'] = $this->getheadimg($info['head']);
                result(RE_SUCCESS, "登录成功", $info);
            } else {
                $data['username'] = 'sy' . GetRandNumStr(6);
                $data['datetime'] = date('Y-m-d H:i:s', time());
                db('member')->insert($data);
                $info = db('member')->where($w)->find();
                $info['head'] = $this->getheadimg($info['head']);
                result(RE_SUCCESS, "首次登录,须绑定手机号", $info);
            }
        }
    }

    //绑定手机号 数据库已存在该手机号即同步，不存在即绑定
    public function bindmobile() {
        if ($_POST) {
            $encryptedData = input('encryptedData');
            $iv = input('iv');
            $sessionKey = input('sessionKey');
            $unionid = input('unionid');
            $pc = new WXBizDataCrypt(config('appid') , $sessionKey);
            $errCode = $pc->decryptData($encryptedData, $iv, $result);
            if ($errCode == 0) {
                $result = json_decode($result, true);
                $mp['mobile'] = $result['phoneNumber'];
                $res = db('member')->where($mp)->find();
                //存在手机号
                if ($res) {
                    $data['unionid'] = input('unionid');
                    $data['openid'] = input('openid');
                    db('member')->where($mp)->update($data);
                    $info = db('member')->where($mp)->find();
                    $info['head'] = $this->getheadimg($info['head']);
                    result(RE_SUCCESS, "同步成功", $info);
                } else {
                    //不存在手机号
                    $d['mobile'] = $result['phoneNumber'];
                    $w['unionid'] = $unionid;
                    db('member')->where($w)->update($d);
                    $info = db('member')->where($w)->find();
                    $info['head'] = $this->getheadimg($info['head']);
                    result(RE_SUCCESS, "绑定成功", $info);
                }
            } else {
                result(RE_ERROR, "绑定手机号失败" . $data);
            }
        }
    }

    //手机号密码登录
    public function mobileLogin() {
        if ($_POST) {
            $mobile = input('mobile');
            $userpass = input('userpass');
            if ($mobile == "" || $userpass == "") {
                result(RE_ERROR, "手机号或密码不能为空");
            }
            $w['mobile'] = $mobile;
            $w['userpass'] = md5($userpass);
            $data['token'] = getRandomString(18);          
            $res = db('member')->where($w)->find();
            if ($res) {
                if ($res['status'] == 1) {
                    result(RE_ERROR, "登录失败，账号已锁定，请联系管理员");
                }
                $data['logintime'] = date('Y-m-d H:i:s', time());
                db('member')->where($w)->update($data);
                $info = db('member')->where($w)->find();
                $info['head'] = $this->getheadimg($info['head']);
                result(RE_SUCCESS, "登录成功", $info);
            } else {
                result(RE_ERROR, "账号密码不正确");
            }
        }
    }

    //上传图片处理
    public function uploadImage() {
        $this->checkLogin();
        $file = request()->file('file');
        if ($file) {
            $size = 1024 * 1024 * 1; //允许上传5M
            $ext = 'jpg,jpeg,gif,png,bmp';
            $info = $file->validate(['size' => $size])->move(ROOT_PATH . DS . 'upload/xcx');
            if ($info) {
                $url = str_replace('\\', '/', $info->getPathname());
                $url = substr($url, strpos($url, '//') + 1);
                result(RE_SUCCESS, '上传成功', $url);
            } else {
                result(RE_ERROR, '上传失败', $file->getError());
            }
        }
    }

    //提交订单
    public function submitOrder() {
        $this->checkLogin();
        if ($_POST) {
            $data = input('post.');
            $data['memid'] = $this->memid;
            $data['datetime'] = date('Y-m-d H:i:s', time());
            $data['orderno'] = date('YmdHis') . getRandomNumber(5);
            $res = db('order')->insert($data);
            if ($res) {
                result(RE_SUCCESS, '订单提交成功', $data['orderno']);
            } else {
                result(RE_ERROR, '订单提交失败');
            }
        }
    }

    //订单详情
    public function orderDetail() {
        $this->checkLogin();
        $w['orderno'] = input('orderno');
        $w['memid'] = $this->memid;
        if ($w['orderno'] == "") {
            result(0, "订单编号不能为空");
        }
        $info = db('order')->where($w)->find();
        if ($info) {
            result(RE_SUCCESS, "获取订单详情成功", $info);
        } else {
            result(RE_ERROR, "该订单不存在");
        }
    }

    //订单退款
    public function refund($orderno) {
        import("Wxpay.lib.WxPay#Api", EXTEND_PATH);
        import('Wxpay.WxPay#Config', EXTEND_PATH);
        if ($orderno == "") {
            result(RE_SUCCESS, "取订单成功,订单号错误");
        }
        //退款配置
        $appid = config('appid'); //APPID
        $appSecret = unlock_key(config('appsecret') , config('openid')); //appsecret;
        $merchantId = config('merchantid'); //商户号
        $appkey = unlock_key(config('appkey') , config('openid')); //支付key
        $notifyUrl = config('weburl') . 'index/api/refundNotify/';
        $config = new \WxPayConfig($appid, $appSecret, $merchantId, $appkey);
        //退款内容
        $id = input('id', '', 'intval');
        $one = db('order')->where(['orderno' => $orderno])->find();
        if ($one['paystate'] == 1 && $one['status'] == 2) {
            $input = new \WxPayRefund();
            $input->SetOut_trade_no($orderno); //订单号
            $input->SetTotal_fee($one['paymoney'] * 100); //订单金额
            $input->SetRefund_fee($one['paymoney'] * 100); //退款金额
            $input->SetOut_refund_no(date("YmdHis") . getRandomNumber(5));
            $input->SetOp_user_id($config->GetMerchantId());
            $result = \WxPayApi::refund($config, $input);
            //p($result);
            if ($result['return_code'] == "SUCCESS" && $result['result_code'] == "SUCCESS") {
                $d['refundtime'] = date('Y-m-d H:i:s', time());
                $d['paystate'] = 2;
                db('order')->where(['orderno' => $orderno])->update($d);
                result(RE_SUCCESS, "取订单成功，已退款");
            } else {
                result(RE_SUCCESS, "取订单成功，退款失败");
            }
        }
    }

    //取消订单
    public function cancelOrder() {
        $this->checkLogin();
        $w['orderno'] = input('orderno');
        $w['memid'] = $this->memid;
        if ($w['orderno'] == "") {
            result(RE_ERROR, "订单编号不能为空");
        }
        $res = db('order')->field('paytime,paystate')->where($w)->find();
        if ($res['paystate'] == 1) {
            $enddate = date('Y-m-d H:i:s', time());
            $minute = floor((strtotime($enddate) - strtotime($res['paytime'])) % 86400 / 60);
            if ($minute > 5) {
                result(RE_ERROR, "支付成功后超过5分钟不能取消订单");
            }
        }
        $d['status'] = 4;
        $info = db('order')->where($w)->update($d);
        if ($info !== false) {
            //自动退款
            $this->refund($w['orderno']);
        } else {
            result(RE_ERROR, "取消订单失败");
        }
    }

    //确认收货
    public function confirmSh() {
        $this->checkLogin();
        $w['orderno'] = input('orderno');
        $w['memid'] = $this->memid;
        if ($w['orderno'] == "") {
            result(RE_ERROR, "订单编号不能为空");
        }
        $d['status'] = 2;
        $info = db('order')->where($w)->update($d);
        if ($info !== false) {
            result(RE_SUCCESS, "收货成功");
        } else {
            result(RE_ERROR, "收货失败");
        }
    }

    //计算支付金额
    public function calcPayPrice() {
        $memcouponid = input('memcouponid', '', 'intval');
        $orderno = input('orderno');
        $orderprice = db('order')->where(['orderno' => $orderno])->value("price");
        if ($orderprice == "") {
            result(RE_ERROR, "订单不存在");
        }
        if ($memcouponid == 0) {
            $couponprice = 0;
            $paymoney = $orderprice;
        } else {
            $couponprice = db('memcoupon')->where(['id' => $memcouponid])->value("couponprice");
            if ($couponprice == "") {
                result(RE_ERROR, "抵扣金额错误");
            }
            if ($orderprice <= $couponprice) {
                $yyhprice = $orderprice;
                $paymoney = 0;
            } else {
                $yyhprice = $orderprice - $couponprice;
                $paymoney = $yyhprice;
            }
        }
        db('order')->where(['orderno' => $orderno])->setField(['paymoney' => $paymoney]);
        result(RE_SUCCESS, "获取支付金额成功", ['couponprice' => $couponprice, 'paymoney' => $paymoney]);
    }

    //订单支付
    public function orderPay() {
        $this->checkLogin();
        if ($_POST) {
            $this->weixinPay();
        }
    }

    //小程序支付生成二次签名
    public function paySign($params, $appid, $key) {
        $data['appId'] = $appid;
        $data['nonceStr'] = $params['nonceStr'];
        $data['package'] = $params['package'];
        $data['signType'] = $params['signType'];
        $data['timeStamp'] = $params['timeStamp'];
        return MakeSign($data, $key);
    }

    /**
     * 微信支付
     */
    private function weixinPay() {
        //支付参数
        $body = input('body');
        $openId = input('openid');
        $orderno = input('orderno');
        if ($openId == "") {
            result(RE_ERROR, "必须授权登录才能完成支付");
        }
        //如果有用优惠券，则将优惠券设为已使用
        $memcouponid = input('memcouponid', '', 'intval');
        if ($memcouponid != 0) {
            $couponmoney = db('memcoupon')->where(['id' => $memcouponid])->value("couponprice");
            db('order')->where(['orderno' => $orderno])->setField(['couponmoney' => $couponmoney]);
            db('memcoupon')->where(['id' => $memcouponid])->setField(['use' => 1]);
        }
        $payMoney = db('order')->where(['orderno' => $orderno])->value("paymoney");
        if ($payMoney == "") {
            result(RE_ERROR, "支付金额错误");
        }
        //如果订单金额为0则可不用支付直接成功
        if ($payMoney == '0' || $payMoney == '0.00') {
            $d['paystate'] = 1;
            $d['paytime'] = date('Y-m-d H:i:s', time());
            db('order')->where(['orderno' => $orderno])->update($d);
            result(RE_SUCCESS, "0元订单无须支付", 0);
        }
        $payMoney = $payMoney * 100;
        import("Wxpay.lib.WxPay#Api", EXTEND_PATH);
        import('Wxpay.WxPay#Config', EXTEND_PATH);
        //支付配置
        $appid = config('appid'); //APPID
        $appSecret = unlock_key(config('appsecret') , config('openid')); //appsecret;
        $merchantId = config('merchantid'); //商户号
        $appkey = unlock_key(config('appkey') , config('openid')); //支付key
        $notifyUrl = config('paynotify'); //回调地址
        //统一下单
        $input = new \WxPayUnifiedOrder();
        $input->SetBody($body);
        //$input->SetAttach($body);
        $input->SetOut_trade_no($orderno);
        $input->SetTotal_fee($payMoney);
        $input->SetTime_start(date("YmdHis"));
        $input->SetTime_expire(date("YmdHis", time() + 600));
        $input->SetAttach("payreturn");
        //$input->SetGoods_tag("test");
        $input->SetNotify_url($notifyUrl);
        $input->SetTrade_type("JSAPI");
        $input->SetOpenid($openId);
        $config = new \WxPayConfig($appid, $appSecret, $merchantId, $appkey, $notifyUrl);
        $unifiedOrder = \WxPayApi::unifiedOrder($config, $input);
        if ($unifiedOrder['result_code'] == 'SUCCESS' && $unifiedOrder['return_code'] == 'SUCCESS') {
            $time = time();
            $data['timeStamp'] = "$time"; //时间戳
            $data['nonceStr'] = $unifiedOrder['nonce_str']; //随机字符串
            $data['signType'] = 'MD5'; //签名算法，暂支持 MD5
            $data['package'] = 'prepay_id=' . $unifiedOrder['prepay_id']; //统一下单接口返回的 prepay_id 参数值，提交格式如：prepay_id=*
            $data['paySign'] = $this->paySign($data, $appid, $appkey); //签名
            result(RE_SUCCESS, "发起支付成功", $data);
        } else {
            result(RE_ERROR, "发起支付失败", $data);
        }
    }

    /**
     * 支付回调
     */
    public function payNotify() {
        $testxml = file_get_contents("php://input");
        $jsonxml = json_encode(simplexml_load_string($testxml, 'SimpleXMLElement', LIBXML_NOCDATA));
        $result = json_decode($jsonxml, true); //转成数组，
        if ($result) {
            //如果成功返回了
            $w['orderno'] = $result['out_trade_no'];
            $d['paystate'] = 1;
            $d['paytime'] = date('Y-m-d H:i:s', time());
            if ($result['return_code'] == "SUCCESS" && $result['result_code'] == "SUCCESS") {
                db('order')->where($w)->update($d);
                return '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
                exit();
            }
        }
    }

    /*
     * 退款回调
    */
    public function refundNotify() {
        return '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
    }

    //获取订单列表
    public function orderList() {
        $this->checkLogin();
        $status = input('status');
        $paystate = input('paystate');
        $current = input('current', '1', 'intval');
        $size = input('size', '10', 'intval');
        if ($status != "") {
            $where['status'] = $status;
        }
        if ($paystate != "") {
            $where['paystate'] = $paystate;
        }
        //24小时未支付自动取消订单
        $list = db('order')->where(['status' => 0, 'paystate' => 0, 'memid' => $this->memid])->select();
        if ($list) {
            foreach ($list as $key => $v) {
                orderAutoCancel($v['id'], $v['datetime']);
            }
        }
        $where['memid'] = $this->memid;
        $count = db('order')->where($where)->count();
        $data['totalPage'] = ceil($count / $size); //总页数
        $data['total'] = $count; //总条数
        $data['list'] = db('order')->where($where)->order("id desc,datetime desc")->limit(($current - 1) * $size, $size)->select();
        result(RE_SUCCESS, "获取订单列表成功", $data);
    }

    //获取会员优惠券列表
    public function memCouponList() {
        $this->checkLogin();
        $use = input('use');
        $current = input('current', '1', 'intval');
        $size = input('size', '10', 'intval');
        if ($use != "") {
            $where['use'] = $use;
            if ($use == 0) {
                //判断未使用的优惠券是否过期，如已过期设置use为2
                $yxlist = db('memcoupon')->where(['use' => 0, 'memid' => $this->memid])->select();
                if ($yxlist) {
                    foreach ($yxlist as $key => $v) {
                        checkCouponUse($v['id'], $v['expiretime']);
                    }
                }
            }
        }
        $where['memid'] = $this->memid;
        $count = db('memcoupon')->where($where)->count();
        $data['use0'] = db('memcoupon')->where(['memid' => $this->memid, 'use' => 0])->count();
        $data['use1'] = db('memcoupon')->where(['memid' => $this->memid, 'use' => 1])->count();
        $data['use2'] = db('memcoupon')->where(['memid' => $this->memid, 'use' => 2])->count();
        $data['totalPage'] = ceil($count / $size); //总页数
        $data['total'] = $count; //总条数
        $data['list'] = db('memcoupon')->where($where)->order("id desc,receivetime desc")->limit(($current - 1) * $size, $size)->select();
        result(RE_SUCCESS, "获取订单列表成功", $data);
    }
}

