When posting to https://bpay.binanceapi.com/binancepay/openapi/v3/order I receive response: {"status":"FAIL","code":"400002","errorMessage":"Signature for this request is not valid."} Check whether the signature parameter and method comply with signature algorithm requirements.

These are the methods I use to build the requests to BinancePay API in C# It should match the API specification in https://developers.binance.com/docs/binance-pay/api-order-create-v3 I think I have good signature based on requirements in https://developers.binance.com/docs/binance-pay/api-common

private (string, string, string) GetData() 
{
    var nonce = GetBinanceNonce();
        
    var request = new StartDepositData
    {
            env = new StartDepositData.Env
            {
                TerminalType = TerminalType
            },
            orderTags = new StartDepositData.OrderTags 
            {
                IfProfitSharing = true
            },
            MerchantTradeNo = nonce,
            OrderAmount = (double)_data.PaymentAmount,
            Currency = _data.PaymentCurrencyId,
            Description = "BinancePay",
            GoodsDetails = new List<StartDepositData.GoodDetail>
            {
                new ()
                {
                    GoodsType = GoodsType,
                    GoodsCategory = GoodsCategory,
                    ReferenceGoodsId = _data.Reference,
                    GoodsName = "BinancePay",
                    GoodsDetail = "BinancePay"
                }
            }
        };
        
        // TODO: API Specification ambiguous, payload could be:
        // 1. var payload = body;
        // 2. var payload = timestamp + "\n" + nonce + "\n" + body + "\n";
        // 1 may just be the payload, 2 may be needed when creating signature maybe
        var timestamp = DateTime.UtcNow.ToUnixTimeMilliseconds().ToString();
        
        var body = JsonConvert.SerializeObject(request);
        var payload = body;
        var signaturePayload = timestamp + "\n" + nonce + "\n" + body + "\n";

        string signature = CreateSignature(signaturePayload, _secret);
        string hexSignature = Hex(Encoding.UTF8.GetBytes(signature));

        return (payload, hexSignature, nonce);
    }
    
    private string CreateSignature(string payload, string secretKey)
    {
        // Initialize a new HMACSHA512 instance with the provided secret key
        var hmac = new HMACSHA512(Encoding.UTF8.GetBytes(secretKey));
        
        // Compute the hash of the payload
        var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(payload));
    
        // Convert the hash to a hexadecimal string, remove any dashes typically included by BitConverter, and convert to uppercase
        return BitConverter.ToString(hash).Replace("-", string.Empty).ToUpper();
    }
    
    public static string Hex(byte[] bytes)
    {
        StringBuilder result = new StringBuilder(bytes.Length * 2);
        string hexAlphabet = "0123456789ABCDEF";

        foreach (byte b in bytes)
        {
            result.Append(hexAlphabet[b >> 4]);
            result.Append(hexAlphabet[b & 0xF]);
        }

        return result.ToString();
    }
    
// A random string with 32 bytes, e.g. random ascii decimal within a-z and A-Z and loop 32 times to form a random string
private static string GetBinanceNonce(int length = 32)
{
const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        return new string(Enumerable.Repeat(chars, length)
            .Select(s => s[new Random().Next(s.Length)]).ToArray());
}

As for the sending it, I send it as so:

var (payload, signature, nonce) = GetData();
    
var timestamp = DateTime.UtcNow.ToUnixTimeMilliseconds().ToString();

var headers = new {
                Content_Type = "application/json",
                BinancePay_Timestamp = timestamp,
                BinancePay_Nonce = nonce,
                BinancePay_Certificate_SN = _apiKey,
                BinancePay_Signature = signature
            };
var reply = await _binanceClient.PostAsync(Endpoint, new StringContent(payload), headers);
// TODO: {"status":"FAIL","code":"400002","errorMessage":"Signature for this request is not valid."}
// TODO: Check whether the signature parameter and method comply with signature algorithm requirements.
var content = await reply.Content.ReadAsStringAsync();

EDIT: This works: var timestamp = DateTime.UtcNow.ToUnixTimeMilliseconds().ToString();

var payload = jsonRequest; var signaturePayload = timestamp + "\n" + nonce + "\n" + jsonRequest + "\n"; private string CreateSignature(string payload) { byte[] keyBytes = Encoding.UTF8.GetBytes(Secret); using (HMACSHA512 hmacsha512 = new HMACSHA512(keyBytes)) { byte[] sourceBytes = Encoding.UTF8.GetBytes(payload);

        byte[] hash = hmacsha512.ComputeHash(sourceBytes);

        // Convert the hash to a hexadecimal string, remove any dashes typically included by BitConverter, and convert to uppercase
        return BitConverter.ToString(hash).Replace("-", "").ToUpper();
    }
}

// A random string with 32 bytes, e.g. random ascii decimal within a-z and A-Z and loop 32 times to form a random string
private static string GetBinanceNonce(int length = 16)
{
    const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    var randomCharacters = new string(Enumerable.Repeat(chars, length)
        .Select(s => s[new Random().Next(s.Length)]).ToArray());

    return BitConverter.ToString(Encoding.UTF8.GetBytes(randomCharacters)).Replace("-", "");
}

string signature = CreateSignature(signaturePayload);

return (payload, signature, nonce, timestamp);

0

There are 0 best solutions below