<?php
namespace crmeb\services;


use think\Request;

class JiaLieService
{
    private static $Url = "https://qrcode.jlpay.com/api/pay/";
    private static $zsUrl = "https://qrcode.jlpay.com/api/pay/";
    private static $dgurl = "https://qrcode-dev.jlpay.com/api/pay/";
    private static $initialize = null;
    private static $org_code =null;
    private static $mch_id =null;
    private static $prikey =null;
    private static $pubkey =null;
    private static $dubeg =null;
    private static $errorMsg = "";
    const DEFAULT_ERROR_MSG = '操作失败,请稍候再试!';
    const MICROPAY = "micropay";  //付款码支付
    const QRCODEPAY = "qrcodepay";  //扫码支付
    const REFUND = "refund";  //退款接口
    const CANCEL = "cancel"; //撤销接口
    const APPPAY = "apppay"; //APP支付接口
    const OFFICIALPAY = "officialpay";//微信公众号、小程序支付接口
    const WAPH5PAY = "waph5pay"; // 支付宝服务窗、小程序支付接口
    const QUERY  = "chnquery"; //订单查询接口
    const UNIONJSPAY = "unionjspay"; //银联行业码支付接口
    const AUTHBIND= "authbind"; //绑定支付目录接口
    const GETOPENID = "getopenid";//授权码获取openId或userId接口
    const MICROPAYPREAUTH  = "micropaypreauth";//付款码预授权
    const QRCODEPAYPREAUTH = "qrcodepaypreauth";//扫码预授权
    const PREAUTHCOMPLETE= "preauthcomplete"; //预授权完成
    const PREAUTHREVIKE = "preauthrevoke"; //预授权撤销
    const PREAUTHCLOSE  = "preauthclose";//预授权关单
    const PREAUTHQUREY = "preauthquery";//预授权查询

    /**
     * 设置错误信息
     * @param string $errorMsg
     * @return bool
     */
    protected static function setErrorInfo($errorMsg = self::DEFAULT_ERROR_MSG, $rollback = false)
    {
        if ($rollback) self::rollbackTrans();
        self::$errorMsg = $errorMsg;
        return false;
    }

    /**
     * 获取错误信息
     * @param string $defaultMsg
     * @return string
     */
    public static function getErrorInfo($defaultMsg = self::DEFAULT_ERROR_MSG)
    {
        return !empty(self::$errorMsg) ? self::$errorMsg : $defaultMsg;
    }
    private function __construct()
    {
        // TODO 初始化配置
        $system = SystemConfigService::more(['jl_org_code', 'jl_mch_id', 'mer_prikey', 'jl_pubkey','jl_dubeg']);
        self::$org_code = $system['jl_org_code'] ?? '';
        self::$mch_id = $system['jl_mch_id'] ?? '';
        self::$prikey = $system['mer_prikey'] ?? '';
        self::$pubkey = $system['jl_pubkey'] ?? '';
        self::$dubeg = $system['jl_dubeg'] ?? '';
        if($system['jl_dubeg']==1)
        {
            self::$Url = self::$dgurl;
        }
        else
        {
            self::$Url = self::$zsUrl;
        }
    }

    /**
     * 初始化静态类
     *
     * @return Test
     */
    public static function initialize(): JiaLieService
    {
        if (!self::$initialize instanceof self) {
            return new self();
        }
        return self::$initialize;
    }
    private static function do_rsaSign($data, $private_key) {

        $search = [
            "-----BEGIN RSA PRIVATE KEY-----",
            "-----END RSA PRIVATE KEY-----",
            "\n",
            "\r",
            "\r\n"
        ];

        $private_key = str_replace($search, "", $private_key);
        $private_key = $search[0] . PHP_EOL . wordwrap($private_key, 64, "\n", true) . PHP_EOL . $search[1];
        $res = openssl_get_privatekey($private_key);
        if ($res) {
            openssl_sign($data, $sign, $res,OPENSSL_ALGO_SHA256);
            openssl_free_key($res);
        } else {
            self::setErrorInfo("私钥格式有误");
        }
        @file_put_contents("xxx.txt",$sign);
        $sign = base64_encode($sign);
        return $sign;
    }
    /**
     * RSA验签
     * @param $data 待签名数据
     * @param $public_key 公钥字符串
     * @param $sign 要校对的的签名结果
     * return 验证结果
     */
    public static function do_rsaCheck($data, $public_key, $sign) {
        $search = [
            "-----BEGIN PUBLIC KEY-----",
            "-----END PUBLIC KEY-----",
            "\n",
            "\r",
            "\r\n"
        ];
        $public_key = str_replace($search, "", $public_key);
        $public_key = $search[0] . PHP_EOL . wordwrap($public_key, 64, "\n", true) . PHP_EOL . $search[1];
        $res = openssl_get_publickey($public_key);
        if ($res) {
            $result = (bool) openssl_verify($data, base64_decode($sign), $res,OPENSSL_ALGO_SHA256);
            file_put_contents("callback.txt", "\n异步验签原字符串\n", FILE_APPEND);
            file_put_contents("callback.txt",$data , FILE_APPEND);
            openssl_free_key($res);
        } else {
            self::setErrorInfo('公钥格式有误');
        }
        return $result;
    }
     public static function rsaSign($params) {
         $dataStr = self::getJsonStr($params);
         return self::do_rsaSign($dataStr, self::$prikey);
     }

