wechat_pay_rust_sdk/
response.rs

1use serde::de::DeserializeOwned;
2use serde::{Deserialize, Serialize};
3
4pub trait ResponseTrait: DeserializeOwned {}
5
6#[derive(Debug, Deserialize)]
7pub struct NativeResponse {
8    pub code: Option<String>,
9    pub message: Option<String>,
10    ///【支付跳转链接】 h5_url为拉起微信支付收银台的中间页面,可通过访问该URL来拉起微信客户端,完成支付,h5_url的有效期为5分钟。
11    pub code_url: Option<String>,
12}
13
14impl ResponseTrait for NativeResponse {}
15
16#[derive(Debug, Deserialize)]
17pub struct JsapiResponse {
18    pub code: Option<String>,
19    pub message: Option<String>,
20    ///【预支付交易会话标识】 预支付交易会话标识。用于后续接口调用中使用,该值有效期为2小时
21    pub prepay_id: Option<String>,
22    ///【签名数据】
23    pub sign_data: Option<SignData>,
24}
25
26#[derive(Debug, Serialize, Deserialize)]
27pub struct SignData {
28    pub app_id: String,
29    pub sign_type: String,
30    pub package: String,
31    pub nonce_str: String,
32    pub timestamp: String,
33    pub pay_sign: String,
34}
35
36impl ResponseTrait for JsapiResponse {}
37
38#[derive(Debug, Deserialize)]
39pub struct AppResponse {
40    pub code: Option<String>,
41    pub message: Option<String>,
42    ///【预支付交易会话标识】 预支付交易会话标识。用于后续接口调用中使用,该值有效期为2小时
43    pub prepay_id: Option<String>,
44    ///【签名数据】
45    pub sign_data: Option<SignData>,
46}
47
48impl ResponseTrait for AppResponse {}
49
50#[derive(Debug, Deserialize)]
51pub struct MicroResponse {
52    pub code: Option<String>,
53    pub message: Option<String>,
54    ///【预支付交易会话标识】 预支付交易会话标识。用于后续接口调用中使用,该值有效期为2小时
55    pub prepay_id: Option<String>,
56    ///【签名数据】
57    pub sign_data: Option<SignData>,
58}
59
60impl ResponseTrait for MicroResponse {}
61
62#[derive(Debug, Deserialize)]
63pub struct H5Response {
64    pub code: Option<String>,
65    pub message: Option<String>,
66    ///【二维码链接】 此URL用于生成支付二维码,然后提供给用户扫码支付。
67    /// 注意:code_url并非固定值,使用时按照URL格式转成二维码即可。
68    pub h5_url: Option<String>,
69}
70
71impl ResponseTrait for H5Response {}
72
73#[derive(Debug, Clone, Deserialize)]
74pub struct EncryptCertificate {
75    pub algorithm: String,
76    pub nonce: String,
77    pub associated_data: String,
78    pub ciphertext: String,
79}
80
81#[derive(Debug, Clone, Deserialize)]
82pub struct Certificate {
83    pub serial_no: String,
84    pub effective_time: String,
85    pub expire_time: String,
86    pub encrypt_certificate: EncryptCertificate,
87}
88
89#[derive(Debug, Deserialize)]
90pub struct CertificateResponse {
91    pub data: Option<Vec<Certificate>>,
92}
93
94impl ResponseTrait for CertificateResponse {}
95
96#[derive(Deserialize, Debug)]
97#[serde(untagged, bound = "T: ResponseTrait + DeserializeOwned")]
98pub enum WeChatResponse<T>
99where
100    T: ResponseTrait + DeserializeOwned,
101{
102    Ok(T),
103    Err(ErrorResponse),
104}
105
106impl<T> ResponseTrait for WeChatResponse<T> where T: ResponseTrait + DeserializeOwned {}
107
108impl<T> WeChatResponse<T>
109where
110    T: ResponseTrait + DeserializeOwned,
111{
112    pub fn is_success(&self) -> bool {
113        matches!(self, WeChatResponse::Ok(_))
114    }
115
116    pub fn ok(&self) -> Option<&T> {
117        if let WeChatResponse::Ok(response) = self {
118            Some(response)
119        } else {
120            None
121        }
122    }
123
124    pub fn err(&self) -> Option<&ErrorResponse> {
125        if let WeChatResponse::Err(error_response) = self {
126            Some(error_response)
127        } else {
128            None
129        }
130    }
131}
132
133#[derive(Deserialize, Debug)]
134pub struct ErrorResponse {
135    /// 【错误码】 错误码
136    pub code: Option<String>,
137    /// 【错误信息】 错误信息
138    pub message: Option<String>,
139}
140
141#[derive(Debug, Deserialize)]
142pub struct RefundsResponse {
143    /// 【微信支付退款单号】申请退款受理成功时,该笔退款单在微信支付侧生成的唯一标识。
144    pub refund_id: String,
145    /// 【商户退款单号】 商户申请退款时传的商户系统内部退款单号。
146    pub out_refund_no: String,
147    /// 【微信支付订单号】微信支付侧订单的唯一标识。
148    pub transaction_id: String,
149    /// 【商户订单号】 商户下单时传入的商户系统内部订单号。
150    pub out_trade_no: String,
151    /// 【退款渠道】 订单退款渠道
152    /// 以下枚举:
153    /// ORIGINAL: 原路退款
154    /// BALANCE: 退回到余额
155    /// OTHER_BALANCE: 原账户异常退到其他余额账户
156    /// OTHER_BANKCARD: 原银行卡异常退到其他银行卡(发起异常退款成功后返回)
157    pub channel: String,
158    /// 【退款入账账户】 取当前退款单的退款入账方,有以下几种情况:
159    /// 1)退回银行卡:{银行名称}{卡类型}{卡尾号}
160    /// 2)退回支付用户零钱:支付用户零钱
161    /// 3)退还商户:商户基本账户商户结算银行账户
162    /// 4)退回支付用户零钱通:支付用户零钱通
163    /// 5)退回支付用户银行电子账户:支付用户银行电子账户
164    /// 6)退回支付用户零花钱:支付用户零花钱
165    /// 7)退回用户经营账户:用户经营账户
166    /// 8)退回支付用户来华零钱包:支付用户来华零钱包
167    /// 9)退回企业支付商户:企业支付商户
168    pub user_received_account: String,
169    /// 【退款成功时间】
170    /// 1、定义:退款成功的时间,该字段在退款状态status为SUCCESS(退款成功)时返回。
171    /// 2、格式:遵循rfc3339标准格式:yyyy-MM-DDTHH:mm:ss+TIMEZONE。yyyy-MM-DD 表示年月日;T 字符用于分隔日期和时间部分;HH:mm:ss 表示具体的时分秒;TIMEZONE 表示时区(例如,+08:00 对应东八区时间,即北京时间)。
172    /// 示例:2015-05-20T13:29:35+08:00 表示北京时间2015年5月20日13点29分35秒。
173    pub success_time: Option<String>,
174    /// 【退款创建时间】
175    /// 1、定义:提交退款申请成功,微信受理退款申请单的时间。
176    /// 2、格式:遵循rfc3339标准格式:yyyy-MM-DDTHH:mm:ss+TIMEZONE。yyyy-MM-DD 表示年月日;T 字符用于分隔日期和时间部分;HH:mm:ss 表示具体的时分秒;TIMEZONE 表示时区(例如,+08:00 对应东八区时间,即北京时间)。
177    /// 示例:2015-05-20T13:29:35+08:00 表示北京时间2015年5月20日13点29分35秒。
178    pub create_time: String,
179    /// 【退款状态】退款单的退款处理状态。
180    /// SUCCESS: 退款成功
181    /// CLOSED: 退款关闭
182    /// PROCESSING: 退款处理中
183    /// ABNORMAL: 退款异常,退款到银行发现用户的卡作废或者冻结了,导致原路退款银行卡失败,可前往商户平台-交易中心,手动处理此笔退款,可参考: 退款异常的处理,或者通过发起异常退款接口进行处理。
184    /// 注:状态流转说明请参考状态流转图
185    pub status: String,
186    /// 【资金账户】 退款所使用资金对应的资金账户类型
187    /// UNSETTLED: 未结算资金
188    /// AVAILABLE: 可用余额
189    /// UNAVAILABLE: 不可用余额
190    /// OPERATION: 运营账户
191    /// BASIC: 基本账户(含可用余额和不可用余额)
192    /// ECNY_BASIC: 数字人民币基本账户
193    pub funds_account: String,
194    /// 【金额信息】订单退款金额信息
195    pub amount: RefundsAmountResponse,
196    /// 【优惠退款详情】 订单各个代金券的退款详情,订单使用了代金券且代金券发生退款时返回。
197    pub promotion_detail: Option<Vec<RefundsPromotionDetailResponse>>,
198}
199
200impl ResponseTrait for RefundsResponse {}
201
202#[derive(Debug, Deserialize)]
203pub struct RefundsAmountResponse {
204    /// 【订单金额】 订单总金额,单位为分
205    pub total: i32,
206    /// 【退款金额】退款金额,单位为分,只能为整数,可以做部分退款,不能超过原订单支付金额。
207    pub refund: i32,
208    /// 【退款出资账户及金额】 退款出资的账户类型及金额信息,若此接口请求时未传该参数,则不会返回。
209    pub from: Option<Vec<RefundsFromResponse>>,
210    /// 【用户实际支付金额】用户现金支付金额,整型,单位为分,例如10元订单用户使用了2元全场代金券,则该金额为用户实际支付的8元。
211    pub payer_total: i32,
212    /// 【用户退款金额】 指用户实际收到的现金退款金额,数据类型为整型,单位为分。例如在一个10元的订单中,用户使用了2元的全场代金券,若商户申请退款5元,则用户将收到4元的现金退款(即该字段所示金额)和1元的代金券退款。
213    /// 注:部分退款用户无法继续使用代金券,只有在订单全额退款且代金券未过期的情况下,且全场券属于银行立减金用户才能继续使用代金券。
214    /// 详情参考含优惠退款说明。
215    pub payer_refund: i32,
216    /// 【应结退款金额】 去掉免充值代金券退款金额后的退款金额,整型,单位为分,例如10元订单用户使用了2元全场代金券(一张免充值1元 + 一张预充值1元),商户申请退款5元,则该金额为 退款金额5元 - 0.5元免充值代金券退款金额 = 4.5元。
217    pub settlement_refund: i32,
218    /// 【应结订单金额】去除免充值代金券金额后的订单金额,整型,单位为分,例如10元订单用户使用了2元全场代金券(一张免充值1元 + 一张预充值1元),则该金额为 订单金额10元 - 免充值代金券金额1元 = 9元。
219    pub settlement_total: i32,
220    /// 【优惠退款金额】 申请退款后用户收到的代金券退款金额,整型,单位为分,例如10元订单用户使用了2元全场代金券,商户申请退款5元,用户收到的是4元现金 + 1元代金券退款金额(该字段) 。
221    pub discount_refund: i32,
222    /// 【退款币种】 固定返回:CNY,代表人民币。
223    pub currency: String,
224    /// 【手续费退款金额】 订单退款时退还的手续费金额,整型,单位为分,例如一笔100元的订单收了0.6元手续费,商户申请退款50元,该金额为等比退还的0.3元手续费。
225    pub refund_fee: Option<i32>,
226}
227
228#[derive(Debug, Deserialize)]
229pub struct RefundsFromResponse {
230    /// 【出资账户类型】下面枚举值多选一。
231    /// 枚举值:
232    /// AVAILABLE : 可用余额
233    /// UNAVAILABLE : 不可用余额
234    pub account: String,
235    /// 【出资金额】 对应账户出资金额,单位为分
236    pub amount: i32,
237}
238
239#[derive(Debug, Deserialize)]
240pub struct RefundsPromotionDetailResponse {
241    /// 【券ID】代金券id,单张代金券的编号
242    pub promotion_id: String,
243    /// 【优惠范围】优惠活动中代金券的适用范围,分为两种类型:
244    /// GLOBAL:全场代金券-以订单整体可优惠的金额为优惠门槛的代金券;
245    /// SINGLE:单品优惠-以订单中具体某个单品的总金额为优惠门槛的代金券
246    pub scope: String,
247    /// 【优惠类型】代金券资金类型,优惠活动中代金券的结算资金类型,分为两种类型:
248    /// CASH:预充值-带有结算资金的代金券,会随订单结算给订单收款商户;
249    /// NOCASH:免充值-不带有结算资金的代金券,无资金结算给订单收款商户。
250    pub r#type: String,
251    /// 【代金券面额】 代金券优惠的金额
252    pub amount: i32,
253    /// 【优惠退款金额】 代金券退款的金额
254    pub refund_amount: i32,
255    /// 【退款商品】 指定商品退款时传的退款商品信息。
256    pub goods_detail: Option<Vec<RefundsGoodsDetailResponse>>,
257}
258
259#[derive(Debug, Deserialize)]
260pub struct RefundsGoodsDetailResponse {
261    /// 【商户侧商品编码】 申请退款的商户侧商品编码。
262    pub merchant_goods_id: Option<String>,
263    /// 【微信侧商品编码】 申请退款的微信侧商品编码。(申请退款时没传则不返回)
264    pub wechatpay_goods_id: Option<String>,
265    /// 【商品名称】 申请退款的商品名称。(申请退款时没传则不返回)
266    pub goods_name: Option<String>,
267    /// 【商品单价】 申请退款的商品单价。
268    pub unit_price: i32,
269    /// 【商品退款金额】 申请退款的商品退款金额。
270    pub refund_amount: i32,
271    /// 【商品退货数量】 申请退款的商品退货数量。
272    pub refund_quantity: i32,
273}