1use std::fs::File;
2use std::io::Read;
3use std::path::Path;
4use std::vec;
5
6use serde::{Serialize, Deserialize};
7use serde_json::{Value};
8
9use crate::{session::SessionStore, request::{RequestType}, WechatCommonResponse, WechatMpClient, LabradorResult, WechatRequest, RequestBody};
10use crate::wechat::mp::constants::IMG_URL;
11use crate::wechat::mp::method::{MpOcrMethod, WechatMpMethod};
12
13#[derive(Debug, Clone)]
15pub struct WechatMpOcr<'a, T: SessionStore> {
16 client: &'a WechatMpClient<T>,
17}
18
19#[allow(unused)]
20impl<'a, T: SessionStore> WechatMpOcr<'a, T> {
21
22 #[inline]
23 pub fn new(client: &WechatMpClient<T>) -> WechatMpOcr<T> {
24 WechatMpOcr {
25 client,
26 }
27 }
28
29 pub async fn id_card(&self, img_url: &str) -> LabradorResult<WechatOcrIdCardResponse> {
31 let img_url = urlencoding::encode(img_url).to_string();
32 let v = self.client.post(WechatMpMethod::Ocr(MpOcrMethod::IdCard), vec![(IMG_URL.to_string(), img_url)], Value::Null, RequestType::Json).await?.json::<Value>()?;
33 WechatCommonResponse::parse::<WechatOcrIdCardResponse>(v)
34 }
35
36 pub async fn id_card_file(&self, file_path: &str) -> LabradorResult<WechatOcrIdCardResponse> {
38 let path = Path::new(file_path);
39 let file_name = path.file_name().map(|v| v.to_str().unwrap_or_default()).unwrap_or_default();
40 let mut f = File::open(path)?;
41 let mut content: Vec<u8> = Vec::new();
42 let _ = f.read_to_end(&mut content)?;
43 let req = WechatMpOcrRequest {
44 ocr_type: 1,
45 filename: "".to_string(),
46 data: content
47 };
48 let v = self.client.execute::<WechatMpOcrRequest, String>(req).await?.json::<Value>()?;
49 WechatCommonResponse::parse::<WechatOcrIdCardResponse>(v)
50 }
51
52 pub async fn back_card(&self, img_url: &str) -> LabradorResult<WechatOcrBankCardResponse> {
55 let img_url = urlencoding::encode(img_url).to_string();
56 let v = self.client.post(WechatMpMethod::Ocr(MpOcrMethod::BankCard), vec![(IMG_URL.to_string(), img_url)], Value::Null, RequestType::Json).await?.json::<Value>()?;
57 WechatCommonResponse::parse::<WechatOcrBankCardResponse>(v)
58 }
59
60 pub async fn back_card_file(&self, file_path: &str) -> LabradorResult<WechatOcrBankCardResponse> {
63 let path = Path::new(file_path);
64 let file_name = path.file_name().map(|v| v.to_str().unwrap_or_default()).unwrap_or_default();
65 let mut f = File::open(path)?;
66 let mut content: Vec<u8> = Vec::new();
67 let _ = f.read_to_end(&mut content)?;
68 let req = WechatMpOcrRequest {
69 ocr_type: 2,
70 filename: "".to_string(),
71 data: content
72 };
73 let v = self.client.execute::<WechatMpOcrRequest, String>(req).await?.json::<Value>()?;
74 WechatCommonResponse::parse::<WechatOcrBankCardResponse>(v)
75 }
76
77 pub async fn driving(&self, img_url: &str) -> LabradorResult<WechatOcrDrivingResponse> {
80 let img_url = urlencoding::encode(img_url).to_string();
81 let v = self.client.post(WechatMpMethod::Ocr(MpOcrMethod::Driving), vec![(IMG_URL.to_string(), img_url)], Value::Null, RequestType::Json).await?.json::<Value>()?;
82 WechatCommonResponse::parse::<WechatOcrDrivingResponse>(v)
83 }
84
85 pub async fn driving_file(&self, file_path: &str) -> LabradorResult<WechatOcrDrivingResponse> {
88 let path = Path::new(file_path);
89 let file_name = path.file_name().map(|v| v.to_str().unwrap_or_default()).unwrap_or_default();
90 let mut f = File::open(path)?;
91 let mut content: Vec<u8> = Vec::new();
92 let _ = f.read_to_end(&mut content)?;
93 let req = WechatMpOcrRequest {
94 ocr_type: 3,
95 filename: "".to_string(),
96 data: content
97 };
98 let v = self.client.execute::<WechatMpOcrRequest, String>(req).await?.json::<Value>()?;
99 WechatCommonResponse::parse::<WechatOcrDrivingResponse>(v)
100 }
101
102 pub async fn driving_license(&self, img_url: &str) -> LabradorResult<WechatOcrDrivingLicenseResponse> {
105 let img_url = urlencoding::encode(img_url).to_string();
106 let v = self.client.post(WechatMpMethod::Ocr(MpOcrMethod::DrivingLicense), vec![(IMG_URL.to_string(), img_url)], Value::Null, RequestType::Json).await?.json::<Value>()?;
107 WechatCommonResponse::parse::<WechatOcrDrivingLicenseResponse>(v)
108 }
109
110 pub async fn driving_license_file(&self, file_path: &str) -> LabradorResult<WechatOcrDrivingLicenseResponse> {
113 let path = Path::new(file_path);
114 let file_name = path.file_name().map(|v| v.to_str().unwrap_or_default()).unwrap_or_default();
115 let mut f = File::open(path)?;
116 let mut content: Vec<u8> = Vec::new();
117 let _ = f.read_to_end(&mut content)?;
118 let req = WechatMpOcrRequest {
119 ocr_type: 4,
120 filename: "".to_string(),
121 data: content
122 };
123 let v = self.client.execute::<WechatMpOcrRequest, String>(req).await?.json::<Value>()?;
124 WechatCommonResponse::parse::<WechatOcrDrivingLicenseResponse>(v)
125 }
126
127 pub async fn biz_license(&self, img_url: &str) -> LabradorResult<WechatOcrBizLicenseResponse> {
130 let img_url = urlencoding::encode(img_url).to_string();
131 let v = self.client.post(WechatMpMethod::Ocr(MpOcrMethod::BizLicense), vec![(IMG_URL.to_string(), img_url)], Value::Null, RequestType::Json).await?.json::<Value>()?;
132 WechatCommonResponse::parse::<WechatOcrBizLicenseResponse>(v)
133 }
134
135 pub async fn biz_license_file(&self, file_path: &str) -> LabradorResult<WechatOcrBizLicenseResponse> {
138 let path = Path::new(file_path);
139 let file_name = path.file_name().map(|v| v.to_str().unwrap_or_default()).unwrap_or_default();
140 let mut f = File::open(path)?;
141 let mut content: Vec<u8> = Vec::new();
142 let _ = f.read_to_end(&mut content)?;
143 let req = WechatMpOcrRequest {
144 ocr_type: 5,
145 filename: "".to_string(),
146 data: content
147 };
148 let v = self.client.execute::<WechatMpOcrRequest, String>(req).await?.json::<Value>()?;
149 WechatCommonResponse::parse::<WechatOcrBizLicenseResponse>(v)
150 }
151
152 pub async fn comm(&self, img_url: &str) -> LabradorResult<WechatOcrCommResponse> {
156 let img_url = urlencoding::encode(img_url).to_string();
157 let v = self.client.post(WechatMpMethod::Ocr(MpOcrMethod::Comm), vec![(IMG_URL.to_string(), img_url)], Value::Null, RequestType::Json).await?.json::<Value>()?;
158 WechatCommonResponse::parse::<WechatOcrCommResponse>(v)
159 }
160
161 pub async fn comm_file(&self, file_path: &str) -> LabradorResult<WechatOcrCommResponse> {
165 let path = Path::new(file_path);
166 let file_name = path.file_name().map(|v| v.to_str().unwrap_or_default()).unwrap_or_default();
167 let mut f = File::open(path)?;
168 let mut content: Vec<u8> = Vec::new();
169 let _ = f.read_to_end(&mut content)?;
170 let req = WechatMpOcrRequest {
171 ocr_type: 6,
172 filename: "".to_string(),
173 data: content
174 };
175 let v = self.client.execute::<WechatMpOcrRequest, String>(req).await?.json::<Value>()?;
176 WechatCommonResponse::parse::<WechatOcrCommResponse>(v)
177 }
178
179}
180
181#[derive(Debug, Clone, Serialize, Deserialize)]
184pub struct WechatOcrIdCardResponse {
185 #[serde(rename="type")]
186 pub r#type: Option<String>,
187 pub name: Option<String>,
188 pub id: Option<String>,
189 pub valid_date: Option<String>,
190}
191#[derive(Debug, Clone, Serialize, Deserialize)]
192pub struct WechatOcrCommResponse {
193 pub img_size: Option<WechatOcrImgSize>,
194 pub items: Option<Vec<WechatOcrItems>>,
195}
196
197#[derive(Debug, Clone, Serialize, Deserialize)]
198pub struct WechatOcrItems {
199 pub text: Option<String>,
200 pub pos: Option<WechatOcrPos>,
201}
202
203#[derive(Debug, Clone, Serialize, Deserialize)]
204pub struct WechatOcrBankCardResponse {
205 pub number: Option<String>,
206}
207
208
209#[derive(Debug, Clone, Serialize, Deserialize)]
210pub struct WechatOcrDrivingLicenseResponse {
211 pub id_num: Option<String>,
213 pub name: Option<String>,
215 pub sex: Option<String>,
217 pub nationality: Option<String>,
219 pub address: Option<String>,
221 pub birth_date: Option<String>,
223 pub issue_date: Option<String>,
225 pub car_class: Option<String>,
227 pub valid_from: Option<String>,
229 pub valid_to: Option<String>,
231 pub official_seal: Option<String>,
233}
234
235
236#[derive(Debug, Clone, Serialize, Deserialize)]
237pub struct WechatOcrBizLicenseResponse {
238 pub reg_num: Option<String>,
240 pub serial: Option<String>,
242 pub legal_representative: Option<String>,
244 pub enterprise_name: Option<String>,
246 pub type_of_organization: Option<String>,
248 pub address: Option<String>,
250 pub type_of_enterprise: Option<String>,
252 pub business_scope: Option<String>,
254 pub registered_capital: Option<String>,
256 pub paid_in_capital: Option<String>,
258 pub valid_period: Option<String>,
260 pub registered_date: Option<String>,
262 pub cert_position: Option<CertPosition>,
264 pub img_size: Option<WechatOcrImgSize>,
266}
267
268#[derive(Debug, Clone, Serialize, Deserialize)]
269pub struct WechatOcrDrivingResponse {
270 pub plate_num: Option<String>,
272 pub vehicle_type: Option<String>,
274 pub owner: Option<String>,
276 pub addr: Option<String>,
278 pub use_character: Option<String>,
280 pub model: Option<String>,
282 pub vin: Option<String>,
284 pub engine_num: Option<String>,
286 pub register_date: Option<String>,
288 pub issue_date: Option<String>,
290 pub plate_num_b: Option<String>,
292 pub record: Option<String>,
294 pub passengers_num: Option<String>,
296 pub total_quality: Option<String>,
298 pub prepare_quality: Option<String>,
300 pub overall_size: Option<String>,
302 pub card_position_front: Option<CardPosition>,
304 pub card_position_back: Option<CardPosition>,
306 pub img_size: Option<WechatOcrImgSize>,
308}
309
310
311#[derive(Debug, Clone, Serialize, Deserialize)]
312pub struct CardPosition {
313 pub pos: Option<WechatOcrPos>,
314}
315
316
317#[derive(Debug, Clone, Serialize, Deserialize)]
318pub struct CertPosition {
319 pub pos: Option<WechatOcrPos>,
320}
321
322
323#[derive(Debug, Clone, Serialize, Deserialize)]
324pub struct WechatOcrPos {
325 pub left_top: Option<Coordinate>,
326 pub right_top: Option<Coordinate>,
327 pub right_bottom: Option<Coordinate>,
328 pub left_bottom: Option<Coordinate>,
329}
330
331#[derive(Debug, Clone, Serialize, Deserialize)]
332pub struct Coordinate {
333 pub x: Option<i64>,
334 pub y: Option<i64>,
335}
336
337#[derive(Debug, Clone, Serialize, Deserialize)]
338pub struct WechatOcrImgSize {
339 pub w: Option<i64>,
340 pub h: Option<i64>,
341}
342
343#[derive(Debug, Clone, Serialize, Deserialize)]
344pub struct WechatMpOcrRequest {
345 pub ocr_type: u8,
347 pub filename: String,
348 pub data: Vec<u8>
349}
350
351impl WechatRequest for WechatMpOcrRequest {
352 fn get_api_method_name(&self) -> String {
353 match self.ocr_type {
354 1 => MpOcrMethod::IdCard.get_method(),
355 2 => MpOcrMethod::BankCard.get_method(),
356 3 => MpOcrMethod::Driving.get_method(),
357 4 => MpOcrMethod::DrivingLicense.get_method(),
358 5 => MpOcrMethod::BizLicense.get_method(),
359 6 => MpOcrMethod::Comm.get_method(),
360 _=> "".to_string()
361 }
362 }
363
364 fn get_request_body<T: Serialize>(&self) -> RequestBody<T> {
365 let form = reqwest::multipart::Form::new().part("media", reqwest::multipart::Part::stream(self.data.to_vec()).file_name(self.filename.to_string()));
366 form.into()
367 }
368}