<?php
namespace app\traits;

use app\model\sxy\DeclareLog;
use crmeb\exceptions\AuthException;
use phpseclib3\Net\SFTP;

use app\controller\Aes;
use phpseclib3\Crypt\RSA;
use think\Exception;
use think\facade\App;
use think\facade\Db;

/**
 * 首信易统一请求API
 * Trait ShouxinyiApiRequest
 * @package app\traits
 */
trait ShouxinyiApiRequest
{

    /**
     * 申请商户
     * @return bool|string
     * @author lin
     * @created 2021/5/13 9:15
     * */
    public static function merchantApply($merchant=[]){
        try {
            $url = env('SHOUXINYI.HOSTNAME') . 'serviceprovider/declaration/declare';
            $data = [];
            $data['merchantId'] = env('SHOUXINYI.MERCHANTID');  //  商户编号
            $data['requestId'] = self::getOrderNumber('sxy');    //申请商户订单号
            $data['operationType'] = $merchant['operationType'] ?? 'CREATE';//CREATE 创建 MODIFY 更新
            $data['notifyUrl'] = env('APP_URL') . '/api/notify/createMerchant_5upay';//回调地址
            $data['extendedParameters'] = 'autoReview:FALSE,sendActiveEmail:FALSE';//autoReview 是否跳过流程 TRUE 是， FALSE 否 sendActiveEmail 是否发送激活邮件 TRUE 是， FALSE 否

            //CREATE 创建 MODIFY 更新
//            switch ($merchant['is_again']) {
//                case 1 || 2:
//                    $data['operationType'] = 'MODIFY';
//                    break;
//                case 0:
//                default:
//                    $data['operationType'] = 'CREATE';
//                    break;
//            }
            $data['operationType'] = 'CREATE';
            /**
             * 商户签约性质：registerRole
             * INDIVIDUAL_BUSINESS 个体工商户
             * PUBLIC_INSTITUTIONS 事业单位
             * PRIVATE_NON_ENTERPRISE_ORGANIZATIONS 民办非企业组织
             * SOCIAL_ORGANIZATION 社会团体
             * UNINCORPORATED_ENTERPRISE 非法人企业
             * ENTERPRISE_LEGAL_PERSON 企业法人
             * NATURAL_PERSON 自然人
             * GOVERNMENT_AGENCIES 政府机关
             * OTHERS 其他
             * */
            /**
             * 证书类型：cerType
             * UNIFORM_SOCIAL_CREDIT_CODE 统一社会信用代码证
             * PRIVATE_NON_ENTERPRISE_UNIT_REGISTRATION_CERTIFICATE 民办非企业单位登记证书
             * INDIVIDUAL_BUSINESS_LICENCE 个体工商户营业执照
             * CERTIFICATE_OF_REGISTRATION_OF_SOCIAL_GROUP_LEGAL_PERSON 社会团体法人登记证书
             * LEGAL_PERSON_CERTIFICATE_OF_INSTITUTION 事业单位法人证书
             * FUND_LEGAL_PERSON_REGISTRATION_CERTIFICATE 基金法人登记证书
             * ID_CARD 身份证
             * BUSINESS_LICENSE 营业执照
             * OTHERS 其他 (当签约性质不为自然人时必传)
             */
            $data['baseInfo'] = [//商户基本信息
                'signedType' => $merchant['signedType'] ?? 'BY_SPLIT_BILL',//BY_SPLIT_BILL 被分账方 GENERAL_SUB_MERCHANT 收单子商户
                'signedName' => $merchant['signedName'],//签约名称
                'registerRole' => $merchant['registerRole'],//商户签约性质
                'cerType' => $merchant['cerType'],//证书类型
                'signedShorthand' => $merchant['signedShorthand'],//商户简称
                'businessAddressProvince' => $merchant['businessAddressProvince'],//省
                'businessAddressCity' => $merchant['businessAddressCity'],//市
                'businessAddressArea' => $merchant['businessAddressArea'],//区
                'businessAddress' => $merchant['businessAddress'],//详细地址
                'contactName' => $merchant['contactName'],//联系人姓名
                'contactEmail' => $merchant['contactEmail'],//联系人邮箱
                'contactPhone' => $merchant['contactPhone'],//联系人电话
                'businessClassification' => $merchant['businessClassification'],//业务分类
                'desireAuth' => $merchant['desireAuth']??'',//开户意愿核实类型
            ];
            $data['bankCardInfo'] = [//结算信息
                'bankCode' => $merchant['bankCode'],//开户行
                'bankBranchName' => $merchant['bankBranchName'],//支行名称（结算银行卡属性为对公时必填）
                'accountName' => $merchant['accountName'],//开户名称
                'bankCardNo' => $merchant['bankCardNo'],//开户账号
                'cityCode' => $merchant['cityCode'],//市编码
                'provinceCode' => $merchant['provinceCode'],//省编码
                'accountType' => $merchant['accountType'],//结算银行卡属性PUBLIC 对公 PRIVATE 对私 （商户类型为个体工商户时必填，个人默认对私，企业等默认对公）
                'liquidationType' => $merchant['liquidationType'] ?? 'WITHDRAW',//SETTLE 结算 WITHDRAW 提现 （不传默认结算）
                'withdrawRateType' => $merchant['withdrawRateType'] ?? 'SINGLE',//SINGLE 单笔 RATE 百分比 （清算方式选择提现时必传）
                'withdrawRate' => $merchant['withdrawRate'] ?? '1',//（清算方式选择提现时必传）如传小数则限制两位小数，配置此项时校验服务商提现费率，如果服务商是百分比费率配置则此项也必须配置百分比，固定值同样，且此项配置费率不能小于服务商费率
            ];
            $data['desireAuthInfo'] = [//开户意愿核实信息(开户意愿核实类型选择手机短信验证时此项必传)
                'legalPersonName' => $merchant['legalPersonName'],//法人姓名
                'legalPersonIdNo' => $merchant['legalPersonIdNo'],//法人身份证号
                'legalPersonPhoneNo' => $merchant['legalPersonPhoneNo'],//法人手机号
            ];
            /**
             * 法人证件类型:legalPersonIdType
             * IDCARD 身份证
             * PASSPORT 护照
             * OFFICERPASS 军官证
             * ARMEDPOLICE 武警证
             * HM_VISITORPASS 港澳居民往来内地通行证
             * RESIDENCEBOOKLET 户口簿
             * T_VISITORPASS 台湾居民来往大陆通行证
             * FOREIGNESTAYFOREVER 外国人永久居留证
             * OTHER 其它证件号
             */
            $data['certificateInfo'] = [//商户资质信息
                'legalPersonName' => $merchant['legalPersonName'],//法人姓名
                'profession' => $merchant['profession'],//法人职业
                'legalPersonIdType' => $merchant['legalPersonIdType'],//法人证件类型
                'legalPersonIdNo' => $merchant['legalPersonIdNoSup'],//证件号码
                'idEffectiveDateStart' => $merchant['idEffectiveDateStart'],//法人证件有效期开始日期
                'idEffectiveDateEnd' => $merchant['idEffectiveDateEnd'],//法人证件有效期结束日期
                'cerNoType' => $merchant['cerNoType'],//企业证件类型:SOCIAL_CREDIT_NO 统一社会信用代码 BUSINESS_LICENSE_NO 营业执照号码 （商户类型不为自然人时必传）
                'cerNo' => $merchant['cerNo'],//资质证书编号
                'sellingArea' => $merchant['sellingArea'],//营业面积:A 500平米以上 B 200-500平米（含） C 200平米以下 （商户类型不为自然人时必传）
                'staffSize' => $merchant['staffSize'],//公司员工规模A 100人以上 B 50-100人（含） C 50人以下 （商户类型不为自然人时必传）
                'tradingScenarios' => $merchant['tradingScenarios'] ?? '',//交易场景说明WEBSITE 网站 APP APP WECHAT_APPLET 公众号/小程序/生活号 （可多选，多选时参数用英文半角逗号隔开，商户类型不为自然人或被分账方时必传）
                'webSite' => $merchant['webSite'] ?? '',//网站网址 （商户类型不为自然人或被分账方时，如交易场景基于PC网站时必传）
                'webSiteName' => $merchant['webSiteName'] ?? '',//网站名称 （商户类型不为自然人或被分账方时，如交易场景基于PC网站时必传）
                'icp' => $merchant['icp'] ?? '',//ICP备案号 （商户类型不为自然人或被分账方时，如交易场景基于PC网站时必传）
                'appName' => $merchant['appName'] ?? '',//App名称 （商户类型不为自然人或被分账方时，如交易场景基于APP时必传）
                'wechatAppletName' => $merchant['wechatAppletName'] ?? '',//公众号/小程序/生活号 （商户类型不为自然人或被分账方时，如交易场景基于公众号/小程序/生活号时必传）
                'testAccountInfo' => $merchant['testAccountInfo'] ?? '',//填写可用于首信易审核人员测试交易全流程的测试账号密码
                'businessLicensePath' => $merchant['businessLicensePath'] ?? '',//营业执照照片路径	需上传到sftp（商户类型不为自然人时必传，最大不超过50M，格式限制为jpg,jpeg,png,pdf）
                'openAccountPath' => $merchant['openAccountPath'] ?? '',//开户许可证照片路径 需上传到sftp（商户类型不为自然人及个体工商户时必传，为个体工商户时此项和legalPersonBankCardPath二选一进行传递，最大不超过50M，格式限制为jpg,jpeg,png,pdf）
                'legalIdCardProsPath' => $merchant['legalIdCardProsPath'] ?? '',//法人证件人像面路径
                'legalIdCardConsPath' => $merchant['legalIdCardConsPath'] ?? '',//法人证件国徽面路径
                'desireAuthPath' => $merchant['desireAuthPath'] ?? '',//确认入网意愿视频路径 认证类型选择视频认证时必填
                'holdingIdCardPath' => $merchant['holdingIdCardPath'] ?? '',//法人手持证件影印件路径 认证类型选择手机验证时必传
                'webSitePath' => $merchant['webSitePath'] ?? '',//商户网址截图影印件路径 商户类型不为自然人或被分账方时，如交易场景基于PC网站时必传
                'wechatAppletPath' => $merchant['wechatAppletPath'] ?? '',//公众号/小程序/生活号业务流程截图影印件路径 商户类型不为自然人或被分账方时，如交易场景基于公众号/小程序/生活号时必传
                'appPath' => $merchant['appPath'] ?? '',//APP首页截图影印件路径 商户类型不为自然人或被分账方时，如交易场景基于APP时必传
                'legalPersonBankCardPath' => $merchant['legalPersonBankCardPath'] ?? '',//法人银行卡图影印件路径 商户类型为自然人时必传，为个体工商户时此项和openAccountPath二选一进行传递
                'desireAuthOtherPath' => $merchant['desireAuthOtherPath'] ?? '',//确认入网意愿其他验证方式路径 开户意愿核实类型选择“其他验证方式”的时候必传
                'otherCerPath' => $merchant['otherCerPath'] ?? '',//其他资质文件路径
                'legalPersonPhone' => $merchant['legalPersonPhoneNo'],//合同类型为“电子签”时必填；必须为法人的手机号。
            ];

            $data['contractInfo'] = [
                'contractType' => 'ELECTRON',//ELECTRON 电子签 PAPER 纸质合同 默认为“纸质合同”，选择“电子签”时将授权首信易通过电子签名的方式进行签约，无需邮寄合同。
            ];

            /**
             * 支付方式:paymentMode
             * B2C个人网银
             * B2B企业网银
             * EXPRESSPAY_ISNOTDIRECT_DEBIT快捷支付标准版借记卡
             * EXPRESS_PAY_ISNOTDIRECT_CREDIT快捷支付标准版贷记卡
             * EXPRESS_PAY_ISDIRECT_DEBIT快捷支付专业版借记卡
             * EXPRESS_PAY_ISDIRECT_CREDIT快捷支付专业版_贷记卡
             * ALIPAY_SCANCODE支付宝扫码
             * WEIXIN_OFFICIAL微信公众号
             * WEIXIN_MINIAPPS微信小程序
             * ALIPAY_WAP支付宝wap
             * ALIPAY_OFFICIAL支付宝生活号
             * WEIXIN_EQRCODE易码付-微信
             * ALIPAY_EQRCODE易码付-支付宝（商户入网类型=收单子商户时可传，如不传则按服务商默认费率）
             * */
            //入网记录
//            echo $data['requestId'].$merchant['signedName'].'<br>';
            $log = new DeclareLog();
//            $is = $log -> getValueLog("id",$merchant['m_id']);
//            if($is){
//                $log -> where('m_id',$merchant['m_id']) -> update(array(
//                    'data' =>json_encode($data),
//                    'type'=>'5upay',
//                    'requestId'=>$data['requestId'],
//                    'time'=>time(),
//                ));
//            }else{
            $log -> setLog(array(
                'data' =>json_encode($data),
                'type'=>'5upay',
                'requestId'=>$data['requestId'],
                'time'=>time(),
                'm_id'=>$merchant['m_id']
            ));
//            }

            $res = self::request($data, $url);
            $log -> updateDe(array(
                'status' => $res['status'] ?? '',
                'message' => $res['errorMessage']??'',
                'requestId'=>$data['requestId']
            ));


            return $res;
        }catch (Exception $exception){
            Db::name("log")->insert(array('data'=>$exception->getFile().'：'.$exception->getLine().'【'.$exception->getMessage().'】'));//日志记录
        }
    }

