use std::sync::{Arc, Weak};
use async_trait::async_trait;
use wx_rust_common::bean::{CommonUploadData, CommonUploadParam};
use wx_rust_common::enums::WxType;
use wx_rust_common::error::WxErrorException;
use wx_rust_common::util::http::MediaUploadRequestExecutor;
use wx_rust_miniapp::api::WxMaService;
use crate::api::WxOpenMinishopService;
use crate::api::WxOpenService;
use crate::api::r#impl::WxOpenMaService;
use crate::bean::MinishopAuditStatus;
use crate::bean::MinishopBrandList;
use crate::bean::MinishopBusiLicense;
use crate::bean::MinishopCategories;
use crate::bean::MinishopIdcardInfo;
use crate::bean::MinishopNameInfo;
use crate::bean::MinishopOrganizationCodeInfo;
use crate::bean::MinishopReturnInfo;
use crate::bean::MinishopShopCatList;
use crate::bean::MinishopSuperAdministratorInfo;
use crate::bean::WxOpenResult;
use crate::enums::url_ma_domain::{minishop_submit_merchant_info_url, minishop_upload_img_url};
pub struct WxOpenMinishopServiceImpl {
wx_open_service: Weak<dyn WxOpenService>,
app_id: String,
}
impl WxOpenMinishopServiceImpl {
pub fn new(wx_open_service: Arc<dyn WxOpenService>, app_id: String) -> Self {
Self {
wx_open_service: Arc::downgrade(&wx_open_service),
app_id,
}
}
fn svc(&self) -> Result<Arc<dyn WxOpenService>, WxErrorException> {
self.wx_open_service
.upgrade()
.ok_or_else(|| WxErrorException::from_code(-99, "门面服务已被释放"))
}
fn ma_service(&self) -> Result<Arc<dyn WxMaService>, WxErrorException> {
let svc = self.svc()?;
let component = svc.wx_open_component_service().ok_or_else(|| {
WxErrorException::from_code(
-99,
"组件子服务未装配(getWxOpenComponentService 返回 null)",
)
})?;
let any = component
.get_wx_ma_service_by_appid(&self.app_id)
.ok_or_else(|| WxErrorException::from_code(-99, "getWxMaServiceByAppid 返回 None"))?;
let ma = any.downcast::<WxOpenMaService>().map_err(|_| {
WxErrorException::from_code(-99, "代 ma 服务 downcast 失败(缓存类型不匹配)")
})?;
Ok(ma as Arc<dyn WxMaService>)
}
}
#[async_trait]
impl WxOpenMinishopService for WxOpenMinishopServiceImpl {
async fn submit_merchant_info(
&self,
app_id: &str,
subject_type: &str,
busi_license: &MinishopBusiLicense,
organization_code_info: &MinishopOrganizationCodeInfo,
idcard_info: &MinishopIdcardInfo,
super_administrator_info: &MinishopSuperAdministratorInfo,
merchant_shortname: &str,
) -> Result<Option<WxOpenResult>, WxErrorException> {
let svc = self.svc()?;
let config = svc.wx_open_config_storage();
let ma = self.ma_service()?;
let body = serde_json::json!({
"app_id": app_id,
"subject_type": subject_type,
"busi_license": minishop_json::busi_license(busi_license),
"organization_code_info": minishop_json::organization_code_info(organization_code_info),
"id_card_info": minishop_json::idcard_info(idcard_info),
"super_administrator_info": minishop_json::super_administrator_info(super_administrator_info),
});
let response = ma
.post(
&minishop_submit_merchant_info_url(config.as_ref()),
&body.to_string(),
)
.await?;
let _ = (merchant_shortname, response);
Ok(None)
}
async fn submit_basic_info(
&self,
_app_id: &str,
_name_info: &MinishopNameInfo,
_return_info: &MinishopReturnInfo,
) -> Result<Option<WxOpenResult>, WxErrorException> {
Ok(None)
}
async fn check_audit_status(
&self,
_wx_name: &str,
) -> Result<Option<MinishopAuditStatus>, WxErrorException> {
Ok(None)
}
async fn upload_image_pic_file(
&self,
height: i32,
width: i32,
file_path: &str,
) -> Result<String, WxErrorException> {
let svc = self.svc()?;
let config = svc.wx_open_config_storage();
let ma = self.ma_service()?;
let access_token = ma.get_access_token_with_force(true).await?;
let url = format!(
"{}?access_token={access_token}&height={height}&width={width}",
minishop_upload_img_url(config.as_ref())
);
let content = std::fs::read(file_path)
.map_err(|e| WxErrorException::from_code(-99, format!("读取上传文件失败: {e}")))?;
let file_name = std::path::Path::new(file_path)
.file_name()
.map(|s| s.to_string_lossy().to_string());
let executor = MediaUploadRequestExecutor::new(ma.http_client().clone());
let param = CommonUploadParam::new("media", CommonUploadData::new(file_name, content));
executor.upload(&url, param, WxType::MiniApp).await
}
async fn get_category(
&self,
_f_cat_id: i32,
) -> Result<Option<MinishopCategories>, WxErrorException> {
Ok(None)
}
async fn get_brands(&self) -> Result<Option<MinishopBrandList>, WxErrorException> {
Ok(None)
}
async fn get_shop_cat(&self) -> Result<Option<MinishopShopCatList>, WxErrorException> {
Ok(None)
}
}
mod minishop_json {
use serde_json::{Value, json};
use crate::bean::{
MinishopBusiLicense, MinishopIdcardInfo, MinishopOrganizationCodeInfo, MinishopPicFile,
MinishopSuperAdministratorInfo,
};
fn pic_file(p: &MinishopPicFile) -> Value {
json!({ "media_id": p.media_id, "pay_media_id": p.pay_media_id })
}
pub(super) fn busi_license(b: &MinishopBusiLicense) -> Value {
let mut v = json!({
"license_type": b.license_type,
"pic_file": pic_file(&b.pic_file),
"registration_num": b.registration_num,
"merchant_name": b.merchant_name,
"legal_representative": b.legal_representative,
"start_date": b.start_date,
"end_date": b.end_date,
});
if !b.registered_addrs.is_empty() {
v["registered_addrs"] = json!(b.registered_addrs);
}
v
}
pub(super) fn organization_code_info(o: &MinishopOrganizationCodeInfo) -> Value {
json!({
"pic_file": pic_file(&o.pic_file),
"organization_code": o.organization_code,
"start_date": o.start_date,
"end_date": o.end_date,
})
}
pub(super) fn idcard_info(i: &MinishopIdcardInfo) -> Value {
json!({
"portrait_pic_file": pic_file(&i.portrait_pic_file),
"nation_pic_file": pic_file(&i.nation_pic_file),
"id_card_name": i.id_card_name,
"id_card_number": i.id_card_number,
"start_date": i.start_date,
"end_date": i.end_date,
})
}
pub(super) fn super_administrator_info(s: &MinishopSuperAdministratorInfo) -> Value {
json!({
"type": s.r#type,
"name": s.name,
"id_card_number": s.id_card_number,
"phone": s.phone,
"mail": s.mail,
})
}
}