How to post a request with parameters and signature?

I have coded as below, but I get the error: "{\"code\":-1022,\"msg\":\"Signature for this request is not valid.\"}"
I have check my api-key/secret and they are ok; now I don't know where is wrong?

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let (symbol, side, trade_type, quantity, price, time_inforce, api_key, api_secret) = (
        "BTCUSDT",
        "BUY",
        "LIMIT",
        "0.1",
        "20000.0",
        "GTC",
        "my-key",
        "my-secret",
    );
    let client = reqwest::Client::new();
    let mut headers_map = reqwest::header::HeaderMap::new();
    headers_map.insert("Content-Type", "application/json".parse().unwrap());
    headers_map.insert("X-MBX-APIKEY", api_key.parse().unwrap());

    let mut param_map = std::collections::HashMap::new();
    param_map.insert("symbol", symbol);
    param_map.insert("side", side);
    param_map.insert("type", trade_type);
    param_map.insert("quantity", quantity);
    let current_timestamp = chrono::Utc::now().timestamp_millis().to_string();
    param_map.insert("timestamp", current_timestamp.as_str());
    if trade_type == "LIMIT" {
        param_map.insert("price", price);
        param_map.insert("timeInForce", time_inforce);
    }
    let mut query = String::new();
    for (key, value) in &param_map {
        query.push_str(&format!("{}={}&", key, value));
    }
    query.pop(); // remove trailing '&'

    let signature = {
        type HmacSha256 = hmac::Hmac<sha2::Sha256>;
        let mut mac = HmacSha256::new_from_slice(api_secret.as_bytes())
            .expect("HMAC can take key of any size");
        mac.update(query.as_bytes());
        hex::encode(mac.finalize().into_bytes())
        // format!("{:02x}", mac.finalize().into_bytes())
    };
    let res = client
        .post("https://fapi.binance.com/fapi/v1/order") // fapi/v1/order/test: for test orders
        .headers(headers_map)
        .body(query)
        .query(&[("timestamp", &current_timestamp), ("signature", &signature)])
        .send()
        .await?
        .text()
        .await?;

    Ok(())
}

I'm not familiar with the Binance API, but you can compare your request with the one generated by this library: binance-rs.

Thank you;
I have resolve this problem;
param_map should be sorted which means we should use BTreeMap to replace HashMap.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.