    /**
     * 入网查询
     * @author lin
     * @created 2021/5/14
    */
    public function merchantQuery($requestId){
        $url = env('SHOUXINYI.HOSTNAME') . 'serviceprovider/declaration/query';

        $data['merchantId'] = env('SHOUXINYI.MERCHANTID');  //  商户编号
//        $data['subMerchantId'] = (string)$subMerchantId;//	二级商户编号
        $data['requestId'] = $requestId;    //请求订单号
        return self::request($data,$url);
    }

    /**
     * 上传图片到sftp
     * @param string $path 远程文件夹
     * @param string $file 远程路径含文件名
     * @param string $file1 本地文件路径
     * @return bool
    */
    public static function uploadSFtp($path,string $file, string $file1): bool
    {
        $sftp = new SFTP(env('SHOUXINYI.SFTPHOST'),env('SHOUXINYI.SFTPPORT'));

        $login = $sftp->login('899104033', RSA::load(file_get_contents(App::getRootPath()."pkey/5upay/899104033")));
        if (!$login) {
            Db::name("log")->insert(array('data'=>'sftp登录失败'));//日志记录
        }
        $sftp -> mkdir($path);
        return $sftp -> put($file,file_get_contents($file1));
    }

    /**
     * 境内收单
     * @param array $datas
     * @return
     *
     */
    public static function onlinePay($datas){
        $url = 'https://apis.5upay.com/onlinePay/order';
        /*
         * SCANCODE-ALI_PAY-P2P  支付宝扫码（需要传入clientIp,接收返回的base64编码并解析成二维码图片）
         * ALIPAY-WAP-P2P   支付宝H5支付
         * ALIPAY-OFFICIAL  支付宝生活号支付
         * MINIAPPS-WEIXIN_PAY-P2P  微信小程序   需要IP、openid 传小程序商编
         * WECHAT-OFFICIAL_PAY  微信公众号   传公众号商编 需要openid
         * SCANCODE-EQRCODE_PAY 易码付 传公众号商编
         * */
        try {

            $data['merchantId'] = env('SHOUXINYI.MERCHANTID');  //  商户编号
            $data['requestId'] = $datas['requestId'];//订单号
            $data['orderAmount'] = $datas['orderAmount'];//金额。单位分
            $data['orderCurrency'] = 'CNY';//交易币种默认CNY（人民币）
//            $data['notifyUrl'] = env('APP_URL') . '/api/notify/pay_5upay';//回调地址;//通知地址
            $data['notifyUrl'] = env('APP_URL') . $datas['notifyUrl'];//回调地址;//通知地址
            $data['callbackUrl'] = $datas['callbackUrl'];//同步地址
            $data['remark'] = $datas['remark'] ?? '1';// 备注，通过支付结果返回商户

            $data['paymentModeCode'] = $datas['paymentModeCode'];//支付方式编码
            switch ($data['paymentModeCode']){
                case "MINIAPPS-WEIXIN_PAY-P2P": //微信小程序   需要IP、openid 传小程序商编
                    $data['appId'] = env('WECHAT_MP.APPID');//小程序appId
                    $data['reportSerialNo'] = env('SHOUXINYI.REPORT_SREIAL_MP_NO1');//报备序列号
                    break;
                case "SCANCODE-EQRCODE_PAY"://易码付
                case "WECHAT-OFFICIAL_PAY"://微信公众号   传公众号商编 需要openid
                case "WECHAT-OFFICIAL_PAY-P2P"://微信公众号   传公众号商编 需要openid
                    $data['appId'] = env('WECHAT.APPID');//微信appId
                    $data['reportSerialNo'] = env('SHOUXINYI.REPORT_SREIAL_NO1');//报备序列号
                    break;
            }

            $data['openId'] = $datas['openId'] ?? '';//微信openId，或者支付宝的buyer_id或者用户的钱包ID，或者微包服务号的openid
            $data['productDetails'] = $datas['productDetails'];//商品信息
            $data['splitMark'] = $datas['splitMark'] ?? 'DO_SPLIT';//DO_SPLIT 分账，NOT_DO_SPLIT 不分帐 默认分账
            $data['payer'] = ['name'=>''];//此json可空，但是不可将此参数整个去掉，需以以下格式传入接口: “payer”:{}
            $data['clientIp'] = $datas['clientIp'] ?? '';//客户端外网IP
            return self::request($data, $url);
        }catch (Exception $exception){
            Db::name("log")->insert(array('data'=>$exception->getFile().'：'.$exception->getLine().'【'.$exception->getMessage().'】'));//日志记录
            return $exception->getFile().'：'.$exception->getLine().'【'.$exception->getMessage().'】';
        }
    }

