Utils.php 4.68 KB
<?php

namespace WebPlugin\Pay\Alimobilemini;

use WebPlugin\Pay\PayAbstract;

/**
 * 支付宝手机极简支付工具类
 * @author Smile
 *
 */
class Utils extends PayAbstract
{
    /**
     * 构造函数
     */
    public function __construct()
    {
    }


    /**RSA签名
     * $data待签名数据
     * 签名用商户私钥,必须是没有经过pkcs8转换的私钥
     * 最后的签名,需要用base64编码
     * return Sign签名
     */
    function sign($data)
    {

        //转换为openssl密钥,必须是没有经过pkcs8转换的私钥
        $res = openssl_get_privatekey($this->priKey);

        //调用openssl内置签名方法,生成签名$sign
        openssl_sign($data, $sign, $res);

        //释放资源
        openssl_free_key($res);

        //base64编码
        $sign = base64_encode($sign);

        return $sign;
    }

    /**
     * RSA验签
     * 验签用支付宝公钥
     *
     * return 验签是否通过 bool值
     * @param array $data 待签名数据
     * @param string $sign 需要验签的签名
     * @return bool 验签是否通过 bool值
     */
    function verify($data, $sign)
    {
        $pubKeyPath = dirname(__FILE__) . '/key/alipay_public_key.pem';
        //转换为openssl格式密钥
        $pubKey = file_get_contents($pubKeyPath);
        $res = openssl_get_publickey($pubKey);
        if ($res == false) {
            while ($text = openssl_error_string())
                echo "$text \n";
        }
        //调用openssl内置方法验签,返回bool值
        $result = (bool)openssl_verify($data, base64_decode($sign), $res);

        //释放资源
        openssl_free_key($res);

        //返回资源是否成功
        return $result;
    }

    /**
     * 获取返回时的签名验证结果
     *
     * @param $para_temp 通知返回来的参数数组
     * @return string $sign 返回的签名结果
     */
    function getSignVeryfy($para_temp)
    {
        //支付宝公钥路径
        $pubKeyPath = dirname(__FILE__) . '/key/alipay_public_key.pem';
        //签名类型:RSA
        $sign_type = $para_temp['sign_type'];

        //签名
        $sign = $para_temp['sign'];

        //除去待签名参数数组中的空值和签名参数
        $para_filter = self::paraFilter($para_temp);

        //对待签名参数数组排序
        $para_sort = self::argSort($para_filter);

        //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
        $prestr = self::createLinkstring($para_sort);

        switch (strtoupper($sign_type)) {
            case "RSA" :
                $isSgin = self::rsaVerify($prestr, $pubKeyPath, $sign);
                break;
            default :
                $isSgin = false;
        }

        return $isSgin;
    }

    /**
     * 除去数组中的空值和签名参数
     * @param array $para 签名参数组
     * @return array 去掉空值与签名参数后的新签名参数组
     */
    function paraFilter($para)
    {
        $para_filter = array();
        while (list ($key, $val) = each($para)) {
            if ($key == "sign" || $key == "sign_type" || $val == "") {
                continue;
            } else {
                $para_filter[$key] = $para[$key];
            }
        }

        return $para_filter;
    }

    /**
     * 对数组排序
     * @param array $para 排序前的数组
     * @return array 排序后的数组
     */
    function argSort($para)
    {
        ksort($para);
        reset($para);

        return $para;
    }

    /**
     * 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
     * @param array $para 需要拼接的数组
     * @return string 拼接完成以后的字符串
     */
    function createLinkstring($para)
    {
        $arg = "";
        while (list ($key, $val) = each($para)) {
            $arg .= $key . "=" . $val . "&";
        }
        //去掉最后一个&字符
        $arg = substr($arg, 0, count($arg) - 2);

        //如果存在转义字符,那么去掉转义
        if (get_magic_quotes_gpc()) {
            $arg = stripslashes($arg);
        }

        return $arg;
    }

    /**
     * RSA验签
     * @param array $data 待签名数据
     * @param string $ali_public_key_path 支付宝的公钥文件路径
     * @param string $sign 要校对的的签名结果
     * @return bool 验证结果
     */
    function rsaVerify($data, $ali_public_key_path, $sign)
    {
        $pubKey = file_get_contents($ali_public_key_path);
        $res = openssl_get_publickey($pubKey);
        $result = (bool)openssl_verify($data, base64_decode($sign), $res);
        openssl_free_key($res);

        return $result;
    }

}