use serde::Deserialize;
use crate::client::WeChatClient;
use crate::error::{Result, WeChatError};
use crate::models::qrcode::{QrCodeAction, QrCodeResponse};
const WECHAT_MP_BASE: &str = "https://mp.weixin.qq.com";
impl WeChatClient {
pub async fn create_qrcode(
&self,
scene_id: u32,
action: QrCodeAction,
expire_seconds: Option<i64>,
) -> Result<QrCodeResponse> {
let mut body = serde_json::json!({
"action_name": action.as_str(),
"action_info": {
"scene": {
"scene_id": scene_id
}
}
});
if let Some(expire) = expire_seconds {
body["expire_seconds"] = serde_json::json!(expire);
}
self.post_json("/qrcode/create", &body).await
}
pub async fn create_qrcode_str(
&self,
scene_str: &str,
action: QrCodeAction,
expire_seconds: Option<i64>,
) -> Result<QrCodeResponse> {
let mut body = serde_json::json!({
"action_name": action.as_str(),
"action_info": {
"scene": {
"scene_str": scene_str
}
}
});
if let Some(expire) = expire_seconds {
body["expire_seconds"] = serde_json::json!(expire);
}
self.post_json("/qrcode/create", &body).await
}
pub fn get_qrcode_url(ticket: &str) -> String {
format!(
"{}/cgi-bin/showqrcode?ticket={}",
WECHAT_MP_BASE,
urlencoding::encode(ticket)
)
}
pub async fn download_qrcode(&self, ticket: &str) -> Result<Vec<u8>> {
let url = Self::get_qrcode_url(ticket);
let resp = self.http.get(&url).send().await?;
if !resp.status().is_success() {
return Err(WeChatError::Api {
errcode: resp.status().as_u16() as i64,
errmsg: "Failed to download QR code".to_string(),
});
}
Ok(resp.bytes().await?.to_vec())
}
pub async fn create_short_url(&self, long_url: &str) -> Result<String> {
let body = serde_json::json!({
"action": "long2short",
"long_url": long_url
});
#[derive(Deserialize)]
struct Response {
short_url: Option<String>,
errcode: Option<i64>,
errmsg: Option<String>,
}
let resp: Response = self.post_json("/shorturl", &body).await?;
if let Some(errcode) = resp.errcode {
if errcode != 0 {
return Err(WeChatError::Api {
errcode,
errmsg: resp.errmsg.unwrap_or_default(),
});
}
}
resp.short_url.ok_or(WeChatError::TokenUnavailable)
}
pub async fn get_callback_ip_list(&self) -> Result<Vec<String>> {
#[derive(Deserialize)]
struct Response {
ip_list: Vec<String>,
}
let resp: Response = self.get("/getcallbackip", &[]).await?;
Ok(resp.ip_list)
}
pub async fn get_api_domain_ip_list(&self) -> Result<Vec<String>> {
#[derive(Deserialize)]
struct Response {
ip_list: Vec<String>,
}
let resp: Response = self.get("/get_api_domain_ip", &[]).await?;
Ok(resp.ip_list)
}
pub async fn check_network(&self) -> Result<bool> {
#[derive(Deserialize)]
#[allow(dead_code)]
struct Response {
dns: Option<Vec<DnsInfo>>,
ping: Option<Vec<PingInfo>>,
}
#[derive(Deserialize)]
#[allow(dead_code)]
struct DnsInfo {
ip: String,
real_operator: String,
}
#[derive(Deserialize)]
#[allow(dead_code)]
struct PingInfo {
ip: String,
from_operator: String,
package_loss: String,
time: String,
}
let body = serde_json::json!({
"action": "all",
"check_operator": "DEFAULT"
});
let _resp: Response = self.post_json("/callback/check", &body).await?;
Ok(true)
}
}