1use chrono::Local;
2use json::{object, JsonValue};
3use crate::{PayMode, Types};
4
5#[derive(Clone, Debug)]
7pub struct Yrcc {
8 pub appid: String,
10 pub secret: String,
12 pub terminal_number: String,
14 pub sp_mchid: String,
16 pub service_provider: String,
18 pub key_name: String,
20 pub app_private: String,
22 pub app_public: String,
24 pub notify_url: String,
26
27}
28impl Yrcc {
29 pub fn http(&mut self, service: &str, mut body: JsonValue) -> Result<JsonValue, String> {
30
31 let now = Local::now();
33 let formatted = now.format("%Y%m%d%H%M%S").to_string();
34 body["seqNo"] = formatted.into();
35 let _sign = "4A227003C3D07580397471B80E4B8384D036BBB7D5D8A7B1A84173EA555455EC688C04E9B3F2AF0E0FEE7C349E6D1252859FDA66A928123F70BCD68064AAAC83";
36 let sign = self.sign(body.clone())?;
37 let mut http = br_reqwest::Client::new();
47 let url = format!("https://cloud.ynrcc.com/YNCashier/acqu/nosign/{service}");
48 let send = http.post(url.as_str()).raw_json(object! {
50 request:body
51 });
52 match send.header("ynrcc-cert", self.key_name.as_str()).header("ynrcc-sign", &sign).send()?.json() {
53 Ok(e) => {
54 if !e.has_key("response") {
55 return Err("响应格式错误".to_string());
56 }
57 let response = e["response"].clone();
58 let code = response["code"].as_str().unwrap_or("");
59 if code != "000000" {
60 return Err(response["msg"].to_string());
61 }
62 println!("{:#}", e["response"]);
63 Ok(e)
64 }
65 Err(e) => Err(e)
66 }
67 }
68
69 fn sign(&self, body: JsonValue) -> Result<String, String> {
70 let body_str = body.to_string();
71 let r = br_crypto::sha256::encrypt_byte(body_str.as_bytes());
72 let res = br_crypto::sm2::sign_rs(&self.app_private.clone(), &r);
73 Ok(res.to_uppercase())
74 }
75}
76impl PayMode for Yrcc {
77 fn get_sub_mchid(&mut self, _sub_mchid: &str) -> Result<JsonValue, String> {
78 todo!()
79 }
80
81 fn notify(&mut self, _data: JsonValue) -> Result<JsonValue, String> {
82 todo!()
83 }
84
85 fn config(&mut self) -> JsonValue {
86 todo!()
87 }
88
89 fn login(&mut self, _code: &str) -> Result<JsonValue, String> {
90 todo!()
91 }
92
93 fn auth(&mut self, _code: &str) -> Result<JsonValue, String> {
94 todo!()
95 }
96
97 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> {
98 let service = match types {
99 Types::Jsapi => "MPCreateTrade",
100 Types::Native => "",
101 Types::H5 => "",
102 Types::MiniJsapi => "MPCreateTrade",
103 Types::App => "",
104 Types::Micropay => ""
105 };
106 let now = Local::now();
108 let formatted = now.format("%Y%m%d%H%M%S").to_string();
109
110 let total = format!("{:.0}", total_fee * 100.0);
111 let body = object! {
112 "service"=>service,
113 "apiVersion"=>"1.1.0",
114 "tranCode"=>"120201",
115 "merId"=>self.sp_mchid.clone(),
116 "temId"=>self.terminal_number.clone(),
117 "accessProviderCode" => self.service_provider.clone(),
118 "seqNo"=>"",
119 "txnTime"=> formatted,
120 "tradeNo"=>out_trade_no,
121 "tradeChannel"=>"01",
122 "businessType"=>"001",
123 "totalAmt"=> total,
124 "totalNum"=>1,
125 "orderDesc"=>description,
126 "onlineFlag"=>"1",
127 "eventFlag"=>"1",
128 "ccy"=>"156",
129 "subOpenId"=>sp_openid,
130 "subAppId"=>self.appid.clone(),
131 "notifyUrl"=>self.notify_url.clone(),
132 };
133 match self.http(service, body) {
134 Ok(e) => {
135 match types {
136 Types::Native => {
137 if e.has_key("code_url") {
138 Ok(e["code_url"].clone())
139 } else {
140 Err(e["message"].to_string())
141 }
142 }
143 Types::Jsapi | Types::MiniJsapi => {
144 if e.has_key("prepay_id") {
145 let signinfo = "".into();
147 Ok(signinfo)
148 } else {
149 Err(e["message"].to_string())
150 }
151 }
152 _ => {
153 Ok(e)
154 }
155 }
156 }
157 Err(e) => Err(e),
158 }
159 }
160
161 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> {
162 todo!()
163 }
164
165 fn close(&mut self, _out_trade_no: &str, _sub_mchid: &str) -> Result<JsonValue, String> {
166 todo!()
167 }
168
169 fn pay_query(&mut self, _out_trade_no: &str, _sub_mchid: &str) -> Result<JsonValue, String> {
170 todo!()
171 }
172
173 fn pay_micropay_query(&mut self, _out_trade_no: &str, _sub_mchid: &str) -> Result<JsonValue, String> {
174 todo!()
175 }
176
177 fn pay_notify(&mut self, _nonce: &str, _ciphertext: &str, _associated_data: &str) -> Result<JsonValue, String> {
178 todo!()
179 }
180
181 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> {
182 todo!()
183 }
184
185 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> {
186 todo!()
187 }
188
189 fn refund_notify(&mut self, _nonce: &str, _ciphertext: &str, _associated_data: &str) -> Result<JsonValue, String> {
190 todo!()
191 }
192
193 fn refund_query(&mut self, _trade_no: &str, _out_refund_no: &str, _sub_mchid: &str) -> Result<JsonValue, String> {
194 todo!()
195 }
196 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> {
197 todo!()
198 }
199}