<?php if (!defined('BASEPATH'))  exit('No direct script access allowed');

class Zmop_class
{
    private $rsaPriKeyFile = null;
    private $rsaPubKeyFile = null;
    private $gatewayUrl = 'https://zmopenapi.zmxy.com.cn/openapi.do';
    /**
     * 设置私钥文件路径
     * @param  String $path 私钥文件路径
     */
    public function setRsaPriKeyFile($path)
    {
        $this->rsaPriKeyFile = $path;
    }

    /**
     * 设置公钥文件路径
     * @param  String $path 公钥文件路径
     */
    public function setRsaPubKeyFile($path)
    {
        $this->rsaPubKeyFile = $path;
    }

    /**
     * 获取待传输的数据
     * @param array $sParam 待传输的数据
     * @return string
     */
    public function getSignature($params)
    {
        $tempStr = $this->Assembling($params);		/** 拼接待签名字符串 */
        $sign = $this->Signature($tempStr);			/** 获取签名 */
        return $sign;
    }

    /**待签名字符串拼接函数
     * @param $params
     * @param bool $isEncode
     * @return string
     */
    private function Assembling($params, $isEncode = true)
    {
        ksort($params);			/** 将参数数组按照键的自然顺序排序 */
        $filterArr = array();
        foreach ($params as $k => $v) {
            if (false === empty($v) && 'sign' != $k) {
                // 转换成目标字符集
                //$v = mb_convert_encoding($v, $params['charset']);
                $filterArr[] = ($isEncode) ? $k.'='.urlencode($v) : $k.'='.$v;
            }
        }
        $stringToBeSigned = implode("&", $filterArr);		//使用 & 连接参数
        unset ($k, $v);
        return $stringToBeSigned;
    }

    /**
     * 获取参数签名方法
     * @param  string $tempStr 待签名的参数字符串
     * @return mixed
     *         String：签名过的参数字符串
     *         boolean：私钥文件不存在；
     */
    private function Signature($tempStr)
    {
        //读取私钥文件
        $priKey = file_get_contents($this->rsaPriKeyFile);
        $priKey = openssl_get_privatekey($priKey);
        ($priKey) or die('您使用的私钥格式错误，请检查RSA私钥配置');
        openssl_sign($tempStr, $sign, $priKey);
        openssl_free_key($priKey);
        $sign = base64_encode($sign);
        return $sign;
    }

    /**
     * 验证签名方法
     * @param  string $stringToBeSigned 待验签的参数
     * @param  string $signature        待验证的签名
     * @return boolean                   验证结果
     */
    public function verify($stringToBeSigned, $signature)
    {
        /** 使用RSA的验签方法，通过签名字符串、签名参数（经过base64解码）及支付宝公钥验证签名。 */
        //读取公钥文件
        $pubKey = file_get_contents($this->rsaPubKeyFile);
        //转换为openssl格式密钥
        $pubKey = openssl_get_publickey($pubKey);
        ($pubKey) or die('支付宝RSA公钥错误。请检查公钥文件格式是否正确');
        //调用openssl内置方法验签，返回bool值
        $result = (bool)openssl_verify($stringToBeSigned, base64_decode($signature), $pubKey);
        openssl_free_key($pubKey);	//释放资源
        return $result;
    }

    /**
     * 根据公钥进行加密
     * @param array $params  待加密参数数组
     * @return string        加密后参数字符串
     */
    public function encrypt($params)
    {
        $paramStr = $this->Assembling($params);
        //读取公钥文件
        $pubKey = file_get_contents($this->rsaPubKeyFile);
        //转换为openssl格式密钥
        $pubKey = openssl_get_publickey($pubKey);
        ($pubKey) or die('支付宝RSA公钥错误。请检查公钥文件格式是否正确');
        //调用openssl内置方法加密
        $encryptData = '';
        foreach (str_split($paramStr, 117) as $chunk) {
            openssl_public_encrypt($chunk, $chunkEncryptData, $pubKey);
            $encryptData .= $chunkEncryptData;
        }
        $encryptData = base64_encode($encryptData);
        openssl_free_key($pubKey);
        return $encryptData;
    }


    /**
     * 根据私钥进行解密
     * @param string $params  待解密参数字符串
     * @return string         解密后参数字符串
     */
    public function decrypt($params)
    {
        $priKey = file_get_contents($this->rsaPriKeyFile);
        $priKey = openssl_get_privatekey($priKey);
        ($priKey) or die('您使用的私钥格式错误，请检查RSA私钥配置');
        //调用openssl内置方法解密
        $decryptData = '';
        foreach (str_split(base64_decode($params), 128) as $chunk) {
            openssl_private_decrypt($chunk, $chunkDecryptData, $priKey);
            $decryptData .= $chunkDecryptData;
        }
        openssl_free_key($priKey);
        return $decryptData;
    }
    /**
     * 校验$value是否非空
     * @param $value
     * @return bool
     */
    protected function checkEmpty($value) {
        if (!isset($value))
            return true;
        if ($value === null)
            return true;
        if (trim($value) === "")
            return true;

        return false;
    }

    /**
     * 请求网关
     * @param $params
     * @return string
     */
    public function request($params) {
        return $this->buildRequestForm($params);
    }


    /**
     * 建立请求，以表单HTML形式构造（默认）
     * @param array $params 请求参数数组
     * @return string 提交表单HTML文本
     */
    protected function buildRequestForm($params) {
        $sHtml = "<form id='alipaysubmit' name='alipaysubmit' action='".$this->gatewayUrl."' method='POST'>";
        foreach ($params as $key => $val) {
            if (false === $this->checkEmpty($val)) {
                //$val = $this->characet($val, $this->postCharset);
                $val = str_replace("'","&apos;",$val);
                //$val = str_replace("\"","&quot;",$val);
                $sHtml.= "<input type='hidden' name='".$key."' value='".$val."'/>";
            }
        }

        //submit按钮控件请不要含有name属性
        $sHtml = $sHtml."<input type='submit' value='ok' style='display:none;'></form>";
        $sHtml = $sHtml."<script>document.forms['alipaysubmit'].submit();</script>";

        return $sHtml;
    }
}