1use serde::{Deserialize, Serialize};
6use thiserror::Error;
7#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Error)]
12#[error("Wechat API response error: errcode {errcode}, errmsg {errmsg}")]
13pub struct CommonError {
14 pub errcode: i32,
15 pub errmsg: String,
16}
17
18#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
20#[serde(untagged)]
21pub enum CommonResponse<T> {
22 Ok(T),
23 Err(CommonError),
24}
25
26#[derive(Error, Debug)]
28pub enum SdkError {
29 #[error("reqwest Error")]
30 ReqwestError(#[from] reqwest::Error),
31
32 #[error("wx received event parse error")]
33 XmlParseError(#[from] roxmltree::Error),
34
35 #[error("get access token error")]
36 AccessTokenError(CommonError),
37
38 #[error(transparent)]
39 WxApiError(#[from] CommonError),
40
41 #[error(transparent)]
42 UrlParseError(#[from] url::ParseError),
43
44 #[error("api request params error: {0}")]
45 InvalidParams(String),
46
47 #[error("parse received encrypt msg error: wrong signature")]
48 InvalidSignature,
49
50 #[error("parse received encrypt msg error: invalid appid")]
51 InvalidAppid,
52
53 #[error("decrypt msg error: {0}")]
54 MsgDecryptError(String),
55
56 #[error("encrypt msg error: {0}")]
57 MsgEncryptError(String),
58
59 #[error("Exile write xml error")]
60 XmlWriteError(#[from] exile::error::Error),
61}
62
63pub type SdkResult<T> = std::result::Result<T, SdkError>;
65
66impl From<CommonError> for SdkResult<()> {
68 fn from(e: CommonError) -> Self {
69 if e.errcode == 0 {
70 Ok(())
71 } else {
72 Err(SdkError::WxApiError(e))
73 }
74 }
75}
76
77impl<T> From<CommonResponse<T>> for SdkResult<T> {
79 fn from(r: CommonResponse<T>) -> Self {
80 match r {
81 CommonResponse::Ok(t) => Ok(t),
82 CommonResponse::Err(e) => Err(SdkError::WxApiError(e)),
83 }
84 }
85}
86
87impl From<CommonResponse<CommonError>> for SdkResult<()> {
89 fn from(r: CommonResponse<CommonError>) -> Self {
90 match r {
91 CommonResponse::Ok(e) => {
92 if e.errcode == 0 {
93 Ok(())
94 } else {
95 Err(SdkError::WxApiError(e))
96 }
97 }
98 CommonResponse::Err(e) => {
99 if e.errcode == 0 {
100 Ok(())
101 } else {
102 Err(SdkError::WxApiError(e))
103 }
104 }
105 }
106 }
107}
108
109#[test]
110fn test_error_from() {
111 let input = r#"{"errcode": 0,"errmsg":"success"}"#;
112 let expected = CommonResponse::Ok(CommonError {
113 errcode: 0,
114 errmsg: "success".to_string(),
115 });
116 assert_eq!(expected.clone(), serde_json::from_str(input).unwrap());
117
118 let into: SdkResult<()> = expected.clone().into();
119 assert!(into.is_ok());
120
121 let input = r#"{"errcode":40013,"errmsg":"invalid appid"}"#;
122 let expected = CommonResponse::Ok(CommonError {
123 errcode: 40013,
124 errmsg: "invalid appid".to_string(),
125 });
126 assert_eq!(expected.clone(), serde_json::from_str(input).unwrap());
127
128 let into: SdkResult<()> = expected.clone().into();
129 assert!(into.is_err());
130}
131
132#[test]
133fn test_data_and_error() {
134 #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
135 pub struct Data {
136 pub aid: String,
137 pub session_key: String,
138 }
139 let input = r#"{ "aid": "ssss", "session_key": "dddddd", "errcode": 22,"errmsg":"errrrr"}"#;
140 let expected_data = &CommonResponse::<Data>::Ok(Data {
146 aid: "ssss".to_string(),
147 session_key: "dddddd".to_string(),
148 });
149
150 assert_eq!(expected_data, &serde_json::from_str(input).unwrap());
151}