mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-27 19:46:48 +08:00
956 lines
28 KiB
Rust
956 lines
28 KiB
Rust
use std::num::NonZeroI64;
|
|
|
|
use common_utils::pii;
|
|
use masking::{PeekInterface, Secret};
|
|
use router_derive::Setter;
|
|
use time::PrimitiveDateTime;
|
|
|
|
use crate::{enums as api_enums, refunds};
|
|
|
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
|
pub enum PaymentOp {
|
|
Create,
|
|
Update,
|
|
Confirm,
|
|
}
|
|
|
|
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)]
|
|
#[serde(deny_unknown_fields)]
|
|
pub struct PaymentsRequest {
|
|
#[serde(default, deserialize_with = "payment_id_type::deserialize_option")]
|
|
pub payment_id: Option<PaymentIdType>,
|
|
pub merchant_id: Option<String>,
|
|
#[serde(default, deserialize_with = "amount::deserialize_option")]
|
|
pub amount: Option<Amount>,
|
|
pub connector: Option<api_enums::Connector>,
|
|
pub currency: Option<String>,
|
|
pub capture_method: Option<api_enums::CaptureMethod>,
|
|
pub amount_to_capture: Option<i64>,
|
|
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
|
|
pub capture_on: Option<PrimitiveDateTime>,
|
|
pub confirm: Option<bool>,
|
|
pub customer_id: Option<String>,
|
|
pub email: Option<Secret<String, pii::Email>>,
|
|
pub name: Option<Secret<String>>,
|
|
pub phone: Option<Secret<String>>,
|
|
pub phone_country_code: Option<String>,
|
|
pub off_session: Option<bool>,
|
|
pub description: Option<String>,
|
|
pub return_url: Option<String>,
|
|
pub setup_future_usage: Option<api_enums::FutureUsage>,
|
|
pub authentication_type: Option<api_enums::AuthenticationType>,
|
|
pub payment_method_data: Option<PaymentMethod>,
|
|
pub payment_method: Option<api_enums::PaymentMethodType>,
|
|
pub payment_token: Option<String>,
|
|
pub card_cvc: Option<Secret<String>>,
|
|
pub shipping: Option<Address>,
|
|
pub billing: Option<Address>,
|
|
pub statement_descriptor_name: Option<String>,
|
|
pub statement_descriptor_suffix: Option<String>,
|
|
pub metadata: Option<serde_json::Value>,
|
|
pub client_secret: Option<String>,
|
|
pub mandate_data: Option<MandateData>,
|
|
pub mandate_id: Option<String>,
|
|
pub browser_info: Option<serde_json::Value>,
|
|
}
|
|
|
|
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, Copy, PartialEq, Eq)]
|
|
pub enum Amount {
|
|
Value(NonZeroI64),
|
|
#[default]
|
|
Zero,
|
|
}
|
|
|
|
impl From<Amount> for i64 {
|
|
fn from(amount: Amount) -> Self {
|
|
match amount {
|
|
Amount::Value(val) => val.get(),
|
|
Amount::Zero => 0,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<i64> for Amount {
|
|
fn from(val: i64) -> Self {
|
|
NonZeroI64::new(val).map_or(Amount::Zero, Amount::Value)
|
|
}
|
|
}
|
|
|
|
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)]
|
|
#[serde(deny_unknown_fields)]
|
|
pub struct PaymentsRedirectRequest {
|
|
pub payment_id: String,
|
|
pub merchant_id: String,
|
|
pub connector: String,
|
|
pub param: String,
|
|
}
|
|
|
|
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)]
|
|
#[serde(deny_unknown_fields)]
|
|
pub struct VerifyRequest {
|
|
// The merchant_id is generated through api key
|
|
// and is later passed in the struct
|
|
pub merchant_id: Option<String>,
|
|
pub customer_id: Option<String>,
|
|
pub email: Option<Secret<String, pii::Email>>,
|
|
pub name: Option<Secret<String>>,
|
|
pub phone: Option<Secret<String>>,
|
|
pub phone_country_code: Option<String>,
|
|
pub payment_method: Option<api_enums::PaymentMethodType>,
|
|
pub payment_method_data: Option<PaymentMethod>,
|
|
pub payment_token: Option<String>,
|
|
pub mandate_data: Option<MandateData>,
|
|
pub setup_future_usage: Option<api_enums::FutureUsage>,
|
|
pub off_session: Option<bool>,
|
|
pub client_secret: Option<String>,
|
|
}
|
|
|
|
impl From<PaymentsRequest> for VerifyRequest {
|
|
fn from(item: PaymentsRequest) -> Self {
|
|
Self {
|
|
client_secret: item.client_secret,
|
|
merchant_id: item.merchant_id,
|
|
customer_id: item.customer_id,
|
|
email: item.email,
|
|
name: item.name,
|
|
phone: item.phone,
|
|
phone_country_code: item.phone_country_code,
|
|
payment_method: item.payment_method,
|
|
payment_method_data: item.payment_method_data,
|
|
payment_token: item.payment_token,
|
|
mandate_data: item.mandate_data,
|
|
setup_future_usage: item.setup_future_usage,
|
|
off_session: item.off_session,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub enum MandateTxnType {
|
|
NewMandateTxn,
|
|
RecurringMandateTxn,
|
|
}
|
|
|
|
#[derive(Default, Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone)]
|
|
#[serde(deny_unknown_fields)]
|
|
pub struct MandateData {
|
|
pub customer_acceptance: CustomerAcceptance,
|
|
pub mandate_type: MandateType,
|
|
}
|
|
|
|
#[derive(Clone, Eq, PartialEq, Copy, Debug, Default, serde::Serialize, serde::Deserialize)]
|
|
pub struct SingleUseMandate {
|
|
pub amount: i64,
|
|
pub currency: api_enums::Currency,
|
|
}
|
|
|
|
#[derive(Clone, Eq, PartialEq, Copy, Debug, Default, serde::Serialize, serde::Deserialize)]
|
|
pub struct MandateAmountData {
|
|
pub amount: i64,
|
|
pub currency: api_enums::Currency,
|
|
}
|
|
|
|
#[derive(Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum MandateType {
|
|
SingleUse(MandateAmountData),
|
|
MultiUse(Option<MandateAmountData>),
|
|
}
|
|
|
|
impl Default for MandateType {
|
|
fn default() -> Self {
|
|
Self::MultiUse(None)
|
|
}
|
|
}
|
|
|
|
#[derive(Default, Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone)]
|
|
#[serde(deny_unknown_fields)]
|
|
pub struct CustomerAcceptance {
|
|
pub acceptance_type: AcceptanceType,
|
|
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
|
|
pub accepted_at: Option<PrimitiveDateTime>,
|
|
pub online: Option<OnlineMandate>,
|
|
}
|
|
|
|
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, PartialEq, Eq, Clone)]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub enum AcceptanceType {
|
|
Online,
|
|
#[default]
|
|
Offline,
|
|
}
|
|
|
|
#[derive(Default, Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone)]
|
|
#[serde(deny_unknown_fields)]
|
|
pub struct OnlineMandate {
|
|
pub ip_address: Secret<String, pii::IpAddress>,
|
|
pub user_agent: String,
|
|
}
|
|
|
|
#[derive(Default, Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize)]
|
|
pub struct CCard {
|
|
pub card_number: Secret<String, pii::CardNumber>,
|
|
pub card_exp_month: Secret<String>,
|
|
pub card_exp_year: Secret<String>,
|
|
pub card_holder_name: Secret<String>,
|
|
pub card_cvc: Secret<String>,
|
|
}
|
|
|
|
#[derive(Default, Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize)]
|
|
pub struct PayLaterData {
|
|
pub billing_email: String,
|
|
pub country: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
|
pub enum PaymentMethod {
|
|
#[serde(rename(deserialize = "card"))]
|
|
Card(CCard),
|
|
#[serde(rename(deserialize = "bank_transfer"))]
|
|
BankTransfer,
|
|
#[serde(rename(deserialize = "wallet"))]
|
|
Wallet(WalletData),
|
|
#[serde(rename(deserialize = "pay_later"))]
|
|
PayLater(PayLaterData),
|
|
#[serde(rename(deserialize = "paypal"))]
|
|
Paypal,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
|
pub struct WalletData {
|
|
pub issuer_name: api_enums::WalletIssuer,
|
|
pub token: String,
|
|
}
|
|
|
|
#[derive(Eq, PartialEq, Clone, Debug, serde::Serialize)]
|
|
pub struct CCardResponse {
|
|
last4: String,
|
|
exp_month: String,
|
|
exp_year: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize)]
|
|
pub enum PaymentMethodDataResponse {
|
|
#[serde(rename = "card")]
|
|
Card(CCardResponse),
|
|
#[serde(rename(deserialize = "bank_transfer"))]
|
|
BankTransfer,
|
|
Wallet(WalletData),
|
|
PayLater(PayLaterData),
|
|
Paypal,
|
|
}
|
|
|
|
impl Default for PaymentMethod {
|
|
fn default() -> Self {
|
|
PaymentMethod::BankTransfer
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
|
pub enum PaymentIdType {
|
|
PaymentIntentId(String),
|
|
ConnectorTransactionId(String),
|
|
PaymentTxnId(String),
|
|
}
|
|
|
|
impl Default for PaymentIdType {
|
|
fn default() -> Self {
|
|
Self::PaymentIntentId(Default::default())
|
|
}
|
|
}
|
|
|
|
//#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
|
//#[serde(untagged)]
|
|
//pub enum enums::CaptureMethod {
|
|
//Automatic,
|
|
//Manual,
|
|
//}
|
|
|
|
//impl Default for enums::CaptureMethod {
|
|
//fn default() -> Self {
|
|
//enums::CaptureMethod::Manual
|
|
//}
|
|
//}
|
|
|
|
#[derive(
|
|
Default,
|
|
Clone,
|
|
Debug,
|
|
Eq,
|
|
PartialEq,
|
|
serde::Deserialize,
|
|
serde::Serialize,
|
|
frunk::LabelledGeneric,
|
|
)]
|
|
#[serde(deny_unknown_fields)]
|
|
pub struct Address {
|
|
pub address: Option<AddressDetails>,
|
|
pub phone: Option<PhoneDetails>,
|
|
}
|
|
|
|
// used by customers also, could be moved outside
|
|
#[derive(
|
|
Clone,
|
|
Default,
|
|
Debug,
|
|
Eq,
|
|
serde::Deserialize,
|
|
serde::Serialize,
|
|
PartialEq,
|
|
frunk::LabelledGeneric,
|
|
)]
|
|
#[serde(deny_unknown_fields)]
|
|
pub struct AddressDetails {
|
|
pub city: Option<String>,
|
|
pub country: Option<String>,
|
|
pub line1: Option<Secret<String>>,
|
|
pub line2: Option<Secret<String>>,
|
|
pub line3: Option<Secret<String>>,
|
|
pub zip: Option<Secret<String>>,
|
|
pub state: Option<Secret<String>>,
|
|
pub first_name: Option<Secret<String>>,
|
|
pub last_name: Option<Secret<String>>,
|
|
}
|
|
|
|
#[derive(
|
|
Debug,
|
|
Clone,
|
|
Default,
|
|
Eq,
|
|
PartialEq,
|
|
serde::Deserialize,
|
|
serde::Serialize,
|
|
frunk::LabelledGeneric,
|
|
)]
|
|
pub struct PhoneDetails {
|
|
pub number: Option<Secret<String>>,
|
|
pub country_code: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Default, Eq, PartialEq, serde::Deserialize)]
|
|
pub struct PaymentsCaptureRequest {
|
|
pub payment_id: Option<String>,
|
|
pub merchant_id: Option<String>,
|
|
pub amount_to_capture: Option<i64>,
|
|
pub refund_uncaptured_amount: Option<bool>,
|
|
pub statement_descriptor_suffix: Option<String>,
|
|
pub statement_descriptor_prefix: Option<String>,
|
|
}
|
|
|
|
#[derive(Default, Clone, Debug, Eq, PartialEq, serde::Serialize)]
|
|
pub struct UrlDetails {
|
|
pub url: String,
|
|
pub method: String,
|
|
}
|
|
#[derive(Default, Clone, Debug, Eq, PartialEq, serde::Serialize)]
|
|
pub struct AuthenticationForStartResponse {
|
|
pub authentication: UrlDetails,
|
|
}
|
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
|
|
#[serde(rename_all = "snake_case")]
|
|
pub enum NextActionType {
|
|
RedirectToUrl,
|
|
DisplayQrCode,
|
|
InvokeSdkClient,
|
|
TriggerApi,
|
|
}
|
|
#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)]
|
|
pub struct NextAction {
|
|
#[serde(rename = "type")]
|
|
pub next_action_type: NextActionType,
|
|
pub redirect_to_url: Option<String>,
|
|
}
|
|
|
|
#[derive(Setter, Clone, Default, Debug, Eq, PartialEq, serde::Serialize)]
|
|
pub struct PaymentsResponse {
|
|
pub payment_id: Option<String>,
|
|
pub merchant_id: Option<String>,
|
|
pub status: api_enums::IntentStatus,
|
|
pub amount: i64,
|
|
pub amount_capturable: Option<i64>,
|
|
pub amount_received: Option<i64>,
|
|
pub connector: Option<String>,
|
|
pub client_secret: Option<Secret<String>>,
|
|
#[serde(with = "common_utils::custom_serde::iso8601::option")]
|
|
pub created: Option<PrimitiveDateTime>,
|
|
pub currency: String,
|
|
pub customer_id: Option<String>,
|
|
pub description: Option<String>,
|
|
pub refunds: Option<Vec<refunds::RefundResponse>>,
|
|
pub mandate_id: Option<String>,
|
|
pub mandate_data: Option<MandateData>,
|
|
pub setup_future_usage: Option<api_enums::FutureUsage>,
|
|
pub off_session: Option<bool>,
|
|
#[serde(with = "common_utils::custom_serde::iso8601::option")]
|
|
pub capture_on: Option<PrimitiveDateTime>,
|
|
pub capture_method: Option<api_enums::CaptureMethod>,
|
|
#[auth_based]
|
|
pub payment_method: Option<api_enums::PaymentMethodType>,
|
|
#[auth_based]
|
|
pub payment_method_data: Option<PaymentMethodDataResponse>,
|
|
pub payment_token: Option<String>,
|
|
pub shipping: Option<Address>,
|
|
pub billing: Option<Address>,
|
|
pub metadata: Option<serde_json::Value>,
|
|
pub email: Option<Secret<String, pii::Email>>,
|
|
pub name: Option<Secret<String>>,
|
|
pub phone: Option<Secret<String>>,
|
|
pub return_url: Option<String>,
|
|
pub authentication_type: Option<api_enums::AuthenticationType>,
|
|
pub statement_descriptor_name: Option<String>,
|
|
pub statement_descriptor_suffix: Option<String>,
|
|
pub next_action: Option<NextAction>,
|
|
pub cancellation_reason: Option<String>,
|
|
pub error_code: Option<String>,
|
|
pub error_message: Option<String>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, serde::Deserialize)]
|
|
#[serde(deny_unknown_fields)]
|
|
pub struct PaymentListConstraints {
|
|
pub customer_id: Option<String>,
|
|
pub starting_after: Option<String>,
|
|
pub ending_before: Option<String>,
|
|
#[serde(default = "default_limit")]
|
|
pub limit: i64,
|
|
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
|
|
pub created: Option<PrimitiveDateTime>,
|
|
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
|
|
#[serde(rename = "created.lt")]
|
|
pub created_lt: Option<PrimitiveDateTime>,
|
|
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
|
|
#[serde(rename = "created.gt")]
|
|
pub created_gt: Option<PrimitiveDateTime>,
|
|
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
|
|
#[serde(rename = "created.lte")]
|
|
pub created_lte: Option<PrimitiveDateTime>,
|
|
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
|
|
#[serde(rename = "created.gte")]
|
|
pub created_gte: Option<PrimitiveDateTime>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, serde::Serialize)]
|
|
pub struct PaymentListResponse {
|
|
pub size: usize,
|
|
pub data: Vec<PaymentsResponse>,
|
|
}
|
|
|
|
#[derive(Setter, Clone, Default, Debug, Eq, PartialEq, serde::Serialize)]
|
|
pub struct VerifyResponse {
|
|
pub verify_id: Option<String>,
|
|
pub merchant_id: Option<String>,
|
|
// pub status: enums::VerifyStatus,
|
|
pub client_secret: Option<Secret<String>>,
|
|
pub customer_id: Option<String>,
|
|
pub email: Option<Secret<String, pii::Email>>,
|
|
pub name: Option<Secret<String>>,
|
|
pub phone: Option<Secret<String>>,
|
|
pub mandate_id: Option<String>,
|
|
#[auth_based]
|
|
pub payment_method: Option<api_enums::PaymentMethodType>,
|
|
#[auth_based]
|
|
pub payment_method_data: Option<PaymentMethodDataResponse>,
|
|
pub payment_token: Option<String>,
|
|
pub error_code: Option<String>,
|
|
pub error_message: Option<String>,
|
|
}
|
|
|
|
fn default_limit() -> i64 {
|
|
10
|
|
}
|
|
|
|
#[derive(Default, Debug, serde::Deserialize, serde::Serialize)]
|
|
pub struct PaymentsRedirectionResponse {
|
|
pub redirect_url: String,
|
|
}
|
|
|
|
pub struct MandateValidationFields {
|
|
pub mandate_id: Option<String>,
|
|
pub confirm: Option<bool>,
|
|
pub customer_id: Option<String>,
|
|
pub mandate_data: Option<MandateData>,
|
|
pub setup_future_usage: Option<api_enums::FutureUsage>,
|
|
pub off_session: Option<bool>,
|
|
}
|
|
|
|
impl From<&PaymentsRequest> for MandateValidationFields {
|
|
fn from(req: &PaymentsRequest) -> Self {
|
|
Self {
|
|
mandate_id: req.mandate_id.clone(),
|
|
confirm: req.confirm,
|
|
customer_id: req.customer_id.clone(),
|
|
mandate_data: req.mandate_data.clone(),
|
|
setup_future_usage: req.setup_future_usage,
|
|
off_session: req.off_session,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<&VerifyRequest> for MandateValidationFields {
|
|
fn from(req: &VerifyRequest) -> Self {
|
|
Self {
|
|
mandate_id: None,
|
|
confirm: Some(true),
|
|
customer_id: req.customer_id.clone(),
|
|
mandate_data: req.mandate_data.clone(),
|
|
off_session: req.off_session,
|
|
setup_future_usage: req.setup_future_usage,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<PaymentsRequest> for PaymentsResponse {
|
|
fn from(item: PaymentsRequest) -> Self {
|
|
let payment_id = match item.payment_id {
|
|
Some(PaymentIdType::PaymentIntentId(id)) => Some(id),
|
|
_ => None,
|
|
};
|
|
|
|
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: item.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 {
|
|
merchant_id: item.merchant_id,
|
|
customer_id: item.customer_id,
|
|
email: item.email,
|
|
name: item.name,
|
|
phone: item.phone,
|
|
payment_method: item.payment_method,
|
|
payment_method_data: item
|
|
.payment_method_data
|
|
.map(PaymentMethodDataResponse::from),
|
|
payment_token: item.payment_token,
|
|
..Default::default()
|
|
}
|
|
}
|
|
}
|
|
|
|
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 {
|
|
Self {
|
|
session_token: vec![],
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<PaymentsStartRequest> for PaymentsRequest {
|
|
fn from(item: PaymentsStartRequest) -> Self {
|
|
Self {
|
|
payment_id: Some(PaymentIdType::PaymentIntentId(item.payment_id)),
|
|
merchant_id: Some(item.merchant_id),
|
|
..Default::default()
|
|
}
|
|
}
|
|
}
|
|
|
|
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<CCard> for CCardResponse {
|
|
fn from(card: CCard) -> Self {
|
|
let card_number_length = card.card_number.peek().clone().len();
|
|
Self {
|
|
last4: card.card_number.peek().clone()[card_number_length - 4..card_number_length]
|
|
.to_string(),
|
|
exp_month: card.card_exp_month.peek().clone(),
|
|
exp_year: card.card_exp_year.peek().clone(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<PaymentMethod> for PaymentMethodDataResponse {
|
|
fn from(payment_method_data: PaymentMethod) -> Self {
|
|
match payment_method_data {
|
|
PaymentMethod::Card(card) => PaymentMethodDataResponse::Card(CCardResponse::from(card)),
|
|
PaymentMethod::BankTransfer => PaymentMethodDataResponse::BankTransfer,
|
|
PaymentMethod::PayLater(pay_later_data) => {
|
|
PaymentMethodDataResponse::PayLater(pay_later_data)
|
|
}
|
|
PaymentMethod::Wallet(wallet_data) => PaymentMethodDataResponse::Wallet(wallet_data),
|
|
PaymentMethod::Paypal => PaymentMethodDataResponse::Paypal,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, serde::Serialize)]
|
|
pub struct PgRedirectResponse {
|
|
pub payment_id: String,
|
|
pub status: api_enums::IntentStatus,
|
|
pub gateway_id: String,
|
|
pub customer_id: Option<String>,
|
|
pub amount: Option<i64>,
|
|
}
|
|
|
|
#[derive(Debug, serde::Serialize, PartialEq, Eq, serde::Deserialize)]
|
|
pub struct RedirectionResponse {
|
|
pub return_url: String,
|
|
pub params: Vec<(String, String)>,
|
|
pub return_url_with_query_params: String,
|
|
pub http_method: String,
|
|
pub headers: Vec<(String, String)>,
|
|
}
|
|
|
|
#[derive(Debug, serde::Deserialize)]
|
|
pub struct PaymentsResponseForm {
|
|
pub transaction_id: String,
|
|
// pub transaction_reference_id: String,
|
|
pub merchant_id: String,
|
|
pub order_id: String,
|
|
}
|
|
|
|
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)]
|
|
pub struct PaymentsRetrieveRequest {
|
|
pub resource_id: PaymentIdType,
|
|
pub merchant_id: Option<String>,
|
|
pub force_sync: bool,
|
|
pub param: Option<String>,
|
|
pub connector: Option<String>,
|
|
}
|
|
|
|
#[derive(Default, Debug, serde::Deserialize, Clone)]
|
|
pub struct PaymentsSessionRequest {
|
|
pub payment_id: String,
|
|
pub client_secret: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
pub struct GpayAllowedMethodsParameters {
|
|
pub allowed_auth_methods: Vec<String>,
|
|
pub allowed_card_networks: Vec<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
pub struct GpayTokenParameters {
|
|
pub gateway: String,
|
|
pub gateway_merchant_id: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
pub struct GpayTokenizationSpecification {
|
|
#[serde(rename = "type")]
|
|
pub token_specification_type: String,
|
|
pub parameters: GpayTokenParameters,
|
|
}
|
|
|
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
pub struct GpayAllowedPaymentMethods {
|
|
#[serde(rename = "type")]
|
|
pub payment_method_type: String,
|
|
pub parameters: GpayAllowedMethodsParameters,
|
|
pub tokenization_specification: GpayTokenizationSpecification,
|
|
}
|
|
|
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
pub struct GpayTransactionInfo {
|
|
pub country_code: String,
|
|
pub currency_code: String,
|
|
pub total_price_status: String,
|
|
pub total_price: i64,
|
|
}
|
|
|
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
pub struct GpayMerchantInfo {
|
|
pub merchant_name: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
pub struct GpayMetadata {
|
|
pub merchant_info: GpayMerchantInfo,
|
|
pub allowed_payment_methods: Vec<GpayAllowedPaymentMethods>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
|
pub struct GpaySessionTokenData {
|
|
pub gpay: GpayMetadata,
|
|
}
|
|
|
|
#[derive(Debug, Clone, serde::Serialize)]
|
|
#[serde(tag = "connector_name")]
|
|
#[serde(rename_all = "lowercase")]
|
|
pub enum SessionToken {
|
|
Gpay {
|
|
allowed_payment_methods: Vec<GpayAllowedPaymentMethods>,
|
|
transaction_info: GpayTransactionInfo,
|
|
},
|
|
Klarna {
|
|
session_token: String,
|
|
session_id: String,
|
|
},
|
|
Paypal {
|
|
session_token: String,
|
|
},
|
|
Applepay {
|
|
epoch_timestamp: u64,
|
|
expires_at: u64,
|
|
merchant_session_identifier: String,
|
|
nonce: String,
|
|
merchant_identifier: String,
|
|
domain_name: String,
|
|
display_name: String,
|
|
signature: String,
|
|
operational_analytics_identifier: String,
|
|
retries: u8,
|
|
psp_id: String,
|
|
},
|
|
}
|
|
|
|
#[derive(Default, Debug, serde::Serialize, Clone)]
|
|
pub struct PaymentsSessionResponse {
|
|
pub session_token: Vec<SessionToken>,
|
|
}
|
|
|
|
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)]
|
|
pub struct PaymentRetrieveBody {
|
|
pub merchant_id: Option<String>,
|
|
pub force_sync: Option<bool>,
|
|
}
|
|
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)]
|
|
pub struct PaymentsCancelRequest {
|
|
#[serde(skip)]
|
|
pub payment_id: String,
|
|
pub cancellation_reason: Option<String>,
|
|
}
|
|
|
|
#[derive(Default, Debug, serde::Deserialize, serde::Serialize)]
|
|
pub struct PaymentsStartRequest {
|
|
pub payment_id: String,
|
|
pub merchant_id: String,
|
|
pub txn_id: String,
|
|
}
|
|
|
|
mod payment_id_type {
|
|
use std::fmt;
|
|
|
|
use serde::{
|
|
de::{self, Visitor},
|
|
Deserializer,
|
|
};
|
|
|
|
use super::PaymentIdType;
|
|
|
|
struct PaymentIdVisitor;
|
|
struct OptionalPaymentIdVisitor;
|
|
|
|
impl<'de> Visitor<'de> for PaymentIdVisitor {
|
|
type Value = PaymentIdType;
|
|
|
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
formatter.write_str("payment id")
|
|
}
|
|
|
|
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
|
where
|
|
E: de::Error,
|
|
{
|
|
Ok(PaymentIdType::PaymentIntentId(value.to_string()))
|
|
}
|
|
}
|
|
|
|
impl<'de> Visitor<'de> for OptionalPaymentIdVisitor {
|
|
type Value = Option<PaymentIdType>;
|
|
|
|
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
|
formatter.write_str("payment id")
|
|
}
|
|
|
|
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
|
where
|
|
D: Deserializer<'de>,
|
|
{
|
|
deserializer.deserialize_any(PaymentIdVisitor).map(Some)
|
|
}
|
|
|
|
fn visit_none<E>(self) -> Result<Self::Value, E>
|
|
where
|
|
E: de::Error,
|
|
{
|
|
Ok(None)
|
|
}
|
|
|
|
fn visit_unit<E>(self) -> Result<Self::Value, E>
|
|
where
|
|
E: de::Error,
|
|
{
|
|
Ok(None)
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub(crate) fn deserialize<'a, D>(deserializer: D) -> Result<PaymentIdType, D::Error>
|
|
where
|
|
D: Deserializer<'a>,
|
|
{
|
|
deserializer.deserialize_any(PaymentIdVisitor)
|
|
}
|
|
|
|
pub(crate) fn deserialize_option<'a, D>(
|
|
deserializer: D,
|
|
) -> Result<Option<PaymentIdType>, D::Error>
|
|
where
|
|
D: Deserializer<'a>,
|
|
{
|
|
deserializer.deserialize_option(OptionalPaymentIdVisitor)
|
|
}
|
|
}
|
|
|
|
mod amount {
|
|
use serde::de;
|
|
|
|
use super::Amount;
|
|
struct AmountVisitor;
|
|
struct OptionalAmountVisitor;
|
|
|
|
// This is defined to provide guarded deserialization of amount
|
|
// which itself handles zero and non-zero values internally
|
|
impl<'de> de::Visitor<'de> for AmountVisitor {
|
|
type Value = Amount;
|
|
|
|
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
write!(formatter, "amount as integer")
|
|
}
|
|
|
|
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
|
|
where
|
|
E: de::Error,
|
|
{
|
|
self.visit_i64(v as i64)
|
|
}
|
|
|
|
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
|
|
where
|
|
E: de::Error,
|
|
{
|
|
Ok(Amount::from(v))
|
|
}
|
|
}
|
|
|
|
impl<'de> de::Visitor<'de> for OptionalAmountVisitor {
|
|
type Value = Option<Amount>;
|
|
|
|
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
write!(formatter, "option of amount (as integer)")
|
|
}
|
|
|
|
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
|
where
|
|
D: serde::Deserializer<'de>,
|
|
{
|
|
deserializer.deserialize_i64(AmountVisitor).map(Some)
|
|
}
|
|
|
|
fn visit_none<E>(self) -> Result<Self::Value, E>
|
|
where
|
|
E: de::Error,
|
|
{
|
|
Ok(None)
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result<Amount, D::Error>
|
|
where
|
|
D: de::Deserializer<'de>,
|
|
{
|
|
deserializer.deserialize_any(AmountVisitor)
|
|
}
|
|
pub(crate) fn deserialize_option<'de, D>(deserializer: D) -> Result<Option<Amount>, D::Error>
|
|
where
|
|
D: de::Deserializer<'de>,
|
|
{
|
|
deserializer.deserialize_option(OptionalAmountVisitor)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_mandate_type() {
|
|
let mandate_type = MandateType::default();
|
|
assert_eq!(
|
|
serde_json::to_string(&mandate_type).unwrap(),
|
|
r#"{"multi_use":null}"#
|
|
)
|
|
}
|
|
}
|