C# POST请求C中的本地比特币API签名#
我试图发送一些带有本地比特币API的比特币,但它会导致错误的请求。当我获得余额时,它会工作,但当我尝试发送比特币时,它会出错 它似乎在签名和参数(地址和金额)方面有问题。因为当我用错误的Hmac_密码发出WalletBalance请求时,它会得到相同的错误(错误400错误请求)C# POST请求C中的本地比特币API签名#,c#,api,C#,Api,我试图发送一些带有本地比特币API的比特币,但它会导致错误的请求。当我获得余额时,它会工作,但当我尝试发送比特币时,它会出错 它似乎在签名和参数(地址和金额)方面有问题。因为当我用错误的Hmac_密码发出WalletBalance请求时,它会得到相同的错误(错误400错误请求) 我遗漏了什么?StringEncode不可能是正确的。ASCII是7位编码,但哈希是8位字节的字节数组,因此任何大于127的字节值都会被问号替换。是否确实需要应用某个字符集才能将字节转换为字符串?通常,当任意字节应编码为
我遗漏了什么?
StringEncode
不可能是正确的。ASCII是7位编码,但哈希是8位字节的字节数组,因此任何大于127的字节值都会被问号替换。是否确实需要应用某个字符集才能将字节转换为字符串?通常,当任意字节应编码为字符串时,这是通过Base64编码或将其转换为十六进制字符串来完成的。除了a)您的GetNonceMethod
可以减少为DateTimeOffset.Now.ToUnixTimeSeconds().ToString()
;b) WebRequest已经过时近10年了-改用HttpClient。另一个问题是您的内容类型不匹配。您声明它是URL编码的表单数据,但实际上发送JSON。因此,您的内容类型应该是“application/json”
,或者您需要将数据作为URL编码的表单数据发送。感谢您的回复,问题在于参数。因此,我将其替换为'string jsonBody=“address=“+address+”&amount=“+amount;”一切都很好。是的,这是URL编码的表单数据格式。尽管您应该使用Uri.EscapeDataString(address)
和Uri.EscapeDataString(amount)
来处理保留字符。尽管像我在使用HttpClient时所说的那样,例如var response=wait HttpClient.PostAsync(端点,新FormUrlEncodedContent(新字典{[“address”]=address,[“amount”]=amount});var result=await response.Content.ReadAsStringAsync();
,将使代码更加简单,并自动处理所有边缘情况。
public string SendBitcoin(string address, string amount)
{
string jsonBody = new JavaScriptSerializer().Serialize(new
{
address = address,
amount = amount
});
return SendRequest("/api/wallet-send/", jsonBody, "POST");
}
public string WalletBalance()
{
return SendRequest("/api/wallet-balance/", "", "GET");
}
private string SendRequest(string endpoint, string bodyJson, string Method)
{
string Hmac_Key = "key";
string Hmac_Secret = "secret";
string timestamp = GetNonce();
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls | SecurityProtocolType.Ssl3;
var httpWebRequest = (HttpWebRequest)WebRequest.Create(urllink + endpoint);
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Method = Method;
httpWebRequest.Headers.Add("Apiauth-Key", Hmac_Key);
httpWebRequest.Headers.Add("Apiauth-Nonce", timestamp);
if (Method == "POST")
{
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(bodyJson);
streamWriter.Flush();
streamWriter.Close();
}
}
httpWebRequest.Headers.Add("Apiauth-Signature", SigneRequest(Hmac_Key, timestamp, Method, endpoint, bodyJson, Hmac_Secret));
HttpWebResponse httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
return result;
}
}
private string GetNonce()
{
DateTimeOffset eposh = new DateTimeOffset(1970, 1, 1, 0, 0, 0, new TimeSpan(0));
DateTimeOffset now = DateTimeOffset.UtcNow;
TimeSpan ts = now.Subtract(eposh);
return ts.TotalMilliseconds.ToString("#0");
}
private string SigneRequest(string HmacKey, string nonce, string method, string endpoint, string body, string HmacSecret)
{
string message = nonce + HmacKey + endpoint + body;
return BitConverter.ToString(HashHMAC(StringEncode(HmacSecret), StringEncode(message))).Replace("-", "").ToUpper();
}
private byte[] StringEncode(string text)
{
var encoding = new ASCIIEncoding();
return encoding.GetBytes(text);
}
private static byte[] HashHMAC(byte[] key, byte[] message)
{
var hash = new HMACSHA256(key);
return hash.ComputeHash(message);
}