    /**
     * 订单查询
     * @param array $datas
     * @return
     */
    public static function onlinePay_query($datas){
        $url = "https://apis.5upay.com/onlinePay/query";
        $data['merchantId'] = env('SHOUXINYI.MERCHANTID');  //  商户编号
        $data['requestId'] = $datas['requestId'];    //订单号要查询的订单号
        return self::request($data, $url);
    }

    /**
     * 分账
     * @param array $datas
     * @return
     */
    public static function split($datas){
        $url = "https://apis.5upay.com/split/order";

        $data['merchantId'] = env('SHOUXINYI.MERCHANTID');  //  商户编号
        $data['notifyUrl'] = env('APP_URL') . '/api/notify/pay_split_5upay';//回调地址
        $data['requestId'] = $datas['requestId'];    //订单号
        $data['orderId'] = $datas['orderId'];//交易订单的订单号
        $data['totalSplitAmount'] = $datas['totalSplitAmount'];//分账金额
        $data['splitDetails'] = $datas['splitDetails'];//分账信息
        /*
         * splitDetails 分账信息:
         * subSplitRequestId: 分账明细订单号
         * splitAccType: 分账类型 MERCHANT_ACC 商户；WALLET_ACC 钱包
         * splitAccId: 分账类型为商户时此参数传商户的merchantId(可传主商户商编)，分账类型为钱包时此参数传用户的walletId
         * splitAmount: 分账明细订单金额
         * remark: 备注
         * */
        return self::request($data, $url);
    }

