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