feat(router): Add payment_methods_session_delete_payment_method endpoint [V2] (#7409)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Anurag Thakur
2025-03-27 16:49:36 +05:30
committed by GitHub
parent e9433d98e1
commit 652fae4fe9
11 changed files with 214 additions and 10 deletions

View File

@ -0,0 +1,3 @@
---
openapi: delete /v2/payment-method-session/:id
---

View File

@ -67,7 +67,8 @@
"api-reference/payment-method-session/payment-method-session--retrieve",
"api-reference/payment-method-session/payment-method-session--list-payment-methods",
"api-reference/payment-method-session/payment-method-session--update-a-saved-payment-method",
"api-reference/payment-method-session/payment-method-session--confirm-a-payment-method-session"
"api-reference/payment-method-session/payment-method-session--confirm-a-payment-method-session",
"api-reference/payment-method-session/payment-method-session--delete-a-saved-payment-method"
]
},
{

View File

@ -2960,6 +2960,62 @@
"ephemeral_key": []
}
]
},
"delete": {
"tags": [
"Payment Method Session"
],
"summary": "Payment Method Session - Delete a saved payment method",
"description": "Delete a saved payment method from the given payment method session.",
"operationId": "Delete a saved payment method",
"parameters": [
{
"name": "id",
"in": "path",
"description": "The unique identifier for the Payment Method Session",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PaymentMethodSessionDeleteSavedPaymentMethod"
},
"examples": {
"Update the card holder name": {
"value": {
"payment_method_id": "12345_pm_0194b1ecabc172e28aeb71f70a4daba3"
}
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "The payment method has been updated successfully",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PaymentMethodDeleteResponse"
}
}
}
},
"404": {
"description": "The request is invalid"
}
},
"security": [
{
"ephemeral_key": []
}
]
}
},
"/v2/payment-method-session/:id/list-payment-methods": {
@ -4462,16 +4518,20 @@
"AuthenticationDetails": {
"type": "object",
"required": [
"status",
"error"
"status"
],
"properties": {
"status": {
"$ref": "#/components/schemas/IntentStatus"
},
"error": {
"allOf": [
{
"$ref": "#/components/schemas/ErrorDetails"
}
],
"nullable": true
}
}
},
"AuthenticationStatus": {
@ -15633,6 +15693,19 @@
}
}
},
"PaymentMethodSessionDeleteSavedPaymentMethod": {
"type": "object",
"required": [
"payment_method_id"
],
"properties": {
"payment_method_id": {
"type": "string",
"description": "The payment method id of the payment method to be updated",
"example": "12345_pm_01926c58bc6e77c09e809964e72af8c8"
}
}
},
"PaymentMethodSessionRequest": {
"type": "object",
"required": [

View File

@ -2781,6 +2781,14 @@ pub struct PaymentMethodSessionUpdateSavedPaymentMethod {
pub payment_method_update_request: PaymentMethodUpdate,
}
#[cfg(feature = "v2")]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct PaymentMethodSessionDeleteSavedPaymentMethod {
/// 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,
}
#[cfg(feature = "v2")]
#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, ToSchema)]
pub struct PaymentMethodSessionConfirmRequest {
@ -2858,6 +2866,6 @@ pub struct AuthenticationDetails {
pub status: common_enums::IntentStatus,
/// Error details of the authentication
#[schema(value_type = ErrorDetails)]
#[schema(value_type = Option<ErrorDetails>)]
pub error: Option<payments::ErrorDetails>,
}

View File

@ -143,6 +143,7 @@ Never share your secret api keys. Keep them guarded and secure.
routes::payment_method::payment_method_session_retrieve,
routes::payment_method::payment_method_session_list_payment_methods,
routes::payment_method::payment_method_session_update_saved_payment_method,
routes::payment_method::payment_method_session_delete_saved_payment_method,
routes::payment_method::payment_method_session_confirm,
//Routes for refunds
@ -212,6 +213,7 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::payment_methods::PaymentMethodCreate,
api_models::payment_methods::PaymentMethodIntentCreate,
api_models::payment_methods::PaymentMethodIntentConfirm,
api_models::payment_methods::AuthenticationDetails,
api_models::payment_methods::PaymentMethodResponse,
api_models::payment_methods::PaymentMethodResponseData,
api_models::payment_methods::CustomerPaymentMethod,
@ -698,6 +700,7 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::feature_matrix::CardSpecificFeatures,
api_models::feature_matrix::SupportedPaymentMethod,
api_models::payment_methods::PaymentMethodSessionUpdateSavedPaymentMethod,
api_models::payment_methods::PaymentMethodSessionDeleteSavedPaymentMethod,
common_utils::types::BrowserInformation,
api_models::enums::TokenizationType,
api_models::enums::NetworkTokenizationToggle,

View File

@ -444,6 +444,35 @@ pub fn payment_method_session_list_payment_methods() {}
)]
pub fn payment_method_session_update_saved_payment_method() {}
/// Payment Method Session - Delete a saved payment method
///
/// Delete a saved payment method from the given payment method session.
#[cfg(feature = "v2")]
#[utoipa::path(
delete,
path = "/v2/payment-method-session/:id",
params (
("id" = String, Path, description = "The unique identifier for the Payment Method Session"),
),
request_body(
content = PaymentMethodSessionDeleteSavedPaymentMethod,
examples(( "Update the card holder name" = (
value =json!( {
"payment_method_id": "12345_pm_0194b1ecabc172e28aeb71f70a4daba3",
}
)
)))
),
responses(
(status = 200, description = "The payment method has been updated successfully", body = PaymentMethodDeleteResponse),
(status = 404, description = "The request is invalid")
),
tag = "Payment Method Session",
operation_id = "Delete a saved payment method",
security(("ephemeral_key" = []))
)]
pub fn payment_method_session_delete_saved_payment_method() {}
/// Card network tokenization - Create using raw card data
///
/// Create a card network token for a customer and store it as a payment method.