    /**
     * 提现
     * @param array $datas
     * @return
     */
    public static function withdrawal($datas){
        $url = "https://apis.5upay.com/wallet/withdraw";

        $data['partnerId'] = env('SHOUXINYI.MERCHANTID');  //  主商户编号
        $data['merchantId'] = $datas['merchantId'];  //  商户编号
        $data['requestId'] = $datas['requestId'];  //  订单编号
        $data['withdrawAmount'] = $datas['withdrawAmount'];  //  提现金额 分为单位，不带小数点
        $data['notifyUrl'] = env('APP_URL') . '/api/notify/withdrawal_5upay';//回调地址

        return self::request($data, $url);
    }
    /**
     * 提现查询
     * @param array $datas
     * @return
     */
    public static function withdrawQuery($datas){
        $url = "https://apis.5upay.com/wallet/withdrawQuery";

        $data['partnerId'] = env('SHOUXINYI.MERCHANTID');  //  主商户编号
        $data['merchantId'] = $datas['merchantId'];  //  商户编号
        $data['requestId'] = $datas['requestId'];  //  订单编号

        return self::request($data, $url);
    }
    /**
     * 查询可提现金额
     * @param array $datas
     * @return
     */
    public static function balanceQuery($datas){
        $url = "https://apis.5upay.com/member/balanceQuery";

        $data['partnerId'] = env('SHOUXINYI.MERCHANTID');  //  主商户编号
        $data['merchantId'] = $datas['merchantId'];  //  商户编号
        $data['requestId'] = $datas['requestId'];  //  订单编号
        $data['currency'] = $datas['currency'];  //  	查询币种
        $data['dateTime'] = $datas['dateTime'];  //  时间戳
        $data['accountType'] = $datas['accountType'];  //  账户类型

        return self::request($data, $url);
    }
    /**
     * 修改银行信息
     * @param array $datas
     * @return
     */
    public static function modifyBankCard($datas){
        $url = "https://apis.5upay.com/serviceprovider/declaration/modifyBankCard";
        $data['merchantId'] = $datas['merchantId'];  //  主商户编号
        $data['subMerchantId'] = $datas['subMerchantId'];  //  二级商户编号
        $data['requestId'] = $datas['requestId'];  //  订单号
        $data['bankCode'] = $datas['bankCode'];  //  开户行
        $data['bankBranchName'] = $datas['bankBranchName'];  //  支行名称
        $data['bankCardNo'] = $datas['bankCardNo'];  //  开户账号
        $data['cityCode'] = $datas['cityCode'];  //  市编码
        $data['provinceCode'] = $datas['provinceCode'];  //  省编码

        return self::request($data, $url);
    }


