sd_model.rs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784
  1. //! 盛大数据模型
  2. use crate::{
  3. backend::{self},
  4. config::Config,
  5. gmssl, Sign, Verify,
  6. };
  7. use anyhow::Context;
  8. use axum::{response::IntoResponse, Json};
  9. use md5::{Digest, Md5};
  10. use serde::de::DeserializeOwned;
  11. #[derive(serde::Serialize, serde::Deserialize, Debug)]
  12. #[serde(rename_all = "camelCase")]
  13. pub struct PubReqHead {
  14. pub app_id: String,
  15. pub method: String,
  16. pub sign_type: String,
  17. pub sign: String,
  18. pub timestamp: String, // yyyy-MM-dd HH:mm:ss
  19. pub version: String,
  20. pub request_id: String,
  21. pub biz_content: String,
  22. }
  23. pub trait TryFromPubHeadConfig: Sized {
  24. fn try_from_pub_req_head_config(head: &PubReqHead, config: &Config) -> anyhow::Result<Self>;
  25. }
  26. impl<T> TryFromPubHeadConfig for T
  27. where
  28. T: Sized + DeserializeOwned + crate::Verify,
  29. {
  30. fn try_from_pub_req_head_config(head: &PubReqHead, config: &Config) -> anyhow::Result<Self> {
  31. let req: T = head.decopy(config)?;
  32. req.verify(config).context("验证出错")?;
  33. Ok(req)
  34. }
  35. }
  36. impl crate::Verify for PubReqHead {
  37. #[tracing::instrument(skip_all, fields(PubReqHead=?self))]
  38. fn verify(&self, config: &Config) -> anyhow::Result<()> {
  39. if self.sign_type != "md5"
  40. || self.app_id != config.sd_config.app_id
  41. || self.method != "sd.tovc.recharge"
  42. {
  43. return Err(anyhow::Error::msg("PubReqHead Verify Value Error"));
  44. }
  45. match hex::decode(&self.sign) {
  46. Ok(o) => {
  47. let new_sign = self.sign_var(config);
  48. if o == new_sign {
  49. Ok(())
  50. } else {
  51. Err(anyhow::Error::msg("sign 不匹配"))
  52. }
  53. }
  54. Err(e) => {
  55. tracing::error!("verify: {self:?} error: {e}");
  56. Err(anyhow::Error::msg(format!(
  57. "PubReqHead Verify Value sign hex::decode Error: {e:#?}"
  58. )))
  59. }
  60. }
  61. }
  62. }
  63. impl Default for PubReqHead {
  64. fn default() -> Self {
  65. let time_format = time::macros::format_description!(
  66. "[year]-[month padding:zero]-[day padding:zero] [hour padding:zero]:[minute padding:zero]:[second padding:zero]"
  67. );
  68. let offset = time::UtcOffset::from_hms(8, 0, 0).unwrap();
  69. let now = time::OffsetDateTime::now_utc().to_offset(offset);
  70. Self {
  71. app_id: "".to_string(),
  72. method: "".to_string(),
  73. sign_type: "md5".to_string(),
  74. sign: "".to_string(),
  75. timestamp: now.format(time_format).unwrap(),
  76. version: "v1.0".to_string(),
  77. request_id: "".to_string(),
  78. biz_content: "".to_string(),
  79. }
  80. }
  81. }
  82. macro_rules! str_per {
  83. ( $($p:ident).*) => {
  84. (str_per!(@internal $($p).*), $($p).*)
  85. };
  86. (@internal $p:ident ) => {
  87. {
  88. let s = stringify!($p);
  89. let mut str = String::new();
  90. let mut capitalize = false;
  91. for i in s.chars(){
  92. if i == '_'{
  93. capitalize = true;
  94. }else if capitalize {
  95. str.push(i.to_ascii_uppercase());
  96. capitalize = false;
  97. }else{
  98. str.push(i)
  99. }
  100. }
  101. str
  102. }
  103. };
  104. (@internal $_p:ident.$($p:ident).*) => {
  105. str_per!(@internal $($p).*)
  106. };
  107. }
  108. macro_rules! bt_map {
  109. ( $( ($k:expr, $v:expr) ),* $(,)?) => {
  110. {
  111. let mut map = std::collections::BTreeMap::new();
  112. $(
  113. map.insert($k, $v)
  114. )*
  115. map
  116. }
  117. };
  118. ($($k:expr),* $(,)?) => {
  119. {
  120. let mut map = std::collections::BTreeMap::new();
  121. $(
  122. let entry: (_,_) = $k;
  123. map.insert(entry.0, entry.1);
  124. )*
  125. map
  126. }
  127. }
  128. }
  129. impl PubReqHead {
  130. pub fn encrypt_sign<T>(&mut self, config: &Config, data: T) -> anyhow::Result<()>
  131. where
  132. T: serde::Serialize,
  133. {
  134. let data = serde_json::to_string(&data)?;
  135. let key = config
  136. .sd_config
  137. .get_pk()
  138. .context("PayReqHead::encrypt_sign")?;
  139. let r = key.encrypt(data, gmssl::sm2::PassOrder::C1C3C2)?;
  140. let data = hex::encode(r);
  141. self.biz_content = data;
  142. self.sign(config);
  143. Ok(())
  144. }
  145. pub fn decopy<T>(&self, config: &Config) -> anyhow::Result<T>
  146. where
  147. T: for<'a> serde::Deserialize<'a>,
  148. {
  149. let key = config.sd_config.get_sk().context("PayReqHead::decopy")?;
  150. let data = hex::decode(&self.biz_content).context("hex::decode Error")?;
  151. let s = key
  152. .decrypt(data, gmssl::sm2::PassOrder::C1C3C2)
  153. .context("解密 biz_content")?;
  154. serde_json::from_slice(&s).context("反序列化 biz_content")
  155. }
  156. fn sign(&mut self, config: &Config) {
  157. self.sign = hex::encode_upper(self.sign_var(config))
  158. }
  159. pub fn sign_var(&self, config: &Config) -> Vec<u8> {
  160. let mut aa = Md5::new();
  161. let s = self.format_str(config);
  162. aa.update(s);
  163. let r = aa.finalize().to_vec();
  164. tracing::debug!("{self:?} Sing:{}", hex::encode(&r));
  165. r
  166. }
  167. pub fn format_str(&self, config: &Config) -> String {
  168. let Self {
  169. app_id,
  170. method,
  171. sign_type,
  172. sign,
  173. timestamp,
  174. version,
  175. request_id,
  176. biz_content,
  177. } = self;
  178. let map = bt_map!(
  179. str_per!(app_id),
  180. str_per!(method),
  181. str_per!(sign_type),
  182. str_per!(sign),
  183. str_per!(timestamp),
  184. str_per!(version),
  185. str_per!(request_id),
  186. str_per!(biz_content)
  187. );
  188. let items: Vec<_> = map
  189. .into_iter()
  190. .map(|(k, v)| (k.trim().to_owned(), v.trim().to_owned()))
  191. .filter(|(k, v)| !v.is_empty() && k != "sign")
  192. .map(|(k, v)| format!("{}={}", k, v))
  193. .collect();
  194. let mut result = items.join("&");
  195. result.push('&');
  196. result.push_str(&format!("key={}", config.sd_config.sin_key));
  197. result
  198. }
  199. }
  200. #[derive(serde::Serialize, serde::Deserialize, Debug)]
  201. #[serde(rename_all = "camelCase")]
  202. pub struct PayReqBody {
  203. pub game_user_id: String,
  204. pub server_type: String,
  205. pub product_no: String,
  206. pub sp_order_id: String,
  207. pub source: String,
  208. }
  209. impl crate::Verify for PayReqBody {
  210. fn verify(&self, _: &Config) -> anyhow::Result<()> {
  211. if self.server_type != "tel" {
  212. return Err(anyhow::Error::msg("仅支持话费"));
  213. }
  214. Ok(())
  215. }
  216. }
  217. impl PayReqBody {
  218. pub fn into_backend_pay_req(
  219. &self,
  220. head: &PubReqHead,
  221. config: &Config,
  222. ) -> backend::Body<backend::PayReqBody> {
  223. let timestamp = head.timestamp.trim().replace(
  224. |c: char| c.is_whitespace() || c == '-' || c == '_' || c == ':',
  225. "",
  226. );
  227. let mut body = backend::Body {
  228. header: backend::Header {
  229. timestamp,
  230. seqno: head.request_id.clone(),
  231. appid: config.fscg_config.app_id.clone(),
  232. ..Default::default()
  233. },
  234. msgbody: backend::PayReqBody {
  235. content: Some(backend::PayReqContent {
  236. user: self.game_user_id.clone(),
  237. packageid: self.product_no.clone(),
  238. extorder: self.sp_order_id.clone(),
  239. note: Some(self.source.clone()),
  240. ..Default::default()
  241. }),
  242. resp: None,
  243. },
  244. };
  245. body.sign(config);
  246. body
  247. }
  248. }
  249. #[derive(serde::Serialize, serde::Deserialize, Debug)]
  250. #[serde(rename_all = "camelCase")]
  251. pub struct PayRespBodyData {
  252. state: String,
  253. order_cash: String,
  254. order_id: String,
  255. sp_order_id: String,
  256. game_user_id: String,
  257. product_name: String,
  258. }
  259. pub type PayRespBody = PubRespBody<PayRespBodyData>;
  260. impl PayRespBody {
  261. pub fn from_backend_pay_resp(
  262. config: &Config,
  263. body: backend::Body<backend::PayRespBody>,
  264. req: &PayReqBody,
  265. ) -> Self {
  266. if let Err(e) = body.verify(config) {
  267. // return Self::error("99", "服务响应验证错误");
  268. return Self::error("99", format!("服务响应验证错误: {:#?}", e));
  269. }
  270. let resp = match body.msgbody.resp {
  271. Some(resp) => resp,
  272. None => {
  273. return Self::error("99", "服务没有响应字段: resp");
  274. }
  275. };
  276. let content = match body.msgbody.content {
  277. Some(content) => content,
  278. None => {
  279. return Self::error(
  280. resp.rcode,
  281. resp.rmsg.unwrap_or("服务没有响应字段: content".to_string()),
  282. );
  283. }
  284. };
  285. let state = if resp.rcode == "00" {
  286. "0".to_string()
  287. } else {
  288. "9".to_string()
  289. };
  290. Self::success(PayRespBodyData {
  291. state,
  292. order_cash: "".to_string(),
  293. order_id: content.orderid,
  294. sp_order_id: content.extorder,
  295. game_user_id: req.game_user_id.clone(),
  296. product_name: req.product_no.clone(),
  297. })
  298. }
  299. }
  300. impl crate::Sign for PayRespBody {
  301. fn sign(&mut self, _: &Config) {}
  302. }
  303. #[derive(serde::Serialize, serde::Deserialize, Debug)]
  304. #[serde(rename_all = "camelCase")]
  305. pub struct BalanceRespBody {
  306. pub result_code: String,
  307. pub result_desc: String,
  308. pub balance: Option<String>,
  309. }
  310. impl BalanceRespBody {
  311. pub fn from_backend_account_resp(
  312. config: &Config,
  313. body: backend::Body<backend::AccountRespBody>,
  314. ) -> Self {
  315. if let Err(e) = body.verify(config) {
  316. return Self::error("99", format!("服务响应验证错误: {:#?}", e));
  317. }
  318. let resp = match body.msgbody.resp {
  319. Some(resp) => resp,
  320. None => {
  321. return Self::error("99", "服务没有响应字段: resp");
  322. }
  323. };
  324. let content = match body.msgbody.content {
  325. Some(content) => content,
  326. None => {
  327. return Self::error(
  328. resp.rcode,
  329. resp.rmsg.unwrap_or("服务没有响应字段: content".to_string()),
  330. );
  331. }
  332. };
  333. Self::success(content.balance)
  334. }
  335. pub fn success(data: impl Into<Option<String>>) -> Self {
  336. Self {
  337. result_code: "000".to_string(),
  338. result_desc: "success".to_string(),
  339. balance: data.into(),
  340. }
  341. }
  342. pub fn error(code: impl ToString, desc: impl ToString) -> Self {
  343. Self {
  344. result_code: code.to_string(),
  345. result_desc: desc.to_string(),
  346. balance: None,
  347. }
  348. }
  349. }
  350. impl crate::Sign for BalanceRespBody {
  351. fn sign(&mut self, _: &Config) {}
  352. }
  353. #[derive(serde::Serialize, serde::Deserialize, Debug)]
  354. #[serde(rename_all = "camelCase")]
  355. pub struct BalanceReqBody {
  356. source: String,
  357. }
  358. impl BalanceReqBody {
  359. pub fn into_backend_account_req(
  360. &self,
  361. config: &Config,
  362. head: &PubReqHead,
  363. ) -> backend::Body<backend::AccountReqBody> {
  364. let backend_req = backend::AccountReqBody::new();
  365. let mut body = backend::Body {
  366. header: backend::Header {
  367. seqno: head.request_id.clone(),
  368. appid: config.fscg_config.app_id.clone(),
  369. ..Default::default()
  370. },
  371. msgbody: backend_req,
  372. };
  373. body.sign(config);
  374. body
  375. }
  376. }
  377. impl crate::Verify for BalanceReqBody {
  378. fn verify(&self, _: &Config) -> anyhow::Result<()> {
  379. if self.source == "SD" {
  380. Ok(())
  381. } else {
  382. Err(anyhow::Error::msg("BalanceReqBody Verify False"))
  383. }
  384. }
  385. }
  386. #[derive(serde::Serialize, serde::Deserialize, Debug)]
  387. #[serde(rename_all = "camelCase")]
  388. pub struct SearchReqBody {
  389. sp_order_id: String,
  390. }
  391. impl SearchReqBody {
  392. pub fn into_backend_search_req(
  393. &self,
  394. head: &PubReqHead,
  395. config: &Config,
  396. ) -> backend::Body<backend::SearchReqBody> {
  397. let mut body = backend::Body {
  398. header: backend::Header {
  399. seqno: head.request_id.clone(),
  400. appid: config.fscg_config.app_id.clone(),
  401. ..Default::default()
  402. },
  403. msgbody: backend::SearchReqBody {
  404. content: Some(backend::SearchReqContent {
  405. // orderid: Some(req.sp_order_id.clone()),
  406. extorderid: Some(self.sp_order_id.clone()),
  407. ..Default::default()
  408. }),
  409. resp: None,
  410. },
  411. };
  412. body.sign(config);
  413. body
  414. }
  415. }
  416. impl crate::Verify for SearchReqBody {}
  417. #[derive(serde::Serialize, serde::Deserialize, Debug)]
  418. #[serde(rename_all = "camelCase")]
  419. pub struct SearchRespData {
  420. state: String,
  421. message: String,
  422. success_time: Option<String>,
  423. order_id: String,
  424. sp_order_id: String,
  425. game_user_id: String,
  426. operator_order: Option<String>,
  427. card_no: Option<String>, // 卡密
  428. card_pwd: Option<String>, // 卡密
  429. effective_time: Option<String>, // 卡密
  430. }
  431. pub type SearchRespBody = PubRespBody<SearchRespData>;
  432. impl SearchRespBody {
  433. pub fn from_backend_search_resp(
  434. config: &Config,
  435. body: backend::Body<backend::SearchRespBody>,
  436. ) -> Self {
  437. if let Err(e) = body.verify(config) {
  438. Self::error("99", format!("服务响应验证错误: {:#?}", e));
  439. }
  440. let resp = match body.msgbody.resp {
  441. Some(resp) => resp,
  442. None => {
  443. return Self::error("99", "服务没有响应字段: resp".to_string());
  444. }
  445. };
  446. let content = match body.msgbody.content {
  447. Some(content) => content,
  448. None => {
  449. return Self::error(
  450. resp.rcode,
  451. resp.rmsg.unwrap_or("服务没有响应字段: content".to_string()),
  452. );
  453. }
  454. };
  455. let state = if content.status == "6" {
  456. "1"
  457. } else if content.status == "4" {
  458. "9"
  459. } else {
  460. "0"
  461. };
  462. let time_str = if content.checktime.is_empty() {
  463. None
  464. } else {
  465. let time_format = time::macros::format_description!("[year]-[month padding:zero]-[day padding:zero] [hour padding:zero]:[minute padding:zero]:[second padding:zero]");
  466. let backend_time = time::macros::format_description!("[year][month padding:zero][day padding:zero][hour padding:zero][minute padding:zero][second padding:zero][subsecond digits:1+]");
  467. let time = time::PrimitiveDateTime::parse(&content.checktime, backend_time).unwrap();
  468. let time_str = time.format(time_format).unwrap();
  469. Some(time_str)
  470. };
  471. let data = SearchRespData {
  472. state: state.to_string(),
  473. message: content.msg,
  474. success_time: time_str,
  475. order_id: content.orderid,
  476. sp_order_id: content.extorder,
  477. game_user_id: content.user,
  478. operator_order: content.attr1,
  479. card_no: None,
  480. card_pwd: None,
  481. effective_time: None,
  482. };
  483. Self::success(data)
  484. }
  485. }
  486. impl crate::Sign for SearchRespBody {
  487. fn sign(&mut self, _: &Config) {}
  488. }
  489. #[derive(serde::Serialize, serde::Deserialize, Debug)]
  490. #[serde(rename_all = "camelCase")]
  491. pub struct PubRespBody<T> {
  492. pub result_code: String,
  493. pub result_desc: String,
  494. pub data: Option<T>,
  495. }
  496. impl<T> PubRespBody<T> {
  497. pub fn success(data: T) -> Self {
  498. Self {
  499. result_code: "000".to_string(),
  500. result_desc: "success".to_string(),
  501. data: Some(data),
  502. }
  503. }
  504. pub fn error(code: impl ToString, desc: impl ToString) -> Self {
  505. Self {
  506. result_code: code.to_string(),
  507. result_desc: desc.to_string(),
  508. data: None,
  509. }
  510. }
  511. }
  512. #[derive(serde::Serialize, serde::Deserialize, Debug)]
  513. #[serde(rename_all = "camelCase")]
  514. pub struct PubRespHead {
  515. #[serde(default = "String::new")]
  516. pub code: String,
  517. #[serde(default = "String::new")]
  518. pub msg: String,
  519. #[serde(default = "String::new")]
  520. pub data: String,
  521. #[serde(default = "String::new")]
  522. pub sign: String,
  523. #[serde(default = "String::new")]
  524. pub request_id: String,
  525. }
  526. impl IntoResponse for PubRespHead {
  527. fn into_response(self) -> axum::response::Response {
  528. Json(self).into_response()
  529. }
  530. }
  531. impl PubRespHead {
  532. pub fn new(config: &Config, data: impl ToString, request_id: impl ToString) -> Self {
  533. let mut result = Self {
  534. data: data.to_string(),
  535. request_id: request_id.to_string(),
  536. ..Default::default()
  537. };
  538. result.sign(config);
  539. result
  540. }
  541. pub fn sign(&mut self, config: &Config) {
  542. self.sign = hex::encode_upper(self.sign_var(config))
  543. }
  544. pub fn sign_var(&self, config: &Config) -> Vec<u8> {
  545. let mut aa = Md5::new();
  546. let s = self.format_str(config);
  547. aa.update(&s);
  548. let r = aa.finalize().to_vec();
  549. tracing::debug!(sign = hex::encode(&r), data = s, "签名");
  550. r
  551. }
  552. pub fn format_str(&self, config: &Config) -> String {
  553. let Self {
  554. code,
  555. msg,
  556. data,
  557. sign,
  558. request_id,
  559. } = self;
  560. let map = bt_map!(
  561. str_per!(code),
  562. str_per!(msg),
  563. str_per!(data),
  564. str_per!(sign),
  565. str_per!(request_id),
  566. );
  567. let items: Vec<_> = map
  568. .into_iter()
  569. .map(|(k, v)| (k.trim().to_owned(), v.trim().to_owned()))
  570. .filter(|(k, v)| !v.is_empty() && k != "sign")
  571. .map(|(k, v)| format!("{}={}", k, v))
  572. .collect();
  573. let mut result = items.join("&");
  574. result.push('&');
  575. result.push_str(&format!("key={}", config.sd_config.sin_key));
  576. result
  577. }
  578. }
  579. impl Default for PubRespHead {
  580. fn default() -> Self {
  581. Self {
  582. code: "000".to_string(),
  583. msg: "success".to_string(),
  584. data: "".to_string(),
  585. sign: "".to_string(),
  586. request_id: "".to_string(),
  587. }
  588. }
  589. }
  590. #[derive(serde::Serialize, serde::Deserialize, Debug)]
  591. #[serde(rename_all = "camelCase")]
  592. pub struct CallbackReqBody {
  593. pub state: String,
  594. pub message: String,
  595. pub order_id: String,
  596. pub sp_order_id: String,
  597. pub game_user_id: String,
  598. pub operator_order: Option<String>,
  599. pub card_no: Option<String>,
  600. pub card_pwd: Option<String>,
  601. pub effective_time: Option<String>,
  602. }
  603. impl Default for CallbackReqBody {
  604. fn default() -> Self {
  605. Self {
  606. state: "".to_string(),
  607. message: "".to_string(),
  608. order_id: "".to_string(),
  609. sp_order_id: "".to_string(),
  610. game_user_id: "".to_string(),
  611. operator_order: None,
  612. card_no: None,
  613. card_pwd: None,
  614. effective_time: None,
  615. }
  616. }
  617. }
  618. #[derive(serde::Serialize, serde::Deserialize, Debug)]
  619. #[serde(rename_all = "camelCase")]
  620. pub struct CallbackRespBody {
  621. pub result_code: String,
  622. pub result_desc: String,
  623. }
  624. #[cfg(test)]
  625. #[allow(unused)]
  626. mod tests {
  627. use crate::config::SdConfig;
  628. use super::*;
  629. #[test]
  630. fn test_aaaa() {
  631. let s = "04f97e835ec530a95df4c999ab0184996b68464bf308239ebb692174812fb4c54349fc217ac5ab13ea8313e458e2cf37fa35345afc4290f8d25dc7c8bb37da1a0ff87a7752c8d03998067b3bf9fec1d7e397aba05fb016b3b48e269e9c87c22b6eef61508de4572c7dacd980530dac913f507ad9aa2a2a8c62edae35c21bf3aaa446168989a1350914499322ebb5b37038e432ed8f37e25083e35087b4fc1dbff3488c1e7cd7810712725a1fd78365a73892bf6b45352ca775b7b2e66a334ed93986728d2c2c78af2bbfaeb590d55a494163371c0c5df7";
  632. let head = PubReqHead{biz_content: s.to_string(), ..Default::default()};
  633. let cfg = Config::default();
  634. let r = head.decopy::<serde_json::Value>(&cfg);
  635. println!("{:#?}", r)
  636. }
  637. #[test]
  638. fn test_sign() {
  639. // 2C5A4C48A9BD07B79C250049A17C21C2
  640. // 2C5A4C48A9BD07B79C250049A17C21C2
  641. let mut a = PubReqHead {
  642. app_id: "asdaw".to_string(),
  643. method: "asdaw".to_string(),
  644. sign_type: "asdaw".to_string(),
  645. sign: "asdaw".to_string(),
  646. timestamp: "2023-03-23 16:25:00".to_string(),
  647. version: "asdaw".to_string(),
  648. request_id: "asdaw".to_string(),
  649. biz_content: "".to_string(),
  650. };
  651. let c = Default::default();
  652. a.sign(&c);
  653. println!("{a:?}");
  654. }
  655. #[test]
  656. fn feature() {
  657. let r = PayReqBody {
  658. game_user_id: "13856023633".to_string(),
  659. server_type: "tel".to_string(),
  660. product_no: "LD_5477".to_string(),
  661. sp_order_id: "QHGHFBGF0235641202".to_string(),
  662. source: "SD".to_string(),
  663. };
  664. let r = serde_json::to_string(&r).unwrap();
  665. println!("{r}")
  666. }
  667. #[test]
  668. fn test_try_into_fscg_req() {
  669. // 470EF517335D444BD003098D6F6ABCE0
  670. // 470EF517335D444BD003098D6F6ABCE0
  671. let now = std::time::Instant::now();
  672. let mut a = PubReqHead {
  673. app_id: "asdaw".to_string(),
  674. method: "asdaw".to_string(),
  675. sign_type: "asdaw".to_string(),
  676. sign: "asdaw".to_string(),
  677. timestamp: "2023-03-23 16:25:00".to_string(),
  678. version: "asdaw".to_string(),
  679. request_id: "asdaw".to_string(),
  680. biz_content: r#"{"gameUserId":"13856023633","serverType":"tel","productNo":"LD_5477","spOrderId":"QHGHFBGF0235641202","source":"SD"}"#.to_string(),
  681. };
  682. let c: Config = Default::default();
  683. // let r = c.sd_config.;
  684. let key = c.sd_config.get_sk().unwrap();
  685. let r = key
  686. .encrypt(a.biz_content, gmssl::sm2::PassOrder::C1C2C3)
  687. .unwrap();
  688. a.biz_content = hex::encode(r);
  689. a.sign(&c);
  690. println!("{a:?}");
  691. let new = std::time::Instant::now();
  692. println!("use Time{:?}", new - now);
  693. }
  694. }