Skip to main content

Cách Tính API Signature

Tài liệu mô tả cách tính API signature cho đối tác, đối tác sẽ dùng API signature khi gọi tới API của Tiki.

Request header

Với mỗi request để được xác thực cần gửi những thông tin sau trong request header

HeaderDescription
X-Tikivip-TimestampThời gian gọi request, tính bằng milliseconds. Timestamp này không được cũ hơn (time_now - 5 phút). Với time_now là thời gian Tiki nhận được API request.
X-Tikivip-SignatureSignature được tính dựa trên request body
X-Tikivip-Client-IdClient id mà đối tác được cấp

Signature Là Gì?

Trong các lệnh gọi API giữa backend của đối tác và backend của Tiki. Tiki sử dụng signature để có thể định danh backend nào đang thực hiện lệnh gọi đến backend của Tiki. Signature này được tính bằng cách lấy shasum của một số data và một API secret được cấp cho đối tác

Cách Tính Như Thế Nào?

Pseudo code để tính signature sẽ như sau:

// request body
body = {
"<field_name>": <field_value>,
"<field_name>": <field_value>,
"<field_name>": <field_value>,
}

payload = timestamp + "." + client_key + "." + json_stringify(body)
secret = "<client_secret>"
encoded_payload = base64_safeurl_encode_no_padding(payload)
signature = HMAC_SHA256(secret, encoded_payload)

Code mẫu

Sau đây là code mẫu để tính signature với các ngôn ngữ khác nhau:

Javascript

const crypto = require("crypto");

const client_key = "RLCKb7Ae9kx4DXtXsCWjnDXtggFnM43W";
const client_secret = "EhjGcsUUuRSJTHiYPbW5fxzyaKEx0JuAZIKRQ4HnIfNFidB2kMg6locQbTIEz3Vf";
const body = {
id: 123
};

const timestamp = 1620621619569;

function base64URLEncode(data) {
const base64 = Buffer.from(data, "utf8").toString("base64");
return base64.replace(/=/g, "").replace(/\+/g, "-").replace(/\//g, "_");
}

function sign(secret, payload) {
const signature = crypto
.createHmac("sha256", client_secret)
.update(payload)
.digest("hex");
return signature;
}

const payload = timestamp + '.' + client_key + '.' + JSON.stringify(body);
console.log("payload: ", payload);
const encodedPayload = base64URLEncode(payload);
console.log("encoded_payload: ", encodedPayload);
const signature = sign(client_secret, encodedPayload);
console.log("signature: ", signature);

// payload: 1620621619569.RLCKb7Ae9kx4DXtXsCWjnDXtggFnM43W.{"id":123}
// encoded_payload: MTYyMDYyMTYxOTU2OS5STENLYjdBZTlreDREWHRYc0NXam5EWHRnZ0ZuTTQzVy57ImlkIjoxMjN9
// signature: 8ebd092b9df2cf90e8ccbcab2ba87ee14f2abb25eb8f18b4d7286d42adcd45c2

Golang

package main

import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"strconv"
)

func Sign(secret string, payload string) (string, error) {
h := hmac.New(sha256.New, []byte(secret))
_, err := h.Write([]byte(payload))
if err != nil {
return "", err
}
signature := hex.EncodeToString(h.Sum(nil))
return signature, nil
}

func main() {
clientKey := "RLCKb7Ae9kx4DXtXsCWjnDXtggFnM43W"
clientSecret := "EhjGcsUUuRSJTHiYPbW5fxzyaKEx0JuAZIKRQ4HnIfNFidB2kMg6locQbTIEz3Vf"
body := map[string]interface{}{
"id": 123,
}

timestamp := int64(1620621619569)
jsonBody, _ := json.Marshal(body)
payload := fmt.Sprintf("%s.%s.%s", strconv.FormatInt(timestamp, 10), clientKey, string(jsonBody))
fmt.Println("payload: ", payload)
encodedPayload := base64.RawURLEncoding.EncodeToString([]byte(payload))
fmt.Println("encoded_payload: ", encodedPayload)
signature, _ := Sign(clientSecret, encodedPayload)
fmt.Println("signature: ", signature)
}

// payload: 1620621619569.RLCKb7Ae9kx4DXtXsCWjnDXtggFnM43W.{"id":123}
// encoded_payload: MTYyMDYyMTYxOTU2OS5STENLYjdBZTlreDREWHRYc0NXam5EWHRnZ0ZuTTQzVy57ImlkIjoxMjN9
// signature: 8ebd092b9df2cf90e8ccbcab2ba87ee14f2abb25eb8f18b4d7286d42adcd45c2

PHP

<?php
$timestamp = '1648463110733';
$clientId = 'YOUR_CLIENT_ID';
$secretKey = 'YOUR_SECRET_KEY';
$body = '{"code":"AoVGh57xCxEq7so22ba6d6pbcEj2Kk2JcImCbHsMQlM.qt90czxRIQAHkQTDgM83tFfm-P9alm8Pd9ja8VVvhV0"}';
$payloadFormat = '%s.%s.%s';
$payload = sprintf($payloadFormat, $timestamp, $clientId, $body);
$encodePayload = preg_replace(['/=/', '/\+/', '/\//'], ['', '-', '_'], base64_encode($payload));
$sig = hash_hmac('sha256', $encodePayload, $secretKey);