<?php
//过时
namespace ciy;

class wxfunc {
    public $appid;
    public $mchid;
    public $appsecret;
    public $pem_path;
    public $pem_no;
    public $accesstoken;

    function __construct($cfg = null) {
        if(!is_array($cfg))
            return;
        $this->appid = $cfg['appid'];
        $this->appsecret = $cfg['appsecret'];
        $this->mchid = $cfg['mchid'];
        $this->pem_no = $cfg['pem_no'];
        $this->pem_path = $cfg['pem_path'];
        if(isset($cfg['accesstoken']))
            $this->accesstoken = $cfg['accesstoken'];
    }

    function getaccess() {
        $cfg['ssl'] = true;
        $result = $this->curlOpen(
            'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $this->appid . '&secret=' . $this->appsecret,
            $cfg
        );
        $json = json_decode($result, true);
        if ($json === null)
            return $this->err('微信服务器无法连接getaccess', $result);
        if (toint(@$json['errcode']) != 0)
            return $this->err(@$json['errmsg'], $result);
        $accesstoken = @$json['access_token'];
        if (empty($accesstoken))
            return $this->err('微信授权失败', $result);
        $exptimes = time() + toint($json['expires_in']);
        return array('accesstoken' => $accesstoken, 'exptimes' => $exptimes);
    }
    function code2Session($code) {
        $cfg['ssl'] = true;
        $result = $this->curlOpen('https://api.weixin.qq.com/sns/jscode2session?grant_type=authorization_code&appid=' . $this->appid . '&secret=' . $this->appsecret . '&js_code=' . $code, $cfg);
        $json = json_decode($result, true);
        if ($json === null)
            return $this->err('微信服务器无法连接code2session', $result);
        if (toint(@$json['errcode']) != 0)
            return $this->err(@$json['errmsg'], $result);
        return $json;
    }
    public function decryptData($encryptedData, $iv, $loginiv) {
        if (strlen($loginiv) != 24)
            return 'AES解密失败session len';
        $aesKey = base64_decode($loginiv);
        if (strlen($iv) != 24)
            return 'AES解密失败iv len';
        $aesIV = base64_decode($iv);
        $aesCipher = base64_decode($encryptedData);
        $result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
        if ($result === false)
            return '请再点击一次';
        $json = json_decode($result, true);
        if ($json === null)
            return 'AES解密失败json';
        return $json;
    }