View File

@ -2021,12 +2021,24 @@ pub async fn delete_payment_method(
key_store: domain::MerchantKeyStore,
merchant_account: domain::MerchantAccount,
) -> RouterResponse<api::PaymentMethodDeleteResponse> {
let db = state.store.as_ref();
let key_manager_state = &(&state).into();
let pm_id = id_type::GlobalPaymentMethodId::generate_from_string(pm_id.payment_method_id)
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Unable to generate GlobalPaymentMethodId")?;
let response = delete_payment_method_core(state, pm_id, key_store, merchant_account).await?;
Ok(services::ApplicationResponse::Json(response))
}
#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
#[instrument(skip_all)]
pub async fn delete_payment_method_core(
state: SessionState,
pm_id: id_type::GlobalPaymentMethodId,
key_store: domain::MerchantKeyStore,
merchant_account: domain::MerchantAccount,
) -> RouterResult<api::PaymentMethodDeleteResponse> {
let db = state.store.as_ref();
let key_manager_state = &(&state).into();
let payment_method = db
.find_payment_method(
@ -2084,7 +2096,7 @@ pub async fn delete_payment_method(
let response = api::PaymentMethodDeleteResponse { id: pm_id };
Ok(services::ApplicationResponse::Json(response))
Ok(response)
}
#[cfg(feature = "v2")]
@ -2415,6 +2427,32 @@ pub async fn payment_methods_session_update_payment_method(
Ok(services::ApplicationResponse::Json(updated_payment_method))
}
#[cfg(feature = "v2")]
pub async fn payment_methods_session_delete_payment_method(
state: SessionState,
key_store: domain::MerchantKeyStore,
merchant_account: domain::MerchantAccount,
pm_id: id_type::GlobalPaymentMethodId,
payment_method_session_id: id_type::GlobalPaymentMethodSessionId,
) -> RouterResponse<api::PaymentMethodDeleteResponse> {
let db = state.store.as_ref();
let key_manager_state = &(&state).into();
// Validate if the session still exists
db.get_payment_methods_session(key_manager_state, &key_store, &payment_method_session_id)
.await
.to_not_found_response(errors::ApiErrorResponse::GenericNotFoundError {
message: "payment methods session does not exist or has expired".to_string(),
})
.attach_printable("Failed to retrieve payment methods session from db")?;
let response = delete_payment_method_core(state, pm_id, key_store, merchant_account)
.await
.attach_printable("Failed to delete saved payment method")?;
Ok(services::ApplicationResponse::Json(response))
}
#[cfg(feature = "v2")]
fn construct_zero_auth_payments_request(
confirm_request: &payment_methods::PaymentMethodSessionConfirmRequest,

View File

@ -1332,7 +1332,10 @@ impl PaymentMethodSession {
.service(
web::resource("")
.route(web::get().to(payment_methods::payment_methods_session_retrieve))
.route(web::put().to(payment_methods::payment_methods_session_update)),
.route(web::put().to(payment_methods::payment_methods_session_update))
.route(web::delete().to(
payment_methods::payment_method_session_delete_saved_payment_method,
)),
)
.service(web::resource("/list-payment-methods").route(
web::get().to(payment_methods::payment_method_session_list_payment_methods),

View File

@ -331,6 +331,7 @@ impl From<Flow> for ApiIdentifier {
| Flow::PaymentMethodSessionRetrieve
| Flow::PaymentMethodSessionConfirm
| Flow::PaymentMethodSessionUpdateSavedPaymentMethod
| Flow::PaymentMethodSessionDeleteSavedPaymentMethod
| Flow::PaymentMethodSessionUpdate => Self::PaymentMethodSession,
}
}

View File

@ -1327,3 +1327,46 @@ pub async fn payment_method_session_update_saved_payment_method(
))
.await
}
#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
#[instrument(skip_all, fields(flow = ?Flow::PaymentMethodSessionUpdateSavedPaymentMethod))]
pub async fn payment_method_session_delete_saved_payment_method(
state: web::Data<AppState>,
req: HttpRequest,
path: web::Path<id_type::GlobalPaymentMethodSessionId>,
json_payload: web::Json<
api_models::payment_methods::PaymentMethodSessionDeleteSavedPaymentMethod,
>,
) -> HttpResponse {
let flow = Flow::PaymentMethodSessionDeleteSavedPaymentMethod;
let payload = json_payload.into_inner();
let payment_method_session_id = path.into_inner();
let request = PaymentMethodsSessionGenericRequest {
payment_method_session_id: payment_method_session_id.clone(),
request: payload,
};
Box::pin(api::server_wrap(
flow,
state,
&req,
request,
|state, auth: auth::AuthenticationData, request, _| {
payment_methods_routes::payment_methods_session_delete_payment_method(
state,
auth.key_store,
auth.merchant_account,
request.request.payment_method_id,
request.payment_method_session_id,
)
},
&auth::V2ClientAuth(
common_utils::types::authentication::ResourceId::PaymentMethodSession(
payment_method_session_id,
),
),
api_locking::LockAction::NotApplicable,
))
.await
}

View File

@ -566,6 +566,8 @@ pub enum Flow {
PaymentMethodSessionUpdate,
/// Update a saved payment method using the payment methods session
PaymentMethodSessionUpdateSavedPaymentMethod,
/// Delete a saved payment method using the payment methods session
PaymentMethodSessionDeleteSavedPaymentMethod,
/// Confirm a payment method session with payment method data
PaymentMethodSessionConfirm,
/// Create Cards Info flow