    /**
     * 退款
     * @param array $datas
     * @return
     */
    public static function refund($datas,$type=1){
        $url = "https://apis.5upay.com/onlinePay/refund";
        try {

            $data['merchantId'] = env('SHOUXINYI.MERCHANTID');  //  商户编号
            $data['notifyUrl'] = env('APP_URL') . '/api/notify/pay_refund_5upay';//回调地址
            $data['requestId'] = $datas['requestId'];    //订单号
            $data['orderId'] = $datas['orderId'];//原交易订单的流水号
            $data['amount'] = $datas['amount'];//退款金额
            $data['remark'] = '备注';
            if($type==1) {
                $data['isCollect'] = $datas['isCollect'];
                $data['refundCollectDetail'] = $datas['refundCollectDetail'];//归集信息
            }
            return self::request($data, $url);

        }catch (Exception $exception){
            Db::name("log")->insert(array('data'=>$exception->getFile().'：'.$exception->getLine().'【'.$exception->getMessage().'】'));//日志记录
            return $exception->getFile().'：'.$exception->getLine().'【'.$exception->getMessage().'】';
        }
    }


    /**
     * 签名
     * @param $data
     * @param int $type 1:其他接口。2：提现接口
     * test2
     * @return array|bool
     * @author lin
     * @created 2021/5/13 17:54
     */
    public static function getSign($data){
        //第一步键名首字母排序
        //第二步sha1签名
        //第三步私钥签名
        //第四步生成十六位aes密钥
        //第五步data用AES加密
        //第六步.公钥加密.加密的数据是第四步生成的AES密钥，防止AES密钥泄露

        try {
            $sort = self::sortArray($data);//第一步键名首字母排序
            $sha1=sha1($sort, true);//第二步sha1签名
            $data['hmac'] = self::rsaPrivateSign($sha1,App::getRootPath(). 'pkey/5upay/private.pfx','IDajxBO5');//第三步CFCA私钥签名
            $randStr = self::getRandStr(16);//第四步生成十六位aes密钥
            $json = json_encode($data);
            $body = Aes::encrypt7($json,$randStr);//第五步AES加密
            //header
//            $header_partnerId = $data['partnerId'];//服务商id.如果业务没有服务商id的话可不传此参数
            $headerArray = array(
                "Content-type:application/vnd.5upay-v3.0+json",
                "merchantId:".$data['merchantId'],//商户编号
                "requestId:".$data['requestId'],//商户订单号
                "encryptKey:".self::rsaPublicEncode(App::getRootPath(). 'pkey/5upay/test.cer',$randStr)//第六步.CFCA公钥加密.加密的数据是第四步生成的AES密钥，防止AES密钥泄露
            );
            if(isset($data['partnerId'])){
                array_push($headerArray,"partnerId:".$data['partnerId']);
            }
            return array('body'=>$body,'header'=>$headerArray,'data'=>json_encode($data));
        }catch (Exception $exception){
            Db::name("log")->insert(array('data'=>$exception->getFile().'：'.$exception->getLine().'【'.$exception->getMessage().'】'));//日志记录
            return false;
        }

    }

