代码样例-数字签名

本文档包含生成api数字签名的代码样例,供开发者参考。

代码样例使用说明

  1. 代码样例不能直接运行,因为代码中的订单号9266892014xxxxx、apikeyjd1gzm6ant2u7pojhbtl0bam0xpzsm1c等信息都是虚构的,请替换成您自己的信息。
  2. 在下面的代码示例中,不同编程语言,甚至同一语言每次执行得到的 url 可能都有所不同,表现为参数的顺序不同,但这并不影响正确性。只要所有参数都存在,并且签名串计算正确即可。
  3. 使用代码样例过程中遇到问题请联系售后客服,我们会为您提供技术支持。

Python

Python数字签名实例
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import json
import time
import base64
import hashlib
import hmac

import requests

class Auth:
    """用于保存用户orderid、apiKey,以及计算签名的对象。"""
    def __init__(self, orderId, apiKey):
        self._orderId = orderId
        self._apiKey = apiKey

    @classmethod
    def get_string_to_sign(cls, method, endpoint, params):
        """ 生成签名原文字符串 """
        s = method + endpoint.split('.com')[1] + '?'
        query_str = '&'.join("%s=%s" % (k, params[k]) for k in sorted(params))
        return s + query_str

    def sign_str(self, raw_str, method=hashlib.sha1):
        """ 生成签名串 """
        try:
            hmac_str = hmac.new(self.apiKey.encode('utf8'), raw_str.encode('utf8'), method).digest()
        except UnicodeDecodeError as e:
            hmac_str = hmac.new(self.apiKey.encode('utf8'), raw_str, method).digest()
        return base64.b64encode(hmac_str)

    @property
    def orderId(self):
        return self._orderId

    @property
    def apiKey(self):
        return self._apiKey


def _get_base_res(method, endpoint, params):
    """处理基础请求,
       若响应为json格式则返回请求结果dict
       否则直接返回原格式
    """
    try:
        r = None
        if method == "GET":
            r = requests.get("https://" + endpoint, params=params)
        elif method == "POST":
            r = requests.post("https://" + endpoint, data=params)
        if r.status_code != 200:
            return 'HTTP Status Code: %s' % r.status_code
        try:
            return json.loads(r.content.decode('utf8'))
        except ValueError as e:  # 返回结果不是json格式, 直接返回
            return r.content.decode('utf8')
    except Exception as e:
        print(str(e))


if __name__ == '__main__':
    orderid = '9266892014xxxxx'
    api_key = 'jd1gzm6ant2u7pojhbtl0bam0xpzsm1c'
    method = 'GET'  # 请求方式
    endpoint = 'dps.kdlapi.com/api/getdpsvalidtime'
    # 除signature外的所有参数都放入params
    params = { 
        'orderid': orderid,
        'sign_type': 'hmacsha1',
        'timestamp': int(time.time()),
        'proxy': '27.42.139.229:2057',
    }

    auth = Auth(orderid, api_key)
    raw_str = auth.get_string_to_sign(method, endpoint, params)
    params['signature'] = auth.sign_str(raw_str)
    res = _get_base_res(method, endpoint, params)
    print(res)

Java

Java数字签名实例
import java.util.TreeMap;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

/**
* 用于保存用户orderid, apiKey, 以及计算签名的对象。
*/
public class Auth {
    private final static String CHARSET = "UTF-8";

    private String orderId;
    private String apiKey;

    public Auth(String orderId, String apiKey) {
        this.orderId = orderId;
        this.apiKey = apiKey;
    }

    public String sign(String s) throws Exception {
        return sign(s, "HmacSHA1");
      }

    /**
    * 生成签名字符串
    *
    * @param method  请求方式
    * @param s  已经拼接好的原字符串
    * @return Hmacsha1加密,并base64编码之后的原字符串。
    * @throws Exception
    */
    public String sign(String s, String method) throws Exception {
        Mac mac = Mac.getInstance(method);
        SecretKeySpec secretKeySpec = new SecretKeySpec(this.apiKey.getBytes(CHARSET), mac.getAlgorithm());
        mac.init(secretKeySpec);
        byte[] hash = mac.doFinal(s.getBytes(CHARSET));
        return DatatypeConverter.printBase64Binary(hash);
    }        


    /**
    * 生成原字符串
    *
    * @param endpoint 访问的地址
    * @param method  请求方式
    * @param params  其他参数
    * @return 返回拼接好的原字符串
    * @throws Exception
    */
    public  String getStringToSign(String method, String endpoint, TreeMap<String, Object> params) {
        String s = method + endpoint.split(".com")[1] + "?";
        StringBuilder s2s = new StringBuilder();
        // 签名时要求对参数进行字典排序,此处用TreeMap保证顺序
        for (String k : params.keySet()) {
            s2s.append(k).append("=").append(params.get(k).toString()).append("&");
        }
        return s + s2s.toString().substring(0, s2s.length() - 1);
    }

    public String getOrderId() {
        return this.orderId;
    }

    public String getApiKey() {
        return this.apiKey;
    }
}

