<?php

namespace web\api;

class weixin {
    public $tokenid;
    public $token;

    function __construct($tokenid) {
        global $db;
        $this->token = null;
        $ret = gettoken($db, $tokenid);
        if (is_string($ret))
            return $this->err($ret);
        $this->tokenid = $tokenid;
        $this->token = $ret;
    }
    function err($ret, $log = '') {
        savelogfile('WXPAY', $ret . $log);
        return $ret;
    }
    public function call($url, $post = null, $isbinary = false) {
        if (!$this->token)
            return 'token不存在';
        if (strpos($url, '{accesstoken}') !== false) {
            $ret = $this->getaccesstoken();
            if (is_string($ret))
                return $ret;
            $url = str_replace('{accesstoken}', $ret['accesstoken'], $url);
        }
        if (strpos($url, '{appid}') !== false)
            $url = str_replace('{appid}', $this->token['appid'], $url);
        if (strpos($url, '{appsecret}') !== false)
            $url = str_replace('{appsecret}', $this->token['appsecret'], $url);

        $http = new \ciy\http();
        $http->set_headeronce('Content-Type', 'application/json');
        $http->set_headeronce('Accept', 'application/json');
        if (is_array($post))
            $post = json_encode($post, JSON_UNESCAPED_UNICODE);
        $http->request($url, $post);
        $statcode = $http->get_statcode();
        if ($statcode != 200 && $statcode != 204)
            return $this->err('微信服务器无法连接，错误码:' . $statcode);
        $result = $http->get_data();
        if ($isbinary) {
            if (@$result[0] != '{')
                return array('bin' => $result);
        }
        $json = json_decode($result, true);
        if ($json === null)
            return $this->err('微信服务器返回数据失败', $result);
        if (isset($json['errcode']) && $json['errcode'] != 0)
            return $this->err('微信服务器返回错误:' . @$json['errmsg']);
        return $json;
    }
    public function refund($param) { //退款
        $result = $this->certcall('https://api.mch.weixin.qq.com', '/v3/refund/domestic/refunds', $param);
        if (is_string($result))
            return $result;
        return $result;
    }
    public function transfer($param) { //提现
        $param['appid'] = $this->token['appid'];
        $result = $this->certcall('https://api.mch.weixin.qq.com', '/v3/fund-app/mch-transfer/transfer-bills', $param);
        if (is_string($result))
            return $result;
        $result['mchid'] = $this->token['mchid'];
        $result['appid'] = $this->token['appid'];
        return $result;
    }
    public function pay($param) { //支付
        $param['appid'] = $this->token['appid'];
        $param['mchid'] = $this->token['mchid'];
        $result = $this->certcall('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->token['pem_path']));
        $message = $this->token['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->token['appid'];
        $ret['timeStamp'] = $timestamp;
        $ret['nonceStr'] = $nonce;
        $ret['package'] = 'prepay_id=' . $result['prepay_id'];
        $ret['signType'] = 'RSA';
        $ret['paySign'] = $sign;
        return $ret;
    }
    private function certcall($domain, $url, $post) {
        if (!file_exists($this->token['pem_path']))
            return $this->err('证书文件不存在', $this->token['pem_path']);
        $timestamp = time() . '';
        $nonce = uniqid() . uniqid();
        $post = json_encode($post, JSON_UNESCAPED_UNICODE);
        $message = "POST\n" . $url . "\n" . $timestamp . "\n" . $nonce . "\n" . $post . "\n";
        $pkey = openssl_pkey_get_private(file_get_contents($this->token['pem_path']));
        openssl_sign($message, $raw_sign, $pkey, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);
        $token = 'mchid="' . $this->token['mchid'] . '",nonce_str="' . $nonce . '",timestamp="' . $timestamp . '",serial_no="' . $this->token['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);
        }
    }
    private function getaccesstoken() {
        global $db;
        if ($this->token['exptimes'] > time())
            return array('accesstoken' => $this->token['accesstoken']);
        $http = new \ciy\http();
        $http->set_headeronce('Content-Type', 'application/json');
        $http->set_headeronce('Accept', 'application/json');
        $http->request('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $this->token['appid'] . '&secret=' . $this->token['appsecret']);
        $result = $http->get_data();
        $json = json_decode($result, true);
        if ($json === null)
            return $this->err('微信服务器无法连接token', $result);
        if (toint(@$json['errcode']) != 0)
            return $this->err($json['errmsg']);
        $accesstoken = @$json['access_token'];
        if (empty($accesstoken))
            return $this->err('微信token授权失败', $result);
        $exptimes = time() + toint($json['expires_in']);
        $updata = array();
        $updata['accesstoken'] = $accesstoken;
        $updata['exptimes'] = $exptimes;
        $ret = settoken($db, $this->tokenid, $updata);
        if (is_string($ret))
            return $this->err($ret);
        return array('accesstoken' => $accesstoken);
    }
}
