اگر یک توسعهدهنده داتنت هستی و میخواهی سیستم معاملاتی، ربات ترید، داشبورد مالی یا هر اپلیکیشن مرتبط با رمزارز بسازی، قطعاً دیر یا زود به این سوال میرسی: چطور API صرافیهای ایرانی را با C# یا ASP.NET وصل کنم؟
صرافیهای ایرانی مثل نوبیتکس (Nobitex)، والکس (Wallex)، اکسیر (Exir) و بیتپین (Bitpin) همگی API عمومی دارند که میشود از طریق HTTP Requests به آنها متصل شد. خبر خوب اینه که اکوسیستم داتنت ابزارهای فوقالعادهای برای این کار داره و در این مقاله قدمبهقدم باهات پیش میریم.
قبل از هر چیز، باید چند تا چیز رو آماده کنی:
در دنیای داتنت، چند گزینه اصلی برای ارسال HTTP Request داریم:
HttpClient کتابخانه بومی داتنت است و برای اکثر پروژهها کافی و بهینهترین گزینه به حساب میاد. از .NET Core 2.1 به بعد با IHttpClientFactory قابل تزریق وابستگی (DI) هم هست.
کتابخانه محبوب RestSharp یک لایه انتزاع زیبا روی HttpClient میزاره و کد رو خیلی تمیزتر میکنه. برای پروژههای بزرگ که نیاز به مدیریت درخواستهای زیاد دارید، گزینه عالیه.
Refit یک کتابخانه فوقالعادهست که با تعریف Interface، بهصورت خودکار HTTP Client میسازه. اگه با TypeSafe API Client آشنا باشی، عاشقش میشی.
نوبیتکس یکی از بزرگترین صرافیهای ایرانی است و API مستنداتش نسبتاً کاملتر از بقیهست. بیایید با این صرافی شروع کنیم.
dotnet new console -n NobitexApiClient cd NobitexApiClient dotnet add package Newtonsoft.Json dotnet add package RestSharp
// Models/MarketStats.cs
public class MarketStatsResponse
{
public string Status { get; set; }
public Dictionary Stats { get; set; }
}
public class Stats
{
public string Bestask { get; set; }
public string Bestbid { get; set; }
public string Last { get; set; }
public string Volume { get; set; }
public string Volumesrc { get; set; }
public string Volumedst { get; set; }
}
// Services/NobitexService.cs
using System.Net.Http.Headers;
using Newtonsoft.Json;
public class NobitexService
{
private readonly HttpClient _httpClient;
private readonly string _baseUrl = “https://api.nobitex.ir”;
private readonly string _apiToken;
public NobitexService(string apiToken)
{
_apiToken = apiToken;
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue(“Token”, _apiToken);
_httpClient.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue(“application/json”));
}
// دریافت آمار بازار (بدون نیاز به احراز هویت)
public async Task GetMarketStatsAsync(
string srcCurrency = “btc”,
string dstCurrency = “rls”)
{
var url = $“{_baseUrl}/market/stats?srcCurrency={srcCurrency}&dstCurrency={dstCurrency}”;
var response = await _httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject(content);
}
// دریافت موجودی کاربر (نیاز به API Token)
public async Task GetUserProfileAsync()
{
var url = $“{_baseUrl}/users/profile”;
var response = await _httpClient.PostAsync(url, null);
response.EnsureSuccessStatusCode();
var content = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject(content);
}
// ثبت سفارش خرید/فروش
public async Task PlaceOrderAsync(
string type,
string srcCurrency,
string dstCurrency,
decimal amount,
decimal price,
string orderType = “limit”)
{
var url = $“{_baseUrl}/market/orders/add”;
var orderData = new
{
type = type, // “buy” or “sell”
srcCurrency = srcCurrency,
dstCurrency = dstCurrency,
amount = amount.ToString(),
price = price.ToString(),
execution = orderType
};
var json = JsonConvert.SerializeObject(orderData);
var content = new StringContent(json,
System.Text.Encoding.UTF8, “application/json”);
var response = await _httpClient.PostAsync(url, content);
response.EnsureSuccessStatusCode();
var responseContent = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject(responseContent);
}
}
// Program.cs
var apiToken = “YOUR_API_TOKEN_HERE”;
var service = new NobitexService(apiToken);
// دریافت قیمت لحظهای بیتکوین
var stats = await service.GetMarketStatsAsync(“btc”, “rls”);
if (stats?.Status == “ok”)
{
Console.WriteLine($“آخرین قیمت BTC: {stats.Stats[“btc-rls”].Last} ریال”);
Console.WriteLine($“بهترین قیمت خرید: {stats.Stats[“btc-rls”].Bestbid}”);
Console.WriteLine($“بهترین قیمت فروش: {stats.Stats[“btc-rls”].Bestask}”);
}
والکس هم یکی دیگه از صرافیهای معتبر ایرانیه که API RESTful داره. ساختار احراز هویتش کمی با نوبیتکس فرق داره:
public class WallexService
{
private readonly HttpClient _httpClient;
private readonly string _baseUrl = “https://api.wallex.ir/v1”;
public WallexService(string apiKey)
{
_httpClient = new HttpClient();
// والکس از x-api-key header استفاده میکند
_httpClient.DefaultRequestHeaders.Add(“x-api-key”, apiKey);
}
public async Task GetMarketsAsync()
{
var response = await _httpClient.GetAsync($“{_baseUrl}/markets”);
return await response.Content.ReadAsStringAsync();
}
public async Task GetOrderBookAsync(string symbol)
{
var response = await _httpClient.GetAsync(
$“{_baseUrl}/depth?symbol={symbol}”);
return await response.Content.ReadAsStringAsync();
}
}
برای پروژههای ASP.NET Core، بهترین روش استفاده از IHttpClientFactory هست تا از مشکلات Socket Exhaustion جلوگیری بشه:
// Program.cs یا Startup.cs
builder.Services.AddHttpClient(“NobitexClient”, client =>
{
client.BaseAddress = new Uri(“https://api.nobitex.ir”);
client.DefaultRequestHeaders.Add(
“Authorization”,
$“Token {configuration[“NobitexApiToken”]}”
);
client.Timeout = TimeSpan.FromSeconds(30);
});
// ثبت سرویس
builder.Services.AddScoped();
// در سرویس
public class NobitexService : INobitexService
{
private readonly HttpClient _httpClient;
public NobitexService(IHttpClientFactory factory)
{
_httpClient = factory.CreateClient(“NobitexClient”);
}
// …
}
API صرافیهای ایرانی گاهی دچار Rate Limit یا قطعی موقت میشن. کتابخانه Polly برای مدیریت Retry و Circuit Breaker عالیه:
dotnet add package Microsoft.Extensions.Http.Polly
// تنظیم Retry Policy
builder.Services.AddHttpClient(“NobitexClient”, client =>
{
client.BaseAddress = new Uri(“https://api.nobitex.ir”);
})
.AddTransientHttpErrorPolicy(policy =>
policy.WaitAndRetryAsync(
retryCount: 3,
sleepDurationProvider: attempt =>
TimeSpan.FromSeconds(Math.Pow(2, attempt)), // 2s, 4s, 8s
onRetry: (outcome, timespan, retryAttempt, context) =>
{
Console.WriteLine($“تلاش مجدد {retryAttempt} پس از {timespan.TotalSeconds}s”);
}
)
)
.AddCircuitBreakerPolicy(policy =>
policy.CircuitBreakerAsync(
handledEventsAllowedBeforeBreaking: 5,
durationOfBreak: TimeSpan.FromSeconds(30)
)
);
یکی از اشتباهات رایج اینه که API Key رو مستقیم توی کد مینویسن. این کار را هرگز نکنید! روشهای امن عبارتند از:
dotnet user-secrets set “NobitexApiToken” “your_token”// خواندن از Configuration در داتنت var token = builder.Configuration[“ExchangeApi:NobitexToken”]; // یا با استفاده از Options Pattern builder.Services.Configure( builder.Configuration.GetSection(“ExchangeApi”)); public class ExchangeApiOptions { public string NobitexToken { get; set; } public string WallexApiKey { get; set; } public int TimeoutSeconds { get; set; } = 30; }
صرافیهای ایرانی Rate Limit دارند. برای جلوگیری از بلاک شدن IP، باید قیمتها رو Cache کنی:
public class CachedNobitexService : INobitexService
{
private readonly NobitexService _nobitexService;
private readonly IMemoryCache _cache;
private readonly TimeSpan _cacheDuration = TimeSpan.FromSeconds(10);
public CachedNobitexService(
NobitexService nobitexService,
IMemoryCache cache)
{
_nobitexService = nobitexService;
_cache = cache;
}
public async Task GetMarketStatsAsync(
string srcCurrency, string dstCurrency)
{
var cacheKey = $“market_stats_{srcCurrency}_{dstCurrency}”;
if (_cache.TryGetValue(cacheKey, out MarketStatsResponse cached))
return cached;
var result = await _nobitexService
.GetMarketStatsAsync(srcCurrency, dstCurrency);
_cache.Set(cacheKey, result, _cacheDuration);
return result;
}
}
اگه نیاز به قیمتهای Real-Time داری، بعضی صرافیهای ایرانی WebSocket API هم دارن. با کلاس ClientWebSocket داتنت میشه بهشون متصل شد:
using System.Net.WebSockets;
using System.Text;
public class RealtimePriceService
{
public async Task ConnectAndListenAsync(string wsUrl,
CancellationToken cancellationToken)
{
using var ws = new ClientWebSocket();
await ws.ConnectAsync(new Uri(wsUrl), cancellationToken);
Console.WriteLine(“اتصال WebSocket برقرار شد”);
var buffer = new byte[4096];
while (ws.State == WebSocketState.Open)
{
var result = await ws.ReceiveAsync(
new ArraySegment(buffer), cancellationToken);
if (result.MessageType == WebSocketMessageType.Text)
{
var message = Encoding.UTF8.GetString(
buffer, 0, result.Count);
Console.WriteLine($“پیام دریافتی: {message}”);
// پردازش قیمت لحظهای اینجا
}
}
}
}
آیا میخواهید سایت شما هم مثل رقبا در صفحه اول گوگل باشد و زنگخورهایتان چند برابر شود؟ سئوی سایت خود را به متخصصان ما بسپارید.
همین حالا برای مشاوره رایگان با ما تماس بگیرید:
📞 09190994063 - 09376846692
یک توسعهدهنده حرفهای بدون Unit Test کد نمیزنه. با xUnit و Moq میشه سرویسهای API رو تست کرد:
dotnet add package xunit dotnet add package Moq dotnet add package RichardSzalay.MockHttp
public class NobitexServiceTests
{
[Fact]
public async Task GetMarketStats_ShouldReturnValidData()
{
// Arrange
var mockHttp = new MockHttpMessageHandler();
mockHttp.When(“https://api.nobitex.ir/market/stats*”)
.Respond(“application/json”,
@“{”“status”“:”“ok”“,”“stats”“:{”“btc-rls”“:{”“last”“:”“3000000000"”}}}");
var client = new HttpClient(mockHttp);
var service = new NobitexService(client, “fake_token”);
// Act
var result = await service.GetMarketStatsAsync(“btc”, “rls”);
// Assert
Assert.Equal(“ok”, result.Status);
Assert.NotNull(result.Stats[“btc-rls”]);
}
}
قبل از ثبت هر سفارش واقعی، حتماً با حساب دمو یا مبالغ خیلی کوچک تست کن. یک باگ ساده در لاجیک ترید میتونه ضرر جدی بزنه!
رقبای شما الان دارن از سئو سود میبرن. هر روز تاخیر، یعنی از دست دادن مشتریان بیشتر. تیم متخصص ما با استراتژیهای اثباتشده، سایت شما رو به قله نتایج گوگل میرسونه.
📞 مشاوره رایگان: 09190994063 - 09376846692
تشکر فراوان بابت این راهنمای جامع. بخش مدیریت خطاها و Polly واقعاً کاربردی بود. آیا برای مدیریت Signature در API هایی که نیاز به آن دارند، کتابخانه خاصی پیشنهاد میکنید یا باید خودمان پیادهسازی کنیم؟
خواهش میکنم، خوشحالیم که مقاله مفید بوده. برای مدیریت Signature در APIها (مثلاً HMAC-SHA256) معمولاً نیازی به کتابخانه خاصی نیست و با استفاده از کلاسهای بومی داتنت مثل System.Security.Cryptography میتوانید Signature را خودتان پیادهسازی کنید. اکثر صرافیها نحوه ساخت Signature را در مستندات خود به وضوح توضیح میدهند. اگر در پیادهسازی نیاز به کمک داشتید، میتوانید با ما تماس بگیرید. 📞 09190994063 - 09376846692
خیلی ممنونم از توضیحات خوبتون. قسمت Caching با IMemoryCache بسیار بهینه و کاربردی بود. فقط میخواستم بپرسم برای پروژههای بزرگتر و توزیعشده، آیا Distributed Cache (مثل Redis) گزینه بهتری است؟
از اینکه مقاله برای شما مفید بوده خوشحالیم. بله، قطعاً برای پروژههای بزرگتر و توزیعشده که نیاز به اشتراکگذاری کش بین چندین سرویس یا سرور دارید، استفاده از Distributed Cache مانند Redis، Memcached یا Azure Cache for Redis گزینه بهتری است. IMemoryCache برای استفاده در یک Single Process مناسب است. برای پیادهسازی و مشاوره در پروژههای بزرگ، با ما تماس بگیرید. 📞 09190994063 - 09376846692
واقعاً لذت بردم از این مقاله. چقدر عالی و مفید! اگر بخواهیم یک UI برای این سرویسها بسازیم، Blazor WebAssembly توصیه میشود یا Blazor Server؟
از اینکه مقاله مورد توجه شما قرار گرفته، بسیار خوشحالیم. انتخاب بین Blazor WebAssembly و Blazor Server بستگی به نیازهای پروژه شما دارد. Blazor Server برای سناریوهایی که نیاز به اتصال Real-time و سریع به بکاند دارید، مناسب است و حجم فایلهای دانلودی اولیه کمتر است. Blazor WebAssembly استقلال بیشتری از سرور دارد و میتواند بدون نیاز به اتصال دائمی به سرور، کار کند، اما زمان بارگذاری اولیه ممکن است کمی بیشتر باشد. برای بحث و تصمیمگیری دقیقتر، با ما تماس بگیرید. 📞 09190994063 - 09376846692
بسیار مطلب کاربردی و کاملی بود، دستتون درد نکنه. در مورد بخش 'بیزینس شما لایق رتبه اول گوگل است'، آیا خدمات SEO خودتون رو هم برای همین پروژههای رمزارز ارائه میدید؟
از اینکه مقاله مورد رضایت شما بوده، سپاسگزاریم. بله، تیم متخصص ما خدمات جامع سئو (SEO) را برای انواع کسبوکارها، از جمله پروژههای مرتبط با رمزارز و بلاکچین، ارائه میدهد. ما میتوانیم به سایت شما کمک کنیم تا در نتایج جستجوی گوگل رتبه بالاتری کسب کنید و مشتریان بیشتری جذب کنید. برای مشاوره رایگان و اطلاع از خدمات سئو، همین حالا با ما تماس بگیرید. 📞 09190994063 - 09376846692
مقاله خیلی کامل و جامع بود. بخش تستنویسی هم عالی بود. آیا برای مدیریت دسترسیها و Role-based access control در رباتهای ترید هم پیشنهادی دارید؟
خوشحالیم که مقاله مورد پسند شما واقع شده است. برای مدیریت دسترسیها در رباتهای ترید، ابتدا باید Principle of Least Privilege را رعایت کنید؛ یعنی به API Key فقط حداقل دسترسیهای لازم را بدهید. برای مدیریت Role-based access در خود ربات، میتوانید یک لایه احراز هویت و مجوزدهی (مثلاً با استفاده از JWT یا OAuth) برای کاربران ربات پیادهسازی کنید تا هر کاربر فقط به عملکردهای مجاز خود دسترسی داشته باشد. برای راهنمایی دقیقتر، با ما در تماس باشید. 📞 09190994063 - 09376846692
توضیحات بسیار شفاف و گامبهگام بود. برای کسی که تازه با داتنت و APIهای صرافی آشنا میشود، یک راهنمای کامل است. ممنون از زحمات شما. آیا توصیه خاصی برای استقرار (Deployment) ربات ترید روی سرورهای لینوکس دارید؟
از بازخورد مثبت شما متشکریم. برای استقرار ربات ترید بر روی سرورهای لینوکس، میتوانید از Docker استفاده کنید تا محیط برنامه شما ایزوله و قابل حمل باشد. همچنین میتوانید برنامه را به صورت Self-contained منتشر کرده و با یک سرویس مدیر (مانند systemd) در پسزمینه اجرا کنید. استفاده از ابزارهای مانیتورینگ برای پیگیری عملکرد ربات هم حیاتی است. برای اطلاعات بیشتر در مورد استقرار، با ما تماس بگیرید. 📞 09190994063 - 09376846692
مقاله شما بسیار آموزنده بود، ممنونم. من با خطای ۴۰۱ در نوبیتکس مواجه شدم، با اینکه API Key رو درست کپی کردم. آیا ممکنه مشکل از دسترسیهای کلید باشه؟
از بازخورد شما متشکریم. بله، احتمالاً مشکل از دسترسیهای API Key است. هنگام ساخت کلید در نوبیتکس، حتماً تمام دسترسیهای مورد نیاز (خواندن قیمت، مشاهده موجودی، ثبت سفارش و...) را فعال کردهاید؟ بعضی endpointها نیاز به دسترسیهای خاصی دارند. توصیه میشود یک کلید جدید با تمام دسترسیها ایجاد کرده و دوباره تست کنید. برای بررسی دقیقتر، با ما تماس بگیرید. 📞 09190994063 - 09376846692
ممنون از مقاله عالی و کاربردی شما. خیلی مفید بود! فقط یک سوال داشتم، آیا برای صرافی بیتپین (Bitpin) هم مثال مشابهی دارید؟ مستنداتشون کمی متفاوت به نظر میرسه.
خوشحالیم که مقاله براتون مفید بوده. بله، اصول اتصال به API بیتپین هم مشابه نوبیتکس و والکس است، اما باید مستندات API خود بیتپین را برای جزئیات endpointها و ساختار request/response بررسی کنید. اگر نیاز به راهنمایی بیشتری دارید، میتوانید با ما تماس بگیرید. 📞 09190994063 - 09376846692
بخش نکات امنیتی و User Secrets و Environment Variables خیلی مهم بود. ممنون از یادآوری. برای لاگگیری امن API Key آیا راهی برای Mask کردن آن در لاگها هست؟
خواهش میکنم، امنیت در کار با API Key بسیار حیاتی است. برای Mask کردن API Key در لاگها، میتوانید یک middleware یا یک Formatter اختصاصی برای لاگگیر خود (مانند Serilog یا NLog) بنویسید که قبل از ذخیره لاگ، مقادیر حساس (مثل 'Authorization' header یا 'apiToken' در بدنه درخواست) را با ستاره () جایگزین کند. این روش تضمین میکند که اطلاعات حساس در فایلهای لاگ شما ذخیره نشود. برای راهنمایی بیشتر، با ما تماس بگیرید. 📞 09190994063 - 09376846692
بسیار خوب توضیح داده شده بود. مخصوصاً بخش IHttpClientFactory و Polly خیلی کمککننده بود. یک سوال: آیا راهکاری برای دریافت اطلاعات تاریخی قیمتها به جز فراخوانی مکرر GetMarketStatsAsync وجود دارد؟
ممنون از بازخورد شما. برای اطلاعات تاریخی قیمتها، برخی صرافیها endpointهای خاصی برای 'Historical Data' یا 'Candlestick Data' دارند که باید در مستندات API آنها جستجو کنید. اگر صرافی مورد نظر شما چنین قابلیتی را ارائه نمیدهد، باید به صورت دورهای دادهها را ذخیره کرده و خودتان تاریخچه بسازید. برای مشاوره بیشتر در این زمینه، با ما تماس بگیرید. 📞 09190994063 - 09376846692
مقاله بینظیری بود! خیلی به دردم خورد. در مورد WebSocket، آیا صرافیهای ایرانی مثل نوبیتکس یا والکس مستندات مشخصی برای WebSocket API دارند؟ من نتونستم پیدا کنم.
از لطف شما سپاسگزاریم. بله، برخی از صرافیهای ایرانی مانند نوبیتکس و والکس دارای WebSocket API هستند، اما ممکن است مستندات آنها به اندازه REST API کامل نباشد یا در بخشهای خاصی از سایتشان قرار گرفته باشد. معمولاً باید به دنبال بخش 'Real-time Data' یا 'Market Feed' در مستنداتشان باشید. اگر در پیدا کردن آنها مشکل دارید، با ما تماس بگیرید تا راهنماییتان کنیم. 📞 09190994063 - 09376846692