use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::vec;
use serde::{Serialize, Deserialize};
use serde_json::{Value};
use crate::{session::SessionStore, request::{RequestType}, WechatCommonResponse, WechatMpClient, LabradorResult, WechatRequest, RequestBody};
use crate::wechat::mp::constants::IMG_URL;
use crate::wechat::mp::method::{MpOcrMethod, WechatMpMethod};
#[derive(Debug, Clone)]
pub struct WechatMpOcr<'a, T: SessionStore> {
client: &'a WechatMpClient<T>,
}
#[allow(unused)]
impl<'a, T: SessionStore> WechatMpOcr<'a, T> {
#[inline]
pub fn new(client: &WechatMpClient<T>) -> WechatMpOcr<T> {
WechatMpOcr {
client,
}
}
pub async fn id_card(&self, img_url: &str) -> LabradorResult<WechatOcrIdCardResponse> {
let img_url = urlencoding::encode(img_url).to_string();
let v = self.client.post(WechatMpMethod::Ocr(MpOcrMethod::IdCard), vec![(IMG_URL.to_string(), img_url)], Value::Null, RequestType::Json).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatOcrIdCardResponse>(v)
}
pub async fn id_card_file(&self, file_path: &str) -> LabradorResult<WechatOcrIdCardResponse> {
let path = Path::new(file_path);
let file_name = path.file_name().map(|v| v.to_str().unwrap_or_default()).unwrap_or_default();
let mut f = File::open(path)?;
let mut content: Vec<u8> = Vec::new();
let _ = f.read_to_end(&mut content)?;
let req = WechatMpOcrRequest {
ocr_type: 1,
filename: "".to_string(),
data: content
};
let v = self.client.execute::<WechatMpOcrRequest, String>(req).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatOcrIdCardResponse>(v)
}
pub async fn back_card(&self, img_url: &str) -> LabradorResult<WechatOcrBankCardResponse> {
let img_url = urlencoding::encode(img_url).to_string();
let v = self.client.post(WechatMpMethod::Ocr(MpOcrMethod::BankCard), vec![(IMG_URL.to_string(), img_url)], Value::Null, RequestType::Json).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatOcrBankCardResponse>(v)
}
pub async fn back_card_file(&self, file_path: &str) -> LabradorResult<WechatOcrBankCardResponse> {
let path = Path::new(file_path);
let file_name = path.file_name().map(|v| v.to_str().unwrap_or_default()).unwrap_or_default();
let mut f = File::open(path)?;
let mut content: Vec<u8> = Vec::new();
let _ = f.read_to_end(&mut content)?;
let req = WechatMpOcrRequest {
ocr_type: 2,
filename: "".to_string(),
data: content
};
let v = self.client.execute::<WechatMpOcrRequest, String>(req).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatOcrBankCardResponse>(v)
}
pub async fn driving(&self, img_url: &str) -> LabradorResult<WechatOcrDrivingResponse> {
let img_url = urlencoding::encode(img_url).to_string();
let v = self.client.post(WechatMpMethod::Ocr(MpOcrMethod::Driving), vec![(IMG_URL.to_string(), img_url)], Value::Null, RequestType::Json).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatOcrDrivingResponse>(v)
}
pub async fn driving_file(&self, file_path: &str) -> LabradorResult<WechatOcrDrivingResponse> {
let path = Path::new(file_path);
let file_name = path.file_name().map(|v| v.to_str().unwrap_or_default()).unwrap_or_default();
let mut f = File::open(path)?;
let mut content: Vec<u8> = Vec::new();
let _ = f.read_to_end(&mut content)?;
let req = WechatMpOcrRequest {
ocr_type: 3,
filename: "".to_string(),
data: content
};
let v = self.client.execute::<WechatMpOcrRequest, String>(req).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatOcrDrivingResponse>(v)
}
pub async fn driving_license(&self, img_url: &str) -> LabradorResult<WechatOcrDrivingLicenseResponse> {
let img_url = urlencoding::encode(img_url).to_string();
let v = self.client.post(WechatMpMethod::Ocr(MpOcrMethod::DrivingLicense), vec![(IMG_URL.to_string(), img_url)], Value::Null, RequestType::Json).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatOcrDrivingLicenseResponse>(v)
}
pub async fn driving_license_file(&self, file_path: &str) -> LabradorResult<WechatOcrDrivingLicenseResponse> {
let path = Path::new(file_path);
let file_name = path.file_name().map(|v| v.to_str().unwrap_or_default()).unwrap_or_default();
let mut f = File::open(path)?;
let mut content: Vec<u8> = Vec::new();
let _ = f.read_to_end(&mut content)?;
let req = WechatMpOcrRequest {
ocr_type: 4,
filename: "".to_string(),
data: content
};
let v = self.client.execute::<WechatMpOcrRequest, String>(req).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatOcrDrivingLicenseResponse>(v)
}
pub async fn biz_license(&self, img_url: &str) -> LabradorResult<WechatOcrBizLicenseResponse> {
let img_url = urlencoding::encode(img_url).to_string();
let v = self.client.post(WechatMpMethod::Ocr(MpOcrMethod::BizLicense), vec![(IMG_URL.to_string(), img_url)], Value::Null, RequestType::Json).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatOcrBizLicenseResponse>(v)
}
pub async fn biz_license_file(&self, file_path: &str) -> LabradorResult<WechatOcrBizLicenseResponse> {
let path = Path::new(file_path);
let file_name = path.file_name().map(|v| v.to_str().unwrap_or_default()).unwrap_or_default();
let mut f = File::open(path)?;
let mut content: Vec<u8> = Vec::new();
let _ = f.read_to_end(&mut content)?;
let req = WechatMpOcrRequest {
ocr_type: 5,
filename: "".to_string(),
data: content
};
let v = self.client.execute::<WechatMpOcrRequest, String>(req).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatOcrBizLicenseResponse>(v)
}
pub async fn comm(&self, img_url: &str) -> LabradorResult<WechatOcrCommResponse> {
let img_url = urlencoding::encode(img_url).to_string();
let v = self.client.post(WechatMpMethod::Ocr(MpOcrMethod::Comm), vec![(IMG_URL.to_string(), img_url)], Value::Null, RequestType::Json).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatOcrCommResponse>(v)
}
pub async fn comm_file(&self, file_path: &str) -> LabradorResult<WechatOcrCommResponse> {
let path = Path::new(file_path);
let file_name = path.file_name().map(|v| v.to_str().unwrap_or_default()).unwrap_or_default();
let mut f = File::open(path)?;
let mut content: Vec<u8> = Vec::new();
let _ = f.read_to_end(&mut content)?;
let req = WechatMpOcrRequest {
ocr_type: 6,
filename: "".to_string(),
data: content
};
let v = self.client.execute::<WechatMpOcrRequest, String>(req).await?.json::<Value>()?;
WechatCommonResponse::parse::<WechatOcrCommResponse>(v)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WechatOcrIdCardResponse {
#[serde(rename="type")]
pub r#type: Option<String>,
pub name: Option<String>,
pub id: Option<String>,
pub valid_date: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WechatOcrCommResponse {
pub img_size: Option<WechatOcrImgSize>,
pub items: Option<Vec<WechatOcrItems>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WechatOcrItems {
pub text: Option<String>,
pub pos: Option<WechatOcrPos>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WechatOcrBankCardResponse {
pub number: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WechatOcrDrivingLicenseResponse {
pub id_num: Option<String>,
pub name: Option<String>,
pub sex: Option<String>,
pub nationality: Option<String>,
pub address: Option<String>,
pub birth_date: Option<String>,
pub issue_date: Option<String>,
pub car_class: Option<String>,
pub valid_from: Option<String>,
pub valid_to: Option<String>,
pub official_seal: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WechatOcrBizLicenseResponse {
pub reg_num: Option<String>,
pub serial: Option<String>,
pub legal_representative: Option<String>,
pub enterprise_name: Option<String>,
pub type_of_organization: Option<String>,
pub address: Option<String>,
pub type_of_enterprise: Option<String>,
pub business_scope: Option<String>,
pub registered_capital: Option<String>,
pub paid_in_capital: Option<String>,
pub valid_period: Option<String>,
pub registered_date: Option<String>,
pub cert_position: Option<CertPosition>,
pub img_size: Option<WechatOcrImgSize>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WechatOcrDrivingResponse {
pub plate_num: Option<String>,
pub vehicle_type: Option<String>,
pub owner: Option<String>,
pub addr: Option<String>,
pub use_character: Option<String>,
pub model: Option<String>,
pub vin: Option<String>,
pub engine_num: Option<String>,
pub register_date: Option<String>,
pub issue_date: Option<String>,
pub plate_num_b: Option<String>,
pub record: Option<String>,
pub passengers_num: Option<String>,
pub total_quality: Option<String>,
pub prepare_quality: Option<String>,
pub overall_size: Option<String>,
pub card_position_front: Option<CardPosition>,
pub card_position_back: Option<CardPosition>,
pub img_size: Option<WechatOcrImgSize>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CardPosition {
pub pos: Option<WechatOcrPos>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CertPosition {
pub pos: Option<WechatOcrPos>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WechatOcrPos {
pub left_top: Option<Coordinate>,
pub right_top: Option<Coordinate>,
pub right_bottom: Option<Coordinate>,
pub left_bottom: Option<Coordinate>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Coordinate {
pub x: Option<i64>,
pub y: Option<i64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WechatOcrImgSize {
pub w: Option<i64>,
pub h: Option<i64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WechatMpOcrRequest {
pub ocr_type: u8,
pub filename: String,
pub data: Vec<u8>
}
impl WechatRequest for WechatMpOcrRequest {
fn get_api_method_name(&self) -> String {
match self.ocr_type {
1 => MpOcrMethod::IdCard.get_method(),
2 => MpOcrMethod::BankCard.get_method(),
3 => MpOcrMethod::Driving.get_method(),
4 => MpOcrMethod::DrivingLicense.get_method(),
5 => MpOcrMethod::BizLicense.get_method(),
6 => MpOcrMethod::Comm.get_method(),
_=> "".to_string()
}
}
fn get_request_body<T: Serialize>(&self) -> RequestBody<T> {
let form = reqwest::multipart::Form::new().part("media", reqwest::multipart::Part::stream(self.data.to_vec()).file_name(self.filename.to_string()));
form.into()
}
}