diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json index 16fcefac0e..aebc0b38c2 100644 --- a/api-reference-v2/openapi_spec.json +++ b/api-reference-v2/openapi_spec.json @@ -2833,6 +2833,47 @@ ] } }, + "/v2/customers/{id}/saved-payment-methods": { + "delete": { + "tags": [ + "Payment Methods" + ], + "summary": "Payment Method - List Customer Saved Payment Methods", + "description": "List the payment methods saved for a customer", + "operationId": "List Customer Saved Payment Methods", + "parameters": [ + { + "name": "id", + "in": "path", + "description": "The unique identifier for the customer", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Payment Methods Retrieved", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerPaymentMethodsListResponse" + } + } + } + }, + "404": { + "description": "Customer Not Found" + } + }, + "security": [ + { + "api_key": [] + } + ] + } + }, "/v2/payment-method-session": { "post": { "tags": [ diff --git a/crates/openapi/src/openapi_v2.rs b/crates/openapi/src/openapi_v2.rs index a4eb67b64f..eeb732f81d 100644 --- a/crates/openapi/src/openapi_v2.rs +++ b/crates/openapi/src/openapi_v2.rs @@ -136,6 +136,7 @@ Never share your secret api keys. Keep them guarded and secure. routes::payment_method::payment_method_update_api, routes::payment_method::payment_method_retrieve_api, routes::payment_method::payment_method_delete_api, + routes::payment_method::list_customer_payment_method_api, //Routes for payment method session routes::payment_method::payment_method_session_create, diff --git a/crates/openapi/src/routes/payment_method.rs b/crates/openapi/src/routes/payment_method.rs index 3c1f66e6e7..1531832239 100644 --- a/crates/openapi/src/routes/payment_method.rs +++ b/crates/openapi/src/routes/payment_method.rs @@ -322,6 +322,26 @@ pub async fn payment_method_update_api() {} #[cfg(feature = "v2")] pub async fn payment_method_delete_api() {} +/// Payment Method - List Customer Saved Payment Methods +/// +/// List the payment methods saved for a customer +#[utoipa::path( + delete, + path = "/v2/customers/{id}/saved-payment-methods", + params ( + ("id" = String, Path, description = "The unique identifier for the customer"), + ), + responses( + (status = 200, description = "Payment Methods Retrieved", body = CustomerPaymentMethodsListResponse), + (status = 404, description = "Customer Not Found"), + ), + tag = "Payment Methods", + operation_id = "List Customer Saved Payment Methods", + security(("api_key" = [])) +)] +#[cfg(feature = "v2")] +pub async fn list_customer_payment_method_api() {} + /// Payment Method Session - Create /// /// Create a payment method session for a customer diff --git a/crates/router/src/core/payment_methods.rs b/crates/router/src/core/payment_methods.rs index 237a097b79..ffb864ea07 100644 --- a/crates/router/src/core/payment_methods.rs +++ b/crates/router/src/core/payment_methods.rs @@ -1264,6 +1264,23 @@ pub async fn list_payment_methods_for_session( )) } +#[cfg(all(feature = "v2", feature = "olap"))] +#[instrument(skip_all)] +pub async fn list_saved_payment_methods_for_customer( + state: SessionState, + merchant_account: domain::MerchantAccount, + key_store: domain::MerchantKeyStore, + customer_id: id_type::GlobalCustomerId, +) -> RouterResponse { + let customer_payment_methods = + list_customer_payment_method_core(&state, &merchant_account, &key_store, &customer_id) + .await?; + + Ok(hyperswitch_domain_models::api::ApplicationResponse::Json( + customer_payment_methods, + )) +} + #[cfg(feature = "v2")] /// Container for the inputs required for the required fields struct RequiredFieldsInput { @@ -1641,11 +1658,7 @@ fn get_pm_list_context( Ok(payment_method_retrieval_context) } -#[cfg(all( - feature = "v2", - feature = "payment_methods_v2", - feature = "customer_v2" -))] +#[cfg(all(feature = "v2", feature = "olap"))] pub async fn list_customer_payment_method_core( state: &SessionState, merchant_account: &domain::MerchantAccount, diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index 760afc26b0..fbf72d8a54 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -1038,6 +1038,10 @@ impl Customers { .route(web::get().to(customers::customers_retrieve)) .route(web::delete().to(customers::customers_delete)), ) + .service( + web::resource("/{id}/saved-payment-methods") + .route(web::get().to(payment_methods::list_customer_payment_method_api)), + ) } route } diff --git a/crates/router/src/routes/payment_methods.rs b/crates/router/src/routes/payment_methods.rs index 036646f719..98be9d6a26 100644 --- a/crates/router/src/routes/payment_methods.rs +++ b/crates/router/src/routes/payment_methods.rs @@ -581,6 +581,43 @@ pub async fn initiate_pm_collect_link_flow( .await } +#[cfg(all(feature = "v2", feature = "olap"))] +#[instrument(skip_all, fields(flow = ?Flow::CustomerPaymentMethodsList))] +pub async fn list_customer_payment_method_api( + state: web::Data, + customer_id: web::Path, + req: HttpRequest, + query_payload: web::Query, +) -> HttpResponse { + let flow = Flow::CustomerPaymentMethodsList; + let payload = query_payload.into_inner(); + let customer_id = customer_id.into_inner(); + + Box::pin(api::server_wrap( + flow, + state, + &req, + payload, + |state, auth: auth::AuthenticationData, _, _| { + payment_methods_routes::list_saved_payment_methods_for_customer( + state, + auth.merchant_account, + auth.key_store, + customer_id.clone(), + ) + }, + auth::auth_type( + &auth::HeaderAuth(auth::ApiKeyAuth), + &auth::JWTAuth { + permission: Permission::MerchantCustomerRead, + }, + req.headers(), + ), + api_locking::LockAction::NotApplicable, + )) + .await +} + #[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))] /// Generate a form link for collecting payment methods for a customer #[instrument(skip_all, fields(flow = ?Flow::PaymentMethodCollectLink))]