PHP调用 API 时对请求参数进行签名验证

 PHP进阶  2019-03-29  admin  2945  3975

一、签名方法
调用 API 时需要对请求参数进行签名验证,服务器会对该请求参数进行验证是否合法的。方法如下:

根据参数名称(除签名和图片文件)将所有请求参数按照字母先后顺序排序:key=value .... &key=value,并且除去待签名参数数组中的空值和签名参数
例如:将foo=1,bar=2,baz=3 排序为bar=2,baz=3,foo=1,参数名和参数值链接后,得到拼装字符串bar=2&baz=3&foo=1

系统暂时只支持MD5加密方式:
md5:将$key='www.cent123.com'拼接到参数字符串尾部进行md5加密,格式是:md5(bar=2&baz=3&foo=1...$key)

二、调用示例

1)输入参数为:
    $parameter = array(
        'method' => 'get_info',
        'timestamp' => 1483620175,
        'format' => 'json',
        'user' => 'admin',
        'order_id' => 100,
    );

2)按照参数名称升序排列:
    $parameter = array(
        'format' => 'json',
        'method' => 'get_info',
        'order_id' => 100,
        'timestamp' => 1483620175,
        'user' => 'admin',
    );
3)连接字符串
    连接参数名与参数值,并在尾部加上$key,如下:
    format=json&method=get_info&order_id=100×tamp=1483620175&user=adminwww.cent123.com

4)生成签名:
    32位MD5值 -> 818d0a37efb41f75ff9e86c703cee2d6

5)拼装HTTP请求    sign => 818d0a37efb41f75ff9e86c703cee2d6
    sign_type => MD5
    sign和sign_type 也会一起作为参数发送
    $dataSubmit = new DataSubmit($url);   

    $html_text = $dataSubmit->buildRequestForm($parameter);    

    echo $html_text;  


DataSubmit.class.php

/**
 * Created by PhpStorm.
 * User: code.cent123.com
 * Date: 2017/1/5
 * Time: 16:02
 */
class DataSubmit
{
    private $data_config;

    function __construct($url = '/', $data_config = array('key' => 'www.cent123.com', 'sign_type' => 'MD5', 'input_charset' => 'utf-8'))
    {
        $this->url = $url;
        $this->data_config = $data_config;
    }

    /**
     * 生成签名结果
     * @param $para_sort 已排序要签名的数组
     * @return string 签名结果字符串
     */
    function buildRequestMysign($para_sort)
    {
        //把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
        $prestr = createLinkstring($para_sort);
        $mysign = "";
        switch (strtoupper(trim($this->data_config['sign_type']))) {
            case "MD5" :
                $mysign = md5($prestr . $this->data_config['key']);
                break;
            default :
                $mysign = "";
        }
        return $mysign;
    }

    /**
     * 生成要请求给支付宝的参数数组
     * @param $para_temp 请求前的参数数组
     * @return 要请求的参数数组
     */
    function buildRequestPara($para_temp)
    {
        //除去待签名参数数组中的空值和签名参数
        $para_filter = paraFilter($para_temp);
        //对待签名参数数组排序
        $para_sort = argSort($para_filter);
        //生成签名结果
        $mysign = $this->buildRequestMysign($para_sort);
        //签名结果与签名方式加入请求提交参数组中
        $para_sort['sign'] = $mysign;
        $para_sort['sign_type'] = strtoupper(trim($this->data_config['sign_type']));
        return $para_sort;
    }

    /**
     * 生成要请求给支付宝的参数数组
     * @param $para_temp 请求前的参数数组
     * @return 要请求的参数数组字符串
     */
    function buildRequestParaToString($para_temp)
    {
        //待请求参数数组
        $para = $this->buildRequestPara($para_temp);
        //把参数组中所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串,并对字符串做urlencode编码
        $request_data = createLinkstringUrlencode($para);
        return $request_data;
    }

    /**
     * 建立请求,以表单HTML形式构造(默认)
     * @param $para_temp 请求参数数组
     * @param $method 提交方式。两个值可选:post、get
     * @param $button_name 确认按钮显示文字
     * @return 提交表单HTML文本
     */
    function buildRequestForm($para_temp, $method = 'post', $button_name = '确认')
    {
        $this->url = trim($this->url, '?&');
        if (strpos($this->url, '?') !== false) {
            $this->url .= '&';
        } else {
            $this->url .= '?';
        }
        //待请求参数数组
        $para = $this->buildRequestPara($para_temp);

        $sHtml = "<form id='datasubmit' name='datasubmit' action='" . $this->url . "input_charset=" . trim(strtolower($this->data_config['input_charset'])) . "' method='" . $method . "'>";
        while (list ($key, $val) = each($para)) {
            $sHtml .= "<input type='hidden' name='" . $key . "' value='" . $val . "'/>";
        }
        //submit按钮控件请不要含有name属性
        $sHtml = $sHtml . "<input type='submit'  value='" . $button_name . "' style='display:none;'></form>";
        $sHtml = $sHtml . "<script>document.forms['datasubmit'].submit();</script>";
        //echo $sHtml;
        return $sHtml;
    }

}


//函数
/**
 * 把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
 * @param $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;
}

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

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

    return $arg;
}

/**
 * 除去数组中的空值和签名参数
 * @param $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 $para 排序前的数组
 * @return 排序前的数组
 */
function argSort($para)
{
    ksort($para);
    reset($para);
    return $para;
}


测试:

include "lib/DataSubmit.class.php";
$parameter = array(
    'method' => 'get_info',
    'timestamp' => 1483620175,
    'format' => 'json',
    'user' => 'admin',
    'order_id' => 100,
);
$url = './test.php';
$dataSubmit = new DataSubmit($url);
$html_text = $dataSubmit->buildRequestForm($parameter, "post", "确认");
echo $html_text;

根据支付宝支付接口修改

如果文章对您有帮助,点击下方的广告,支持一下作者吧!

相关推荐


Android各个版本与API等级之间的对应关系

API等级 1 - 3:Android 1.0 (Astro,也被称为“铁臂阿童木”)Android 1.1 (Petit Four,即“花色小蛋糕”)Android 1.5 (Cupcake)API等级 4:Android 1.6 (Donut)API等级 5 - 7:Android 2.0/2.0.1/2.1 (Éclair)API等级 8:Android 2.2/2.2.3 (Froyo)A

go WaitGroup 的使用方法

在 Go 中,sync 包下的 WaitGroup 能有助于我们控制协程之间的同步。当需要等待一组协程都执行完各自任务后,才能继续后续逻辑。这种场景,就非常适合使用它。WaitGroup 提供三个 API。Add(delta int) 函数提供了 WaitGroup 的任务计数,delta 的值可以为正也可以为负,通常在添加任务时使用。Done() 函数其实就是 Add(-1),在任务完成时调用。

解决ThinkPHP6 tp6 多应用控制器不存在app\controller\Index的问题

解决ThinkPHP6 tp6 多应用控制器不存在app\controller\Index的问题

go web框架大全

go web框架大全