    /**
     * CFCA公钥加密
     */
    public static function rsaPublicEncode($public_key,$rands): string
    {
        $encryptKey=file_get_contents($public_key);
        $pem = chunk_split(base64_encode($encryptKey),64,"\n");//转换为pem格式的公钥
        $public_key = "-----BEGIN CERTIFICATE-----\n".$pem."-----END CERTIFICATE-----\n";
        $pu_key =  openssl_pkey_get_public($public_key);//这个函数可用来判断公钥是否是可用的
        openssl_public_encrypt($rands,$encryptKey,$pu_key);//公钥加密
        $encryptKey = base64_encode($encryptKey);
        return $encryptKey;
    }

    /**
     * CFCA私钥签名
    */
    public static function rsaPrivateSign($data,$path='',$password=''){
        $pubKey = file_get_contents($path);
        $results=array();
        openssl_pkcs12_read($pubKey,$results,$password);
        $private_key=$results['pkey'];
        $pi_key =  openssl_pkey_get_private($private_key);//这个函数可用来判断私钥是否是可用的，可用返回资源id Resource id
        openssl_sign($data, $signature,$private_key,"md5");
        $signature=base64_encode($signature);
        return $signature;
    }

    /**
     * 随机字符串
     */
    public static function getRandStr($length){
        //字符组合
        $str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $len = strlen($str)-1;
        $randstr = '';
        for ($i=0;$i<$length;$i++) {
            $num=mt_rand(0,$len);
            $randstr .= $str[$num];
        }
        return $randstr;
    }

