اگر یک فروشگاه آنلاین دارید یا یک سیستم مدیریت سفارش میسازید، احتمالاً با این مشکل آشنا هستید: چطور میتوانیم به صورت خودکار مرسولههای پستی را ثبت و پیگیری کنیم؟ پاسخ این سوال، استفاده از API رسمی پست جمهوری اسلامی ایران است.
پست ایران یک وبسرویس (Web Service) رسمی دارد که به توسعهدهندگان اجازه میدهد سیستمهای نرمافزاری خود را مستقیماً به سامانه پستی متصل کنند. شما با استفاده از این API میتوانید:
در این مقاله قدمبهقدم یاد میگیرید چطور با C# و ASP.NET به این API وصل شوید، کدهای آماده دریافت کنید و رایجترین خطاها را رفع کنید.
قبل از نوشتن حتی یک خط کد، باید چند چیز را آماده کنید. این مرحله را جدی بگیرید چون بسیاری از توسعهدهندگان به دلیل رد شدن همین مرحله ساعتها وقت تلف میکنند.
برای استفاده از وبسرویس پست ایران، باید از طریق سامانه رسمی پست ثبتنام کنید و Credentials دریافت کنید. این اطلاعات شامل:
API پست ایران از پروتکل SOAP (Simple Object Access Protocol) و همچنین در نسخههای جدیدتر از REST پشتیبانی میکند. برای پروژههای داتنتی، کار با هر دو رویکرد امکانپذیر است، اما SOAP به دلیل WSDL ساختارمند، خطاهای کمتری در پیادهسازی ایجاد میکند.
حالا وارد بخش اصلی میشویم. در ادامه کدهای کامل و تستشده برای اتصال به سرویس پستی با دات نت را میبینید.
اگر از رویکرد SOAP استفاده میکنید، باید ابتدا WSDL پست ایران را به پروژه اضافه کنید:
// در Visual Studio:
// راستکلیک روی پروژه > Add > Service Reference
// آدرس WSDL پست ایران را وارد کنید
// نام فضای نام: IranPostService
// Models/PostParcelModel.cs
public class PostParcelRequest
{
public string SenderName { get; set; }
public string SenderAddress { get; set; }
public string SenderPostCode { get; set; }
public string SenderTel { get; set; }
public string ReceiverName { get; set; }
public string ReceiverAddress { get; set; }
public string ReceiverPostCode { get; set; }
public string ReceiverTel { get; set; }
public decimal Weight { get; set; } // وزن به گرم
public string ServiceType { get; set; } // نوع سرویس: پیشتاز، ویژه، …
public decimal CODAmount { get; set; } // مبلغ پرداخت در مقصد
public string Description { get; set; }
}
public class PostParcelResponse
{
public bool IsSuccess { get; set; }
public string Barcode { get; set; }
public string TrackingCode { get; set; }
public string ErrorMessage { get; set; }
public decimal PostPrice { get; set; }
}
// Services/IranPostService.cs
using System.Net.Http;
using System.Text;
using System.Text.Json;
public class IranPostApiService
{
private readonly HttpClient _httpClient;
private readonly string _username;
private readonly string _password;
private readonly string _baseUrl = “https://www.post.ir/api/”;
public IranPostApiService(HttpClient httpClient, IConfiguration config)
{
_httpClient = httpClient;
_username = config[“IranPost:Username”];
_password = config[“IranPost:Password”];
}
// متد احراز هویت و دریافت Token
public async Task GetAuthTokenAsync()
{
var authData = new
{
username = _username,
password = _password
};
var content = new StringContent(
JsonSerializer.Serialize(authData),
Encoding.UTF8,
“application/json”
);
var response = await _httpClient.PostAsync($“{_baseUrl}auth/token”, content);
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsStringAsync();
var tokenData = JsonSerializer.Deserialize(result);
return tokenData?.Token;
}
throw new Exception($“خطا در احراز هویت: {response.StatusCode}”);
}
// متد ثبت مرسوله
public async Task AddParcelAsync(PostParcelRequest request)
{
try
{
var token = await GetAuthTokenAsync();
_httpClient.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue(“Bearer”, token);
var content = new StringContent(
JsonSerializer.Serialize(request),
Encoding.UTF8,
“application/json”
);
var response = await _httpClient.PostAsync($“{_baseUrl}parcel/add”, content);
var responseBody = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var result = JsonSerializer.Deserialize(responseBody);
result.IsSuccess = true;
return result;
}
return new PostParcelResponse
{
IsSuccess = false,
ErrorMessage = $“کد خطا: {response.StatusCode} - {responseBody}”
};
}
catch (Exception ex)
{
return new PostParcelResponse
{
IsSuccess = false,
ErrorMessage = $“خطای سیستمی: {ex.Message}”
};
}
}
// متد پیگیری مرسوله
public async Task TrackParcelAsync(string barcode)
{
var token = await GetAuthTokenAsync();
_httpClient.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue(“Bearer”, token);
var response = await _httpClient
.GetAsync($“{_baseUrl}parcel/track/{barcode}”);
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize(result);
}
throw new Exception($“مرسوله با بارکد {barcode} یافت نشد.”);
}
// متد محاسبه هزینه ارسال
public async Task CalculatePostPriceAsync(
string originPostCode,
string destPostCode,
decimal weightInGrams,
string serviceType)
{
var token = await GetAuthTokenAsync();
_httpClient.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue(“Bearer”, token);
var queryString = $“origin={originPostCode}&dest={destPostCode}” +
$“&weight={weightInGrams}&service={serviceType}”;
var response = await _httpClient
.GetAsync($“{_baseUrl}price/calculate?{queryString}”);
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsStringAsync();
var priceData = JsonSerializer.Deserialize(result);
return priceData?.Price ?? 0;
}
throw new Exception(“خطا در محاسبه هزینه ارسال”);
}
}
{
“IranPost”: {
“Username”: “your_username_here”,
“Password”: “your_password_here”,
“ServiceCode”: “your_service_code”,
“BaseUrl”: “https://www.post.ir/api/”
}
}
// Program.cs (.NET 6+)
builder.Services.AddHttpClient(client =>
{
client.BaseAddress = new Uri(builder.Configuration[“IranPost:BaseUrl”]);
client.Timeout = TimeSpan.FromSeconds(30);
client.DefaultRequestHeaders.Add(“Accept”, “application/json”);
});
// یا با Policy (توصیه شده برای Production)
builder.Services.AddHttpClient()
.AddTransientHttpErrorPolicy(p =>
p.WaitAndRetryAsync(3, _ => TimeSpan.FromMilliseconds(600)));
// Controllers/ShippingController.cs
[ApiController]
[Route(“api/[controller]”)]
public class ShippingController : ControllerBase
{
private readonly IranPostApiService _postService;
private readonly ILogger _logger;
public ShippingController(
IranPostApiService postService,
ILogger logger)
{
_postService = postService;
_logger = logger;
}
[HttpPost(“register”)]
public async Task RegisterParcel([FromBody] PostParcelRequest model)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
var result = await _postService.AddParcelAsync(model);
if (result.IsSuccess)
{
_logger.LogInformation(
“مرسوله با بارکد {Barcode} ثبت شد”, result.Barcode);
return Ok(result);
}
_logger.LogError(“خطا در ثبت مرسوله: {Error}”, result.ErrorMessage);
return BadRequest(result.ErrorMessage);
}
[HttpGet(“track/{barcode}”)]
public async Task TrackParcel(string barcode)
{
if (string.IsNullOrWhiteSpace(barcode))
return BadRequest(“بارکد نمیتواند خالی باشد”);
var status = await _postService.TrackParcelAsync(barcode);
return Ok(status);
}
[HttpGet(“price”)]
public async Task GetPostPrice(
[FromQuery] string origin,
[FromQuery] string dest,
[FromQuery] decimal weight,
[FromQuery] string service = “normal”)
{
var price = await _postService
.CalculatePostPriceAsync(origin, dest, weight, service);
return Ok(new { Price = price, Currency = “ریال” });
}
}
بر اساس تجربه توسعهدهندگان ایرانی، این خطاها بیشترین تکرار را دارند:
علت: نام کاربری یا رمز عبور اشتباه است یا Token منقضی شده.
راهحل: مطمئن شوید Credentials را درست از پنل پست دریافت کردهاید. Token را قبل از هر درخواست تجدید کنید.
علت: کدپستی وارد شده معتبر نیست یا فرمت آن اشتباه است.
راهحل: کدپستی باید دقیقاً ۱۰ رقم باشد. از متد ValidatePostCode برای اعتبارسنجی قبل از ارسال استفاده کنید.
علت: سرورهای پست ایران گاهی کند پاسخ میدهند.
راهحل: از Retry Policy استفاده کنید (نمونه کد در Program.cs بالا) و Timeout را به ۴۵ ثانیه تنظیم کنید.
// فقط در محیط Development - هرگز در Production استفاده نکنید!
builder.Services.AddHttpClient()
.ConfigurePrimaryHttpMessageHandler(() =>
new HttpClientHandler
{
ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
});
پیادهسازی API پست ایران فقط یک قدم از راهاندازی یک فروشگاه موفق است. اما بدون سئوی حرفهای، هیچکس سایت شما را پیدا نمیکند و این تلاشها به هدر میرود.
آیا میخواهید سایت شما هم مثل رقبا در صفحه اول گوگل باشد و زنگخورهایتان چند برابر شود؟ سئوی سایت خود را به متخصصان ما بسپارید.
📞 همین حالا برای مشاوره رایگان با ما تماس بگیرید:
09190994063 | 09376846692
برخی سیستمهای قدیمیتر هنوز از پروتکل SOAP استفاده میکنند. برای دات نت، کار با SOAP هم بسیار ساده است:
// استفاده از Connected Service / WSDL
// بعد از اضافه کردن Service Reference، کد به این شکل میشود:
using IranPostService; // namespace ایجاد شده توسط Visual Studio
public class SoapPostService
{
public async Task AddParcelViaSoapAsync(PostParcelRequest request)
{
var client = new PostWebServiceClient(
PostWebServiceClient.EndpointConfiguration.PostWebServiceSoap
);
var soapRequest = new AddParcelRequest
{
Username = “your_username”,
Password = “your_password”,
ReceiverName = request.ReceiverName,
ReceiverAddress = request.ReceiverAddress,
ReceiverPostCode = request.ReceiverPostCode,
Weight = (int)request.Weight,
ServiceType = request.ServiceType
};
var response = await client.AddParcelAsync(soapRequest);
if (response.ResultCode == “0”)
return response.Barcode;
throw new Exception($“خطای پست: {response.ResultDescription}”);
}
}
public class IranPostApiService
{
private readonly IMemoryCache _cache;
private const string TOKEN_CACHE_KEY = “IranPost_AuthToken”;
public IranPostApiService(HttpClient httpClient,
IConfiguration config, IMemoryCache cache)
{
_httpClient = httpClient;
_cache = cache;
// …
}
public async Task GetAuthTokenWithCacheAsync()
{
if (_cache.TryGetValue(TOKEN_CACHE_KEY, out string cachedToken))
return cachedToken;
var freshToken = await GetAuthTokenAsync();
// توکن را برای ۲۳ ساعت Cache کنید (معمولاً توکنها ۲۴ ساعت اعتبار دارند)
_cache.Set(TOKEN_CACHE_KEY, freshToken, TimeSpan.FromHours(23));
return freshToken;
}
}
اگر فروشگاه اینترنتی دارید و میخواهید ارسال پست را کاملاً اتوماتیک کنید، علاوه بر پیادهسازی API، باید سایت شما در گوگل دیده شود تا اصلاً سفارشی وجود داشته باشد! سئوی سایت شما مستقیماً روی تعداد سفارشهایتان تأثیر میگذارد. برای مشاوره رایگان با شمارههای 09190994063 یا 09376846692 تماس بگیرید.
// Tests/IranPostServiceTests.cs
using Moq;
using Xunit;
public class IranPostServiceTests
{
[Fact]
public async Task AddParcel_WithValidData_ShouldReturnBarcode()
{
// Arrange
var mockHttpClient = new Mock();
// … تنظیم Mock
var service = new IranPostApiService(mockHttpClient.Object,
mockConfig.Object, mockCache.Object);
var request = new PostParcelRequest
{
SenderName = “علی محمدی”,
SenderPostCode = “1234567890”,
ReceiverName = “رضا احمدی”,
ReceiverPostCode = “9876543210”,
Weight = 500
};
// Act
var result = await service.AddParcelAsync(request);
// Assert
Assert.True(result.IsSuccess);
Assert.NotNull(result.Barcode);
}
}
اتصال به API پست ایران با دات نت با رعایت ساختار صحیح، کاری نسبتاً ساده است. در این مقاله یاد گرفتیم:
استفاده از API پست ایران نیازمند عقد قرارداد با اداره پست است. برای مشتریان عمده و فروشگاههای اینترنتی، پست ایران امکان دسترسی به وبسرویس را فراهم میکند. هزینهها بسته به حجم ارسال و نوع قرارداد متفاوت است. برای اطلاعات دقیقتر با اداره پست منطقه خود تماس بگیرید.
بله، کاملاً امکانپذیر است. کدهای نشان داده شده در این مقاله با .NET 6، .NET 7 و .NET 8 سازگار هستند. فقط کافی است پکیجهای مربوطه را نصب کنید و از IHttpClientFactory استفاده کنید که در Program.cs توضیح داده شد.
با استفاده از متد TrackParcelAsync که در این مقاله معرفی شد، میتوانید یک صفحه پیگیری مرسوله در سایت خود بسازید. کافی است شماره بارکد مرسوله را از کاربر بگیرید، به API بفرستید و نتیجه را نمایش دهید. این کار با یک Controller Action و یک View ساده در ASP.NET MVC انجام میشود.
پست ایران هر دو پروتکل را پشتیبانی میکند. برای پروژههای جدید با .NET 6 به بالا، REST API توصیه میشود چون سبکتر، سریعتر و debug کردنش آسانتر است. اگر سیستم قدیمی دارید که از SOAP استفاده میکند، میتوانید با Connected Service در Visual Studio به سادگی WSDL را import کنید.
اگر سایت شما وردپرس است، نیاز به دات نت ندارید. اما اگر بکاند جداگانهای با ASP.NET دارید که به وردپرس متصل است، کاملاً میتوانید از این کدها استفاده کنید. همچنین پلاگینهای اختصاصی وردپرس برای پست ایران هم وجود دارند که نیازی به کدنویسی ندارند.
این یک نگرانی رایج است. توصیه میشود از Circuit Breaker Pattern با Polly استفاده کنید. همچنین سفارشهای دریافتی را ابتدا در Database ذخیره کنید و بعد به صورت Background Job به API پست بفرستید. این رویکرد مقاومت سیستم شما در برابر خطاهای خارجی را بسیار بالا میبرد.