49 lines
3.3 KiB
C#
49 lines
3.3 KiB
C#
using System.Text.Json;
|
|
|
|
namespace Kbx.Shared.Providers;
|
|
|
|
public sealed class OpenDartAdapter(HttpClient http, IKbxProviderSecretStore secrets) : IKbxExternalProviderAdapter
|
|
{
|
|
private static readonly Uri BaseUri = new("https://opendart.fss.or.kr/api/");
|
|
public string ProviderId => "provider.opendart";
|
|
|
|
public Task<KbxProviderResult<JsonDocument>> GetDisclosuresAsync(IReadOnlyDictionary<string,string?> query, CancellationToken ct)
|
|
=> GetJsonAsync("list.json", query, ct);
|
|
public Task<KbxProviderResult<JsonDocument>> GetCompanyAsync(string corpCode, CancellationToken ct)
|
|
=> GetJsonAsync("company.json", new Dictionary<string,string?> { ["corp_code"] = corpCode }, ct);
|
|
|
|
public async Task<KbxProviderResult<byte[]>> DownloadCorpCodeAsync(CancellationToken ct)
|
|
{
|
|
var key = await secrets.GetRequiredAsync("ExternalProviders:OpenDart:ApiKey", ct);
|
|
var uri = new Uri(BaseUri, $"corpCode.xml?crtfc_key={Uri.EscapeDataString(key)}");
|
|
using var response = await http.GetAsync(uri, ct);
|
|
var bytes = await response.Content.ReadAsByteArrayAsync(ct);
|
|
if (response.IsSuccessStatusCode) return new(KbxProviderResultKind.Success, bytes, HttpStatus:(int)response.StatusCode);
|
|
return new((int)response.StatusCode >= 500 ? KbxProviderResultKind.TransientFailure : KbxProviderResultKind.PermanentFailure, Code:$"HTTP_{(int)response.StatusCode}", Message:"OPENDART 고유번호 파일 호출 실패", HttpStatus:(int)response.StatusCode);
|
|
}
|
|
|
|
private async Task<KbxProviderResult<JsonDocument>> GetJsonAsync(string path, IReadOnlyDictionary<string,string?> query, CancellationToken ct)
|
|
{
|
|
var key = await secrets.GetRequiredAsync("ExternalProviders:OpenDart:ApiKey", ct);
|
|
var pairs = new List<string> { $"crtfc_key={Uri.EscapeDataString(key)}" };
|
|
pairs.AddRange(query.Where(x=>x.Value is not null).Select(x=>$"{Uri.EscapeDataString(x.Key)}={Uri.EscapeDataString(x.Value!)}"));
|
|
var uri = new Uri(BaseUri, path + "?" + string.Join("&", pairs));
|
|
using var response = await http.GetAsync(uri, ct);
|
|
var text = await response.Content.ReadAsStringAsync(ct);
|
|
if (!response.IsSuccessStatusCode)
|
|
return new((int)response.StatusCode >= 500 || (int)response.StatusCode == 429 ? KbxProviderResultKind.TransientFailure : KbxProviderResultKind.PermanentFailure, Code:$"HTTP_{(int)response.StatusCode}", Message:"OPENDART HTTP 호출 실패", HttpStatus:(int)response.StatusCode);
|
|
JsonDocument doc;
|
|
try { doc = JsonDocument.Parse(text); } catch { return new(KbxProviderResultKind.PermanentFailure, Code:"DART_INVALID_JSON", Message:"OPENDART 응답 JSON을 해석할 수 없습니다."); }
|
|
var root = doc.RootElement;
|
|
var status = root.TryGetProperty("status", out var s) ? s.GetString() : null;
|
|
var message = root.TryGetProperty("message", out var m) ? m.GetString() : null;
|
|
return status switch
|
|
{
|
|
"000" or null => new(KbxProviderResultKind.Success, doc),
|
|
"013" => new(KbxProviderResultKind.NoData, doc, status, message),
|
|
"020" or "800" or "900" => new(KbxProviderResultKind.TransientFailure, doc, status, message),
|
|
_ => new(KbxProviderResultKind.PermanentFailure, doc, status, message)
|
|
};
|
|
}
|
|
}
|