    /**
     * 统一请求
     * @return bool|string
     * @author php迷途小书童
     * @created 2021/5/13 9:15
     */
    public static function request($data,$url){
        try {
            $data = self::getSign($data);//签名
            Db::name("log")->insert(array('data'=>json_encode($data)));//日志记录
            if(!$data) return false;
            $postUrl = self::posturl($url,$data['body'],$data['header'],$data['data']);
            return self::returnDecode($postUrl);
        } catch (\Throwable $e) {
            return $e->getMessage();
        }
    }

    /**
     * 返回数据解密
     * */
    public static function returnDecode($postUrl){
        //一、CFCA私钥解密
        $res = self::rsaPrivateDecode($postUrl['encryptKey'],App::getRootPath(). 'pkey/5upay/private.pfx','IDajxBO5');//CFCA私钥解密
        //二、AES解密
        $getInfo = Aes::decrypt7($postUrl['data'],$res);
        Db::name("log")->insert(array('data'=>json_encode($getInfo)));//日志记录
        return $getInfo;
    }
    /**
     * CFCA 私钥解密
     * */
    public static function rsaPrivateDecode($encryptKey,$private_key,$password){
        $prikey=file_get_contents($private_key);
        $results=array();
        openssl_pkcs12_read($prikey,$results,$password);
        $private_key=$results['pkey'];
        $pi_key =  openssl_pkey_get_public($private_key);
        openssl_private_decrypt(base64_decode($encryptKey),$decrypted,$private_key);
        return $decrypted;
    }

