<?php
/*
 * @Author: wang jun
 * @Date: 2022-01-18 11:12:23
 * @Last Modified by: wang jun
 * @Last Modified time: 2022-01-19 10:38:13
 * 微信类
 */
namespace app\index\logic;

use app\index\model\payordermodel;
use app\index\model\wxusermodel;
use \think\Log;

class wechatlogic extends baselogic
{
    /**
     * 设置请求数据规则
     * 20220107
     * wj
     */
    protected function setrules()
    {
        $list = [
            'getOpenid' => [
                ['name' => 'code', 'title' => 'code', 'require' => true, 'type' => 'string'],
            ],
            'create_qrcode' => [
                ['name' => 'scene', 'title' => 'scene', 'require' => true, 'type' => 'string'],
                ['name' => 'page', 'title' => 'page', 'require' => true, 'type' => 'string'],
                ['name' => 'width', 'title' => 'width', 'require' => true, 'type' => 'numeric'],
                ['name' => 'dir', 'title' => '文件夹', 'require' => false, 'type' => 'string', 'default' => ""],
            ],
            'createorder' => [
                ['name' => 'openid', 'title' => 'openid', 'require' => true, 'type' => 'string'],
                ['name' => 'total_fee', 'title' => '支付费用', 'require' => true, 'type' => 'numeric'], //以分为单位
                ['name' => 'body', 'title' => '支付说明', 'require' => true, 'type' => 'string'],
                ['name' => 'out_trade_no', 'title' => '商户支付单号', 'require' => true, 'type' => 'string'],
                ['name' => 'notify_url', 'title' => '回调地址', 'require' => true, 'type' => 'string'],
                ['name' => 'trade_type', 'title' => 'trade_type', 'require' => true, 'type' => 'string'],
                ['name' => 'wid', 'title' => 'wid', 'require' => true, 'type' => 'numeric'],
            ],
        ];
        return $list;
    }
    /**
     * 获取小程序配置信息
     *
     * @return void
     * @author wj
     * @date 2022-07-22
     */
    public function getselfwxconfig()
    {
        $config = [
            //'appid' => 'wx47d6be96fb2d466c',
            //'appSecret' => 'c0252b0cea090a1f3fb41ea7c71d55d6',
            'appid' => 'wxcacf6eb6e7478e29',
            'appSecret' => '3722c3f95df0569498a0e32ae6e85153',
        ];
        return $config;
    }
    /**
     * 获取商户配置信息
     *
     * @return void
     * @author wj
     * @date 2022-07-22
     */
    public function getpayconfig()
    {
        $config = [
            'mchid' => '1616316171', //零散务工工会
            'key' => 'WaterCat20211001ShuiMaoGongJiang', //商户号key
        ];
        return $config;
    }
    private function curl_get($url, &$httpCode = 0)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        //不做证书校验,部署在linux环境下请改为true
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        $file_contents = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        return $file_contents;
    }

    private function getAccessToken()
    {
        $config = $this->getselfwxconfig();
        $appid = $config['appid'];
        $appSecret = $config['appSecret'];
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $appid . "&secret=" . $appSecret;
        $result = $this->curl_get($url);
        $wxResult = json_decode($result, true);
        return $wxResult;
    }

    //开启curl post请求
    private function sendCmd($url, $data)
    {
        $curl = curl_init(); // 启动一个CURL会话
        curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检测
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); // 从证书中检查SSL加密算法是否存在
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Expect:')); //解决数据包大不能提交
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
        curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
        curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循
        curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回

        $tmpInfo = curl_exec($curl); // 执行操作
        if (curl_errno($curl)) {
            echo 'Errno' . curl_error($curl);
        }
        curl_close($curl); // 关键CURL会话
        return $tmpInfo; // 返回数据
    }

    /**
     * 获取openid
     * 20220118
     * wj
     * code 必填
     */
    public function getOpenid($arr)
    {
        $result = $this->checkparam(__FUNCTION__, $arr);
        if (1 != $result['status']) {
            return $result;
        }
        $data = $result['data'];
        $code = $data['code'];
        $config = $this->getselfwxconfig();
        $appid = $config['appid'];
        $appSecret = $config['appSecret'];
        $wxUrl = 'https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code';
        $getUrl = sprintf($wxUrl, $appid, $appSecret, $code);
        $result = $this->curl_get($getUrl);
        $wxResult = json_decode($result, true);
        Log::info($wxResult);
        if (empty($wxResult)) {
            return backarr(0, "无返回数据");
        }
        $logfail = array_key_exists('errcode', $wxResult);
        if ($logfail) {
            return backarr(0, 'error', $logfail['errmsg']);
        }
        $openid = $wxResult['openid'];
        $data = ['openid' => $openid];
        if (isset($wxResult['unionid'])) {
            $unionid = $wxResult['unionid'];
            $m_wu = new wxusermodel();
            $result = $m_wu->updateunionidbyopenid($openid, $unionid);
            if (empty($result['status'])) {
                return backarr(0, $result['msg']);
            }
        }
        return backarr(1, 'success', $data);
    }

    //获得二维码
    public function create_qrcode($arr)
    {
        $result = $this->checkparam(__FUNCTION__, $arr);
        if (1 != $result['status']) {
            return $result;
        }
        $data = $result['data'];
        $scene = $data['scene'];
        $width = $data['width'];
        $page = $data['page'];
        $dir = $data['dir'];

        $qr_path = "./Uploads/";
        if (empty($dir)) {
            $dir = 'default';
        }
        $uploaddir = $qr_path . 'qrcode/' . $dir . "/";
        $getdir = '/Uploads/qrcode/' . $dir . "/";
        if (!file_exists($uploaddir)) {
            mkdir($uploaddir, 0700, true); //判断保存目录是否存在，不存在自动生成文件目录
        }
        $filename = time() . '.png';
        $file = $uploaddir . $filename;
        $getdir .= $filename;

        $access = $this->getAccessToken();
        $access_token = $access['access_token'];
        $url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' . $access_token;
        $qrcode = array(
            'scene' => $scene, //二维码所带参数
            'width' => $width,
            'page' => $page, //二维码跳转路径（要已发布小程序）
            'auto_color' => true,
        );
        $result = $this->sendCmd($url, json_encode($qrcode)); //请求微信接口
        Log::info($result);
        $errcode = json_decode($result, true)['errcode'];
        $errmsg = json_decode($result, true)['errmsg'];
        if ($errcode) {
            return backarr(0, $errmsg);
        }
        $res = file_put_contents($file, $result); //将微信返回的图片数据流写入文件
        if ($res === false) {
            return backarr(0, '生成二维码失败');
        } else {
            $path = getselfurl('default') . $getdir;
            return backarr(1, 'success', ['path' => $path]);
        }
    }
    /**
     * 创建支付订单 统一下单接口
     *
     * @param  [type] $arr
     * @return void
     * @author wj
     * @date 2022-07-22
     */
    public function createorder($arr)
    {
        $result = $this->checkparam(__FUNCTION__, $arr);
        if (1 != $result['status']) {
            return $result;
        }
        $data = $result['data'];
        $openid = $data['openid'];
        $total_fee = $data['total_fee'];
        $body = $data['body'];
        $out_trade_no = $data['out_trade_no'];
        $notify_url = $data['notify_url'];
        $trade_type = $data['trade_type'];
        $wid = $data['wid'];
        $appointentid = $data['appointent_id'];

        $payconfig = $this->getpayconfig();
        $mchid = $payconfig['mchid'];
        $key = $payconfig['key'];
        $nonce_str = getRandomStrings($mchid);
        $config = $this->getselfwxconfig();
        $appid = $config['appid'];
        $data = [
            'appid' => $appid,
            'mch_id' => $mchid,
            'nonce_str' => $nonce_str,
            'openid' => $openid,
            'body' => $body,
            'out_trade_no' => $out_trade_no,
            'total_fee' => $total_fee,
            'spbill_create_ip' => '8.8.8.8',
            'notify_url' => $notify_url,
            'trade_type' => $trade_type,
        ];
        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";

        ksort($data);
        $sign_str = $this->ToUrlParams($data);
        $sign_str = $sign_str . "&key=" . $key;
        $data['sign'] = strtoupper(md5($sign_str));
        $xml = $this->arrayToXml($data);
        log::info($xml);
        $r = $this->postXmlCurl($xml, $url, true);
        log::info($r);
        $result = json_decode($this->xml_to_json($r));
        log::info($result); //保留这个做记录，以便出错后查询
        //var_dump($result);

        if ($result->return_code == 'SUCCESS') {
            $sdata['appId'] = $appid;
            $sdata['timeStamp'] = time();
            $sdata['nonceStr'] = md5(time() . rand() . rand() . $openid);
            $sdata['package'] = "prepay_id=" . $result->prepay_id;
            $sdata['signType'] = "MD5";

            $payorder['openid'] = $openid;
            $payorder['prepay_id'] = $result->prepay_id;
            $payorder['create_date'] = date('Y-m-d H:i:s');
            $payorder['payfee'] = $data['total_fee'];
            $payorder['outorderno'] = $data['out_trade_no'];
            $payorder['order_type'] = 1;
            $payorder['wid'] = $wid;
            $payorder['appointent_id'] = $appointentid;

            $l_po = new payordermodel();
            $poid = $l_po->insertData($payorder);
            if (empty($poid)) {
                return backarr(0, '订单创建失败');
            }

            ksort($sdata);
            $sign_str = $this->ToUrlParams($sdata);
            $sign_str = $sign_str . "&key=" . $key;
            $sdata['paySign'] = strtoupper(md5($sign_str));
            $sdata['outorderno'] = $data['out_trade_no'];
            return backarr(1, '订单创建成功', json_encode($sdata));
        }
    }
    /*
     *   用于微信支付转换认证的信息用的
     *   by:leoyi
     *   date:2018-4-8
     */
    public function ToUrlParams($data)
    {
        $buff = "";
        foreach ($data as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }

        $buff = trim($buff, "&");
        return $buff;
    }
    /*
     *   微信支付-数组转xml
     *   by:leoyi
     *   date:2018-4-8
     */
    public function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else {
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
            }
        }
        $xml .= "</xml>";
        return $xml;
    }
    /*
     *   微信支付-数组转xml
     *   by:leoyi
     *   date:2018-4-8
     */
    public function xml_to_json($xmlstring)
    {
        return json_encode($this->xml_to_array($xmlstring), JSON_UNESCAPED_UNICODE);
    }
    /*
     * 把xml转换成array
     * by:leoyi
     * Date:2018-4-11
     */
    public function xml_to_array($xml)
    {
        //return ((array) simplexml_load_string($xmlstring));
        return simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);

        //return json_decode(xml_to_json($xmlstring));
    }
    /**
     * 用户post方法请求xml信息用的 支付用
     * @author write by leoyi 2018-04-8
     */
    public function postXmlCurl($xml, $url, $useCert = false, $second = 10)
    {
        $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //严格校验2
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, false);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        //运行curl
        $data = curl_exec($ch);
        //返回结果
        if ($data) {
            curl_close($ch);
            return $data;
        } else {
            $error = curl_errno($ch);
            curl_close($ch);
            return $error;
        }
    }
    /**
     * 微信回调返回信息
     *
     * @param  [type] $data
     * @return void
     * @author wj
     * @date 2022-07-23
     */
    public function paybackxml($data)
    {
        $xmlback = $this->arrayToXml($data);
        Log::info('返回信息');
        Log::info($xmlback);
        exit($xmlback);
    }
}
