use crate::{
SDKResult,
api::{ApiRequest, RequestData},
config::Config,
constants::{APPLY_APP_TICKET_PATH, AccessTokenType, ERR_CODE_APP_TICKET_INVALID},
req_option::RequestOption,
};
pub(crate) async fn recover_app_ticket_if_needed(
is_success: bool,
code: i32,
config: &Config,
) -> SDKResult<()> {
if !is_success && code == ERR_CODE_APP_TICKET_INVALID {
resend_app_ticket(config).await?;
}
Ok(())
}
pub(crate) async fn resend_app_ticket(config: &Config) -> SDKResult<()> {
let url = format!("{}{}", config.base_url(), APPLY_APP_TICKET_PATH);
let body = serde_json::json!({
"app_id": config.app_id(),
"app_secret": config.app_secret(),
});
let mut req = ApiRequest::<()>::post(url).body(RequestData::Json(body));
let req_builder = crate::request_execution::UnifiedRequestBuilder::build(
&mut req,
AccessTokenType::None,
config,
&RequestOption::default(),
)
.await?;
let _ = req_builder.body(req.to_bytes()).send().await?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use crate::constants::APPLY_APP_TICKET_PATH;
use wiremock::matchers::{body_json, method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};
fn cfg(base_url: &str, app_id: &str, app_secret: &str) -> Config {
Config::builder()
.app_id(app_id)
.app_secret(app_secret)
.base_url(base_url)
.enable_token_cache(false)
.build()
}
#[tokio::test]
async fn recover_noop_on_success() {
let config = cfg("http://unreachable.invalid", "id", "sec");
assert!(
recover_app_ticket_if_needed(true, ERR_CODE_APP_TICKET_INVALID, &config)
.await
.is_ok()
);
}
#[tokio::test]
async fn recover_noop_on_unrelated_error_code() {
let config = cfg("http://unreachable.invalid", "id", "sec");
assert!(
recover_app_ticket_if_needed(false, 99999, &config)
.await
.is_ok()
);
}
#[tokio::test]
async fn recover_triggers_resend_on_app_ticket_invalid() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path(APPLY_APP_TICKET_PATH))
.and(body_json(
serde_json::json!({"app_id":"id","app_secret":"sec"}),
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({"code":0})))
.expect(1)
.mount(&server)
.await;
let config = cfg(&server.uri(), "id", "sec");
recover_app_ticket_if_needed(false, ERR_CODE_APP_TICKET_INVALID, &config)
.await
.expect("resend should succeed");
}
}