    public function pay($param) {
        $param['appid'] = $this->appid;
        $param['mchid'] = $this->mchid;
        $result = $this->httppay('https://api.mch.weixin.qq.com','/v3/pay/transactions/jsapi',$param);
        if(is_string($result))
            return $result;

        $timestamp = time() . '';
        $nonce = uniqid() . uniqid();
        $pkey = openssl_pkey_get_private(file_get_contents($this->pem_path));
        $message = $this->appid . "\n" . $timestamp . "\n" . $nonce . "\nprepay_id=" . $result['prepay_id'] . "\n";

        openssl_sign($message, $raw_sign, $pkey, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);

        $ret['appId'] = $this->appid;
        $ret['timeStamp'] = $timestamp;
        $ret['nonceStr'] = $nonce;
        $ret['package'] = 'prepay_id=' . $result['prepay_id'];
        $ret['signType'] = 'RSA';
        $ret['paySign'] = $sign;
        return $ret;
    }
    public function transfer($param) {
        $param['appid'] = $this->appid;
        $result = $this->httppay('https://api.mch.weixin.qq.com','/v3/fund-app/mch-transfer/transfer-bills',$param);
        if(is_string($result))
            return $result;
        return $result;
    }
    public function getwxacodeunlimit($param) {
        $cfg['ssl'] = true;
        $cfg['post'] = json_encode($param, JSON_UNESCAPED_UNICODE);
        $result = $this->curlOpen(
            'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' . $this->accesstoken,
            $cfg
        );
        return $result;
    }
    function httppay($domain, $url, $param) {
        if(!file_exists($this->pem_path))
            return '证书文件不存在'.$this->pem_path;
        $timestamp = time() . '';
        $nonce = uniqid() . uniqid();
        $post = json_encode($param, JSON_UNESCAPED_UNICODE);
        $message = "POST\n".$url."\n" . $timestamp . "\n" . $nonce . "\n" . $post . "\n";
        $pkey = openssl_pkey_get_private(file_get_contents($this->pem_path));
        openssl_sign($message, $raw_sign, $pkey, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);
        $token = 'mchid="' . $this->mchid . '",nonce_str="' . $nonce . '",timestamp="' . $timestamp . '",serial_no="' . $this->pem_no . '",signature="' . $sign . '"';
        $http = new \ciy\http();
        $http->set_headeronce('Content-Type','application/json');
        $http->set_headeronce('Accept','application/json');
        $http->set_headeronce('Authorization','WECHATPAY2-SHA256-RSA2048 ' . $token);
        $http->request($domain.$url, $post);
        $statcode = $http->get_statcode();
        if($statcode == 200 || $statcode == 204){
            $result = $http->get_data();
            $json = json_decode($result, true);
            if ($json === null)
                return array('code' => 1);
            if (isset($json['message']))
                return $this->err('微信服务器返回错误:' . $json['message']);
            $json['code'] = 1;
            return $json;
        }else{
            $res['errmsg'] = 1;
            $result = $http->get_data();
            $json = json_decode($result, true);
            if ($json === null)
                return $this->err('微信服务器无法连接pay', $result);
            if (isset($json['message']))
                return $this->err('微信服务器返回错误:' . $json['message']);
            return $this->err('微信服务器返回json:' . $result);
        }
    }
    public function pay2($param) {
        $param['appid'] = $this->appid;
        $param['mchid'] = $this->mchid;
        $cfg['ssl'] = true;
        $cfg['post'] = json_encode($param, JSON_UNESCAPED_UNICODE);
        $cfg['header'] = array();
        $cfg['header'][] = 'Content-Type: application/json';
        $timestamp = time() . '';
        $nonce = uniqid() . uniqid();
        $message = "POST\n/v3/pay/transactions/jsapi\n" . $timestamp . "\n" . $nonce . "\n" . $cfg['post'] . "\n";
        $pkey = openssl_pkey_get_private(file_get_contents($this->pem_path));
        openssl_sign($message, $raw_sign, $pkey, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);
        $token = 'mchid="' . $param['mchid'] . '",nonce_str="' . $nonce . '",timestamp="' . $timestamp . '",serial_no="' . $this->pem_no . '",signature="' . $sign . '"';
        $cfg['header'][] = 'Authorization: WECHATPAY2-SHA256-RSA2048 ' . $token;
        $result = $this->curlOpen('https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi', $cfg);
        $json = json_decode($result, true);
        if ($json === null)
            return $this->err('微信服务器无法连接pay', $result);
        if (isset($json['message']))
            return $this->err('微信服务器返回错误:' . $json['message']);

        $message = $param['appid'] . "\n" . $timestamp . "\n" . $nonce . "\nprepay_id=" . $json['prepay_id'] . "\n";

        openssl_sign($message, $raw_sign, $pkey, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);

        $ret['appId'] = $param['appid'];
        $ret['timeStamp'] = $timestamp;
        $ret['nonceStr'] = $nonce;
        $ret['package'] = 'prepay_id=' . $json['prepay_id'];
        $ret['signType'] = 'RSA';
        $ret['paySign'] = $sign;
        return $ret;
    }
    public function payrefund($param) {
        $json = $this->httppay('https://api.mch.weixin.qq.com','/v3/refund/domestic/refunds',$param);
        return $json;
    }

