Change errors
This commit is contained in:
parent
9aeb78d64e
commit
4886a76a76
@ -96,7 +96,7 @@ impl From<Product> for pay_u::Product {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, actix::Message)]
|
#[derive(Debug, actix::Message)]
|
||||||
#[rtype(result = "Result<PaymentResult>")]
|
#[rtype(result = "Result<pay_u::OrderId>")]
|
||||||
pub struct RequestPayment {
|
pub struct RequestPayment {
|
||||||
pub products: Vec<Product>,
|
pub products: Vec<Product>,
|
||||||
pub redirect_uri: String,
|
pub redirect_uri: String,
|
||||||
@ -106,11 +106,13 @@ pub struct RequestPayment {
|
|||||||
pub customer_ip: String,
|
pub customer_ip: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pay_async_handler!(RequestPayment, request_payment, pay_u::OrderId);
|
||||||
|
|
||||||
pub(crate) async fn request_payment(
|
pub(crate) async fn request_payment(
|
||||||
msg: RequestPayment,
|
msg: RequestPayment,
|
||||||
client: PayUClient,
|
client: PayUClient,
|
||||||
) -> Result<pay_u::OrderId> {
|
) -> Result<pay_u::OrderId> {
|
||||||
let mut client = &mut *client.lock();
|
let client = &mut *client.lock();
|
||||||
let order = client
|
let order = client
|
||||||
.create_order(
|
.create_order(
|
||||||
OrderCreateRequest::new(msg.buyer.into(), msg.customer_ip, msg.currency)
|
OrderCreateRequest::new(msg.buyer.into(), msg.customer_ip, msg.currency)
|
||||||
|
228
pay_u/src/lib.rs
228
pay_u/src/lib.rs
@ -1,7 +1,6 @@
|
|||||||
mod deserialize;
|
mod deserialize;
|
||||||
mod serialize;
|
mod serialize;
|
||||||
|
|
||||||
use std::fmt::Display;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use reqwest::redirect;
|
use reqwest::redirect;
|
||||||
@ -40,19 +39,39 @@ pub enum Error {
|
|||||||
Refund,
|
Refund,
|
||||||
#[error("Create order returned invalid response")]
|
#[error("Create order returned invalid response")]
|
||||||
CreateOrder,
|
CreateOrder,
|
||||||
<<<<<<< HEAD
|
|
||||||
#[error("Operation failed with {0:?}")]
|
|
||||||
OpFailed(Status),
|
|
||||||
=======
|
|
||||||
#[error("Failed to fetch order transactions")]
|
#[error("Failed to fetch order transactions")]
|
||||||
OrderTransactions,
|
OrderTransactions,
|
||||||
>>>>>>> 3ec4b209cd6a2ebefb4419083f9379794784d11c
|
#[error("PayU rejected to create order. {status_code:?}")]
|
||||||
|
CreateFailed {
|
||||||
|
status_code: String,
|
||||||
|
status_desc: Option<String>,
|
||||||
|
code: Option<String>,
|
||||||
|
severity: Option<String>,
|
||||||
|
code_literal: Option<CodeLiteral>,
|
||||||
|
},
|
||||||
|
#[error("PayU rejected to perform refund. {status_code:?}")]
|
||||||
|
RefundFailed {
|
||||||
|
status_code: String,
|
||||||
|
status_desc: Option<String>,
|
||||||
|
code: Option<String>,
|
||||||
|
severity: Option<String>,
|
||||||
|
code_literal: Option<CodeLiteral>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
/// PayU internal order id
|
/// PayU internal order id
|
||||||
#[derive(derive_more::Display, derive_more::From, derive_more::Deref)]
|
#[derive(
|
||||||
|
Debug,
|
||||||
|
Clone,
|
||||||
|
serde::Deserialize,
|
||||||
|
serde::Serialize,
|
||||||
|
derive_more::Display,
|
||||||
|
derive_more::From,
|
||||||
|
derive_more::Deref,
|
||||||
|
)]
|
||||||
|
#[serde(transparent)]
|
||||||
pub struct OrderId(pub String);
|
pub struct OrderId(pub String);
|
||||||
|
|
||||||
impl OrderId {
|
impl OrderId {
|
||||||
@ -546,8 +565,8 @@ impl Status {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod result {
|
pub mod res {
|
||||||
use crate::{Refund, Status};
|
use crate::{OrderId, Refund, Status};
|
||||||
|
|
||||||
#[derive(serde::Deserialize, Debug)]
|
#[derive(serde::Deserialize, Debug)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
@ -557,7 +576,7 @@ pub mod result {
|
|||||||
/// Client should be redirected to this URI
|
/// Client should be redirected to this URI
|
||||||
pub redirect_uri: String,
|
pub redirect_uri: String,
|
||||||
/// This should be connected to your own order
|
/// This should be connected to your own order
|
||||||
pub order_id: String,
|
pub order_id: OrderId,
|
||||||
/// This is YOUR_EXT_ORDER_ID
|
/// This is YOUR_EXT_ORDER_ID
|
||||||
pub ext_order_id: Option<String>,
|
pub ext_order_id: Option<String>,
|
||||||
}
|
}
|
||||||
@ -569,6 +588,73 @@ pub mod result {
|
|||||||
pub refund: Option<Refund>,
|
pub refund: Option<Refund>,
|
||||||
pub status: Status,
|
pub status: Status,
|
||||||
}
|
}
|
||||||
|
#[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<Transaction>,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
@ -614,9 +700,8 @@ pub struct Refund {
|
|||||||
pub mod notify {
|
pub mod notify {
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use crate::OrderId;
|
|
||||||
|
|
||||||
use super::deserialize;
|
use super::deserialize;
|
||||||
|
use crate::OrderId;
|
||||||
|
|
||||||
/// Payment notification object received on [super::Order].[notify_url]
|
/// Payment notification object received on [super::Order].[notify_url]
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
@ -692,76 +777,6 @@ 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<Transaction>,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
sandbox: bool,
|
sandbox: bool,
|
||||||
merchant_pos_id: MerchantPosId,
|
merchant_pos_id: MerchantPosId,
|
||||||
@ -856,7 +871,7 @@ impl Client {
|
|||||||
/// .await;
|
/// .await;
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub async fn create_order(&mut self, order: OrderCreateRequest) -> Result<result::CreateOrder> {
|
pub async fn create_order(&mut self, order: OrderCreateRequest) -> Result<res::CreateOrder> {
|
||||||
self.authorize().await?;
|
self.authorize().await?;
|
||||||
if order.total_amount
|
if order.total_amount
|
||||||
!= order
|
!= order
|
||||||
@ -887,12 +902,25 @@ impl Client {
|
|||||||
.text()
|
.text()
|
||||||
.await?;
|
.await?;
|
||||||
log::trace!("Response: {}", text);
|
log::trace!("Response: {}", text);
|
||||||
let res: result::CreateOrder = serde_json::from_str(&text).map_err(|e| {
|
let res: res::CreateOrder = serde_json::from_str(&text).map_err(|e| {
|
||||||
log::error!("{e:?}");
|
log::error!("{e:?}");
|
||||||
Error::CreateOrder
|
Error::CreateOrder
|
||||||
})?;
|
})?;
|
||||||
if res.status.status_code != "Success" {
|
if res.status.status_code != "Success" {
|
||||||
return Err(Error::OpFailed(res.status));
|
let Status {
|
||||||
|
status_code,
|
||||||
|
status_desc,
|
||||||
|
code,
|
||||||
|
severity,
|
||||||
|
code_literal,
|
||||||
|
} = res.status;
|
||||||
|
return Err(Error::CreateFailed {
|
||||||
|
status_desc,
|
||||||
|
status_code,
|
||||||
|
code,
|
||||||
|
severity,
|
||||||
|
code_literal,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
@ -927,7 +955,7 @@ impl Client {
|
|||||||
/// .sandbox();
|
/// .sandbox();
|
||||||
/// let res = client
|
/// let res = client
|
||||||
/// .partial_refund(
|
/// .partial_refund(
|
||||||
/// "H9LL64F37H160126GUEST000P01",
|
/// OrderId::new("H9LL64F37H160126GUEST000P01"),
|
||||||
/// RefundRequest::new("Refund", 1000),
|
/// RefundRequest::new("Refund", 1000),
|
||||||
/// )
|
/// )
|
||||||
/// .await;
|
/// .await;
|
||||||
@ -937,7 +965,7 @@ impl Client {
|
|||||||
&mut self,
|
&mut self,
|
||||||
order_id: OrderId,
|
order_id: OrderId,
|
||||||
refund: RefundRequest,
|
refund: RefundRequest,
|
||||||
) -> Result<result::PartialRefund> {
|
) -> Result<res::PartialRefund> {
|
||||||
self.authorize().await?;
|
self.authorize().await?;
|
||||||
if refund.description().trim().is_empty() {
|
if refund.description().trim().is_empty() {
|
||||||
return Err(Error::NoDescription);
|
return Err(Error::NoDescription);
|
||||||
@ -955,12 +983,25 @@ impl Client {
|
|||||||
.text()
|
.text()
|
||||||
.await?;
|
.await?;
|
||||||
log::trace!("Response: {}", text);
|
log::trace!("Response: {}", text);
|
||||||
let res: result::PartialRefund = serde_json::from_str(&text).map_err(|e| {
|
let res: res::PartialRefund = serde_json::from_str(&text).map_err(|e| {
|
||||||
log::error!("Invalid PayU response {e:?}");
|
log::error!("Invalid PayU response {e:?}");
|
||||||
Error::Refund
|
Error::Refund
|
||||||
})?;
|
})?;
|
||||||
if res.status.status_code.as_str() != "Success" {
|
if res.status.status_code.as_str() != "Success" {
|
||||||
return Err(Error::OpFailed(res.status));
|
let Status {
|
||||||
|
status_code,
|
||||||
|
status_desc,
|
||||||
|
code,
|
||||||
|
severity,
|
||||||
|
code_literal,
|
||||||
|
} = res.status;
|
||||||
|
return Err(Error::RefundFailed {
|
||||||
|
status_desc,
|
||||||
|
status_code,
|
||||||
|
code,
|
||||||
|
severity,
|
||||||
|
code_literal,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
@ -984,7 +1025,7 @@ impl Client {
|
|||||||
/// .with_bearer("d9a4536e-62ba-4f60-8017-6053211d3f47", 2000)
|
/// .with_bearer("d9a4536e-62ba-4f60-8017-6053211d3f47", 2000)
|
||||||
/// .sandbox();
|
/// .sandbox();
|
||||||
/// let res = client
|
/// let res = client
|
||||||
/// .order_transactions("H9LL64F37H160126GUEST000P01")
|
/// .order_transactions(OrderId::new("H9LL64F37H160126GUEST000P01"))
|
||||||
/// .await;
|
/// .await;
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
@ -1099,7 +1140,6 @@ mod tests {
|
|||||||
RefundRequest::new("Refund", 1000),
|
RefundRequest::new("Refund", 1000),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
eprintln!("{:?}", res);
|
|
||||||
assert!(matches!(res, Ok(_)));
|
assert!(matches!(res, Ok(_)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1108,7 +1148,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_accepted_refund_json() {
|
fn check_accepted_refund_json() {
|
||||||
let res = serde_json::from_str::<result::PartialRefund>(include_str!(
|
let res = serde_json::from_str::<res::PartialRefund>(include_str!(
|
||||||
"../tests/responses/accepted_refund.json"
|
"../tests/responses/accepted_refund.json"
|
||||||
));
|
));
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
@ -1150,14 +1190,14 @@ mod tests {
|
|||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn check_rejection_json() {
|
fn check_rejection_json() {
|
||||||
let res = serde_json::from_str::<result::PartialRefund>(include_str!(
|
let res = serde_json::from_str::<res::PartialRefund>(include_str!(
|
||||||
"../tests/responses/rejection.json"
|
"../tests/responses/rejection.json"
|
||||||
));
|
));
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
fn check_custom_literal_json() {
|
fn check_custom_literal_json() {
|
||||||
let res = serde_json::from_str::<result::PartialRefund>(include_str!(
|
let res = serde_json::from_str::<res::PartialRefund>(include_str!(
|
||||||
"../tests/responses/custom_code_literal.json"
|
"../tests/responses/custom_code_literal.json"
|
||||||
));
|
));
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
|
Loading…
Reference in New Issue
Block a user