Golang

Golang数字签名实例
import (
    "crypto/hmac"
    "crypto/sha1"
    "encoding/base64"
    "sort"
    "strings"

    "github.com/kuaidaili/golang-sdk/api-sdk/kdl/utils"
)

// Auth 用于保存用户orderid、apiKey,以及计算签名
type Auth struct {
    OrderID string
    APIKey  string
}

// GetStringToSign 生成签名原文字符串
func (auth Auth) GetStringToSign(method string, endpoint string, params map[string]interface{}) string {
    s := method + strings.Split(endpoint, ".com")[1] + "?"
    var keys []string
    for k := range params {
        keys = append(keys, k)
    }
    sort.Strings(keys)
    var arr []string
    for _, k := range keys {
        arr = append(arr, k+"="+utils.TypeSwitcher(params[k]))
    }
    queryStr := strings.Join(arr, "&")
    return s + queryStr
}

// SignStr 计算签名串
func (auth Auth) SignStr(rawStr string) string {
    key := []byte(auth.APIKey)
    hash := hmac.New(sha1.New, key)
    hash.Write([]byte(rawStr))
    sig := base64.StdEncoding.EncodeToString([]byte(string(hash.Sum(nil))))
    return sig
}

NodeJS

NodeJS数字签名实例
global.crypto = require('crypto');

class Auth {
    constructor(orderId, apiKey) {
        this.orderId = orderId;
        this.apiKey = apiKey;
    }

    get order_id() {
        return this.orderId;
    }
    get api_key() {
        return this.apiKey;
    }

    /**
     * 生成签名原文字符串
     *
     * @method getStringToSign
     * @for Auth
     * @param {String} method 要访问的方式
     * @param {String} ENDPOINT 地址
     * @param {Array} params 不定长参数。就是携带的参数了。
     * @return {String}  返回值原文字符串
     */
    getStringToSign(method, ENDPOINT, params) {
        let s = method + ENDPOINT.split('.com')[1] + '?';
        let newParams = sortDict(params);
        let queryStr = getQueryStr(newParams);
        return s+queryStr;
    }

    /**
     * 进行Hmacsha1加密
     *
     * @method signStr
     * @for Auth
     * @param {String} rawStr 原字符串
     * @return {String}  Hmacsha1加密,并base64编码之后的原字符串。
     */
    signStr(rawStr, ) {
        return crypto.createHmac('sha1',this.api_key).update(rawStr).digest().toString('base64');
    }
}

/**
* getQueryStr 将参数字典进行&拼接,构成formData格式
*
* @param {Array} dic 字典
* @return {String} 拼接好的字典
*/
function getQueryStr(dic){
    let str = "";
    let dicKey  = Object.keys(dic);
    for (let i = 0;i<dicKey.length;i++){
        str += dicKey[i] + '=' + dic[dicKey[i]];
        if(i!==dicKey.length-1){
            str += '&';
        }
    }
    return str;
}

/**
* sortDict 根据字典的key进行字典序排序
* 
* @param {Array} dic 字典
* @return {Array} 新的已经排序好的字典
*/
function sortDict(dic){
    let newDic = {};
    let dickey = Object.keys(dic).sort();
    for(let i = 0;i<dickey.length;i++){
        newDic[dickey[i]] = dic[dickey[i]];
    }
    return newDic;
}

PHP

PHP数字签名实例
<?php
class Auth{
    public $orderId;
    public $apiKey;

    function __construct($orderId, $apiKey){
        $this -> orderId = $orderId;
        $this -> apiKey = $apiKey;
    }


    /*
    *   生成签名原文字符串
    *    @param string $method 请求方法
    *    @param string $endpoint
    *    @parms array  $params 
    *    @return string  签名原文字符串
    */
    public function getStringToSign($method, $endpoint, $params){
        $query_string = "";
        ksort($params);
        # 此处不应该使用http_build_query函数进行url编码, 而是用"&"符将各个参数连接
        #$query_string = http_build_query($params);
        foreach($params as $key => $value){
            $query_string .= "$key=$value&";         
       }
        $query_string = rtrim($query_string, "&");

        list(, $string) = explode(".com", $endpoint);
        $string = "$method"."$string"."?"."$query_string";
        return $string;
    }


    /*
    *   生成签名串
    *    @param string $raw_str 签名原文字符串
    *    @param string $method  加密方法,默认sha1
    *    @return string  签名串
    */
    public function signStr($raw_str, $method="sha1"){
        $hmac_str = hash_hmac($method, $raw_str, $this->apiKey, true);
        $sign_str = base64_encode($hmac_str);
        return $sign_str;
    }

}
?>
联系我们
  • 售前在线咨询
    咨询享免费测试,专业工程师提供技术支持
  • 客服热线
    400-058-0638  周一至周六 9:00-18:30
  • 提交工单
    您的每一次反馈我们都认真对待
  • 客服微信 & QQ
    客服微信:kuaidaili,客服QQ:800849628
  • 企业客户通道
    提交需求后专业的售前工程师为您提供服务