Webhook-验签

在商家端后台,添加webhook订阅的时候,会有一个是否验签的选项,您开启后,并生成了secretKey密钥,那么在推送数据的时候,将会出现一个access_key. 也就是签名。

签名是为了安全,对于fecify推送的数据,接收方先进行签名的验证,验证通过后,在继续其他的数据的处理,因为在理论上,知道您的推送地址的任何人都可以推送数据到 您的接收地址url。但是在实际操作中,这种情况很少发生,因此,为了省劲,您不进行验签也没啥大问题(可以将您的接收数据的url用的长一点),这个看您对数据安全的衡量。

签名的本质:就是fecify这边通过一个算法逻辑,将发送的post数据和密钥通过算法得到一个字符串,这个字符串就是签名字符串。 发送到第三方系统后,第三方系统本地也保存了一份相同的密钥字符串,第三方系统使用相同的算法,通过接收的post数组和密钥得到一个字符串。 将计算得到的签名字符串,和post发送的签名字符串进行核对,如果字符串一致,则验签通过,否则验签失败。 大多数的支付方式发送webhook消息(譬如:订单支付成功,订单支付失败等),都会加入签名机制,用于验证发送数据的安全性。

验签步骤逻辑:

1.fecify会请求第三方系统的url,post请求,会发送一个post参数数组。为了容易表述,我们将post参数数组赋值到变量$postParams

2.从post参数中得到fecify发送的签名字符串: $postParams['access_key'] (也就是post数组,数组key为access_key就是系统发送的签名字符串)

然后我们需要通过逻辑计算出来一个签名,然后和post参数中传递的签名进行字符串对比,如果一致则验签通过,如果不一致则验签失败。

3.计算签名

3.1fecify系统中创建webhook后,会生成一个密钥,您需要将密钥保存到第三方系统中,用于验签。

3.2计算签名函数(通过下面的php代码部分可以看到该函数的逻辑逻辑)

getSignKey($postParams, $secret_key)
  • $postParams 是post数组
  • $secret_key是私钥字符串

3.3通过调用函数getSignKey()来得到签名,然后核验计算出来的签名和系统发送的签名是否一致即可

  • 字符串一致,验签通过
  • 字符串不一致,验签失败

签名原理

webhook,本质是一个post类型的api请求,发送一个post数组参数。为了容易表述,我们将post参数数组赋值到变量$postParams

1.我们通过一个封装函数,进行签名的生成,再这个函数里面,将密钥加入$postParams, 数组key为'secret_key', 譬如php代码: $postParams['secret_key'] = $secretKey; ($secretKey是密钥字符串)

2.将推送的post数组,进行排序, 对数组根据键名升序排序

3.将排序后的数组,转换成json格式的字符串

4.进行sha256哈希加密处理,返回的字符串就是签名

到这里,通过计算就得到签名字符串了。

php示例代码

/**
 * 得到签名
 * @param $params
 * @param $secretKey
 * @return mixed
 * @author Terry
 */
public static function getSignKey(array $params, $secretKey)
{
    if (isset($params['access_key'])) {
        // 如果存在key:access_key,则该字段不参与签名,因为这个字段是签名
        unset($params['access_key']);
    }
    // 加入私钥(本地存储)
    $params['secret_key'] = $secretKey;
    $params = self::paraFilter($params);
    $params = self::argSort($params);
    $params = json_encode($params);

    return hash('sha256', $params);
}


public static function paraFilter($para)
{
    $para_filter = array ();
    foreach ($para as $key=>$va) {
        $para_filter [$key] = $para [$key];
    }
    return $para_filter;
}

public static function argSort($para)
{
    ksort ( $para );
    reset ( $para );
    return $para;
}

调用:

getSignKey($postParams, $secret_key)
  • $postParams 是post数组
  • $secret_key是私钥字符串
Copyright © fecify.com 2022 all right reserved,powered by Gitbook该文件修订时间: 2024-03-01 10:48:11

results matching ""

    No results matching ""