algotradelib 0.0.0.9000
C++ header-only library for algorithmic trading
Loading...
Searching...
No Matches
auth.hpp
1#pragma once
2
3#include "./config.hpp"
4#include "./errors.hpp"
5#include "./network.hpp"
6
7#include <mutex>
8#include <stdexcept>
9#include <string>
10
11namespace algotradelib {
12namespace kiwoom {
13
14class KiwoomAuth;
15
22public:
29 KiwoomAuth(net::io_context& ioc, ssl::context& ctx, const KiwoomConfig& config)
30 : ioc_(ioc), ctx_(ctx), req_(config) {}
31
33 virtual ~KiwoomAuth() = default;
34
42 std::string accessToken() {
43 std::lock_guard<std::mutex> lock(mtx_);
44 if (!rest_resp_.valid()) {
45 refresh();
46 }
47 return rest_resp_.access_token_;
48 }
49
50private:
51 net::io_context& ioc_;
52 ssl::context& ctx_;
53 KiwoomConfig req_;
54 KiwoomRest rest_resp_;
55 std::mutex mtx_;
56
57 void refresh() {
58 const std::string jsonbody = req_.to_jsonbody();
59 KiwoomHttpClient rest(ioc_, ctx_, req_.rest_host(), req_.rest_port());
60 auto response = rest.post(
61 "/oauth2/token", jsonbody, {{"Content-Type", "application/json;charset=UTF-8"}}
62 );
63 if (response.result_int() < 200 || response.result_int() >= 300) {
64 throw std::runtime_error(
65 "Token authentication failed with HTTP status " + std::to_string(response.result_int())
66 );
67 }
68 const std::string resp = std::move(response.body());
69 boost::system::error_code ec;
70 const auto jv = json::parse(resp, ec);
71 if (ec || !jv.is_object()) {
72 // Not the body: a token reply that did not parse may still hold the token.
73 throw std::runtime_error(
74 "Kiwoom authentication failed: the reply is not a JSON object (" + std::to_string(resp.size()) + " bytes)"
75 );
76 }
77 // Kiwoom states a business failure in the body of an HTTP 200, so a successful status is not
78 // a successful token. The classification lives in `kiwoom_declared_error` and is shared with
79 // every other endpoint rather than restated here: `8020` (no appkey or secretkey), `8011` and
80 // `8012` (a missing or wrong grant_type) all arrive this way.
81 const auto& doc = jv.as_object();
82 if (const auto declared = kiwoom_declared_error(doc)) {
83 throw std::runtime_error(
84 "Kiwoom authentication failed [" + declared->broker_code_ + "]: " + declared->message_
85 );
86 }
87 rest_resp_.from_json(doc);
88 }
89};
90
91} // namespace kiwoom
92} // namespace algotradelib
Obtains and caches a Kiwoom access token with blocking requests; thread-safe.
Definition auth.hpp:21
KiwoomAuth(net::io_context &ioc, ssl::context &ctx, const KiwoomConfig &config)
Constructs the wrapper.
Definition auth.hpp:29
std::string accessToken()
Returns an access token, requesting a new one if none is held or it expires within five minutes.
Definition auth.hpp:42
virtual ~KiwoomAuth()=default
Destroys the wrapper.
std::string to_jsonbody() const
Builds a JSON token-request body (grant type, key and secret under the broker's field names).
Definition oauth.hpp:75
The Kiwoom Securities REST API client.
Definition auth.hpp:12
std::optional< BrokerError > kiwoom_declared_error(const boost::json::object &document)
Reads the failure a Kiwoom response declares in its body (Kiwoom reports business failures with HTTP ...
Definition errors.hpp:97
network::HttpClient KiwoomHttpClient
The blocking HTTP client KiwoomAuth uses.
Definition network.hpp:9
The library: broker-neutral types (core), and the modules below.
Kiwoom credentials (app key and secret key), demo or real account, the market-data tape,...
Definition config.hpp:154
const char * rest_port() const noexcept
The REST port, which is the same for both environments.
Definition config.hpp:327
const char * rest_host() const noexcept
The REST host for the selected environment.
Definition config.hpp:319
A Kiwoom REST access token (au10001's token) and its expiry (expires_dt).
Definition config.hpp:354