code "1004", msg "sign invalid"

Discussing technical aspects of Yun development products, including IoT Core and other cloud service APIs, data analysis products, etc.


Post Reply
adiot
Posts: 3

Hi,
I'm trying to call the API using Postman, but I'm getting a "sign invalid" error

The Postman json file and Enviroments were added by referring to "https://developer.tuya.com/en/docs/iot/ ... o385w1svns"

Below is Postman pre-scripte, where "client_id" and "secret" entered the AccessID and Access Secret without a hitch.
I can't find the cause. Please help me

Code: Select all

(function () { 
	var timestamp = getTime();
    	pm.environment.set("timestamp",timestamp);
	var clientId = pm.environment.get("client_id");
	var secret = pm.environment.get("secret");
	var sign = calcSign(clientId,secret,timestamp);
	pm.environment.set('easy_sign', sign);
})();

function getTime(){
    var timestamp = new Date().getTime();
    
return timestamp; } function calcSign(clientId,secret,timestamp){ var str = clientId + timestamp; var hash = CryptoJS.HmacSHA256(str, secret); var hashInBase64 = hash.toString(); var signUp = hashInBase64.toUpperCase(); return signUp; }

Code: Select all

{
    "code": 1004,
    "msg": "sign invalid",
    "success": false,
    "t": 1698735333523,
    "tid": "7cb98d1777ba11ee946f2e28f447d5d3"
}
panda-cat
Posts: 23

Re: code "1004", msg "sign invalid"

If you encounter this problem, you can check whether the "Current value" set by client_id and secret in the environment configuration file is correct.
Image

panda-cat
Posts: 23

Re: code "1004", msg "sign invalid"

I found that your pre-scripte is incomplete. You can re-download a postman collection file and import it into postman. The complete information parameters are as follows:

Code: Select all

(function () {
    var timestamp = getTime();
    pm.environment.set("timestamp",timestamp);

const clientId = pm.environment.get("client_id");
const secret = pm.environment.get("secret");

var accessToken = "";
if(pm.environment.has("easy_access_token")){
    accessToken = pm.environment.get("easy_access_token")
}

const httpMethod = pm.request.method.toUpperCase();
const query = pm.request.url.query;
const mode = pm.request.body.mode;
const headers = pm.request.headers;

// sha256
var signMap = stringToSign(query, mode, httpMethod, secret)
var urlStr = signMap["url"]
var signStr = signMap["signUrl"]
pm.request.url = pm.request.url.host + urlStr
var nonce = ""
if (headers.has("nonce")) {
    var jsonHeaders = JSON.parse(JSON.stringify(headers))
    jsonHeaders.forEach(function(item){
        if (item.key == "nonce" && !item.disabled) {
            nonce = headers.get("nonce")
        }
    })
}
var sign = calcSign(clientId, timestamp, nonce, signStr, secret);
pm.environment.set('easy_sign', sign);
})();

function getTime(){
    var timestamp = new Date().getTime();
    return timestamp;
}

// Token verification calculation
function calcSign(clientId,timestamp,nonce,signStr,secret){
    var str = clientId +timestamp + nonce + signStr;
    var hash = CryptoJS.HmacSHA256(str, secret);
    var hashInBase64 = hash.toString();
    var signUp = hashInBase64.toUpperCase();
    return signUp;
}

// // Business verification calculation
// function calcSign(clientId,accessToken,timestamp,nonce,signStr,secret){
//     var str = clientId + accessToken +timestamp + nonce + signStr;
//     var hash = CryptoJS.HmacSHA256(str, secret);
//     var hashInBase64 = hash.toString();
//     var signUp = hashInBase64.toUpperCase();
//     return signUp;
// }

// Generate signature string
function stringToSign(query, mode, method, secret){
    var sha256 = "";
    var url = "";
    var headersStr = ""
    const headers = pm.request.headers;
    var map = {}
    var arr = []
    var bodyStr = ""
    if(query){
        toJsonObj(query, arr, map)
    }
    if (pm.request.body && mode) {
        if (mode != "formdata" && mode != "urlencoded"){
            bodyStr = replacePostmanParams(pm.request.body.toString())
        } else if (mode == "formdata") {
            // Traversing form key value pairs
            toJsonObj(pm.request.body["formdata"], arr, map)
        } else if (mode == "urlencoded") {
            // Traversing form key value pairs
            toJsonObj(pm.request.body["urlencoded"], arr, map)
        }
    } 
    sha256 = CryptoJS.SHA256(bodyStr)
    arr = arr.sort()
    arr.forEach(function(item){
            url += item + "=" + map[item] + "&"
    })
    if (url.length > 0 ) {
        url = url.substring(0, url.length-1)
        url = "/" + pm.request.url.path.join("/") + "?" + url
    } else {
        url = "/" + pm.request.url.path.join("/") 
    }
    
if (headers.has("Signature-Headers") && headers.get("Signature-Headers")) { var jsonHeaders = JSON.parse(JSON.stringify(headers)) var signHeaderStr = headers.get("Signature-Headers") const signHeaderKeys = signHeaderStr.split(":") signHeaderKeys.forEach(function(item){ var val = "" if (isSelected(jsonHeaders,item) && headers.get(item)) { val = headers.get(item) } headersStr += item + ":" + val + "\n" }) } var map = {} url = replacePostmanUrl(url) map["signUrl"] = method + "\n" + sha256 + "\n" + headersStr + "\n" + url map["url"] = url return map } function isSelected(jsonHeaders,key){ var result = true; jsonHeaders.forEach(function(item){ if (item.key == key && item.disabled) { result = false } }) return result } function replacePostmanParams(str){ while(str.indexOf("{{")!=-1&&str.indexOf("}}")!=-1){ const key = str.substring(str.indexOf("{{")+2,str.indexOf("}}")) var value = pm.environment.get(key) if(!value) value="" str = str.replace("{{"+key+"}}", value) } return str } function replacePostmanUrl(str){ console.log("str:",str) while(str.indexOf("{{")!=-1&&str.indexOf("}}")!=-1){ const key = str.substring(str.indexOf("{{")+2,str.indexOf("}}")) var value = pm.environment.get(key) if(!value) value="" str = str.replace("{{"+key+"}}", value) } while(str.indexOf(":")!=-1){ const tempStr = str.substring(str.indexOf(":")+1,str.length); var key = ""; if(tempStr.indexOf("/")!=-1){ key = tempStr.substring(0,tempStr.indexOf("/")) }else if(tempStr.indexOf("?")!=-1){ key = tempStr.substring(0,tempStr.indexOf("?")) }else { key = tempStr.substring(0,tempStr.length) } var value = pm.request.url.variables.get(key) if(!value) value="" str = str.replace(":"+key, value) } return str } function toJsonObj(params, arr, map){ var jsonBodyStr = JSON.stringify(params) var jsonBody = JSON.parse(jsonBodyStr) jsonBody.forEach(function(item){ if(!item.disabled){ arr.push(item.key) map[item.key] = item.value } }) }
adiot
Posts: 3

Re: code "1004", msg "sign invalid"

Thank you for your answer. However, the environment configuration is normal no matter how much I check.

What's strange is that even though Tuya API Explorer and PostMan used the same Timestamp value, the HMAC value was different.
Obviously, ClientID, Secret, and Timestamp values are the same, so why are HMAC values different?

adiot
Posts: 3

Re: code "1004", msg "sign invalid"

Thank you. There was a problem with the pre-scripte.
The new download solved the problem.
Is the previous download the past version.. It's..

Anyway, thanks to you, I solved it. Thank you.

Post Reply