diff --git a/api/src/actors/payment_manager.rs b/api/src/actors/payment_manager.rs index e4bb2ae..3634875 100644 --- a/api/src/actors/payment_manager.rs +++ b/api/src/actors/payment_manager.rs @@ -111,12 +111,13 @@ pub(crate) async fn request_payment( client: PayUClient, ) -> Result { let mut client = &mut *client.lock(); - Ok(client + let order = client .create_order( OrderCreateRequest::new(msg.buyer.into(), msg.customer_ip, msg.currency) .with_description(msg.description) .with_notify_url(msg.redirect_uri) .with_products(msg.products.into_iter().map(Into::into)), ) - .await?) + .await?; + Ok(order) } diff --git a/pay_u/src/lib.rs b/pay_u/src/lib.rs index 7742055..41d5dea 100644 --- a/pay_u/src/lib.rs +++ b/pay_u/src/lib.rs @@ -1,6 +1,7 @@ mod deserialize; mod serialize; +use std::fmt::Display; use std::sync::Arc; use reqwest::redirect; @@ -39,8 +40,13 @@ pub enum Error { Refund, #[error("Create order returned invalid response")] CreateOrder, +<<<<<<< HEAD #[error("Operation failed with {0:?}")] OpFailed(Status), +======= + #[error("Failed to fetch order transactions")] + OrderTransactions, +>>>>>>> 3ec4b209cd6a2ebefb4419083f9379794784d11c } pub type Result = std::result::Result; @@ -674,6 +680,76 @@ pub mod notify { } } +pub mod res { + #[derive(serde::Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct TransactionPayMethod { + pub value: String, + } + + #[derive(serde::Deserialize)] + #[serde(rename_all = "SCREAMING_SNAKE_CASE")] + pub enum CardProfile { + Consumer, + Business, + } + + #[derive(serde::Deserialize)] + #[serde(rename_all = "SCREAMING_SNAKE_CASE")] + pub enum CardClassification { + Debit, + Credit, + } + + #[derive(serde::Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct TransactionCartData { + /// // "543402******4014", + pub card_number_masked: String, + /// MC (MasterCard/Maestro), VS (Visa) + /// Example; "MC" + pub card_scheme: String, + pub card_profile: CardProfile, + pub card_classification: CardClassification, + /// Example: "000" + pub card_response_code: String, + /// Example: "000 - OK" + pub card_response_code_desc: String, + /// Example: "5" + pub card_eci_code: String, + /// Example: "AY", + pub card3ds_status: String, + /// Example: "PL", + pub card_bin_country: String, + /// Example: "MCC0111LL1121" + pub first_transaction_id: String, + } + + #[derive(serde::Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct TransactionCardInstallmentProposal {} + + #[derive(serde::Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct TransactionCart { + pub cart_data: TransactionCartData, + pub card_installment_proposal: TransactionCardInstallmentProposal, + } + + #[derive(serde::Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct Transaction { + pub pay_method: TransactionPayMethod, + pub payment_flow: String, + } + + #[derive(serde::Deserialize)] + #[serde(rename_all = "camelCase")] + pub struct Transactions { + pub transactions: Vec, + } +} + pub struct Client { sandbox: bool, merchant_pos_id: MerchantPosId, @@ -880,6 +956,51 @@ impl Client { Ok(res) } + /// The transaction retrieve request message enables you to retrieve the + /// details of transactions created for an order. + /// + /// Using this endpoint is extremely useful if you would like to get bank + /// account details or card details. + /// + /// > Please note that although card details are available right after + /// > transaction has been processed, the bank details may be available + /// > either after few minutes or on the next business day, depending on the + /// > bank. + /// # Examples + /// + /// ``` + /// # use pay_u::*; + /// async fn order_transactions() { + /// let mut client = Client::new("145227", "12f071174cb7eb79d4aac5bc2f07563f", 300746) + /// .with_bearer("d9a4536e-62ba-4f60-8017-6053211d3f47", 2000) + /// .sandbox(); + /// let res = client + /// .order_transactions("H9LL64F37H160126GUEST000P01") + /// .await; + /// } + /// ``` + pub async fn order_transactions( + &mut self, + order_id: OrderId, + ) -> Result { + self.authorize().await?; + let bearer = self.bearer.as_ref().cloned().unwrap_or_default(); + let path = format!("{}/orders/{}/transactions", self.base_url(), order_id); + let client = get_client!(self); + let text = client + .post(path) + .bearer_auth(bearer) + .send() + .await? + .text() + .await?; + log::trace!("Response: {}", text); + serde_json::from_str(&text).map_err(|e| { + log::error!("{e:?}"); + Error::OrderTransactions + }) + } + /// Get or refresh token pub async fn authorize(&mut self) -> Result { use chrono::{Duration, Utc};