使用C#调用NowPayments API发送HTTP Get请求时出现404错误
问题重现
我编写了C#代码调用NowPayments API查询支付发票状态,但返回404错误,Postman调用相同接口却能成功。代码如下:
var client2 = new HttpClient(); var request2 = new HttpRequestMessage(HttpMethod.Get, "https://api.nowpayments.io/v1/payment/" + paymentId); request2.Headers.Add("x-api-key", apiKey); var response2 = await client2.SendAsync(request2); response2.EnsureSuccessStatusCode(); Console.WriteLine(await response2.Content.ReadAsStringAsync());
响应信息:
Response: "{StatusCode: 404, ReasonPhrase: 'Not Found', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Connection: keep-alive
x-dns-prefetch-control: off
x-frame-options: SAMEORIGIN
strict-transport-security: max-age=15552000; includeSubDomains
strict-transport-security: max-age=15768000
x-download-options: noopen
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
vary: Origin
vary: Accept-Encoding
CF-Cache-Status: DYNAMIC
Report-To: {"endpoints":[{"url":"https://a.nel.cloudflare.com/report/v3?s=OdTo2JBrpASej8JsgICuTwKgyGmvadtradnnwieH8OI6lPFXH38c%2F5YwSg6jUfMQEnKGoTa6Q7TLI4rhrqYt8K0XkdOK0qX%2BsSFmmkF6qfkQqAK66fA46l6ci8gVXusvmuzjoQ%3D%3D"}],"group":"cf-nel","max_age":604800}
NEL: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
CF-RAY: 7a330879af87b75b-AMS
Date: Sun, 05 Mar 2023 14:26:17 GMT
Server: cloudflare
Content-Length: 82
Content-Type: application/json; charset=utf-8
}}"
已确认API URL和API Key正确,Postman调用正常,目标是获取已创建支付发票的状态。
排查与解决步骤
1. 检查paymentId有效性与URL拼接问题
手动拼接URL时,若paymentId包含特殊字符(如斜杠、空格、编码字符)会导致URL无效。建议用UriBuilder构建合法URL:
var baseUrl = new Uri("https://api.nowpayments.io/v1/payment/"); var requestUrl = new Uri(baseUrl, paymentId); var request2 = new HttpRequestMessage(HttpMethod.Get, requestUrl);
同时确认paymentId非空、无多余空格,与Postman中使用的完全一致。
2. 添加必要请求头
Postman默认会发送Accept: application/json头,部分API会因缺少该头返回404,补充该头:
request2.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
3. 复用HttpClient而非每次实例化
频繁创建HttpClient会导致连接池耗尽或请求异常,建议复用单例实例:
// 全局或类级别声明 private static readonly HttpClient _httpClient = new HttpClient(); // 调用时 var request2 = new HttpRequestMessage(HttpMethod.Get, requestUrl); request2.Headers.Add("x-api-key", apiKey); request2.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); var response2 = await _httpClient.SendAsync(request2);
4. 对比Postman请求细节
在Postman中点击「Code」按钮选择C# HttpClient代码,对比以下差异:
- 是否有额外请求头(如
User-Agent) - URL是否完全一致(包括末尾斜杠)
- API Key的大小写和格式是否匹配
5. 确认API环境一致性
NowPayments分测试环境(https://api-sandbox.nowpayments.io)和生产环境,确保代码与Postman使用同一环境。
修正后的完整代码示例
private static readonly HttpClient _httpClient = new HttpClient(); public async Task<string> GetPaymentStatus(string apiKey, string paymentId) { var baseUrl = new Uri("https://api.nowpayments.io/v1/payment/"); var requestUrl = new Uri(baseUrl, paymentId); var request = new HttpRequestMessage(HttpMethod.Get, requestUrl); request.Headers.Add("x-api-key", apiKey); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); var response = await _httpClient.SendAsync(request); var responseContent = await response.Content.ReadAsStringAsync(); if (!response.IsSuccessStatusCode) { Console.WriteLine($"Error response: {responseContent}"); response.EnsureSuccessStatusCode(); } return responseContent; }
内容的提问来源于stack exchange,提问作者user19951222