    // static public function xcx_setactive($accesstoken, $param) {
    //     $cfg['ssl'] = true;
    //     $cfg['post'] = json_encode($param, JSON_UNESCAPED_UNICODE);
    //     $result = curlOpen('https://api.weixin.qq.com/cgi-bin/message/wxopen/updatablemsg/send?access_token=' . $accesstoken, $cfg);
    //     $json = json_decode($result, true);
    //     if ($json === null)
    //         return xcxerr('微信服务器无法连接setactive', $result);
    //     if (toint(@$json['errcode']) != 0)
    //         return xcxerr(@$json['errmsg'], $result);
    //     return $json;
    // }
    // function xcx_getactive($accesstoken) { // 开房/开团后返回activeID，调用updateShareMenu后分享，每次进人setactive，直至开始/成功。
    //     $cfg['ssl'] = true;
    //     $result = curlOpen('https://api.weixin.qq.com/cgi-bin/message/wxopen/activityid/create?access_token=' . $accesstoken, $cfg);
    //     $json = json_decode($result, true);
    //     if ($json === null)
    //         return xcxerr('微信服务器无法连接getactive', $result);
    //     if (toint(@$json['errcode']) != 0)
    //         return xcxerr(@$json['errmsg'], $result);
    //     return $json;
    // }
    // function xcx_sendsubscribe($accesstoken, $param) { // 发送模板消息
    //     $cfg['ssl'] = true;
    //     $cfg['post'] = json_encode($param, JSON_UNESCAPED_UNICODE);
    //     $result = curlOpen('https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=' . $accesstoken, $cfg);
    //     $json = json_decode($result, true);
    //     if ($json === null)
    //         return xcxerr('微信服务器无法连接sendsubscribe', $result);
    //     if (toint(@$json['errcode']) != 0)
    //         return xcxerr(@$json['errmsg'], $result);
    //     return $json;
    // }
    // function xcx_sendmb($accesstoken, $param) { // 发送模板消息
    //     $cfg['ssl'] = true;
    //     $cfg['post'] = json_encode($param, JSON_UNESCAPED_UNICODE);
    //     $result = curlOpen('https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=' . $accesstoken, $cfg);
    //     $json = json_decode($result, true);
    //     if ($json === null)
    //         return xcxerr('微信服务器无法连接sendmb', $result);
    //     if (toint(@$json['errcode']) != 0)
    //         return xcxerr(@$json['errmsg'], $result);
    //     return $json;
    // }
    // function xcx_senduniform($accesstoken, $param) { // 发送统一服务消息
    //     $cfg['ssl'] = true;
    //     //https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/uniform-message/uniformMessage.send.html
    //     $cfg['post'] = json_encode($param, JSON_UNESCAPED_UNICODE);
    //     $result = curlOpen('https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send?access_token=' . $accesstoken, $cfg);
    //     $json = json_decode($result, true);
    //     if ($json === null)
    //         return xcxerr('微信服务器无法连接senduniform', $result);
    //     if (toint(@$json['errcode']) != 0)
    //         return xcxerr(@$json['errmsg'], $result);
    //     return $json;
    // }
    // function xcx_getqrcode($accesstoken, $tmppath, $fname, $param, $bgparam = null) {
    //     $cfg['ssl'] = true;
    //     $cfg['post'] = json_encode($param, JSON_UNESCAPED_UNICODE);
    //     $result = curlOpen('https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' . $accesstoken, $cfg);
    //     if (empty($result))
    //         return xcxerr('微信服务器无法连接getqrcode');
    //     if ($result[0] == '{') {
    //         $json = json_decode($result, true);
    //         if (toint(@$json['errcode']) != 0)
    //             return xcxerr(@$json['errmsg'], $result);
    //         else
    //             return xcxerr('未知错误', $result);
    //     }
    //     if (empty($fname))
    //         $fname = date('Y-m-d_H-i-s', time()) . '_' . rand(100000, 999999);
    //     $filename = $tmppath . $fname;
    //     if ($bgparam === null) {
    //         if ($param['is_hyaline'])
    //             $filename .= '.png';
    //         else
    //             $filename .= '.jpg';
    //         $fp = fopen(PATH_ROOT . $filename, 'w');
    //         fwrite($fp, $result);
    //         @fclose($fp);
    //     } else {
    //         // 背景图
    //         $x = toint($bgparam['x']);
    //         $y = toint($bgparam['y']);
    //         $wh = toint($param['width']);

    //         $imgbg = imagecreatefrompng($bgparam['bgimg']);
    //         if (isset($bgparam['icon'])) {
    //             $icon = $bgparam['icon'];
    //             $ext = substr($icon['img'], -4);
    //             if ($ext == 'png')
    //                 $imgicon = imagecreatefrompng($icon['img']);
    //             else
    //                 $imgicon = imagecreatefromjpeg($icon['img']);
    //             $iconw = imagesx($imgicon);
    //             $iconh = imagesy($imgicon);
    //             if (function_exists('imagecopyresampled'))
    //                 imagecopyresampled($imgbg, $imgicon, $icon['x'], $icon['y'], 0, 0, $icon['w'], $icon['h'], $iconw, $iconh);
    //             else
    //                 imagecopyresized($imgbg, $imgicon, $icon['x'], $icon['y'], 0, 0, $icon['w'], $icon['h'], $iconw, $iconh);
    //         }
    //         if (isset($bgparam['text'])) {
    //             $text = $bgparam['text'];
    //             $color = imagecolorallocate($imgbg, toint(@$text['r']), toint(@$text['g']), toint(@$text['b']));
    //             imagettftext($imgbg, $text['size'], 0, $text['x'], $text['y'], $color, 'pingfangbold.ttf', $text['txt']);
    //         }
    //         $imgqrcode = imagecreatefromstring($result);
    //         imagecopy($imgbg, $imgqrcode, $x, $y, 0, 0, $wh, $wh);
    //         $filename = $filename . '.jpg';
    //         $ret = imagejpeg($imgbg, PATH_ROOT . $filename, 80);
    //         imagedestroy($imgbg);
    //         imagedestroy($imgqrcode);
    //         if (!$ret)
    //             return xcxerr('保存合并图失败');
    //     }
    //     return array('url' => $filename);
    // }
    // function xcx_decryptData($encryptedData, $iv, $loginiv) {
    //     if (strlen($loginiv) != 24)
    //         return 'AES解密失败session len';
    //     $aesKey = base64_decode($loginiv);
    //     if (strlen($iv) != 24)
    //         return 'AES解密失败iv len';
    //     $aesIV = base64_decode($iv);
    //     $aesCipher = base64_decode($encryptedData);
    //     $result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
    //     if ($result === false)
    //         return '请再点击一次';
    //     $json = json_decode($result, true);
    //     if ($json === null)
    //         return xcxerr('AES解密失败', $result . '');
    //     return $json;
    // }
    // function calsign($param, $key) {
    //     ksort($param);
    //     $buff = '';
    //     foreach ($param as $k => $v) {
    //         if ($k != 'sign' && $v != '' && !is_array($v))
    //             $buff .= $k . '=' . $v . '&';
    //     }
    //     $buff .= 'key=' . $key;
    //     $string = strtoupper(md5($buff));
    //     return $string;
    // }
    function err($ret, $log = '') {
        if (!empty($log))
            savelogfile('WXPAY', $ret . $log);
        return $ret;
    }
    function filter_utf8_char($ostr) {
        preg_match_all('/[\x{FF00}-\x{FFEF}|\x{0000}-\x{00ff}|\x{4e00}-\x{9fff}]+/u', $ostr, $matches);
        $str = join('', $matches[0]);
        if ($str == '') { // 含有特殊字符需要逐個處理
            $returnstr = '';
            $i = 0;
            $str_length = strlen($ostr);
            while ($i <= $str_length) {
                $temp_str = substr($ostr, $i, 1);
                $ascnum = Ord($temp_str);
                if ($ascnum >= 224) {
                    $returnstr = $returnstr . substr($ostr, $i, 3);
                    $i = $i + 3;
                } elseif ($ascnum >= 192) {
                    $returnstr = $returnstr . substr($ostr, $i, 2);
                    $i = $i + 2;
                } elseif ($ascnum >= 65 && $ascnum <= 90) {
                    $returnstr = $returnstr . substr($ostr, $i, 1);
                    $i = $i + 1;
                } elseif ($ascnum >= 128 && $ascnum <= 191) { // 特殊字符
                    $i = $i + 1;
                } else {
                    $returnstr = $returnstr . substr($ostr, $i, 1);
                    $i = $i + 1;
                }
            }
            $str = $returnstr;
            preg_match_all('/[\x{FF00}-\x{FFEF}|\x{0000}-\x{00ff}|\x{4e00}-\x{9fff}]+/u', $str, $matches);
            $str = join('', $matches[0]);
        }
        return $str;
    }

