Skip to main content

futu_backend/
websig_refresh.rs

1use futu_command_spec::{CommandSpecId, WebSigRefreshOperation};
2use futu_core::error::{FutuError, Result};
3use futu_domain_auth::{
4    WebSigRefreshChannelKind, WebSigRefreshDecision, WebSigRefreshReplyFacts,
5    plan_websig_refresh_reply_like_cpp,
6};
7use futu_proto_internal::f3clogin_sig::{GetBrokerWebsigResponse, GetWebsigResponse};
8use prost::Message;
9
10use crate::conn::BackendConn;
11use crate::connection_lifecycle_runtime::execute_connection_lifecycle;
12
13/// Send one C++ CMD1013 transaction with an empty business body.
14pub async fn refresh_platform_websig(conn: &BackendConn) -> Result<WebSigRefreshDecision> {
15    refresh_websig(conn, WebSigRefreshOperation::Platform).await
16}
17
18/// Send one C++ CMD20203 transaction with an empty business body.
19pub async fn refresh_broker_websig(conn: &BackendConn) -> Result<WebSigRefreshDecision> {
20    refresh_websig(conn, WebSigRefreshOperation::Broker).await
21}
22
23async fn refresh_websig(
24    conn: &BackendConn,
25    operation: WebSigRefreshOperation,
26) -> Result<WebSigRefreshDecision> {
27    let response =
28        execute_connection_lifecycle(conn, CommandSpecId::WebSigRefresh(operation), Vec::new())
29            .await?;
30
31    match operation {
32        WebSigRefreshOperation::Platform => {
33            let response = GetWebsigResponse::decode(response.body.as_ref()).map_err(|error| {
34                FutuError::Codec(format!("decode Platform WebSig refresh response: {error}"))
35            })?;
36            Ok(plan_websig_refresh_reply_like_cpp(
37                WebSigRefreshChannelKind::Platform,
38                WebSigRefreshReplyFacts {
39                    ret_code: response.ret_code,
40                    ret_msg: response.ret_msg.as_deref(),
41                    primary_web_sig: response.websig.as_deref(),
42                    secondary_web_sig: response.moomoo_websig.as_deref(),
43                    refresh_ttl_secs: response.refresh_ttl,
44                },
45            ))
46        }
47        WebSigRefreshOperation::Broker => {
48            let response =
49                GetBrokerWebsigResponse::decode(response.body.as_ref()).map_err(|error| {
50                    FutuError::Codec(format!("decode Broker WebSig refresh response: {error}"))
51                })?;
52            Ok(plan_websig_refresh_reply_like_cpp(
53                WebSigRefreshChannelKind::Broker,
54                WebSigRefreshReplyFacts {
55                    ret_code: response.ret_code,
56                    ret_msg: response.ret_msg.as_deref(),
57                    primary_web_sig: response.broker_websig.as_deref(),
58                    secondary_web_sig: None,
59                    refresh_ttl_secs: response.refresh_ttl,
60                },
61            ))
62        }
63    }
64}
65
66#[cfg(test)]
67mod tests;