    public static function verify($params) {
        if (!isset($params['sign'])) {
            throw new Exception("没有sign签名参数");
        }
        $sign = $params['sign'];
        unset($params['sign']);
        $dataStr = self::getJsonStr($params);
        return self::do_rsaCheck($dataStr, self::$pubkey, $sign);
    }
    public static function getJsonStr($params) {
        if (!is_array($params)) {
            return $params;
        }
        if (count($params) <= 0) {
            throw new Exception("检查参数");
        }
        ksort($params);
        return json_encode($params,JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
    }
    public static function getKeyValueStr($params) {
        if (!is_array($params)) {
            return $params;
        }
        if (count($params) <= 0) {
            throw new Exception("检查参数");
        }
        $dataStr = "";
        ksort($params);
        foreach ($params as $key => $value) {
            if ($key == "sign") {
                continue;
            }
            if ($value === "" || $value === null) {
                continue;
            }

            $dataStr .= $key . "=" . $value;
            $dataStr .= "&";
        }

        return rtrim($dataStr, "&");
    }
    public static function checkTradeType($authCode) {
        if (empty($authCode)) {
            return "";
        }
        $prefix = substr($authCode, 0, 2);
        $aliPayCode = array("25", "26", "27", "28", "29", "30");
        $wxPayCode = array("10", "11", "12", "13", "14", "15");
        $unionPayCode = array("62");

        if (in_array($prefix, $aliPayCode)) {
            return "alipay";
        } else if (in_array($prefix, $wxPayCode)) {
            return "wxpay";
        } else if (in_array($prefix, $unionPayCode)) {
            return "unionpay";
        }
        return "";
    }
    public static function dataRecodes($title, $data) {
        $handler = fopen('logs/result.txt', 'a+');
        $content = "================" . $title . "===================\n";
        if (is_string($data) === true) {
            $content .= $data . "\n";
        }
        if (is_array($data) === true) {
            foreach ($data as $k => $v) {
                $content .= "key:【" . $k . "】,value: 【" . var_export($v, true) . "】\n";
            }
        }
        $flag = fwrite($handler, $content);
        fclose($handler);
        return $flag;
    }

    /**
     * 调取支付
     * @param string $URL
     * @param array $Params
     * @return bool|string
     */
    public static function paymentOrder($URL=self::MICROPAY,$Params=[])
    {
        $headers = array("Content-Type:application/json");
        $config = [
            'org_code' => self::$org_code,
            'mch_id' => self::$mch_id,
            'version' => "1.0.0",
            'charset' => "UTF-8",
            'sign_type' => "RSA",
            'pay_type' => 'wxpay',
            'notify_url'=> sys_config('site_url')."/api/jialie/notify",
        ];
        $requestParams = array_merge($config, $Params);
        $requestParams['sign'] = self::rsaSign($requestParams);
        $http = new HttpClient();
        $http->setDebug(true);
        self::dataRecodes('付款码支付request报文 ', $requestParams);
        $rs = $http->post(self::$Url.$URL,json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers);
        //$rs = self::http(self::$Url.$URL,"POST",json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers);
        self::dataRecodes('付款码支付response报文 ', self::$Url.$URL.'--'.json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
        self::dataRecodes('付款码支付response报文 ', $rs);
        return $rs;
    }
    public static function paymentquery($URL=self::QUERY,$Params)
    {
        $headers = array("Content-Type:application/json");
        $config = [
            'org_code' => self::$org_code,
            'mch_id' => self::$mch_id,
            'version' => "1.0.0",
            'charset' => "UTF-8",
            'sign_type' => "RSA",
        ];
        $requestParams = array_merge($config, $Params);
        $requestParams['sign'] = self::rsaSign($requestParams);
        $http = new HttpClient();
        //$http->setDebug(true);
        //self::dataRecodes('订单查询request报文 ', $requestParams);
        $rs = $http->post(self::$Url.$URL,json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers);
        //$rs = self::http(self::$Url.$URL,"POST",json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers);
        //self::dataRecodes('订单查询response报文 ', self::$Url.$URL.'--'.json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
        //self::dataRecodes('订单查询response报文 ', $rs);
        return $rs;
    }
    public static function payOrderRefund($orderNo, array $opt)
    {
        if (!isset($opt['pay_price'])) exception('缺少pay_price');
        $totalFee = floatval(bcmul($opt['pay_price'], 100, 0));
        $refundFee = isset($opt['refund_price']) ? floatval(bcmul($opt['refund_price'], 100, 0)) : null;
        $refundReason = isset($opt['desc']) ? $opt['desc'] : '';
        $headers = array("Content-Type:application/json");
        $config = [
            'org_code' => self::$org_code,
            'mch_id' => self::$mch_id,
            'charset' => "UTF-8",
            'sign_type' => "RSA",
        ];
        $Params['nonce_str'] = uniqid();
        $Params['out_trade_no'] = 'ref'.uniqid();
        $Params['ori_out_trade_no'] = $orderNo;
        $Params['total_fee'] = intval($refundFee);
        $Params['mch_create_ip'] = app('request')->ip();
        $Params['remark'] = $refundReason;
        $requestParams = array_merge($config, $Params);
        $requestParams['sign'] = self::rsaSign($requestParams);
        $http = new HttpClient();
        $http->setDebug(true);
        self::dataRecodes('订单退款request报文 ', $requestParams);
        $rs = $http->post(self::$Url.self::REFUND,json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers);
        //$rs = self::http(self::$Url.$URL,"POST",json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),$headers);
        self::dataRecodes('订单退款request报文 ', self::$Url.self::REFUND.'--'.json_encode($requestParams, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
        self::dataRecodes('订单退款request报文 ', $rs);
        return $rs;
    }




}
