Skip to main content

wechat_mp_sdk/api/
cloud.rs

1//! Cloud Base API
2
3use std::collections::HashMap;
4use std::sync::Arc;
5
6use serde::{Deserialize, Serialize};
7use serde_json::Value;
8
9use super::{WechatApi, WechatContext};
10use crate::error::WechatError;
11
12#[non_exhaustive]
13#[derive(Debug, Clone, Serialize)]
14pub struct InvokeCloudFunctionRequest {
15    #[serde(flatten)]
16    pub payload: HashMap<String, Value>,
17}
18
19#[non_exhaustive]
20#[derive(Debug, Clone, Serialize)]
21pub struct DelayedFunctionTaskRequest {
22    #[serde(flatten)]
23    pub payload: HashMap<String, Value>,
24}
25
26#[non_exhaustive]
27#[derive(Debug, Clone, Serialize)]
28pub struct CloudDatabaseRequest {
29    pub query: String,
30}
31
32#[non_exhaustive]
33#[derive(Debug, Clone, Serialize)]
34pub struct UploadFileLinkRequest {
35    pub env: String,
36    pub path: String,
37}
38
39#[non_exhaustive]
40#[derive(Debug, Clone, Serialize)]
41pub struct DownloadFileLinkRequest {
42    pub env: String,
43    pub file_list: Vec<String>,
44}
45
46#[non_exhaustive]
47#[derive(Debug, Clone, Serialize)]
48pub struct DeleteCloudFileRequest {
49    pub env: String,
50    pub fileid_list: Vec<String>,
51}
52
53#[non_exhaustive]
54#[derive(Debug, Clone, Serialize)]
55pub struct SendCloudBaseSmsRequest {
56    #[serde(flatten)]
57    pub payload: HashMap<String, Value>,
58}
59
60#[non_exhaustive]
61#[derive(Debug, Clone, Deserialize, Serialize)]
62pub struct CloudResponse {
63    #[serde(default)]
64    pub(crate) errcode: i32,
65    #[serde(default)]
66    pub(crate) errmsg: String,
67    #[serde(flatten)]
68    pub extra: HashMap<String, Value>,
69}
70
71pub struct CloudApi {
72    context: Arc<WechatContext>,
73}
74
75impl CloudApi {
76    pub fn new(context: Arc<WechatContext>) -> Self {
77        Self { context }
78    }
79
80    pub async fn invoke_cloud_function(
81        &self,
82        request: &InvokeCloudFunctionRequest,
83    ) -> Result<CloudResponse, WechatError> {
84        self.post_json("/tcb/invokecloudfunction", request).await
85    }
86
87    pub async fn add_delayed_function_task(
88        &self,
89        request: &DelayedFunctionTaskRequest,
90    ) -> Result<CloudResponse, WechatError> {
91        self.post_json("/tcb/adddelayedfunctiontask", request).await
92    }
93
94    pub async fn database_add(
95        &self,
96        request: &CloudDatabaseRequest,
97    ) -> Result<CloudResponse, WechatError> {
98        self.post_json("/tcb/databaseadd", request).await
99    }
100
101    pub async fn database_delete(
102        &self,
103        request: &CloudDatabaseRequest,
104    ) -> Result<CloudResponse, WechatError> {
105        self.post_json("/tcb/databasedelete", request).await
106    }
107
108    pub async fn database_update(
109        &self,
110        request: &CloudDatabaseRequest,
111    ) -> Result<CloudResponse, WechatError> {
112        self.post_json("/tcb/databaseupdate", request).await
113    }
114
115    pub async fn database_query(
116        &self,
117        request: &CloudDatabaseRequest,
118    ) -> Result<CloudResponse, WechatError> {
119        self.post_json("/tcb/databasequery", request).await
120    }
121
122    pub async fn get_upload_file_link(
123        &self,
124        request: &UploadFileLinkRequest,
125    ) -> Result<CloudResponse, WechatError> {
126        self.post_json("/tcb/uploadfile", request).await
127    }
128
129    pub async fn get_download_file_link(
130        &self,
131        request: &DownloadFileLinkRequest,
132    ) -> Result<CloudResponse, WechatError> {
133        self.post_json("/tcb/batchdownloadfile", request).await
134    }
135
136    pub async fn delete_cloud_file(
137        &self,
138        request: &DeleteCloudFileRequest,
139    ) -> Result<CloudResponse, WechatError> {
140        self.post_json("/tcb/batchdeletefile", request).await
141    }
142
143    pub async fn new_send_cloud_base_sms(
144        &self,
145        request: &SendCloudBaseSmsRequest,
146    ) -> Result<CloudResponse, WechatError> {
147        self.post_json("/tcb/sendsms_v2", request).await
148    }
149
150    async fn post_json<B: Serialize>(
151        &self,
152        endpoint: &str,
153        body: &B,
154    ) -> Result<CloudResponse, WechatError> {
155        let response: CloudResponse = self.context.authed_post(endpoint, body).await?;
156        WechatError::check_api(response.errcode, &response.errmsg)?;
157        Ok(response)
158    }
159}
160
161impl WechatApi for CloudApi {
162    fn context(&self) -> &WechatContext {
163        &self.context
164    }
165
166    fn api_name(&self) -> &'static str {
167        "cloud"
168    }
169}
170
171#[cfg(test)]
172mod tests {
173    use super::*;
174
175    #[test]
176    fn cloud_response_deserializes() {
177        let json = r#"{"errcode":0,"errmsg":"ok","request_id":"x"}"#;
178        let response: CloudResponse = serde_json::from_str(json).unwrap();
179        assert_eq!(response.errcode, 0);
180        assert!(response.extra.contains_key("request_id"));
181    }
182}