mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 20:23:43 +08:00
feat(payment_methods_session_v2): add payment methods session endpoints (#7107)
Co-authored-by: Sanchith Hegde <sanchith.hegde@juspay.in> Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com> Co-authored-by: Anurag Thakur <anurag.thakur@juspay.in> Co-authored-by: Pa1NarK <69745008+pixincreate@users.noreply.github.com> Co-authored-by: Shankar Singh C <83439957+ShankarSinghC@users.noreply.github.com> Co-authored-by: Sai Harsha Vardhan <56996463+sai-harsha-vardhan@users.noreply.github.com> Co-authored-by: hrithikesh026 <hrithikesh.vm@juspay.in> Co-authored-by: Debarati Ghatak <88573135+cookieg13@users.noreply.github.com> Co-authored-by: awasthi21 <107559116+awasthi21@users.noreply.github.com> Co-authored-by: Gnanasundari24 <118818938+Gnanasundari24@users.noreply.github.com> Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Arindam Sahoo <88739246+arindam-sahoo@users.noreply.github.com> Co-authored-by: Arindam Sahoo <arindam.sahoo@Arindam-Sahoo-F565040VFJ.local> Co-authored-by: Sakil Mostak <73734619+Sakilmostak@users.noreply.github.com> Co-authored-by: AkshayaFoiger <131388445+AkshayaFoiger@users.noreply.github.com> Co-authored-by: Riddhiagrawal001 <50551695+Riddhiagrawal001@users.noreply.github.com> Co-authored-by: Suman Maji <77887221+sumanmaji4@users.noreply.github.com> Co-authored-by: Sandeep Kumar <83278309+tsdk02@users.noreply.github.com> Co-authored-by: Debarshi Gupta <debarshigupta47@gmail.com> Co-authored-by: Debarshi Gupta <debarshi.gupta@Debarshi-Gupta-CM92YWDXFD.local> Co-authored-by: Sanchith Hegde <22217505+SanchithHegde@users.noreply.github.com> Co-authored-by: Swangi Kumari <85639103+swangi-kumari@users.noreply.github.com> Co-authored-by: pranav-arjunan <pranav.arjunan@juspay.in> Co-authored-by: Kashif <kashif.dev@protonmail.com> Co-authored-by: Sagnik Mitra <83326850+ImSagnik007@users.noreply.github.com> Co-authored-by: sweta-kumari-sharma <77436883+Sweta-Kumari-Sharma@users.noreply.github.com>
This commit is contained in:
@ -213,8 +213,8 @@ pub struct CustomerResponse {
|
||||
#[schema(value_type = Option<Object>,example = json!({ "city": "NY", "unit": "245" }))]
|
||||
pub metadata: Option<pii::SecretSerdeValue>,
|
||||
/// The identifier for the default payment method.
|
||||
#[schema(max_length = 64, example = "pm_djh2837dwduh890123")]
|
||||
pub default_payment_method_id: Option<String>,
|
||||
#[schema(value_type = Option<String>, max_length = 64, example = "12345_pm_01926c58bc6e77c09e809964e72af8c8")]
|
||||
pub default_payment_method_id: Option<id_type::GlobalPaymentMethodId>,
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "customer_v2"))]
|
||||
@ -340,8 +340,8 @@ pub struct CustomerUpdateRequest {
|
||||
#[schema(value_type = Option<Object>,example = json!({ "city": "NY", "unit": "245" }))]
|
||||
pub metadata: Option<pii::SecretSerdeValue>,
|
||||
/// The unique identifier of the payment method
|
||||
#[schema(example = "card_rGK4Vi5iSW70MY7J2mIg")]
|
||||
pub default_payment_method_id: Option<String>,
|
||||
#[schema(value_type = Option<String>, example = "12345_pm_01926c58bc6e77c09e809964e72af8c8")]
|
||||
pub default_payment_method_id: Option<id_type::GlobalPaymentMethodId>,
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "customer_v2"))]
|
||||
|
||||
@ -19,51 +19,69 @@ pub struct EphemeralKeyCreateRequest {
|
||||
}
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
/// Information required to create an ephemeral key.
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||
pub struct EphemeralKeyCreateRequest {
|
||||
/// Customer ID for which an ephemeral key must be created
|
||||
#[schema(
|
||||
min_length = 32,
|
||||
max_length = 64,
|
||||
value_type = String,
|
||||
example = "12345_cus_01926c58bc6e77c09e809964e72af8c8"
|
||||
)]
|
||||
pub customer_id: id_type::GlobalCustomerId,
|
||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, PartialEq, Eq, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ResourceId {
|
||||
#[schema(value_type = String)]
|
||||
Customer(id_type::GlobalCustomerId),
|
||||
}
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
/// ephemeral_key for the customer_id mentioned
|
||||
/// Information required to create a client secret.
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||
pub struct ClientSecretCreateRequest {
|
||||
/// Resource ID for which a client secret must be created
|
||||
pub resource_id: ResourceId,
|
||||
}
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
/// client_secret for the resource_id mentioned
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, Eq, PartialEq, ToSchema)]
|
||||
pub struct EphemeralKeyResponse {
|
||||
/// Ephemeral key id
|
||||
pub struct ClientSecretResponse {
|
||||
/// Client Secret id
|
||||
#[schema(value_type = String, max_length = 32, min_length = 1)]
|
||||
pub id: id_type::EphemeralKeyId,
|
||||
/// customer_id to which this ephemeral key belongs to
|
||||
#[schema(value_type = String, max_length = 64, min_length = 32, example = "12345_cus_01926c58bc6e77c09e809964e72af8c8")]
|
||||
pub customer_id: id_type::GlobalCustomerId,
|
||||
/// time at which this ephemeral key was created
|
||||
pub id: id_type::ClientSecretId,
|
||||
/// resource_id to which this client secret belongs to
|
||||
#[schema(value_type = ResourceId)]
|
||||
pub resource_id: ResourceId,
|
||||
/// time at which this client secret was created
|
||||
pub created_at: time::PrimitiveDateTime,
|
||||
/// time at which this ephemeral key would expire
|
||||
/// time at which this client secret would expire
|
||||
pub expires: time::PrimitiveDateTime,
|
||||
#[schema(value_type=String)]
|
||||
/// ephemeral key
|
||||
/// client secret
|
||||
pub secret: Secret<String>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1")]
|
||||
impl common_utils::events::ApiEventMetric for EphemeralKeyCreateRequest {
|
||||
fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
|
||||
Some(common_utils::events::ApiEventsType::Miscellaneous)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
impl common_utils::events::ApiEventMetric for EphemeralKeyResponse {
|
||||
#[cfg(feature = "v1")]
|
||||
impl common_utils::events::ApiEventMetric for EphemeralKeyCreateResponse {
|
||||
fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
|
||||
Some(common_utils::events::ApiEventsType::Miscellaneous)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
impl common_utils::events::ApiEventMetric for ClientSecretCreateRequest {
|
||||
fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
|
||||
Some(common_utils::events::ApiEventsType::Miscellaneous)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
impl common_utils::events::ApiEventMetric for ClientSecretResponse {
|
||||
fn get_api_event_type(&self) -> Option<common_utils::events::ApiEventsType> {
|
||||
Some(common_utils::events::ApiEventsType::Miscellaneous)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v1")]
|
||||
/// ephemeral_key for the customer_id mentioned
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, Eq, PartialEq, ToSchema)]
|
||||
pub struct EphemeralKeyCreateResponse {
|
||||
|
||||
@ -179,6 +179,16 @@ impl<T> ApiEventMetric for DisputesMetricsResponse<T> {
|
||||
Some(ApiEventsType::Miscellaneous)
|
||||
}
|
||||
}
|
||||
#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
|
||||
impl ApiEventMetric for PaymentMethodIntentConfirmInternal {
|
||||
fn get_api_event_type(&self) -> Option<ApiEventsType> {
|
||||
Some(ApiEventsType::PaymentMethod {
|
||||
payment_method_id: self.id.clone(),
|
||||
payment_method_type: Some(self.request.payment_method_type),
|
||||
payment_method_subtype: Some(self.request.payment_method_subtype),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
|
||||
impl ApiEventMetric for PaymentMethodIntentCreate {
|
||||
@ -192,3 +202,15 @@ impl ApiEventMetric for DisputeListFilters {
|
||||
Some(ApiEventsType::ResourceListAPI)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
impl ApiEventMetric for PaymentMethodSessionRequest {}
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
impl ApiEventMetric for PaymentMethodsSessionResponse {
|
||||
fn get_api_event_type(&self) -> Option<ApiEventsType> {
|
||||
Some(ApiEventsType::PaymentMethodSession {
|
||||
payment_method_session_id: self.id.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,7 +160,7 @@ impl ApiEventMetric for PaymentsRequest {
|
||||
}
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
impl ApiEventMetric for PaymentsResponse {
|
||||
impl ApiEventMetric for payments::PaymentsResponse {
|
||||
fn get_api_event_type(&self) -> Option<ApiEventsType> {
|
||||
Some(ApiEventsType::Payment {
|
||||
payment_id: self.id.clone(),
|
||||
|
||||
@ -194,6 +194,20 @@ impl PaymentMethodIntentConfirm {
|
||||
}
|
||||
}
|
||||
|
||||
/// This struct is used internally only
|
||||
#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct PaymentMethodIntentConfirmInternal {
|
||||
pub id: id_type::GlobalPaymentMethodId,
|
||||
pub request: PaymentMethodIntentConfirm,
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
|
||||
impl From<PaymentMethodIntentConfirmInternal> for PaymentMethodIntentConfirm {
|
||||
fn from(item: PaymentMethodIntentConfirmInternal) -> Self {
|
||||
item.request
|
||||
}
|
||||
}
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
/// This struct is only used by and internal api to migrate payment method
|
||||
pub struct PaymentMethodMigrate {
|
||||
@ -871,10 +885,6 @@ pub struct PaymentMethodResponse {
|
||||
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
|
||||
pub last_used_at: Option<time::PrimitiveDateTime>,
|
||||
|
||||
/// For Client based calls
|
||||
#[schema(value_type=Option<String>)]
|
||||
pub ephemeral_key: Option<masking::Secret<String>>,
|
||||
|
||||
pub payment_method_data: Option<PaymentMethodResponseData>,
|
||||
}
|
||||
|
||||
@ -1105,6 +1115,9 @@ impl From<CardDetailFromLocker> for payments::AdditionalCardInfo {
|
||||
pub struct PaymentMethodListResponse {
|
||||
/// The list of payment methods that are enabled for the business profile
|
||||
pub payment_methods_enabled: Vec<ResponsePaymentMethodTypes>,
|
||||
|
||||
/// The list of saved payment methods of the customer
|
||||
pub customer_payment_methods: Vec<CustomerPaymentMethod>,
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
@ -1797,8 +1810,6 @@ pub struct CustomerPaymentMethodsListResponse {
|
||||
pub struct CustomerPaymentMethodsListResponse {
|
||||
/// List of payment methods for customer
|
||||
pub customer_payment_methods: Vec<CustomerPaymentMethod>,
|
||||
/// Returns whether a customer id is not tied to a payment intent (only when the request is made against a client secret)
|
||||
pub is_guest_customer: Option<bool>,
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
@ -1844,12 +1855,9 @@ pub struct CustomerDefaultPaymentMethodResponse {
|
||||
#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
|
||||
#[derive(Debug, Clone, serde::Serialize, ToSchema)]
|
||||
pub struct CustomerPaymentMethod {
|
||||
/// Token for payment method in temporary card locker which gets refreshed often
|
||||
#[schema(example = "7ebf443f-a050-4067-84e5-e6f6d4800aef")]
|
||||
pub payment_token: Option<String>,
|
||||
/// The unique identifier of the customer.
|
||||
#[schema(example = "pm_iouuy468iyuowqs")]
|
||||
pub payment_method_id: String,
|
||||
/// The unique identifier of the payment method.
|
||||
#[schema(value_type = String, example = "12345_pm_01926c58bc6e77c09e809964e72af8c8")]
|
||||
pub id: id_type::GlobalPaymentMethodId,
|
||||
|
||||
/// The unique identifier of the customer.
|
||||
#[schema(
|
||||
@ -1865,8 +1873,8 @@ pub struct CustomerPaymentMethod {
|
||||
pub payment_method_type: api_enums::PaymentMethod,
|
||||
|
||||
/// This is a sub-category of payment method.
|
||||
#[schema(value_type = Option<PaymentMethodType>,example = "credit_card")]
|
||||
pub payment_method_subtype: Option<api_enums::PaymentMethodType>,
|
||||
#[schema(value_type = PaymentMethodType,example = "credit")]
|
||||
pub payment_method_subtype: api_enums::PaymentMethodType,
|
||||
|
||||
/// Indicates whether the payment method is eligible for recurring payments
|
||||
#[schema(example = true)]
|
||||
@ -1884,17 +1892,15 @@ pub struct CustomerPaymentMethod {
|
||||
#[serde(with = "common_utils::custom_serde::iso8601")]
|
||||
pub created: time::PrimitiveDateTime,
|
||||
|
||||
/// Surcharge details for this saved card
|
||||
pub surcharge_details: Option<SurchargeDetailsResponse>,
|
||||
|
||||
/// Whether this payment method requires CVV to be collected
|
||||
#[schema(example = true)]
|
||||
pub requires_cvv: bool,
|
||||
|
||||
/// A timestamp (ISO 8601 code) that determines when the payment method was last used
|
||||
#[schema(value_type = Option<PrimitiveDateTime>,example = "2024-02-24T11:04:09.922Z")]
|
||||
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
|
||||
pub last_used_at: Option<time::PrimitiveDateTime>,
|
||||
#[schema(value_type = PrimitiveDateTime,example = "2024-02-24T11:04:09.922Z")]
|
||||
#[serde(default, with = "common_utils::custom_serde::iso8601")]
|
||||
pub last_used_at: time::PrimitiveDateTime,
|
||||
|
||||
/// Indicates if the payment method has been set to default or not
|
||||
#[schema(example = true)]
|
||||
pub is_default: bool,
|
||||
@ -2299,6 +2305,7 @@ type PaymentMethodMigrationResponseType = (
|
||||
Result<PaymentMethodMigrateResponse, String>,
|
||||
PaymentMethodRecord,
|
||||
);
|
||||
|
||||
#[cfg(all(
|
||||
any(feature = "v2", feature = "v1"),
|
||||
not(feature = "payment_methods_v2")
|
||||
@ -2464,29 +2471,72 @@ impl From<(PaymentMethodRecord, id_type::MerchantId)> for customers::CustomerReq
|
||||
}
|
||||
}
|
||||
|
||||
// #[cfg(feature = "v2")]
|
||||
// impl From<PaymentMethodRecord> for customers::CustomerRequest {
|
||||
// fn from(record: PaymentMethodRecord) -> Self {
|
||||
// Self {
|
||||
// merchant_reference_id: Some(record.customer_id),
|
||||
// name: record.name.unwrap(),
|
||||
// email: record.email.unwrap(),
|
||||
// phone: record.phone,
|
||||
// description: None,
|
||||
// phone_country_code: record.phone_country_code,
|
||||
// default_billing_address: Some(payments::AddressDetails {
|
||||
// city: Some(record.billing_address_city),
|
||||
// country: record.billing_address_country,
|
||||
// line1: Some(record.billing_address_line1),
|
||||
// line2: record.billing_address_line2,
|
||||
// state: Some(record.billing_address_state),
|
||||
// line3: record.billing_address_line3,
|
||||
// zip: Some(record.billing_address_zip),
|
||||
// first_name: Some(record.billing_address_first_name),
|
||||
// last_name: Some(record.billing_address_last_name),
|
||||
// }),
|
||||
// default_shipping_address: None,
|
||||
// metadata: None,
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
#[cfg(feature = "v2")]
|
||||
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, ToSchema)]
|
||||
pub struct PaymentMethodSessionRequest {
|
||||
/// The customer id for which the payment methods session is to be created
|
||||
#[schema(value_type = String, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
|
||||
pub customer_id: id_type::GlobalCustomerId,
|
||||
|
||||
/// The billing address details of the customer. This will also be used for any new payment methods added during the session
|
||||
#[schema(value_type = Option<Address>)]
|
||||
pub billing: Option<payments::Address>,
|
||||
|
||||
/// The tokenization type to be applied
|
||||
#[schema(value_type = Option<PspTokenization>)]
|
||||
pub psp_tokenization: Option<common_types::payment_methods::PspTokenization>,
|
||||
|
||||
/// The network tokenization configuration if applicable
|
||||
#[schema(value_type = Option<NetworkTokenization>)]
|
||||
pub network_tokenization: Option<common_types::payment_methods::NetworkTokenization>,
|
||||
|
||||
/// The time (seconds ) when the session will expire
|
||||
/// If not provided, the session will expire in 15 minutes
|
||||
#[schema(example = 900, default = 900)]
|
||||
pub expires_in: Option<u32>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, ToSchema)]
|
||||
pub struct PaymentMethodSessionUpdateSavedPaymentMethod {
|
||||
/// The payment method id of the payment method to be updated
|
||||
#[schema(value_type = String, example = "12345_pm_01926c58bc6e77c09e809964e72af8c8")]
|
||||
pub payment_method_id: id_type::GlobalPaymentMethodId,
|
||||
|
||||
/// The update request for the payment method update
|
||||
#[serde(flatten)]
|
||||
pub payment_method_update_request: PaymentMethodUpdate,
|
||||
}
|
||||
|
||||
#[cfg(feature = "v2")]
|
||||
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, ToSchema)]
|
||||
pub struct PaymentMethodsSessionResponse {
|
||||
#[schema(value_type = String, example = "12345_pms_01926c58bc6e77c09e809964e72af8c8")]
|
||||
pub id: id_type::GlobalPaymentMethodSessionId,
|
||||
|
||||
/// The customer id for which the payment methods session is to be created
|
||||
#[schema(value_type = String, example = "12345_cus_01926c58bc6e77c09e809964e72af8c8")]
|
||||
pub customer_id: id_type::GlobalCustomerId,
|
||||
|
||||
/// The billing address details of the customer. This will also be used for any new payment methods added during the session
|
||||
#[schema(value_type = Option<Address>)]
|
||||
pub billing: Option<payments::Address>,
|
||||
|
||||
/// The tokenization type to be applied
|
||||
#[schema(value_type = Option<PspTokenization>)]
|
||||
pub psp_tokenization: Option<common_types::payment_methods::PspTokenization>,
|
||||
|
||||
/// The network tokenization configuration if applicable
|
||||
#[schema(value_type = Option<NetworkTokenization>)]
|
||||
pub network_tokenization: Option<common_types::payment_methods::NetworkTokenization>,
|
||||
|
||||
/// The iso timestamp when the session will expire
|
||||
/// Trying to retrieve the session or any operations on the session after this time will result in an error
|
||||
#[schema(value_type = PrimitiveDateTime, example = "2023-01-18T11:04:09.922Z")]
|
||||
#[serde(with = "common_utils::custom_serde::iso8601")]
|
||||
pub expires_at: time::PrimitiveDateTime,
|
||||
|
||||
/// Client Secret
|
||||
#[schema(value_type = String)]
|
||||
pub client_secret: masking::Secret<String>,
|
||||
}
|
||||
|
||||
@ -27,12 +27,13 @@ use time::{Date, PrimitiveDateTime};
|
||||
use url::Url;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
#[cfg(feature = "v1")]
|
||||
use crate::ephemeral_key::EphemeralKeyCreateResponse;
|
||||
#[cfg(feature = "v2")]
|
||||
use crate::payment_methods;
|
||||
use crate::{
|
||||
admin::{self, MerchantConnectorInfo},
|
||||
disputes, enums as api_enums,
|
||||
ephemeral_key::EphemeralKeyCreateResponse,
|
||||
mandates::RecurringDetails,
|
||||
refunds,
|
||||
};
|
||||
|
||||
@ -285,7 +285,7 @@ pub enum OutgoingWebhookContent {
|
||||
#[serde(tag = "type", content = "object", rename_all = "snake_case")]
|
||||
#[cfg(feature = "v2")]
|
||||
pub enum OutgoingWebhookContent {
|
||||
#[schema(value_type = PaymentsResponse, title = "PaymentsResponse")]
|
||||
#[schema(value_type = PaymentsRetrieveResponse, title = "PaymentsResponse")]
|
||||
PaymentDetails(Box<payments::PaymentsRetrieveResponse>),
|
||||
#[schema(value_type = RefundResponse, title = "RefundResponse")]
|
||||
RefundDetails(Box<refunds::RefundResponse>),
|
||||
|
||||
Reference in New Issue
Block a user