use serde::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Error)]
#[error("Wechat API response error: errcode {errcode}, errmsg {errmsg}")]
pub struct CommonError {
pub errcode: i32,
pub errmsg: String,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
#[serde(untagged)]
pub enum CommonResponse<T> {
Ok(T),
Err(CommonError),
}
#[derive(Error, Debug)]
pub enum SdkError {
#[error("reqwest Error")]
ReqwestError(#[from] reqwest::Error),
#[error("wx received event parse error")]
XmlParseError(#[from] roxmltree::Error),
#[error("get access token error")]
AccessTokenError(CommonError),
#[error(transparent)]
WxApiError(#[from] CommonError),
#[error(transparent)]
UrlParseError(#[from] url::ParseError),
#[error("api request params error: {0}")]
InvalidParams(String),
#[error("parse received encrypt msg error: wrong signature")]
InvalidSignature,
#[error("parse received encrypt msg error: invalid appid")]
InvalidAppid,
#[error("decrypt msg error: {0}")]
MsgDecryptError(String),
#[error("encrypt msg error: {0}")]
MsgEncryptError(String),
#[error("Exile write xml error")]
XmlWriteError(#[from] exile::error::Error),
}
pub type SdkResult<T> = std::result::Result<T, SdkError>;
impl From<CommonError> for SdkResult<()> {
fn from(e: CommonError) -> Self {
if e.errcode == 0 {
Ok(())
} else {
Err(SdkError::WxApiError(e))
}
}
}
impl<T> From<CommonResponse<T>> for SdkResult<T> {
fn from(r: CommonResponse<T>) -> Self {
match r {
CommonResponse::Ok(t) => Ok(t),
CommonResponse::Err(e) => Err(SdkError::WxApiError(e)),
}
}
}
impl From<CommonResponse<CommonError>> for SdkResult<()> {
fn from(r: CommonResponse<CommonError>) -> Self {
match r {
CommonResponse::Ok(e) => {
if e.errcode == 0 {
Ok(())
} else {
Err(SdkError::WxApiError(e))
}
}
CommonResponse::Err(e) => {
if e.errcode == 0 {
Ok(())
} else {
Err(SdkError::WxApiError(e))
}
}
}
}
}
#[test]
fn test_error_from() {
let input = r#"{"errcode": 0,"errmsg":"success"}"#;
let expected = CommonResponse::Ok(CommonError {
errcode: 0,
errmsg: "success".to_string(),
});
assert_eq!(expected.clone(), serde_json::from_str(input).unwrap());
let into: SdkResult<()> = expected.clone().into();
assert!(into.is_ok());
let input = r#"{"errcode":40013,"errmsg":"invalid appid"}"#;
let expected = CommonResponse::Ok(CommonError {
errcode: 40013,
errmsg: "invalid appid".to_string(),
});
assert_eq!(expected.clone(), serde_json::from_str(input).unwrap());
let into: SdkResult<()> = expected.clone().into();
assert!(into.is_err());
}
#[test]
fn test_data_and_error() {
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct Data {
pub aid: String,
pub session_key: String,
}
let input = r#"{ "aid": "ssss", "session_key": "dddddd", "errcode": 22,"errmsg":"errrrr"}"#;
let expected_data = &CommonResponse::<Data>::Ok(Data {
aid: "ssss".to_string(),
session_key: "dddddd".to_string(),
});
assert_eq!(expected_data, &serde_json::from_str(input).unwrap());
}