    /**
     * 字符排序
     * @return string
     * @author lin
     * @created 2021/5/13 17:50
     */
    public static function sortArray($para=null)
    {
//        $vars = $para ? '' : get_object_vars($this);
//        unset($vars['response_hmac_fields']);
        $data = array();
        foreach ($para as $k => $var) {
            if (is_scalar($var) && $var !== '' && $var !== null) {
                $data[$k] = $var;
            } else if (is_object($var)) {
                $data[$k] = array_filter((array)$var);
            } else if (is_array($var)) {
                $data[$k] = array_filter($var);
            }
            if (empty($data[$k])) {
                unset($data[$k]);
            }
        }

        ksort($data);
        $hmacSource = '';
        foreach($data as $key => $value){
            if (is_array($value)) {
                ksort($value);
                foreach ($value as $key2 => $value2) {
                    if (is_object($value2)) {
                        $value2 = array_filter((array)$value2);
                        ksort($value2);
                        foreach ($value2 as $oKey => $oValue) {
                            $oValue .= '#';
                            $hmacSource .= trim($oValue);
                        }
                    } else if(is_array($value2)){
                        ksort($value2);
                        foreach ($value2 as $key3 => $value3) {
                            if (is_object($value3)) {
                                $value3 = array_filter((array)$value3);
                                ksort($value3);
                                foreach ($value3 as $oKey => $oValue) {
                                    $oValue .= '#';
                                    $hmacSource .= trim($oValue);
                                }
                            } else{
                                $value3 .= '#';
                                $hmacSource .= trim($value3);
                            }
                        }
                    } else{
                        $value2 .= '#';
                        $hmacSource .= trim($value2);
                    }
                }
            } else {
                $value .= '#';
                $hmacSource .= trim($value);
            }
        }
        return $hmacSource;
    }

    public static function getOrderNumber($type){
        list($msec, $sec) = explode(' ', microtime());
        $msectime = number_format((floatval($msec) + floatval($sec)) * 1000, 0, '', '');
        return $type . '_' . $msectime . mt_rand(10000, max(intval($msec * 10000) + 10000, 98369));
    }

    /**
     * @return array
     */
    public static function posturl($url,$body,$headerArray,$data){
//        $json  = json_encode($data, JSON_UNESCAPED_UNICODE);
        $num = md5(time().rand(100,1000));
        Db::name("log")->insert(array('data'=>'【'.$url.'】data:'.$data));//日志记录
        Db::name("log")->insert(array('data'=>'【'.$url.'】body:'.json_encode($body)));//日志记录
        Db::name("log")->insert(array('data'=>'【'.$url.'】headerArray:'.json_encode($headerArray)));//日志记录
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl,CURLOPT_HEADER, 1 ); // 过滤HTTP头
        curl_setopt($curl,CURLOPT_HTTPHEADER,$headerArray);
        curl_setopt($curl,CURLOPT_RETURNTRANSFER, 1);// 显示输出结果
        curl_setopt($curl,CURLOPT_POST,true); // post传输数据
        curl_setopt($curl,CURLOPT_POSTFIELDS,$body);// post传输数据
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);//SSL证书认证
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);//严格认证
        $output = curl_exec($curl);
        curl_close($curl);
        Db::name("log")->insert(array('data'=>json_encode($output)));//日志记录
        preg_match_all('/(encryptKey|merchantId|data"):(\s+|")([^"\s]+)/s',$output,$m);
        list($encryptKey, $merchantId, $data) = $m[3];
        $responsedata = array("data" =>$data,"encryptKey"=>$encryptKey,"merchantId"=>$merchantId);
        return $responsedata;
    }

}
