<?php
namespace app\admin\server\payment;

class TonglianPayment
{
    public static $url = 'https://vsp.allinpay.com/apiweb/unitorder';

    public static function createOrder($trxamt, $orderid, $pay_type = 'W01' ,$open_id = '')
    {
        $param = array(
            'cusid'     => static::_getConfig('cusid'),//商户号
            'appid'     => static::_getConfig('appid'),//平台分配ID
            'version'   => static::_getConfig('version'),//版本
            'paytype'   => $pay_type, //交易方式  W01=微信扫码  A01=支付宝扫码
            'notify_url' => static::_getConfig('notify_url'),//异步通知地址
            'trxamt'    => $trxamt, //付款金额
            'reqsn'     => $orderid, //订单编号
            'randomstr' => time(),
            'signtype'  => 'RSA',  //加密方式
        );
        if($pay_type == 'W06'){
            $param['acct'] = $open_id;
            $param['sub_appid'] = static::_getConfig('sub_appid');//小程序appid
        }
        $param['sign'] = urlencode(static::Sign($param));
        $paramsStr = static::ToUrlParams($param);
        $url = static::$url . '/pay';
        $rsp = static::request($url, $paramsStr);
        $result = json_decode($rsp, true);
        if($result['retcode'] != 'SUCCESS')
        {
            throw new \Exception($result['retmsg'], 500);
        }
        return $result;
    }
    //交易撤销（当天）
    public static function cancel($trxamt, $orderid)
    {
        $param = array(
            'cusid'     => static::_getConfig('cusid'),//商户号
            'appid'     => static::_getConfig('appid'),//平台分配ID
            'version'   => static::_getConfig('version'),//版本
            'trxamt'    => $trxamt, //付款金额
            'reqsn'     => $orderid.'TK', //退款订单编号
            'oldreqsn'  => $orderid, //订单编号
            'randomstr' => time(),
            'signtype'  => 'RSA',  //加密方式
        );
        $param['sign'] = urlencode(static::Sign($param));
        $paramsStr = static::ToUrlParams($param);
        $url = 'https://vsp.allinpay.com/apiweb/tranx/cancel';
        $rsp = static::request($url, $paramsStr);
        $result = json_decode($rsp, true);
        if($result['retcode'] != 'SUCCESS')
        {
            throw new \Exception($result['retmsg'], 500);
        }
        return $result;
    }
    //交易退款（隔天）
    public static function refund($trxamt, $orderid)
    {
        $param = array(
            'cusid'     => static::_getConfig('cusid'),//商户号
            'appid'     => static::_getConfig('appid'),//平台分配ID
            'version'   => static::_getConfig('version'),//版本
            'trxamt'    => $trxamt, //付款金额
            'reqsn'     => $orderid, //退款订单编号
            'oldreqsn'  => $orderid, //订单编号
            'randomstr' => time(),
            'signtype'  => 'RSA',  //加密方式
        );
        $param['sign'] = urlencode(static::Sign($param));
        $paramsStr = static::ToUrlParams($param);
        $url = 'https://vsp.allinpay.com/apiweb/tranx/refund';
        $rsp = static::request($url, $paramsStr);
        $result = json_decode($rsp, true);
        if($result['retcode'] != 'SUCCESS')
        {
            throw new \Exception($result['retmsg'], 500);
        }
        
        return $result;
    }

    /**
     * Notes:RSA签名
     * @param array $array
     * @return string
     * @throws \Exception
     * User: yym
     * Date: 2022/9/2
     */
    public static function Sign(array $array){
        ksort($array);
        $bufSignSrc  = static::ToUrlParams($array);
        $private_key = static::_getConfig('private_key');
        $private_key = chunk_split($private_key , 64, "\n");
        $key = "-----BEGIN RSA PRIVATE KEY-----\n".wordwrap($private_key)."-----END RSA PRIVATE KEY-----";
        //   echo $key;
        if(openssl_sign($bufSignSrc, $signature, $key )){

        }else{
            throw new \Exception('签名生成失败：sign fail');
        }
        $sign = base64_encode($signature);//加密后的内容通常含有特殊字符，需要编码转换下，在网络间通过url传输时要注意base64编码是否是url安全的
        return $sign;
    }

    /**
     * Notes:排序生成
     * @param array $array
     * @return string
     * User: yym
     * Date: 2022/9/2
     */
    public static function ToUrlParams(array $array)
    {
        $buff = "";
        foreach ($array as $k => $v)
        {
            if($v != "" && !is_array($v)){
                $buff .= $k . "=" . $v . "&";
            }
        }

        $buff = trim($buff, "&");
        return $buff;
    }

    /**
     * Notes:效验签名
     * @param array $array
     * @return int
     * User: yym
     * Date: 2022/9/2
     */
    public static function ValidSign(array $array){
        $sign = $array['sign'];
        unset($array['sign']);
        ksort($array);
        $bufSignSrc = static::ToUrlParams($array);
        //$public_key = static::_getConfig('public_key');
        $public_key = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCm9OV6zH5DYH/ZnAVYHscEELdCNfNTHGuBv1nYYEY9FrOzE0/4kLl9f7Y9dkWHlc2ocDwbrFSm0Vqz0q2rJPxXUYBCQl5yW3jzuKSXif7q1yOwkFVtJXvuhf5WRy+1X5FOFoMvS7538No0RpnLzmNi3ktmiqmhpcY/1pmt20FHQQIDAQAB';
        $public_key = chunk_split($public_key , 64, "\n");
        $key = "-----BEGIN PUBLIC KEY-----\n$public_key-----END PUBLIC KEY-----\n";
        $result= openssl_verify($bufSignSrc,base64_decode($sign), $key );
        return $result;
    }

    /**
     * @desc: 获取配置文件
     * @param string $key
     * @return array|string
     */
    private static function _getConfig(string $key = '')
    {
        $config = config('app.tonglian_payment');
        if (empty($config)) {
            throw new \Exception('payment配置文件不存在');
        }
        if(!empty($key))
        {
            return $config[$key] ?? '';
        }
        return $config;
    }

    /**
     * Notes:发送请求
     * @param $url
     * @param $params
     * @return bool|string
     * User: yym
     * Date: 2022/9/2
     */
    public static function request($url,$params){
        $ch = curl_init();
        $this_header = array("content-type: application/x-www-form-urlencoded;charset=UTF-8");
        curl_setopt($ch,CURLOPT_HTTPHEADER,$this_header);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);

        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);//如果不加验证,就设false,商户自行处理
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);

        $output = curl_exec($ch);
        curl_close($ch);
        return  $output;
    }
}
