mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-27 19:46:48 +08:00
Co-authored-by: Sangamesh Kulkarni <59434228+Sangamesh26@users.noreply.github.com> Co-authored-by: ItsMeShashank <shashank.attarde@juspay.in> Co-authored-by: Abhishek <abhishek.marrivagu@juspay.in> Co-authored-by: Jagan <jaganelavarasan@gmail.com> Co-authored-by: SamraatBansal <55536657+SamraatBansal@users.noreply.github.com> Co-authored-by: Sampras Lopes <lsampras@protonmail.com>
This commit is contained in:
@ -16,6 +16,7 @@ serde = { version = "1.0.152", features = ["derive"] }
|
||||
serde_json = "1.0.91"
|
||||
strum = { version = "0.24.1", features = ["derive"] }
|
||||
time = { version = "0.3.17", features = ["serde", "serde-well-known", "std"] }
|
||||
url = { version = "2.3.1", features = ["serde"] }
|
||||
utoipa = { version = "3.0.1", features = ["preserve_order"] }
|
||||
|
||||
# First party crates
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use common_utils::pii;
|
||||
use masking::{Secret, StrongSecret};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use super::payments::AddressDetails;
|
||||
@ -26,7 +27,7 @@ pub struct CreateMerchantAccount {
|
||||
|
||||
/// The URL to redirect after the completion of the operation
|
||||
#[schema(max_length = 255, example = "https://www.example.com/success")]
|
||||
pub return_url: Option<String>,
|
||||
pub return_url: Option<url::Url>,
|
||||
|
||||
/// Webhook related details
|
||||
pub webhook_details: Option<WebhookDetails>,
|
||||
|
||||
@ -11,6 +11,7 @@ use utoipa::ToSchema;
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
@ -572,8 +573,10 @@ pub enum MandateStatus {
|
||||
pub enum Connector {
|
||||
Aci,
|
||||
Adyen,
|
||||
Airwallex,
|
||||
Applepay,
|
||||
Authorizedotnet,
|
||||
Bluesnap,
|
||||
Braintree,
|
||||
Checkout,
|
||||
Cybersource,
|
||||
@ -583,6 +586,7 @@ pub enum Connector {
|
||||
Fiserv,
|
||||
Globalpay,
|
||||
Klarna,
|
||||
Nuvei,
|
||||
Payu,
|
||||
Rapyd,
|
||||
Shift4,
|
||||
@ -593,7 +597,7 @@ pub enum Connector {
|
||||
|
||||
impl Connector {
|
||||
pub fn supports_access_token(&self) -> bool {
|
||||
matches!(self, Self::Globalpay | Self::Payu)
|
||||
matches!(self, Self::Airwallex | Self::Globalpay | Self::Payu)
|
||||
}
|
||||
}
|
||||
|
||||
@ -614,7 +618,9 @@ impl Connector {
|
||||
pub enum RoutableConnectors {
|
||||
Aci,
|
||||
Adyen,
|
||||
Airwallex,
|
||||
Authorizedotnet,
|
||||
Bluesnap,
|
||||
Braintree,
|
||||
Checkout,
|
||||
Cybersource,
|
||||
@ -622,6 +628,7 @@ pub enum RoutableConnectors {
|
||||
Fiserv,
|
||||
Globalpay,
|
||||
Klarna,
|
||||
Nuvei,
|
||||
Payu,
|
||||
Rapyd,
|
||||
Shift4,
|
||||
|
||||
@ -296,7 +296,7 @@ pub struct ListPaymentMethodResponse {
|
||||
}
|
||||
]
|
||||
))]
|
||||
pub payment_methods: HashSet<ListPaymentMethod>,
|
||||
pub payment_methods: Vec<ListPaymentMethod>,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, Debug, serde::Deserialize, ToSchema)]
|
||||
@ -362,9 +362,12 @@ pub struct ListPaymentMethod {
|
||||
/// Type of payment experience enabled with the connector
|
||||
#[schema(value_type = Option<Vec<PaymentExperience>>, example = json!(["redirect_to_url"]))]
|
||||
pub payment_experience: Option<Vec<api_enums::PaymentExperience>>,
|
||||
|
||||
/// Eligible connectors for this payment method
|
||||
#[schema(example = json!(["stripe", "adyen"]))]
|
||||
pub eligible_connectors: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
/// We need a custom serializer to only send relevant fields in ListPaymentMethodResponse
|
||||
/// Currently if the payment method is Wallet or Paylater the relevant fields are `payment_method`
|
||||
/// and `payment_method_issuers`. Otherwise only consider
|
||||
/// `payment_method`,`payment_method_issuers`,`payment_method_types`,`payment_schemes` fields.
|
||||
@ -377,6 +380,7 @@ impl serde::Serialize for ListPaymentMethod {
|
||||
let mut state = serializer.serialize_struct("ListPaymentMethod", 4)?;
|
||||
state.serialize_field("payment_method", &self.payment_method)?;
|
||||
state.serialize_field("payment_experience", &self.payment_experience)?;
|
||||
state.serialize_field("eligible_connectors", &self.eligible_connectors)?;
|
||||
match self.payment_method {
|
||||
api_enums::PaymentMethodType::Wallet | api_enums::PaymentMethodType::PayLater => {
|
||||
state.serialize_field("payment_method_issuers", &self.payment_method_issuers)?;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::num::NonZeroI64;
|
||||
|
||||
use common_utils::{errors, ext_traits::Encode, pii};
|
||||
use common_utils::pii;
|
||||
use masking::{PeekInterface, Secret};
|
||||
use router_derive::Setter;
|
||||
use time::PrimitiveDateTime;
|
||||
@ -38,7 +38,7 @@ pub struct PaymentsRequest {
|
||||
pub amount: Option<Amount>,
|
||||
/// This allows the merchant to manually select a connector with which the payment can go through
|
||||
#[schema(value_type = Option<Connector>, max_length = 255, example = "stripe")]
|
||||
pub connector: Option<api_enums::Connector>,
|
||||
pub connector: Option<Vec<api_enums::Connector>>,
|
||||
/// The currency of the payment request can be specified here
|
||||
#[schema(value_type = Option<Currency>, example = "USD")]
|
||||
pub currency: Option<api_enums::Currency>,
|
||||
@ -80,7 +80,7 @@ pub struct PaymentsRequest {
|
||||
pub description: Option<String>,
|
||||
/// The URL to redirect after the completion of the operation
|
||||
#[schema(example = "https://hyperswitch.io")]
|
||||
pub return_url: Option<String>,
|
||||
pub return_url: Option<url::Url>,
|
||||
/// Indicates that you intend to make future payments with this Payment’s payment method. Providing this parameter will attach the payment method to the Customer, if present, after the Payment is confirmed and any required actions from the user are complete.
|
||||
#[schema(value_type = Option<FutureUsage>, example = "off_session")]
|
||||
pub setup_future_usage: Option<api_enums::FutureUsage>,
|
||||
@ -795,46 +795,6 @@ impl From<&VerifyRequest> for MandateValidationFields {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PaymentsRequest> for PaymentsResponse {
|
||||
type Error = error_stack::Report<errors::ParsingError>;
|
||||
fn try_from(item: PaymentsRequest) -> Result<Self, Self::Error> {
|
||||
let payment_id = match item.payment_id {
|
||||
Some(PaymentIdType::PaymentIntentId(id)) => Some(id),
|
||||
_ => None,
|
||||
};
|
||||
let metadata = item
|
||||
.metadata
|
||||
.as_ref()
|
||||
.map(Encode::<Metadata>::encode_to_value)
|
||||
.transpose()?;
|
||||
Ok(Self {
|
||||
payment_id,
|
||||
merchant_id: item.merchant_id,
|
||||
setup_future_usage: item.setup_future_usage,
|
||||
off_session: item.off_session,
|
||||
shipping: item.shipping,
|
||||
billing: item.billing,
|
||||
metadata,
|
||||
capture_method: item.capture_method,
|
||||
payment_method: item.payment_method,
|
||||
capture_on: item.capture_on,
|
||||
payment_method_data: item
|
||||
.payment_method_data
|
||||
.map(PaymentMethodDataResponse::from),
|
||||
email: item.email,
|
||||
name: item.name,
|
||||
phone: item.phone,
|
||||
payment_token: item.payment_token,
|
||||
return_url: item.return_url,
|
||||
authentication_type: item.authentication_type,
|
||||
statement_descriptor_name: item.statement_descriptor_name,
|
||||
statement_descriptor_suffix: item.statement_descriptor_suffix,
|
||||
mandate_data: item.mandate_data,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VerifyRequest> for VerifyResponse {
|
||||
fn from(item: VerifyRequest) -> Self {
|
||||
Self {
|
||||
@ -853,25 +813,6 @@ impl From<VerifyRequest> for VerifyResponse {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PaymentsStartRequest> for PaymentsResponse {
|
||||
fn from(item: PaymentsStartRequest) -> Self {
|
||||
Self {
|
||||
payment_id: Some(item.payment_id),
|
||||
merchant_id: Some(item.merchant_id),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PaymentsSessionRequest> for PaymentsResponse {
|
||||
fn from(item: PaymentsSessionRequest) -> Self {
|
||||
Self {
|
||||
payment_id: Some(item.payment_id),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PaymentsSessionRequest> for PaymentsSessionResponse {
|
||||
fn from(item: PaymentsSessionRequest) -> Self {
|
||||
let client_secret: Secret<String, pii::ClientSecret> = Secret::new(item.client_secret);
|
||||
@ -893,43 +834,6 @@ impl From<PaymentsStartRequest> for PaymentsRequest {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PaymentsRetrieveRequest> for PaymentsResponse {
|
||||
// After removing the request from the payments_to_payments_response this will no longer be needed
|
||||
fn from(item: PaymentsRetrieveRequest) -> Self {
|
||||
let payment_id = match item.resource_id {
|
||||
PaymentIdType::PaymentIntentId(id) => Some(id),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
Self {
|
||||
payment_id,
|
||||
merchant_id: item.merchant_id,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PaymentsCancelRequest> for PaymentsResponse {
|
||||
fn from(item: PaymentsCancelRequest) -> Self {
|
||||
Self {
|
||||
payment_id: Some(item.payment_id),
|
||||
cancellation_reason: item.cancellation_reason,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PaymentsCaptureRequest> for PaymentsResponse {
|
||||
// After removing the request from the payments_to_payments_response this will no longer be needed
|
||||
fn from(item: PaymentsCaptureRequest) -> Self {
|
||||
Self {
|
||||
payment_id: item.payment_id,
|
||||
amount_received: item.amount_to_capture,
|
||||
..Self::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Card> for CardResponse {
|
||||
fn from(card: Card) -> Self {
|
||||
let card_number_length = card.card_number.peek().clone().len();
|
||||
@ -1096,18 +1000,18 @@ pub struct GpaySessionTokenData {
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum SessionToken {
|
||||
/// The session response structure for Google Pay
|
||||
Gpay(Box<GpayData>),
|
||||
Gpay(Box<GpaySessionTokenResponse>),
|
||||
/// The session response structure for Klarna
|
||||
Klarna(Box<KlarnaData>),
|
||||
Klarna(Box<KlarnaSessionTokenResponse>),
|
||||
/// The session response structure for PayPal
|
||||
Paypal(Box<PaypalData>),
|
||||
Paypal(Box<PaypalSessionTokenResponse>),
|
||||
/// The session response structure for Apple Pay
|
||||
Applepay(Box<ApplepayData>),
|
||||
Applepay(Box<ApplepaySessionTokenResponse>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct GpayData {
|
||||
pub struct GpaySessionTokenResponse {
|
||||
/// The merchant info
|
||||
pub merchant_info: GpayMerchantInfo,
|
||||
/// List of the allowed payment meythods
|
||||
@ -1118,7 +1022,7 @@ pub struct GpayData {
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct KlarnaData {
|
||||
pub struct KlarnaSessionTokenResponse {
|
||||
/// The session token for Klarna
|
||||
pub session_token: String,
|
||||
/// The identifier for the session
|
||||
@ -1127,29 +1031,29 @@ pub struct KlarnaData {
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct PaypalData {
|
||||
pub struct PaypalSessionTokenResponse {
|
||||
/// The session token for PayPal
|
||||
pub session_token: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, ToSchema)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub struct ApplepayData {
|
||||
pub struct ApplepaySessionTokenResponse {
|
||||
/// Session object for Apple Pay
|
||||
pub session_object: ApplePaySessionObject,
|
||||
pub session_token_data: ApplePaySessionResponse,
|
||||
/// Payment request object for Apple Pay
|
||||
pub payment_request_object: ApplePayRequest,
|
||||
pub payment_request_data: ApplePayPaymentRequest,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, ToSchema, serde::Deserialize)]
|
||||
pub struct ApplePaySessionObject {
|
||||
pub struct ApplePaySessionResponse {
|
||||
/// Timestamp at which session is requested
|
||||
pub epoch_timestamp: u64,
|
||||
/// Timestamp at which session expires
|
||||
pub expires_at: u64,
|
||||
/// The identifier for the merchant session
|
||||
pub merchant_session_identifier: String,
|
||||
/// Applepay generates unique ID (UUID) value
|
||||
/// Apple pay generated unique ID (UUID) value
|
||||
pub nonce: String,
|
||||
/// The identifier for the merchant
|
||||
pub merchant_identifier: String,
|
||||
@ -1168,7 +1072,7 @@ pub struct ApplePaySessionObject {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, ToSchema, serde::Deserialize)]
|
||||
pub struct ApplePayRequest {
|
||||
pub struct ApplePayPaymentRequest {
|
||||
/// The code for country
|
||||
pub country_code: String,
|
||||
/// The code for currency
|
||||
@ -1183,11 +1087,11 @@ pub struct ApplePayRequest {
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize, ToSchema, serde::Deserialize)]
|
||||
pub struct AmountInfo {
|
||||
/// the label must be non-empty to pass validation.
|
||||
/// The label must be the name of the merchant.
|
||||
pub label: String,
|
||||
/// The type of label
|
||||
/// A value that indicates whether the line item(Ex: total, tax, discount, or grand total) is final or pending.
|
||||
#[serde(rename = "type")]
|
||||
pub label_type: String,
|
||||
pub total_type: String,
|
||||
/// The total amount for the payment
|
||||
pub amount: String,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user