Files
hyperswitch/crates/api_models/src/payment_methods.rs
2023-01-18 19:27:11 +05:30

344 lines
12 KiB
Rust

use std::collections::HashSet;
use common_utils::pii;
use serde::de;
use utoipa::ToSchema;
use crate::enums as api_enums;
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct CreatePaymentMethod {
pub payment_method: api_enums::PaymentMethodType,
pub payment_method_type: Option<api_enums::PaymentMethodSubType>,
pub payment_method_issuer: Option<String>,
pub payment_method_issuer_code: Option<api_enums::PaymentMethodIssuerCode>,
pub card: Option<CardDetail>,
pub metadata: Option<serde_json::Value>,
pub customer_id: Option<String>,
}
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct UpdatePaymentMethod {
pub card: Option<CardDetail>,
// Add more payment method update field in future
pub metadata: Option<serde_json::Value>,
}
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct CardDetail {
pub card_number: masking::Secret<String, pii::CardNumber>,
pub card_exp_month: masking::Secret<String>,
pub card_exp_year: masking::Secret<String>,
pub card_holder_name: Option<masking::Secret<String>>,
}
#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub struct PaymentMethodResponse {
pub merchant_id: String,
pub customer_id: Option<String>,
pub payment_method_id: String,
pub payment_method: api_enums::PaymentMethodType,
pub payment_method_type: Option<api_enums::PaymentMethodSubType>,
pub payment_method_issuer: Option<String>,
pub payment_method_issuer_code: Option<api_enums::PaymentMethodIssuerCode>,
pub card: Option<CardDetailFromLocker>,
pub recurring_enabled: bool,
pub installment_payment_enabled: bool,
pub payment_experience: Option<Vec<PaymentExperience>>,
pub metadata: Option<serde_json::Value>,
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
pub created: Option<time::PrimitiveDateTime>,
}
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct CardDetailFromLocker {
pub scheme: Option<String>,
pub issuer_country: Option<String>,
pub last4_digits: Option<String>,
#[serde(skip)]
pub card_number: Option<masking::Secret<String, pii::CardNumber>>,
pub expiry_month: Option<masking::Secret<String>>,
pub expiry_year: Option<masking::Secret<String>>,
pub card_token: Option<masking::Secret<String>>,
pub card_holder_name: Option<masking::Secret<String>>,
pub card_fingerprint: Option<masking::Secret<String>>,
}
//List Payment Method
#[derive(Debug, serde::Serialize, Default)]
#[serde(deny_unknown_fields)]
pub struct ListPaymentMethodRequest {
pub client_secret: Option<String>,
pub accepted_countries: Option<Vec<String>>,
pub accepted_currencies: Option<Vec<api_enums::Currency>>,
pub amount: Option<i64>,
pub recurring_enabled: Option<bool>,
pub installment_payment_enabled: Option<bool>,
}
impl<'de> serde::Deserialize<'de> for ListPaymentMethodRequest {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct FieldVisitor;
impl<'de> de::Visitor<'de> for FieldVisitor {
type Value = ListPaymentMethodRequest;
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str("Failed while deserializing as map")
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: de::MapAccess<'de>,
{
let mut output = ListPaymentMethodRequest::default();
while let Some(key) = map.next_key()? {
match key {
"client_secret" => {
set_or_reject_duplicate(
&mut output.client_secret,
"client_secret",
map.next_value()?,
)?;
}
"accepted_countries" => match output.accepted_countries.as_mut() {
Some(inner) => inner.push(map.next_value()?),
None => {
output.accepted_countries = Some(vec![map.next_value()?]);
}
},
"accepted_currencies" => match output.accepted_currencies.as_mut() {
Some(inner) => inner.push(map.next_value()?),
None => {
output.accepted_currencies = Some(vec![map.next_value()?]);
}
},
"amount" => {
set_or_reject_duplicate(
&mut output.amount,
"amount",
map.next_value()?,
)?;
}
"recurring_enabled" => {
set_or_reject_duplicate(
&mut output.recurring_enabled,
"recurring_enabled",
map.next_value()?,
)?;
}
"installment_payment_enabled" => {
set_or_reject_duplicate(
&mut output.installment_payment_enabled,
"installment_payment_enabled",
map.next_value()?,
)?;
}
_ => {}
}
}
Ok(output)
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
// Try to set the provided value to the data otherwise throw an error
fn set_or_reject_duplicate<T, E: de::Error>(
data: &mut Option<T>,
name: &'static str,
value: T,
) -> Result<(), E> {
match data {
Some(_inner) => Err(de::Error::duplicate_field(name)),
None => {
*data = Some(value);
Ok(())
}
}
}
#[derive(Debug, serde::Serialize)]
pub struct ListPaymentMethodResponse {
pub redirect_url: Option<String>,
pub payment_methods: HashSet<ListPaymentMethod>,
}
#[derive(Eq, PartialEq, Hash, Debug, serde::Deserialize)]
pub struct ListPaymentMethod {
pub payment_method: api_enums::PaymentMethodType,
pub payment_method_types: Option<Vec<api_enums::PaymentMethodSubType>>,
pub payment_method_issuers: Option<Vec<String>>,
pub payment_method_issuer_code: Option<Vec<api_enums::PaymentMethodIssuerCode>>,
pub payment_schemes: Option<Vec<String>>,
pub accepted_countries: Option<Vec<String>>,
pub accepted_currencies: Option<Vec<api_enums::Currency>>,
pub minimum_amount: Option<i64>,
pub maximum_amount: Option<i64>,
pub recurring_enabled: bool,
pub installment_payment_enabled: bool,
pub payment_experience: Option<Vec<PaymentExperience>>,
}
/// 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.
impl serde::Serialize for ListPaymentMethod {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeStruct;
let mut state = serializer.serialize_struct("ListPaymentMethod", 4)?;
state.serialize_field("payment_method", &self.payment_method)?;
state.serialize_field("payment_experience", &self.payment_experience)?;
match self.payment_method {
api_enums::PaymentMethodType::Wallet | api_enums::PaymentMethodType::PayLater => {
state.serialize_field("payment_method_issuers", &self.payment_method_issuers)?;
}
_ => {
state.serialize_field("payment_method_issuers", &self.payment_method_issuers)?;
state.serialize_field("payment_method_types", &self.payment_method_types)?;
state.serialize_field("payment_schemes", &self.payment_schemes)?;
}
}
state.end()
}
}
#[derive(Debug, serde::Serialize)]
pub struct ListCustomerPaymentMethodsResponse {
pub enabled_payment_methods: HashSet<ListPaymentMethod>,
pub customer_payment_methods: Vec<CustomerPaymentMethod>,
}
#[derive(Debug, serde::Serialize)]
pub struct DeletePaymentMethodResponse {
pub payment_method_id: String,
pub deleted: bool,
}
#[derive(Debug, serde::Serialize)]
pub struct CustomerPaymentMethod {
pub payment_token: String,
pub customer_id: String,
pub payment_method: api_enums::PaymentMethodType,
pub payment_method_type: Option<api_enums::PaymentMethodSubType>,
pub payment_method_issuer: Option<String>,
pub payment_method_issuer_code: Option<api_enums::PaymentMethodIssuerCode>,
pub recurring_enabled: bool,
pub installment_payment_enabled: bool,
pub payment_experience: Option<Vec<PaymentExperience>>,
pub card: Option<CardDetailFromLocker>,
pub metadata: Option<serde_json::Value>,
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
pub created: Option<time::PrimitiveDateTime>,
}
#[derive(Eq, PartialEq, Hash, Clone, Debug, serde::Serialize, serde::Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum PaymentExperience {
/// The URL to which the customer needs to be redirected for completing the payment.The URL to
/// which the customer needs to be redirected for completing the payment.
RedirectToUrl,
/// Contains the data for invoking the sdk client for completing the payment.
InvokeSdkClient,
/// The QR code data to be displayed to the customer.
DisplayQrCode,
/// Contains data to finish one click payment.
OneClick,
/// Redirect customer to link wallet
LinkWallet,
/// Contains the data for invoking the sdk client for completing the payment.
InvokePaymentApp,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct PaymentMethodId {
pub payment_method_id: String,
}
//------------------------------------------------TokenizeService------------------------------------------------
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizePayloadEncrypted {
pub payload: String,
pub key_id: String,
pub version: Option<String>,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizePayloadRequest {
pub value1: String,
pub value2: String,
pub lookup_key: String,
pub service_name: String,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct GetTokenizePayloadRequest {
pub lookup_key: String,
pub get_value2: bool,
}
#[derive(Debug, serde::Serialize)]
pub struct DeleteTokenizeByTokenRequest {
pub lookup_key: String,
}
#[derive(Debug, serde::Serialize)] // Blocked: Yet to be implemented by `basilisk`
pub struct DeleteTokenizeByDateRequest {
pub buffer_minutes: i32,
pub service_name: String,
pub max_rows: i32,
}
#[derive(Debug, serde::Deserialize)]
pub struct GetTokenizePayloadResponse {
pub lookup_key: String,
pub get_value2: Option<bool>,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TokenizedCardValue1 {
pub card_number: String,
pub exp_year: String,
pub exp_month: String,
pub name_on_card: Option<String>,
pub nickname: Option<String>,
pub card_last_four: Option<String>,
pub card_token: Option<String>,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct TokenizedCardValue2 {
pub card_security_code: Option<String>,
pub card_fingerprint: Option<String>,
pub external_id: Option<String>,
pub customer_id: Option<String>,
pub payment_method_id: Option<String>,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizedWalletValue1 {
pub issuer: String,
pub token: Option<String>,
}
#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizedWalletValue2 {
pub customer_id: Option<String>,
}