br_pay/
lib.rs

1use chrono::{DateTime, FixedOffset, Local, NaiveDateTime};
2use crate::wechat::{Wechat};
3use json::{object, JsonValue};
4use crate::alipay::AliPay;
5use crate::allinpay::Allinpay;
6use crate::ccbc::Ccbc;
7use crate::yrcc::Yrcc;
8
9pub mod alipay;
10pub mod wechat;
11pub mod ccbc;
12pub mod yrcc;
13pub mod allinpay;
14
15#[derive(Clone, Debug)]
16pub enum Pay {
17    /// 微信支付
18    Wechat(Wechat),
19    /// 支付宝支付
20    Alipay(AliPay),
21    /// 建设银行
22    Ccbc(Ccbc),
23    /// 农村商业银行
24    Yrcc(Yrcc),
25    /// 通联支付
26    Allinpay(Allinpay),
27    None,
28}
29
30impl Pay {
31    pub fn new(data: JsonValue) -> Self {
32        match data["mode"].as_str().unwrap_or("") {
33            "wechat" => {
34                Pay::Wechat(Wechat {
35                    appid: data["appid"].to_string(),
36                    sp_mchid: data["sp_mchid"].to_string(),
37                    serial_no: data["serial_no"].to_string(),
38                    app_private: data["app_private"].to_string(),
39                    apikey: data["apikey"].to_string(),
40                    apiv2: data["apiv2"].to_string(),
41                    notify_url: data["notify_url"].to_string(),
42                })
43            }
44            "alipay" => Pay::Alipay(AliPay {
45                appid: data["appid"].to_string(),
46                sp_mchid: data["sp_mchid"].to_string(),
47                app_private: data["app_private"].to_string(),
48                app_auth_token: data["app_auth_token"].as_str().unwrap_or("").to_string(),
49                content_encryp: data["content_encryp"].to_string(),
50                alipay_public_key: data["alipay_public_key"].to_string(),
51                notify_url: data["notify_url"].to_string(),
52                appid_mini: data["appid_mini"].to_string(),
53            }),
54            "yrcc" => Pay::Yrcc(Yrcc {
55                appid: "".to_string(),
56                secret: "".to_string(),
57                terminal_number: data["terminal_number"].to_string(),
58                sp_mchid: data["sp_mchid"].to_string(),
59                app_private: data["app_private"].to_string(),
60                app_public: data["app_public"].to_string(),
61                notify_url: data["notify_url"].as_str().unwrap_or("").to_string(),
62                key_name: data["key_name"].to_string(),
63                service_provider: data["service_provider"].to_string(),
64            }),
65            "ccbc" => Pay::Ccbc(Ccbc {
66                appid: data["appid"].as_str().unwrap_or("").to_string(),
67                branchid: data["branchid"].as_str().unwrap_or("").to_string(),
68                appid_subscribe: data["appid_subscribe"].as_str().unwrap_or("").to_string(),
69                sp_mchid: data["sp_mchid"].as_str().unwrap_or("").to_string(),
70                sp_user_id: data["sp_user_id"].as_str().unwrap_or("").to_string(),
71                sp_pass: data["sp_pass"].as_str().unwrap_or("").to_string(),
72                sp_posid: data["sp_posid"].as_str().unwrap_or("").to_string(),
73                notify_url: data["notify_url"].as_str().unwrap_or("").to_string(),
74                sub_posid: data["sub_posid"].as_str().unwrap_or("").to_string(),
75                public_key: data["public_key"].as_str().unwrap_or("").to_string(),
76                client_ip: data["client_ip"].as_str().unwrap_or("").to_string(),
77                retry: 0,
78                debug: data["debug"].as_bool().unwrap_or(false),
79                query_url: data["query_url"].as_str().unwrap_or("").to_string(),
80            }),
81            "allinpay" => Pay::Allinpay(Allinpay {
82                debug: data["debug"].as_bool().unwrap_or(false),
83                appid: data["appid"].as_str().unwrap_or("").to_string(),
84                sp_mchid: data["sp_mchid"].as_str().unwrap_or("").to_string(),
85                notify_url: data["notify_url"].as_str().unwrap_or("").to_string(),
86                appid_mini: data["appid_mini"].as_str().unwrap_or("").to_string(),
87                rsa_private: data["rsa_private"].as_str().unwrap_or("").to_string(),
88            }),
89            _ => Pay::None
90        }
91    }
92}
93impl PayMode for Pay {
94    fn check(&mut self) -> Result<bool, String> {
95        match self {
96            Self::Wechat(e) => e.check(),
97            Self::Alipay(e) => e.check(),
98            Pay::Allinpay(e) => e.check(),
99            Self::Ccbc(_) => todo!(),
100            Self::Yrcc(_) => todo!(),
101            Self::None => Err("No login data".to_owned()),
102        }
103    }
104
105    fn get_sub_mchid(&mut self, sub_mchid: &str) -> Result<JsonValue, String> {
106        match self {
107            Self::Wechat(e) => e.get_sub_mchid(sub_mchid),
108            Self::Alipay(e) => e.get_sub_mchid(sub_mchid),
109            Pay::None => Err("No login data".to_owned()),
110            &mut Pay::Ccbc(_) => todo!(),
111            &mut Pay::Yrcc(_) => todo!(),
112            &mut Pay::Allinpay(_) => todo!(),
113        }
114    }
115
116
117    fn config(&mut self) -> JsonValue {
118        match self {
119            Self::Wechat(e) => object! {
120                sp_mchid:e.sp_mchid.clone(),
121                appid:e.appid.clone(),
122            },
123            Self::Alipay(e) => object! {
124                appid:e.appid.clone(),
125                sp_mchid:e.sp_mchid.clone()
126            },
127            Pay::None => object! {
128                appid:"",
129                sp_mchid:""
130            },
131            Pay::Ccbc(e) => object! {
132                appid:e.appid.clone(),
133                sp_mchid:e.sp_mchid.clone()
134            },
135            Pay::Yrcc(e) => object! {
136                appid:e.appid.clone(),
137                sp_mchid:e.sp_mchid.clone()
138            },
139            &mut Pay::Allinpay(_) => todo!(),
140        }
141    }
142    fn pay(&mut self, channel: &str, types: Types, sub_mchid: &str, out_trade_no: &str, description: &str, total_fee: f64, sp_openid: &str) -> Result<JsonValue, String> {
143        match self {
144            Self::Wechat(e) => e.pay(channel,
145                                     types,
146                                     sub_mchid,
147                                     out_trade_no,
148                                     description,
149                                     total_fee,
150                                     sp_openid,
151            ),
152            Self::Alipay(e) => e.pay(channel,
153                                     types,
154                                     sub_mchid,
155                                     out_trade_no,
156                                     description,
157                                     total_fee,
158                                     sp_openid,
159            ),
160            Pay::None => Err("No login data".to_owned()),
161            Pay::Ccbc(e) => e.pay(
162                channel,
163                types,
164                sub_mchid,
165                out_trade_no,
166                description,
167                total_fee,
168                sp_openid,
169            ),
170            Pay::Yrcc(e) => e.pay(
171                channel,
172                types,
173                sub_mchid,
174                out_trade_no,
175                description,
176                total_fee,
177                sp_openid,
178            ),
179            Pay::Allinpay(e) => e.pay(
180                channel,
181                types,
182                sub_mchid,
183                out_trade_no,
184                description,
185                total_fee,
186                sp_openid,
187            ),
188        }
189    }
190
191    fn micropay(&mut self, channel: &str, auth_code: &str, sub_mchid: &str, out_trade_no: &str, description: &str, total_fee: f64, org_openid: &str, ip: &str) -> Result<JsonValue, String> {
192        match self {
193            Self::Wechat(e) => e.micropay(
194                channel,
195                auth_code,
196                sub_mchid,
197                out_trade_no,
198                description,
199                total_fee,
200                org_openid,
201                ip,
202            ),
203            Self::Alipay(e) => e.micropay(
204                channel,
205                auth_code,
206                sub_mchid,
207                out_trade_no,
208                description,
209                total_fee,
210                org_openid,
211                ip,
212            ),
213            Pay::Ccbc(e) => e.micropay(
214                channel,
215                auth_code,
216                sub_mchid,
217                out_trade_no,
218                description,
219                total_fee,
220                org_openid,
221                ip,
222            ),
223            Pay::None => Err("No login data".to_owned()),
224            Pay::Yrcc(_) => todo!(),
225            Pay::Allinpay(e) => e.micropay(
226                channel,
227                auth_code,
228                sub_mchid,
229                out_trade_no,
230                description,
231                total_fee,
232                org_openid,
233                ip,
234            ),
235        }
236    }
237
238    fn close(&mut self, out_trade_no: &str, sub_mchid: &str) -> Result<JsonValue, String> {
239        match self {
240            Self::Wechat(e) => e.close(
241                out_trade_no, sub_mchid,
242            ),
243            Self::Alipay(e) => e.close(
244                out_trade_no, sub_mchid,
245            ),
246            Pay::Ccbc(e) => e.close(
247                out_trade_no, sub_mchid,
248            ),
249            Pay::None => Err("No login data".to_owned()),
250            Pay::Yrcc(e) => e.close(
251                out_trade_no, sub_mchid,
252            ),
253            Pay::Allinpay(e) => e.close(
254                out_trade_no, sub_mchid,
255            ),
256        }
257    }
258
259    fn pay_query(&mut self, out_trade_no: &str, sub_mchid: &str) -> Result<JsonValue, String> {
260        match self {
261            Self::Wechat(e) => e.pay_query(
262                out_trade_no,
263                sub_mchid,
264            ),
265            Self::Alipay(e) => e.pay_query(
266                out_trade_no,
267                sub_mchid,
268            ),
269            Self::Ccbc(e) => e.pay_query(
270                out_trade_no,
271                sub_mchid,
272            ),
273            Pay::None => Err("No login data".to_owned()),
274            Pay::Yrcc(e) => e.pay_query(
275                out_trade_no,
276                sub_mchid,
277            ),
278            Pay::Allinpay(e) => e.pay_query(
279                out_trade_no,
280                sub_mchid,
281            ),
282        }
283    }
284    fn pay_micropay_query(&mut self, out_trade_no: &str, sub_mchid: &str, channel: &str) -> Result<JsonValue, String> {
285        match self {
286            Self::Wechat(e) => e.pay_micropay_query(
287                out_trade_no,
288                sub_mchid,
289                channel,
290            ),
291            Self::Alipay(e) => e.pay_query(
292                out_trade_no,
293                sub_mchid,
294            ),
295            Pay::Ccbc(e) => e.pay_micropay_query(
296                out_trade_no,
297                sub_mchid,
298                channel,
299            ),
300            Pay::None => Err("No login data".to_owned()),
301            Pay::Yrcc(e) => e.pay_micropay_query(
302                out_trade_no,
303                sub_mchid,
304                channel,
305            ),
306            Pay::Allinpay(e) => e.pay_micropay_query(
307                out_trade_no,
308                sub_mchid,
309                channel,
310            ),
311        }
312    }
313
314    fn pay_notify(&mut self, nonce: &str, ciphertext: &str, associated_data: &str) -> Result<JsonValue, String> {
315        match self {
316            Self::Wechat(e) => e.pay_notify(
317                nonce,
318                ciphertext,
319                associated_data,
320            ),
321            Self::Alipay(e) => e.pay_notify(
322                nonce,
323                ciphertext,
324                associated_data,
325            ),
326            Pay::None => Err("No login data".to_owned()),
327            &mut Pay::Ccbc(_) | &mut Pay::Yrcc(_) => todo!(),
328            Pay::Allinpay(e) => e.pay_notify(
329                nonce,
330                ciphertext,
331                associated_data,
332            ),
333        }
334    }
335
336    fn refund(&mut self, sub_mchid: &str, out_trade_no: &str, transaction_id: &str, out_refund_no: &str, amount: f64, total: f64, currency: &str) -> Result<JsonValue, String> {
337        match self {
338            Self::Wechat(e) => e.refund(
339                sub_mchid,
340                out_trade_no,
341                transaction_id,
342                out_refund_no,
343                amount,
344                total,
345                currency,
346            ),
347            Self::Alipay(e) => e.refund(
348                sub_mchid,
349                out_trade_no,
350                transaction_id,
351                out_refund_no,
352                amount,
353                total,
354                currency,
355            ),
356            Self::Ccbc(e) => e.refund(
357                sub_mchid,
358                out_trade_no,
359                transaction_id,
360                out_refund_no,
361                amount,
362                total,
363                currency,
364            ),
365            Pay::None => Err("No login data".to_owned()),
366            Pay::Yrcc(e) => e.refund(
367                sub_mchid,
368                out_trade_no,
369                transaction_id,
370                out_refund_no,
371                amount,
372                total,
373                currency,
374            ),
375            Pay::Allinpay(e) => e.refund(
376                sub_mchid,
377                out_trade_no,
378                transaction_id,
379                out_refund_no,
380                amount,
381                total,
382                currency,
383            ),
384        }
385    }
386
387    fn micropay_refund(&mut self, sub_mchid: &str, out_trade_no: &str, transaction_id: &str, out_refund_no: &str, amount: f64, total: f64, currency: &str, refund_text: &str) -> Result<JsonValue, String> {
388        match self {
389            Self::Wechat(e) => e.micropay_refund(
390                sub_mchid,
391                out_trade_no,
392                transaction_id,
393                out_refund_no,
394                amount,
395                total,
396                currency,
397                refund_text,
398            ),
399            Self::Alipay(e) => e.refund(
400                sub_mchid,
401                out_trade_no,
402                transaction_id,
403                out_refund_no,
404                amount,
405                total,
406                currency,
407            ),
408            Pay::None => Err("No login data".to_owned()),
409            Pay::Ccbc(_) | &mut Pay::Yrcc(_) => todo!(),
410            Pay::Allinpay(e) => e.micropay_refund(
411                sub_mchid,
412                out_trade_no,
413                transaction_id,
414                out_refund_no,
415                amount,
416                total,
417                currency,
418                refund_text,
419            ),
420        }
421    }
422
423    fn refund_notify(&mut self, nonce: &str, ciphertext: &str, associated_data: &str) -> Result<JsonValue, String> {
424        match self {
425            Self::Wechat(e) => e.refund_notify(
426                nonce,
427                ciphertext,
428                associated_data,
429            ),
430            Self::Alipay(e) => e.refund_notify(
431                nonce,
432                ciphertext,
433                associated_data,
434            ),
435            Pay::None => Err("No login data".to_owned()),
436            Pay::Ccbc(_) | Pay::Yrcc(_) => todo!(),
437            Pay::Allinpay(e) => e.refund_notify(
438                nonce,
439                ciphertext,
440                associated_data,
441            ),
442        }
443    }
444
445    fn refund_query(&mut self, trade_no: &str, out_refund_no: &str, sub_mchid: &str) -> Result<JsonValue, String> {
446        match self {
447            Self::Wechat(e) => e.refund_query(
448                trade_no,
449                out_refund_no,
450                sub_mchid,
451            ),
452            Self::Alipay(e) => e.refund_query(
453                trade_no,
454                out_refund_no,
455                sub_mchid,
456            ),
457            Pay::Ccbc(e) => e.refund_query(
458                trade_no,
459                out_refund_no,
460                sub_mchid),
461            Pay::None => Err("No login data".to_owned()),
462            Pay::Yrcc(e) => e.refund_query(
463                trade_no,
464                out_refund_no,
465                sub_mchid),
466            Pay::Allinpay(e) => e.refund_query(
467                trade_no,
468                out_refund_no,
469                sub_mchid),
470        }
471    }
472
473    fn incoming(&mut self, business_code: &str, contact_info: JsonValue, subject_info: JsonValue, business_info: JsonValue, settlement_info: JsonValue, bank_account_info: JsonValue) -> Result<JsonValue, String> {
474        match self {
475            Self::Wechat(e) => e.incoming(
476                business_code,
477                contact_info,
478                subject_info,
479                business_info,
480                settlement_info,
481                bank_account_info,
482            ),
483            Self::Alipay(e) => e.incoming(
484                business_code,
485                contact_info,
486                subject_info,
487                business_info,
488                settlement_info,
489                bank_account_info,
490            ),
491            Pay::None => Err("No incoming data".to_owned()),
492            &mut Pay::Ccbc(_) | &mut Pay::Yrcc(_) => todo!(),
493            Pay::Allinpay(e) => e.incoming(
494                business_code,
495                contact_info,
496                subject_info,
497                business_info,
498                settlement_info,
499                bank_account_info,
500            ),
501        }
502    }
503}
504
505pub trait PayMode {
506    /// 检查账户是否通畅
507    fn check(&mut self) -> Result<bool, String>;
508    /// 获取商户号和状态
509    fn get_sub_mchid(&mut self, sub_mchid: &str) -> Result<JsonValue, String>;
510    fn config(&mut self) -> JsonValue;
511    #[allow(clippy::too_many_arguments)]
512    /// 支付
513    /// * channel 渠道 wechat alipay
514    /// * out_trade_no 商户订单号
515    /// * sub_mchid 子商户号
516    /// * description 商品名称
517    /// * total_fee 支付金额
518    /// * notify_url 通知地址
519    /// * sp_openid 支付客户ID
520    fn pay(&mut self, channel: &str, types: Types, sub_mchid: &str, out_trade_no: &str, description: &str, total_fee: f64, sp_openid: &str) -> Result<JsonValue, String>;
521
522    #[allow(clippy::too_many_arguments)]
523    fn micropay(&mut self, channel: &str, auth_code: &str, sub_mchid: &str, out_trade_no: &str, description: &str, total_fee: f64, org_openid: &str, ip: &str) -> Result<JsonValue, String>;
524    /// 关闭订单
525    fn close(&mut self, out_trade_no: &str, sub_mchid: &str) -> Result<JsonValue, String>;
526    /// 订单查询
527    /// * out_trade_no 商户订单号
528    /// * sub_mchid 子商户号
529    fn pay_query(&mut self, out_trade_no: &str, sub_mchid: &str) -> Result<JsonValue, String>;
530    fn pay_micropay_query(&mut self, out_trade_no: &str, sub_mchid: &str, channel: &str) -> Result<JsonValue, String>;
531    /// 支付成功通知
532    fn pay_notify(&mut self, nonce: &str, ciphertext: &str, associated_data: &str) -> Result<JsonValue, String>;
533
534    #[allow(clippy::too_many_arguments)]
535    /// 订单退款
536    fn refund(&mut self, sub_mchid: &str, out_trade_no: &str, transaction_id: &str, out_refund_no: &str, amount: f64, total: f64, currency: &str) -> Result<JsonValue, String>;
537    #[allow(clippy::too_many_arguments)]
538    fn micropay_refund(&mut self, sub_mchid: &str, out_trade_no: &str, transaction_id: &str, out_refund_no: &str, amount: f64, total: f64, currency: &str, refund_text: &str) -> Result<JsonValue, String>;
539    /// 退款通知
540    fn refund_notify(&mut self, nonce: &str, ciphertext: &str, associated_data: &str) -> Result<JsonValue, String>;
541    /// 退款查询
542    fn refund_query(&mut self, trade_no: &str, out_refund_no: &str, sub_mchid: &str) -> Result<JsonValue, String>;
543    /// 进件
544    fn incoming(&mut self, business_code: &str, contact_info: JsonValue, subject_info: JsonValue, business_info: JsonValue, settlement_info: JsonValue, bank_account_info: JsonValue) -> Result<JsonValue, String>;
545}
546
547/// 支付回调数据
548#[derive(Debug)]
549pub struct PayNotify {
550    /// 支付方式
551    trade_type: TradeType,
552    /// 商户订单号
553    out_trade_no: String,
554    /// 服务商商户号
555    sp_mchid: String,
556    /// 子商户号
557    sub_mchid: String,
558    /// 应用APPID
559    sp_appid: String,
560    /// 微信内部订单号
561    transaction_id: String,
562    /// 成功时间
563    success_time: i64,
564    /// 服务商用户ID
565    sp_openid: String,
566    /// 子商户用户ID
567    sub_openid: String,
568    /// 支付金额
569    total: f64,
570    /// 实际支付金额
571    payer_total: f64,
572    /// 币种
573    currency: String,
574    /// 实际支付币种
575    payer_currency: String,
576    /// 状态
577    trade_state: TradeState,
578}
579impl PayNotify {
580    pub fn json(&self) -> JsonValue {
581        object! {
582            "trade_type" => self.trade_type.to_string(),
583            "out_trade_no" => self.out_trade_no.to_string(),
584            "sp_mchid" => self.sp_mchid.to_string(),
585            "sub_mchid" => self.sub_mchid.to_string(),
586            "sp_appid" => self.sp_appid.to_string(),
587            "transaction_id" => self.transaction_id.to_string(),
588            "success_time" => self.success_time,
589            "sp_openid" => self.sp_openid.to_string(),
590            "sub_openid" => self.sub_openid.to_string(),
591            "total" => self.total,
592            "payer_total" => self.payer_total,
593            "currency" => self.currency.clone(),
594            "payer_currency" => self.payer_currency.clone(),
595            "trade_state" => self.trade_state.to_string(),
596        }
597    }
598    pub fn success_time(datetime: &str) -> i64 {
599        if datetime.is_empty() {
600            return 0;
601        }
602        let datetime = DateTime::parse_from_rfc3339(datetime).unwrap();
603        datetime.timestamp()
604    }
605    pub fn datetime_to_timestamp(datetime: &str, fmt: &str) -> i64 {
606        let t = NaiveDateTime::parse_from_str(datetime, fmt).unwrap();
607        let tz = FixedOffset::east_opt(Local::now().offset().local_minus_utc()).unwrap();
608        t.and_local_timezone(tz).unwrap().timestamp()
609    }
610}
611#[derive(Debug)]
612pub enum TradeType {
613    /// 小程序与JSAPI
614    JSAPI,
615    MICROPAY,
616    /// 支付方式未知
617    None,
618}
619impl TradeType {
620    fn from(code: &str) -> TradeType {
621        match code {
622            "JSAPI" => TradeType::JSAPI,
623            "MICROPAY" => TradeType::MICROPAY,
624            _ => TradeType::None
625        }
626    }
627    fn to_string(&self) -> &'static str {
628        match self {
629            TradeType::JSAPI => "JSAPI",
630            TradeType::MICROPAY => "MICROPAY",
631            TradeType::None => ""
632        }
633    }
634}
635#[derive(Debug)]
636pub enum TradeState {
637    /// 支付成功
638    SUCCESS,
639    /// 转入退款
640    REFUND,
641    /// 未支付
642    NOTPAY,
643    /// 已关闭
644    CLOSED,
645    /// 已撤销(仅付款码支付会返回)
646    REVOKED,
647    /// 用户支付中(仅付款码支付会返回)
648    USERPAYING,
649    /// 支付失败(仅付款码支付会返回)
650    PAYERROR,
651    None,
652}
653impl TradeState {
654    fn from(code: &str) -> TradeState {
655        match code {
656            "SUCCESS" | "TRADE_SUCCESS" | "成功" => TradeState::SUCCESS,
657            "REFUND" | "已全额退款" | "已部分退款" => TradeState::REFUND,
658            "NOTPAY" | "WAIT_BUYER_PAY" => TradeState::NOTPAY,
659            "CLOSED" | "TRADE_CLOSED" => TradeState::CLOSED,
660            "REVOKED" => TradeState::REVOKED,
661            "USERPAYING" | "待银行确认" => TradeState::USERPAYING,
662            "PAYERROR" | "TRADE_FINISHED" | "失败" => TradeState::PAYERROR,
663            _ => TradeState::None
664        }
665    }
666
667    fn to_string(&self) -> &'static str {
668        match self {
669            TradeState::SUCCESS => "已支付",
670            TradeState::REFUND => "已退款",
671            TradeState::NOTPAY => "待支付",
672            TradeState::CLOSED => "已关闭",
673            TradeState::REVOKED => "已关闭",
674            TradeState::USERPAYING => "待支付",
675            TradeState::PAYERROR => "支付失败",
676            TradeState::None => "待支付"
677        }
678    }
679}
680
681#[derive(Debug)]
682pub enum RefundStatus {
683    /// 退款成功
684    SUCCESS,
685    /// 退款关闭
686    CLOSED,
687    /// 退款处理中
688    PROCESSING,
689    /// 退款异常,手动处理此笔退款
690    ABNORMAL,
691    None,
692}
693impl RefundStatus {
694    fn from(code: &str) -> RefundStatus {
695        match code {
696            "SUCCESS" | "Y" | "REFUND_SUCCESS" => RefundStatus::SUCCESS,
697            "CLOSED" => RefundStatus::CLOSED,
698            "PROCESSING" | "N" => RefundStatus::PROCESSING,
699            "ABNORMAL" => RefundStatus::ABNORMAL,
700            _ => RefundStatus::None
701        }
702    }
703    fn to_string(&self) -> &'static str {
704        match self {
705            RefundStatus::SUCCESS => "已退款",
706            RefundStatus::None => "未退款",
707            RefundStatus::CLOSED => "已关闭",
708            RefundStatus::PROCESSING => "退款中",
709            RefundStatus::ABNORMAL => "退款异常"
710        }
711    }
712}
713/// 退款回调数据
714#[derive(Debug)]
715pub struct RefundNotify {
716    /// 商户订单号
717    out_trade_no: String,
718    refund_no: String,
719    /// 服务商商户号
720    sp_mchid: String,
721    /// 子商户号
722    sub_mchid: String,
723    /// 微信内部订单号
724    transaction_id: String,
725    /// 退款订单号
726    refund_id: String,
727    /// 成功时间
728    success_time: i64,
729    /// 支付金额
730    total: f64,
731    /// 退款金额
732    refund: f64,
733    /// 实际支付金额
734    payer_total: f64,
735    /// 实际退款金额
736    payer_refund: f64,
737    /// 状态
738    status: RefundStatus,
739}
740
741impl RefundNotify {
742    pub fn json(&self) -> JsonValue {
743        object! {
744            "out_trade_no" => self.out_trade_no.clone(),
745            "sp_mchid" => self.sp_mchid.clone(),
746            "sub_mchid" => self.sub_mchid.clone(),
747            "transaction_id" => self.transaction_id.clone(),
748            "success_time" => self.success_time,
749            "total" => self.total,
750            "refund" => self.refund,
751            "payer_total" => self.payer_total,
752            "payer_refund" => self.payer_refund,
753            "status" => self.status.to_string(),
754            "refund_no"=>self.refund_no.clone(),
755            "refund_id"=>self.refund_id.clone()
756        }
757    }
758}
759
760#[derive(Debug, Clone)]
761pub enum Types {
762    /// JS支付
763    Jsapi,
764    /// 扫码支付
765    Native,
766    /// H5页面
767    H5,
768    /// 小程序
769    MiniJsapi,
770    /// App
771    App,
772    /// 付款码
773    Micropay,
774}
775impl Types {
776    pub fn str(self) -> &'static str {
777        match self {
778            Types::Jsapi => "jsapi",
779            Types::Native => "native",
780            Types::H5 => "h5",
781            Types::MiniJsapi => "minijsapi",
782            Types::App => "app",
783            Types::Micropay => "micropay"
784        }
785    }
786    pub fn from(name: &str) -> Self {
787        match name {
788            "jsapi" => Types::Jsapi,
789            "native" => Types::Native,
790            "h5" => Types::H5,
791            "minijsapi" => Types::MiniJsapi,
792            "app" => Types::App,
793            "micropay" => Types::Micropay,
794            _ => Types::Jsapi
795        }
796    }
797}