use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
pub trait ParamsTrait {
fn to_json(&self) -> String;
}
#[derive(Serialize, Debug, Clone)]
pub enum Currency {
CNY,
}
impl Display for Currency {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Currency::CNY => write!(f, "CNY"),
}
}
}
unsafe impl Send for Currency {}
unsafe impl Sync for Currency {}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct AmountInfo {
pub total: i32,
}
impl From<i32> for AmountInfo {
fn from(value: i32) -> Self {
Self { total: value }
}
}
unsafe impl Send for AmountInfo {}
unsafe impl Sync for AmountInfo {}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct PayerInfo {
pub openid: String,
}
impl From<&str> for PayerInfo {
fn from(value: &str) -> Self {
Self {
openid: value.to_string(),
}
}
}
unsafe impl Send for PayerInfo {}
unsafe impl Sync for PayerInfo {}
#[derive(Serialize, Debug, Clone)]
pub struct GoodsDetail {
pub merchant_goods_id: String,
pub quantity: i32,
pub unit_price: i32,
#[serde(skip_serializing_if = "Option::is_none")]
pub wechatpay_goods_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub goods_name: Option<String>,
}
unsafe impl Send for GoodsDetail {}
unsafe impl Sync for GoodsDetail {}
#[derive(Serialize, Debug, Clone)]
pub struct OrderDetail {
#[serde(skip_serializing_if = "Option::is_none")]
pub cost_price: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub invoice_id: Option<String>,
pub goods_detail: Vec<GoodsDetail>,
}
unsafe impl Send for OrderDetail {}
unsafe impl Sync for OrderDetail {}
#[derive(Serialize, Debug, Clone)]
pub struct StoreInfo {
pub id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub area_code: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub address: Option<String>,
}
#[derive(Serialize, Debug, Clone)]
pub struct SceneInfo {
pub payer_client_ip: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub device_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub store_info: Option<StoreInfo>,
}
#[derive(Serialize, Debug, Clone)]
pub enum H5Type {
Ios,
Android,
Wap,
}
impl Display for H5Type {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
H5Type::Ios => write!(f, "iOS"),
H5Type::Android => write!(f, "Android"),
H5Type::Wap => write!(f, "Wap"),
}
}
}
#[derive(Serialize, Debug, Clone)]
pub struct H5Info {
#[serde(rename = "type")]
pub h5_type: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub app_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub app_url: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bundle_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub package_name: Option<String>,
}
#[derive(Serialize, Debug, Clone)]
pub struct H5SceneInfo {
pub payer_client_ip: String,
pub h5_info: H5Info,
#[serde(skip_serializing_if = "Option::is_none")]
pub device_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub store_info: Option<StoreInfo>,
}
impl H5SceneInfo {
pub fn new<S: AsRef<str>>(payer_client_ip: S, app_name: S, app_url: S) -> Self {
Self {
payer_client_ip: payer_client_ip.as_ref().to_string(),
h5_info: H5Info {
h5_type: H5Type::Wap.to_string(),
app_name: Some(app_name.as_ref().to_string()),
app_url: Some(app_url.as_ref().to_string()),
bundle_id: None,
package_name: None,
},
device_id: None,
store_info: None,
}
}
}
unsafe impl Send for SceneInfo {}
unsafe impl Sync for SceneInfo {}
impl ParamsTrait for SceneInfo {
fn to_json(&self) -> String {
serde_json::to_string(self).unwrap()
}
}
#[derive(Serialize, Debug, Clone)]
pub struct JsapiParams {
pub description: String,
pub out_trade_no: String,
pub amount: AmountInfo,
pub payer: PayerInfo,
#[serde(skip_serializing_if = "Option::is_none")]
pub attach: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<OrderDetail>,
#[serde(skip_serializing_if = "Option::is_none")]
pub time_expire: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scene_info: Option<SceneInfo>,
}
impl ParamsTrait for JsapiParams {
fn to_json(&self) -> String {
serde_json::to_string(self).unwrap()
}
}
#[derive(Serialize, Debug, Clone)]
pub struct MicroParams {
pub description: String,
pub out_trade_no: String,
pub amount: AmountInfo,
pub payer: PayerInfo,
#[serde(skip_serializing_if = "Option::is_none")]
pub attach: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<OrderDetail>,
#[serde(skip_serializing_if = "Option::is_none")]
pub time_expire: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scene_info: Option<SceneInfo>,
}
impl ParamsTrait for MicroParams {
fn to_json(&self) -> String {
serde_json::to_string(self).unwrap()
}
}
impl MicroParams {
pub fn new<S: AsRef<str>>(
description: S,
out_trade_no: S,
amount: AmountInfo,
payer: PayerInfo,
) -> Self {
Self {
description: description.as_ref().to_string(),
out_trade_no: out_trade_no.as_ref().to_string(),
amount,
payer,
time_expire: None,
attach: None,
detail: None,
scene_info: None,
}
}
}
impl JsapiParams {
pub fn new<S: AsRef<str>>(
description: S,
out_trade_no: S,
amount: AmountInfo,
payer: PayerInfo,
) -> Self {
Self {
description: description.as_ref().to_string(),
out_trade_no: out_trade_no.as_ref().to_string(),
amount,
payer,
time_expire: None,
attach: None,
detail: None,
scene_info: None,
}
}
}
#[derive(Serialize, Debug, Clone)]
pub struct SettleInfo {
#[serde(skip_serializing_if = "Option::is_none")]
pub profit_sharing: Option<bool>,
}
unsafe impl Send for SettleInfo {}
unsafe impl Sync for SettleInfo {}
#[derive(Serialize, Debug, Clone)]
pub struct NativeParams {
pub description: String,
pub out_trade_no: String,
pub amount: AmountInfo,
#[serde(skip_serializing_if = "Option::is_none")]
pub time_expire: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub attach: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub goods_tag: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub support_fapiao: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scene_info: Option<SceneInfo>,
#[serde(skip_serializing_if = "Option::is_none")]
pub settle_info: Option<SettleInfo>,
}
impl ParamsTrait for NativeParams {
fn to_json(&self) -> String {
serde_json::to_string(self).unwrap()
}
}
#[derive(Serialize, Debug, Clone)]
pub struct AppParams {
pub description: String,
pub out_trade_no: String,
pub amount: AmountInfo,
#[serde(skip_serializing_if = "Option::is_none")]
pub time_expire: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub attach: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub goods_tag: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub support_fapiao: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<OrderDetail>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scene_info: Option<SceneInfo>,
#[serde(skip_serializing_if = "Option::is_none")]
pub settle_info: Option<SettleInfo>,
}
impl ParamsTrait for AppParams {
fn to_json(&self) -> String {
serde_json::to_string(self).unwrap()
}
}
impl AppParams {
pub fn new<S: AsRef<str>>(description: S, out_trade_no: S, amount: AmountInfo) -> Self {
Self {
description: description.as_ref().to_string(),
out_trade_no: out_trade_no.as_ref().to_string(),
amount,
time_expire: None,
attach: None,
goods_tag: None,
support_fapiao: None,
detail: None,
scene_info: None,
settle_info: None,
}
}
}
#[derive(Serialize, Debug, Clone)]
pub struct H5Params {
pub description: String,
pub out_trade_no: String,
pub amount: AmountInfo,
#[serde(skip_serializing_if = "Option::is_none")]
pub time_expire: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub attach: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub goods_tag: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub support_fapiao: Option<bool>,
pub scene_info: H5SceneInfo,
#[serde(skip_serializing_if = "Option::is_none")]
pub settle_info: Option<SettleInfo>,
}
impl ParamsTrait for H5Params {
fn to_json(&self) -> String {
serde_json::to_string(self).unwrap()
}
}
impl H5Params {
pub fn new<S: AsRef<str>>(
description: S,
out_trade_no: S,
amount: AmountInfo,
scene_info: H5SceneInfo,
) -> Self {
Self {
description: description.as_ref().to_string(),
out_trade_no: out_trade_no.as_ref().to_string(),
amount,
time_expire: None,
attach: None,
goods_tag: None,
support_fapiao: None,
scene_info,
settle_info: None,
}
}
}
impl NativeParams {
pub fn new<S: AsRef<str>>(description: S, out_trade_no: S, amount: AmountInfo) -> Self {
Self {
description: description.as_ref().to_string(),
out_trade_no: out_trade_no.as_ref().to_string(),
amount,
time_expire: None,
attach: None,
goods_tag: None,
support_fapiao: None,
scene_info: None,
settle_info: None,
}
}
}
unsafe impl Send for NativeParams {}
unsafe impl Sync for NativeParams {}
unsafe impl Send for JsapiParams {}
unsafe impl Sync for JsapiParams {}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct WechatPayNotifySource {
pub algorithm: String,
pub ciphertext: String,
pub associated_data: Option<String>,
pub original_type: String,
pub nonce: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct WechatPayNotify {
pub id: String,
pub create_time: String,
pub event_type: String,
pub resource_type: String,
pub resource: WechatPayNotifySource,
pub summary: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct WechatPayDecodeData {
pub mchid: String,
pub appid: String,
pub out_trade_no: String,
pub transaction_id: String,
pub trade_type: String,
pub trade_state: String,
pub trade_state_desc: String,
pub bank_type: String,
pub attach: String,
pub success_time: String,
pub payer: PayerInfo,
pub amount: AmountInfo,
}