    function curlOpen($url, $config = array()) {
        $arr = array('post' => false, 'referer' => $url, 'cookie' => '', 'useragent' => 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; customie8)', 'timeout' => 50, 'return' => 1, 'proxy' => '', 'userpwd' => '', 'nobody' => 0, 'gzip' => 0, 'ssl' => 1);
        $arr['header'] = array();
        $arr = array_merge($arr, $config);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //$arr['return']
        curl_setopt($ch, CURLOPT_NOBODY, $arr['nobody']);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_USERAGENT, $arr['useragent']);
        curl_setopt($ch, CURLOPT_REFERER, $arr['referer']);
        //curl_setopt($ch, CURLOPT_TIMEOUT, $arr['timeout']);
        if ($arr['gzip']) curl_setopt($ch, CURLOPT_ENCODING, 'gzip,deflate');
        if ($arr['ssl']) {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        }
        if (!empty($arr['cookie'])) {
            curl_setopt($ch, CURLOPT_COOKIEJAR, $arr['cookie']);
            curl_setopt($ch, CURLOPT_COOKIEFILE, $arr['cookie']);
        }

        if (!empty($arr['proxy'])) {
            //curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);  
            curl_setopt($ch, CURLOPT_PROXY, $arr['proxy']);
            if (!empty($arr['userpwd'])) {
                curl_setopt($ch, CURLOPT_PROXYUSERPWD, $arr['userpwd']);
            }
        }

        //ip比较特殊，用键值表示
        if (!empty($arr['header']['ip'])) {
            array_push($arr['header'], 'X-FORWARDED-FOR:' . $arr['header']['ip'], 'CLIENT-IP:' . $arr['header']['ip']);
            unset($arr['header']['ip']);
        }
        $arr['header'] = array_filter($arr['header']);

        if (!empty($arr['header'])) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $arr['header']);
        }

        if ($arr['post'] != false) {
            curl_setopt($ch, CURLOPT_POST, true);
            if (is_array($arr['post'])) {
                $post = http_build_query($arr['post']);
            } else {
                $post = $arr['post'];
            }
            curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
        }
        $result = curl_exec($ch);
        //var_dump(curl_getinfo($ch));
        curl_close($ch);
        $ind = strpos($result, 'HTTP');
        if ($ind < 2) {
            $ind = strpos($result, "\r\n\r\n");
            if ($ind > 0) {
                $result = substr($result, $ind + 4);
            }
        }
        if (strpos($result, '{') === 0) {
            $ind = strrpos($result, '}');
            if ($ind < strlen($result))
                $result = substr($result, 0, $ind + 1);
        }
        return $result;
    }
}
