راهنمای Spring Boot برای API ارز
اتصال Spring Boot به وبسرویس و API سرویکس
اتصال امن Java و Spring Boot به وبسرویس و API نرخ ارز سرویکس را با RestClient، نگهداری امن API Key، timeout، response تایپشده، کنترل تازگی و retry محدود پیادهسازی و تست کنید.
در این راهنما یک اتصال واقعی و سمت بکاند با Java 21 و Spring Boot برای وبسرویس و API احرازشده داده بازار سرویکس میسازیم. پروژه کامل Maven در مسیر docs/examples/spring-boot قرار دارد و با یک HTTP server محلی و responseهای ساختگی تست میشود.
API Key سرویکس را در secret store سمت سرور نگه دارید. کلید نباید وارد bundle مرورگر، URL، HTML عمومی، analytics، گزارش خطا یا مخزن کد شود. نمونه برای محیط واقعی فقط HTTPS را میپذیرد و HTTP را صرفاً برای تست روی loopback مجاز میداند.
ساخت پروژه Spring Boot
از Java 21 یا نسخه جدیدتر و نسخه فعلی Spring Boot استفاده کنید. spring-boot-starter-web، کلاس RestClient را در اختیار پروژه میگذارد و spring-boot-starter-test برای تست قرارداد محلی به کار میرود:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.0.4</version>
</parent>
<properties>
<java.version>21</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
تنظیم RestClient و اعتبارسنجی response
کد تستشده timeout اتصال و خواندن را جدا تنظیم میکند، X-API-Key را فقط در header میفرستد، response را به recordهای تایپشده تبدیل میکند و داده خراب، stale، missing، unknown یا بدون پوشش را کنار میگذارد.
SimpleClientHttpRequestFactory requestFactory =
new SimpleClientHttpRequestFactory();
requestFactory.setConnectTimeout(Duration.ofSeconds(3));
requestFactory.setReadTimeout(Duration.ofSeconds(10));
RestClient client = RestClient.builder()
.baseUrl(System.getenv().getOrDefault(
"SERVIX_API_BASE_URL", "https://servix.cc"))
.requestFactory(requestFactory)
.defaultHeader(HttpHeaders.ACCEPT, "application/json")
.defaultHeader("X-API-Key", requireApiKey(System.getenv("SERVIX_API_KEY")))
.build();
SupportedAssetsResponse payload = client.get()
.uri("/api/v1/assets/supported")
.retrieve()
.body(SupportedAssetsResponse.class);
SupportedAsset asset = payload.assets().stream()
.filter(candidate -> candidate.code().equals("USD_RLS"))
.findFirst()
.orElseThrow(ServixUnavailableException::new);
if (!Boolean.TRUE.equals(asset.providerSupported())
|| !Boolean.TRUE.equals(asset.latestValueAvailable())) {
throw new ServixUnavailableException();
}
if (Boolean.TRUE.equals(asset.stale())
|| !"FRESH".equals(asset.availabilityStatus())) {
throw new ServixStaleDataException();
}
record SupportedAssetsResponse(List<SupportedAsset> assets) {}
record SupportedAsset(
String code,
String labelEn,
Boolean providerSupported,
Boolean latestValueAvailable,
BigDecimal latestValue,
String businessTime,
String availabilityStatus,
Boolean stale) {}
نسخه کامل base URL، شکل asset code، نوع فیلدهای boolean، عدد بودن مقدار، timezone در businessTime، هماهنگی وضعیت تازگی و request ID امن را هم بررسی میکند. متن خطا هیچوقت body پاسخ، API Key یا مقدار بازار را در خود ندارد.
اجرای نمونه تستشده
export SERVIX_API_KEY="<your-servix-api-key>"
export SERVIX_ASSET_CODE="USD_RLS"
./mvnw -f docs/examples/spring-boot/pom.xml test
./mvnw -f docs/examples/spring-boot/pom.xml spring-boot:run
تستها response موفق، header و timeout، retry خطای شبکه و چند status موقت 5xx، توقف فوری روی 401 و 429، JSON خراب، فیلد ناقص، تازگی ناسازگار، داده stale یا unavailable، تنظیم ناامن و asset code نامعتبر را پوشش میدهند. برنامه فقط کد نماد و زمان منبع را چاپ میکند؛ AssetQuote را در بکاند قابل اعتماد خود مصرف کنید.
قرارداد response احرازشده
در مستندات عمومی بهجای نرخ جاری یا تاریخی بازار از placeholder استفاده میکنیم:
{
"code": "USD_RLS",
"providerSupported": true,
"latestValueAvailable": true,
"latestValue": "<protected-market-value>",
"businessTime": "<source-timestamp>",
"availabilityStatus": "FRESH",
"stale": false
}
businessTimeزمان خود داده است، نه زمان تمام شدن درخواست HTTP.latestValueAvailable=falseیعنی باید وضعیت unavailable نشان دهید؛ صفر جایگزین نکنید.stale=trueیعنی داده از آستانه تازگی سرور قدیمیتر است و نباید تازه نمایش داده شود.- کدهای پایانیافته به
_RLSبر حسب ریال هستند. تبدیل به تومان را فقط در لایه نمایش خودتان انجام دهید و واحد را روشن بنویسید.
رفتار خطا، retry، cache و سهمیه
| وضعیت | رفتار بکاند |
|---|---|
| timeout اتصال یا خواندن | حداکثر سه بار با فاصله نمایی retry کنید و بعد خطای عملیاتی امن بدهید. |
| 400، 401، 403، 404 | ورودی، credential، دسترسی یا کد نماد را اصلاح کنید؛ درخواست بدون تغییر را دوباره نفرستید. |
| 429 | با تمام شدن سهمیه روزانه polling را متوقف کنید و حلقه retry نسازید. |
| 500، 502، 503، 504 | همان retry محدود خطاهای موقت شبکه را اجرا کنید. |
| response خراب یا stale | آن را رد کنید و فقط در صورت اجازه محصول، cache قبلی و معتبر را با وضعیت stale روشن نگه دارید. |
بهجای polling جدا برای هر مرورگر، یک cache احرازشده و مشترک در بکاند داشته باشید. cache را با asset code کلیدگذاری کنید، businessTime را نگه دارید، TTL را کوتاهتر از پنجره تازگی محصول بگذارید و داده قدیمی را تازه نشان ندهید.
ادامه مسیر
احراز هویت با API Key، endpointهای قیمت جاری، نمادهای پشتیبانیشده و خطا و سهمیه را مرور کنید. برای مقایسه، نمونه تستشده Python و نمونه تستشده PHP هم در دسترساند.
ساخت حساب و فعالسازی دسترسی API · مقایسه پلنها و سهمیه روزانه