mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 04:04:55 +08:00
feat(list_pm): allow client secret authentication for list payment method api (#126)
This commit is contained in:
@ -1,11 +1,9 @@
|
|||||||
use common_utils::pii;
|
use common_utils::pii;
|
||||||
use masking::Secret;
|
use serde::de;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use time::PrimitiveDateTime;
|
|
||||||
|
|
||||||
use crate::enums as api_enums;
|
use crate::enums as api_enums;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct CreatePaymentMethod {
|
pub struct CreatePaymentMethod {
|
||||||
pub merchant_id: Option<String>,
|
pub merchant_id: Option<String>,
|
||||||
@ -18,16 +16,16 @@ pub struct CreatePaymentMethod {
|
|||||||
pub customer_id: Option<String>,
|
pub customer_id: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct CardDetail {
|
pub struct CardDetail {
|
||||||
pub card_number: Secret<String, pii::CardNumber>,
|
pub card_number: masking::Secret<String, pii::CardNumber>,
|
||||||
pub card_exp_month: Secret<String>,
|
pub card_exp_month: masking::Secret<String>,
|
||||||
pub card_exp_year: Secret<String>,
|
pub card_exp_year: masking::Secret<String>,
|
||||||
pub card_holder_name: Option<Secret<String>>,
|
pub card_holder_name: Option<masking::Secret<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
||||||
pub struct PaymentMethodResponse {
|
pub struct PaymentMethodResponse {
|
||||||
pub payment_method_id: String,
|
pub payment_method_id: String,
|
||||||
pub payment_method: api_enums::PaymentMethodType,
|
pub payment_method: api_enums::PaymentMethodType,
|
||||||
@ -45,27 +43,28 @@ pub struct PaymentMethodResponse {
|
|||||||
pub payment_experience: Option<Vec<String>>, //TODO change it to enum
|
pub payment_experience: Option<Vec<String>>, //TODO change it to enum
|
||||||
pub metadata: Option<serde_json::Value>,
|
pub metadata: Option<serde_json::Value>,
|
||||||
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
|
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
|
||||||
pub created: Option<PrimitiveDateTime>,
|
pub created: Option<time::PrimitiveDateTime>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||||
pub struct CardDetailFromLocker {
|
pub struct CardDetailFromLocker {
|
||||||
pub scheme: Option<String>,
|
pub scheme: Option<String>,
|
||||||
pub issuer_country: Option<String>,
|
pub issuer_country: Option<String>,
|
||||||
pub last4_digits: Option<String>,
|
pub last4_digits: Option<String>,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub card_number: Option<Secret<String, pii::CardNumber>>,
|
pub card_number: Option<masking::Secret<String, pii::CardNumber>>,
|
||||||
pub expiry_month: Option<Secret<String>>,
|
pub expiry_month: Option<masking::Secret<String>>,
|
||||||
pub expiry_year: Option<Secret<String>>,
|
pub expiry_year: Option<masking::Secret<String>>,
|
||||||
pub card_token: Option<Secret<String>>,
|
pub card_token: Option<masking::Secret<String>>,
|
||||||
pub card_holder_name: Option<Secret<String>>,
|
pub card_holder_name: Option<masking::Secret<String>>,
|
||||||
pub card_fingerprint: Option<Secret<String>>,
|
pub card_fingerprint: Option<masking::Secret<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
//List Payment Method
|
//List Payment Method
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, serde::Serialize, Default)]
|
||||||
#[serde(deny_unknown_fields)]
|
#[serde(deny_unknown_fields)]
|
||||||
pub struct ListPaymentMethodRequest {
|
pub struct ListPaymentMethodRequest {
|
||||||
|
pub client_secret: Option<String>,
|
||||||
pub accepted_countries: Option<Vec<String>>,
|
pub accepted_countries: Option<Vec<String>>,
|
||||||
pub accepted_currencies: Option<Vec<api_enums::Currency>>,
|
pub accepted_currencies: Option<Vec<api_enums::Currency>>,
|
||||||
pub amount: Option<i32>,
|
pub amount: Option<i32>,
|
||||||
@ -73,7 +72,65 @@ pub struct ListPaymentMethodRequest {
|
|||||||
pub installment_payment_enabled: Option<bool>,
|
pub installment_payment_enabled: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
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" => {
|
||||||
|
output.client_secret = Some(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" => {
|
||||||
|
output.amount = Some(map.next_value()?);
|
||||||
|
}
|
||||||
|
"recurring_enabled" => {
|
||||||
|
output.recurring_enabled = Some(map.next_value()?);
|
||||||
|
}
|
||||||
|
"installment_payment_enabled" => {
|
||||||
|
output.installment_payment_enabled = Some(map.next_value()?);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deserializer.deserialize_identifier(FieldVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct ListPaymentMethodResponse {
|
pub struct ListPaymentMethodResponse {
|
||||||
pub payment_method: api_enums::PaymentMethodType,
|
pub payment_method: api_enums::PaymentMethodType,
|
||||||
pub payment_method_types: Option<Vec<api_enums::PaymentMethodSubType>>,
|
pub payment_method_types: Option<Vec<api_enums::PaymentMethodSubType>>,
|
||||||
@ -89,19 +146,19 @@ pub struct ListPaymentMethodResponse {
|
|||||||
pub payment_experience: Option<Vec<String>>, //TODO change it to enum
|
pub payment_experience: Option<Vec<String>>, //TODO change it to enum
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, serde::Serialize)]
|
||||||
pub struct ListCustomerPaymentMethodsResponse {
|
pub struct ListCustomerPaymentMethodsResponse {
|
||||||
pub enabled_payment_methods: Vec<ListPaymentMethodResponse>,
|
pub enabled_payment_methods: Vec<ListPaymentMethodResponse>,
|
||||||
pub customer_payment_methods: Vec<CustomerPaymentMethod>,
|
pub customer_payment_methods: Vec<CustomerPaymentMethod>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, serde::Serialize)]
|
||||||
pub struct DeletePaymentMethodResponse {
|
pub struct DeletePaymentMethodResponse {
|
||||||
pub payment_method_id: String,
|
pub payment_method_id: String,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, serde::Serialize)]
|
||||||
pub struct CustomerPaymentMethod {
|
pub struct CustomerPaymentMethod {
|
||||||
pub payment_token: String,
|
pub payment_token: String,
|
||||||
pub customer_id: String,
|
pub customer_id: String,
|
||||||
@ -120,23 +177,23 @@ pub struct CustomerPaymentMethod {
|
|||||||
pub card: Option<CardDetailFromLocker>,
|
pub card: Option<CardDetailFromLocker>,
|
||||||
pub metadata: Option<serde_json::Value>,
|
pub metadata: Option<serde_json::Value>,
|
||||||
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
|
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
|
||||||
pub created: Option<PrimitiveDateTime>,
|
pub created: Option<time::PrimitiveDateTime>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct PaymentMethodId {
|
pub struct PaymentMethodId {
|
||||||
pub payment_method_id: String,
|
pub payment_method_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------TokenizeService------------------------------------------------
|
//------------------------------------------------TokenizeService------------------------------------------------
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct TokenizePayloadEncrypted {
|
pub struct TokenizePayloadEncrypted {
|
||||||
pub payload: String,
|
pub payload: String,
|
||||||
pub key_id: String,
|
pub key_id: String,
|
||||||
pub version: Option<String>,
|
pub version: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct TokenizePayloadRequest {
|
pub struct TokenizePayloadRequest {
|
||||||
pub value1: String,
|
pub value1: String,
|
||||||
pub value2: String,
|
pub value2: String,
|
||||||
@ -144,30 +201,30 @@ pub struct TokenizePayloadRequest {
|
|||||||
pub service_name: String,
|
pub service_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct GetTokenizePayloadRequest {
|
pub struct GetTokenizePayloadRequest {
|
||||||
pub lookup_key: String,
|
pub lookup_key: String,
|
||||||
pub get_value2: bool,
|
pub get_value2: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, serde::Serialize)]
|
||||||
pub struct DeleteTokenizeByTokenRequest {
|
pub struct DeleteTokenizeByTokenRequest {
|
||||||
pub lookup_key: String,
|
pub lookup_key: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)] //FIXME yet to be implemented
|
#[derive(Debug, serde::Serialize)] //FIXME yet to be implemented
|
||||||
pub struct DeleteTokenizeByDateRequest {
|
pub struct DeleteTokenizeByDateRequest {
|
||||||
pub buffer_minutes: i32,
|
pub buffer_minutes: i32,
|
||||||
pub service_name: String,
|
pub service_name: String,
|
||||||
pub max_rows: i32,
|
pub max_rows: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, serde::Deserialize)]
|
||||||
pub struct GetTokenizePayloadResponse {
|
pub struct GetTokenizePayloadResponse {
|
||||||
pub lookup_key: String,
|
pub lookup_key: String,
|
||||||
pub get_value2: Option<bool>,
|
pub get_value2: Option<bool>,
|
||||||
}
|
}
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct TokenizedCardValue1 {
|
pub struct TokenizedCardValue1 {
|
||||||
pub card_number: String,
|
pub card_number: String,
|
||||||
@ -179,7 +236,7 @@ pub struct TokenizedCardValue1 {
|
|||||||
pub card_token: Option<String>,
|
pub card_token: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct TokenizedCardValue2 {
|
pub struct TokenizedCardValue2 {
|
||||||
pub card_security_code: Option<String>,
|
pub card_security_code: Option<String>,
|
||||||
|
|||||||
@ -1,20 +1,18 @@
|
|||||||
use std::{collections::HashSet, hash::Hash};
|
use std::collections;
|
||||||
|
|
||||||
use error_stack::{report, ResultExt};
|
use error_stack::{report, ResultExt};
|
||||||
use router_env::{tracing, tracing::instrument};
|
use router_env::{tracing, tracing::instrument};
|
||||||
use serde_json::Value;
|
|
||||||
use uuid::Uuid;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
configs::settings::Keys,
|
configs::settings,
|
||||||
core::{
|
core::{
|
||||||
errors::{self, CustomResult, RouterResponse, RouterResult, StorageErrorExt},
|
errors::{self, StorageErrorExt},
|
||||||
payment_methods::transformers as payment_methods,
|
payment_methods::transformers as payment_methods,
|
||||||
|
payments::helpers,
|
||||||
},
|
},
|
||||||
db::StorageInterface,
|
db,
|
||||||
pii::prelude::*,
|
pii::prelude::*,
|
||||||
routes::AppState,
|
routes, services,
|
||||||
services,
|
|
||||||
types::{
|
types::{
|
||||||
api::{self, CreatePaymentMethodExt},
|
api::{self, CreatePaymentMethodExt},
|
||||||
storage::{self, enums},
|
storage::{self, enums},
|
||||||
@ -25,12 +23,12 @@ use crate::{
|
|||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn create_payment_method(
|
pub async fn create_payment_method(
|
||||||
db: &dyn StorageInterface,
|
db: &dyn db::StorageInterface,
|
||||||
req: &api::CreatePaymentMethod,
|
req: &api::CreatePaymentMethod,
|
||||||
customer_id: String,
|
customer_id: String,
|
||||||
payment_method_id: String,
|
payment_method_id: String,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
) -> CustomResult<storage::PaymentMethod, errors::StorageError> {
|
) -> errors::CustomResult<storage::PaymentMethod, errors::StorageError> {
|
||||||
let response = db
|
let response = db
|
||||||
.insert_payment_method(storage::PaymentMethodNew {
|
.insert_payment_method(storage::PaymentMethodNew {
|
||||||
customer_id,
|
customer_id,
|
||||||
@ -48,10 +46,10 @@ pub async fn create_payment_method(
|
|||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn add_payment_method(
|
pub async fn add_payment_method(
|
||||||
state: &AppState,
|
state: &routes::AppState,
|
||||||
req: api::CreatePaymentMethod,
|
req: api::CreatePaymentMethod,
|
||||||
merchant_id: String,
|
merchant_id: String,
|
||||||
) -> RouterResponse<api::PaymentMethodResponse> {
|
) -> errors::RouterResponse<api::PaymentMethodResponse> {
|
||||||
req.validate()?;
|
req.validate()?;
|
||||||
|
|
||||||
let customer_id = req.customer_id.clone().get_required_value("customer_id")?;
|
let customer_id = req.customer_id.clone().get_required_value("customer_id")?;
|
||||||
@ -92,12 +90,12 @@ pub async fn add_payment_method(
|
|||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn add_card(
|
pub async fn add_card(
|
||||||
state: &AppState,
|
state: &routes::AppState,
|
||||||
req: api::CreatePaymentMethod,
|
req: api::CreatePaymentMethod,
|
||||||
card: api::CardDetail,
|
card: api::CardDetail,
|
||||||
customer_id: String,
|
customer_id: String,
|
||||||
merchant_id: &str,
|
merchant_id: &str,
|
||||||
) -> CustomResult<api::PaymentMethodResponse, errors::CardVaultError> {
|
) -> errors::CustomResult<api::PaymentMethodResponse, errors::CardVaultError> {
|
||||||
let locker = &state.conf.locker;
|
let locker = &state.conf.locker;
|
||||||
let db = &*state.store;
|
let db = &*state.store;
|
||||||
let request = payment_methods::mk_add_card_request(locker, &card, &customer_id, &req)?;
|
let request = payment_methods::mk_add_card_request(locker, &card, &customer_id, &req)?;
|
||||||
@ -118,7 +116,7 @@ pub async fn add_card(
|
|||||||
}?;
|
}?;
|
||||||
response
|
response
|
||||||
} else {
|
} else {
|
||||||
let card_id = Uuid::new_v4().to_string();
|
let card_id = uuid::Uuid::new_v4().to_string();
|
||||||
mock_add_card(db, &card_id, &card).await?
|
mock_add_card(db, &card_id, &card).await?
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -137,15 +135,15 @@ pub async fn add_card(
|
|||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn mock_add_card(
|
pub async fn mock_add_card(
|
||||||
db: &dyn StorageInterface,
|
db: &dyn db::StorageInterface,
|
||||||
card_id: &str,
|
card_id: &str,
|
||||||
card: &api::CardDetail,
|
card: &api::CardDetail,
|
||||||
) -> CustomResult<payment_methods::AddCardResponse, errors::CardVaultError> {
|
) -> errors::CustomResult<payment_methods::AddCardResponse, errors::CardVaultError> {
|
||||||
let locker_mock_up = storage::LockerMockUpNew {
|
let locker_mock_up = storage::LockerMockUpNew {
|
||||||
card_id: card_id.to_string(),
|
card_id: card_id.to_string(),
|
||||||
external_id: Uuid::new_v4().to_string(),
|
external_id: uuid::Uuid::new_v4().to_string(),
|
||||||
card_fingerprint: Uuid::new_v4().to_string(),
|
card_fingerprint: uuid::Uuid::new_v4().to_string(),
|
||||||
card_global_fingerprint: Uuid::new_v4().to_string(),
|
card_global_fingerprint: uuid::Uuid::new_v4().to_string(),
|
||||||
merchant_id: "mm01".to_string(),
|
merchant_id: "mm01".to_string(),
|
||||||
card_number: card.card_number.peek().to_string(),
|
card_number: card.card_number.peek().to_string(),
|
||||||
card_exp_year: card.card_exp_year.peek().to_string(),
|
card_exp_year: card.card_exp_year.peek().to_string(),
|
||||||
@ -174,9 +172,9 @@ pub async fn mock_add_card(
|
|||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn mock_get_card<'a>(
|
pub async fn mock_get_card<'a>(
|
||||||
db: &dyn StorageInterface,
|
db: &dyn db::StorageInterface,
|
||||||
card_id: &'a str,
|
card_id: &'a str,
|
||||||
) -> CustomResult<payment_methods::GetCardResponse, errors::CardVaultError> {
|
) -> errors::CustomResult<payment_methods::GetCardResponse, errors::CardVaultError> {
|
||||||
let locker_mock_up = db
|
let locker_mock_up = db
|
||||||
.find_locker_by_card_id(card_id)
|
.find_locker_by_card_id(card_id)
|
||||||
.await
|
.await
|
||||||
@ -202,10 +200,10 @@ pub async fn mock_get_card<'a>(
|
|||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn get_card_from_legacy_locker<'a>(
|
pub async fn get_card_from_legacy_locker<'a>(
|
||||||
state: &'a AppState,
|
state: &'a routes::AppState,
|
||||||
merchant_id: &'a str,
|
merchant_id: &'a str,
|
||||||
card_id: &'a str,
|
card_id: &'a str,
|
||||||
) -> RouterResult<payment_methods::GetCardResponse> {
|
) -> errors::RouterResult<payment_methods::GetCardResponse> {
|
||||||
let locker = &state.conf.locker;
|
let locker = &state.conf.locker;
|
||||||
let request = payment_methods::mk_get_card_request(locker, merchant_id, card_id)
|
let request = payment_methods::mk_get_card_request(locker, merchant_id, card_id)
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
@ -236,10 +234,10 @@ pub async fn get_card_from_legacy_locker<'a>(
|
|||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn delete_card<'a>(
|
pub async fn delete_card<'a>(
|
||||||
state: &'a AppState,
|
state: &'a routes::AppState,
|
||||||
merchant_id: &'a str,
|
merchant_id: &'a str,
|
||||||
card_id: &'a str,
|
card_id: &'a str,
|
||||||
) -> RouterResult<payment_methods::DeleteCardResponse> {
|
) -> errors::RouterResult<payment_methods::DeleteCardResponse> {
|
||||||
let request = payment_methods::mk_delete_card_request(&state.conf.locker, merchant_id, card_id)
|
let request = payment_methods::mk_delete_card_request(&state.conf.locker, merchant_id, card_id)
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
.attach_printable("Making Delete card request Failed")?;
|
.attach_printable("Making Delete card request Failed")?;
|
||||||
@ -255,10 +253,18 @@ pub async fn delete_card<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn list_payment_methods(
|
pub async fn list_payment_methods(
|
||||||
db: &dyn StorageInterface,
|
db: &dyn db::StorageInterface,
|
||||||
merchant_account: storage::MerchantAccount,
|
merchant_account: storage::MerchantAccount,
|
||||||
mut req: api::ListPaymentMethodRequest,
|
mut req: api::ListPaymentMethodRequest,
|
||||||
) -> RouterResponse<Vec<api::ListPaymentMethodResponse>> {
|
) -> errors::RouterResponse<Vec<api::ListPaymentMethodResponse>> {
|
||||||
|
helpers::verify_client_secret(
|
||||||
|
db,
|
||||||
|
merchant_account.storage_scheme,
|
||||||
|
req.client_secret.clone(),
|
||||||
|
&merchant_account.merchant_id,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let all_mcas = db
|
let all_mcas = db
|
||||||
.find_merchant_connector_account_by_merchant_id_list(&merchant_account.merchant_id)
|
.find_merchant_connector_account_by_merchant_id_list(&merchant_account.merchant_id)
|
||||||
.await
|
.await
|
||||||
@ -283,7 +289,7 @@ pub async fn list_payment_methods(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn filter_payment_methods(
|
fn filter_payment_methods(
|
||||||
payment_methods: Vec<Value>,
|
payment_methods: Vec<serde_json::Value>,
|
||||||
req: &mut api::ListPaymentMethodRequest,
|
req: &mut api::ListPaymentMethodRequest,
|
||||||
resp: &mut Vec<api::ListPaymentMethodResponse>,
|
resp: &mut Vec<api::ListPaymentMethodResponse>,
|
||||||
) {
|
) {
|
||||||
@ -325,14 +331,14 @@ fn filter_payment_methods(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filter_accepted_enum_based<T: Eq + Hash + Clone>(
|
fn filter_accepted_enum_based<T: Eq + std::hash::Hash + Clone>(
|
||||||
left: &Option<Vec<T>>,
|
left: &Option<Vec<T>>,
|
||||||
right: &Option<Vec<T>>,
|
right: &Option<Vec<T>>,
|
||||||
) -> (Option<Vec<T>>, Option<Vec<T>>, bool) {
|
) -> (Option<Vec<T>>, Option<Vec<T>>, bool) {
|
||||||
match (left, right) {
|
match (left, right) {
|
||||||
(Some(ref l), Some(ref r)) => {
|
(Some(ref l), Some(ref r)) => {
|
||||||
let a: HashSet<&T> = HashSet::from_iter(l.iter());
|
let a: collections::HashSet<&T> = collections::HashSet::from_iter(l.iter());
|
||||||
let b: HashSet<&T> = HashSet::from_iter(r.iter());
|
let b: collections::HashSet<&T> = collections::HashSet::from_iter(r.iter());
|
||||||
|
|
||||||
let y: Vec<T> = a.intersection(&b).map(|&i| i.to_owned()).collect();
|
let y: Vec<T> = a.intersection(&b).map(|&i| i.to_owned()).collect();
|
||||||
(Some(y), Some(r.to_vec()), true)
|
(Some(y), Some(r.to_vec()), true)
|
||||||
@ -381,10 +387,10 @@ fn filter_installment_based(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn list_customer_payment_method(
|
pub async fn list_customer_payment_method(
|
||||||
state: &AppState,
|
state: &routes::AppState,
|
||||||
merchant_account: storage::MerchantAccount,
|
merchant_account: storage::MerchantAccount,
|
||||||
customer_id: &str,
|
customer_id: &str,
|
||||||
) -> RouterResponse<api::ListCustomerPaymentMethodsResponse> {
|
) -> errors::RouterResponse<api::ListCustomerPaymentMethodsResponse> {
|
||||||
let db = &*state.store;
|
let db = &*state.store;
|
||||||
let all_mcas = db
|
let all_mcas = db
|
||||||
.find_merchant_connector_account_by_merchant_id_list(&merchant_account.merchant_id)
|
.find_merchant_connector_account_by_merchant_id_list(&merchant_account.merchant_id)
|
||||||
@ -427,7 +433,7 @@ pub async fn list_customer_payment_method(
|
|||||||
}
|
}
|
||||||
let mut vec = Vec::new();
|
let mut vec = Vec::new();
|
||||||
for pm in resp.into_iter() {
|
for pm in resp.into_iter() {
|
||||||
let payment_token = Uuid::new_v4().to_string();
|
let payment_token = uuid::Uuid::new_v4().to_string();
|
||||||
let card = if pm.payment_method == enums::PaymentMethodType::Card {
|
let card = if pm.payment_method == enums::PaymentMethodType::Card {
|
||||||
Some(get_lookup_key_from_locker(state, &payment_token, &pm).await?)
|
Some(get_lookup_key_from_locker(state, &payment_token, &pm).await?)
|
||||||
} else {
|
} else {
|
||||||
@ -462,10 +468,10 @@ pub async fn list_customer_payment_method(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_lookup_key_from_locker(
|
pub async fn get_lookup_key_from_locker(
|
||||||
state: &AppState,
|
state: &routes::AppState,
|
||||||
payment_token: &str,
|
payment_token: &str,
|
||||||
pm: &storage::PaymentMethod,
|
pm: &storage::PaymentMethod,
|
||||||
) -> RouterResult<api::CardDetailFromLocker> {
|
) -> errors::RouterResult<api::CardDetailFromLocker> {
|
||||||
let get_card_resp = get_card_from_legacy_locker(
|
let get_card_resp = get_card_from_legacy_locker(
|
||||||
state,
|
state,
|
||||||
pm.merchant_id.as_str(),
|
pm.merchant_id.as_str(),
|
||||||
@ -487,10 +493,10 @@ pub struct BasiliskCardSupport;
|
|||||||
#[cfg(not(feature = "basilisk"))]
|
#[cfg(not(feature = "basilisk"))]
|
||||||
impl BasiliskCardSupport {
|
impl BasiliskCardSupport {
|
||||||
async fn create_payment_method_data_in_locker(
|
async fn create_payment_method_data_in_locker(
|
||||||
state: &AppState,
|
state: &routes::AppState,
|
||||||
payment_token: &str,
|
payment_token: &str,
|
||||||
card: api::CardDetailFromLocker,
|
card: api::CardDetailFromLocker,
|
||||||
) -> RouterResult<api::CardDetailFromLocker> {
|
) -> errors::RouterResult<api::CardDetailFromLocker> {
|
||||||
let card_number = card
|
let card_number = card
|
||||||
.card_number
|
.card_number
|
||||||
.clone()
|
.clone()
|
||||||
@ -530,10 +536,10 @@ impl BasiliskCardSupport {
|
|||||||
impl BasiliskCardSupport {
|
impl BasiliskCardSupport {
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
async fn create_payment_method_data_in_locker(
|
async fn create_payment_method_data_in_locker(
|
||||||
state: &AppState,
|
state: &routes::AppState,
|
||||||
payment_token: &str,
|
payment_token: &str,
|
||||||
card: api::CardDetailFromLocker,
|
card: api::CardDetailFromLocker,
|
||||||
) -> RouterResult<api::CardDetailFromLocker> {
|
) -> errors::RouterResult<api::CardDetailFromLocker> {
|
||||||
let card_number = card
|
let card_number = card
|
||||||
.card_number
|
.card_number
|
||||||
.clone()
|
.clone()
|
||||||
@ -579,9 +585,9 @@ impl BasiliskCardSupport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_card_info_value(
|
pub async fn get_card_info_value(
|
||||||
keys: &Keys,
|
keys: &settings::Keys,
|
||||||
card_info: String,
|
card_info: String,
|
||||||
) -> RouterResult<serde_json::Value> {
|
) -> errors::RouterResult<serde_json::Value> {
|
||||||
let key = services::KeyHandler::get_encryption_key(keys)
|
let key = services::KeyHandler::get_encryption_key(keys)
|
||||||
.await
|
.await
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
||||||
@ -593,9 +599,9 @@ pub async fn get_card_info_value(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_card_info_from_value(
|
pub async fn get_card_info_from_value(
|
||||||
keys: &Keys,
|
keys: &settings::Keys,
|
||||||
card_info: serde_json::Value,
|
card_info: serde_json::Value,
|
||||||
) -> RouterResult<String> {
|
) -> errors::RouterResult<String> {
|
||||||
let key = services::KeyHandler::get_encryption_key(keys)
|
let key = services::KeyHandler::get_encryption_key(keys)
|
||||||
.await
|
.await
|
||||||
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
.change_context(errors::ApiErrorResponse::InternalServerError)?;
|
||||||
@ -608,9 +614,9 @@ pub async fn get_card_info_from_value(
|
|||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn retrieve_payment_method(
|
pub async fn retrieve_payment_method(
|
||||||
state: &AppState,
|
state: &routes::AppState,
|
||||||
pm: api::PaymentMethodId,
|
pm: api::PaymentMethodId,
|
||||||
) -> RouterResponse<api::PaymentMethodResponse> {
|
) -> errors::RouterResponse<api::PaymentMethodResponse> {
|
||||||
let db = &*state.store;
|
let db = &*state.store;
|
||||||
let pm = db
|
let pm = db
|
||||||
.find_payment_method(&pm.payment_method_id)
|
.find_payment_method(&pm.payment_method_id)
|
||||||
@ -644,10 +650,10 @@ pub async fn retrieve_payment_method(
|
|||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
pub async fn delete_payment_method(
|
pub async fn delete_payment_method(
|
||||||
state: &AppState,
|
state: &routes::AppState,
|
||||||
merchant_account: storage::MerchantAccount,
|
merchant_account: storage::MerchantAccount,
|
||||||
pm: api::PaymentMethodId,
|
pm: api::PaymentMethodId,
|
||||||
) -> RouterResponse<api::DeletePaymentMethodResponse> {
|
) -> errors::RouterResponse<api::DeletePaymentMethodResponse> {
|
||||||
let pm = state
|
let pm = state
|
||||||
.store
|
.store
|
||||||
.delete_payment_method_by_merchant_id_payment_method_id(
|
.delete_payment_method_by_merchant_id_payment_method_id(
|
||||||
@ -678,11 +684,11 @@ pub async fn delete_payment_method(
|
|||||||
|
|
||||||
//------------------------------------------------TokenizeService------------------------------------------------
|
//------------------------------------------------TokenizeService------------------------------------------------
|
||||||
pub async fn create_tokenize(
|
pub async fn create_tokenize(
|
||||||
state: &AppState,
|
state: &routes::AppState,
|
||||||
value1: String,
|
value1: String,
|
||||||
value2: Option<String>,
|
value2: Option<String>,
|
||||||
lookup_key: String,
|
lookup_key: String,
|
||||||
) -> RouterResult<String> {
|
) -> errors::RouterResult<String> {
|
||||||
let payload_to_be_encrypted = api::TokenizePayloadRequest {
|
let payload_to_be_encrypted = api::TokenizePayloadRequest {
|
||||||
value1,
|
value1,
|
||||||
value2: value2.unwrap_or_default(),
|
value2: value2.unwrap_or_default(),
|
||||||
@ -738,10 +744,10 @@ pub async fn create_tokenize(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_tokenized_data(
|
pub async fn get_tokenized_data(
|
||||||
state: &AppState,
|
state: &routes::AppState,
|
||||||
lookup_key: &str,
|
lookup_key: &str,
|
||||||
should_get_value2: bool,
|
should_get_value2: bool,
|
||||||
) -> RouterResult<api::TokenizePayloadRequest> {
|
) -> errors::RouterResult<api::TokenizePayloadRequest> {
|
||||||
let payload_to_be_encrypted = api::GetTokenizePayloadRequest {
|
let payload_to_be_encrypted = api::GetTokenizePayloadRequest {
|
||||||
lookup_key: lookup_key.to_string(),
|
lookup_key: lookup_key.to_string(),
|
||||||
get_value2: should_get_value2,
|
get_value2: should_get_value2,
|
||||||
@ -792,7 +798,10 @@ pub async fn get_tokenized_data(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn delete_tokenized_data(state: &AppState, lookup_key: &str) -> RouterResult<String> {
|
pub async fn delete_tokenized_data(
|
||||||
|
state: &routes::AppState,
|
||||||
|
lookup_key: &str,
|
||||||
|
) -> errors::RouterResult<String> {
|
||||||
let payload_to_be_encrypted = api::DeleteTokenizeByTokenRequest {
|
let payload_to_be_encrypted = api::DeleteTokenizeByTokenRequest {
|
||||||
lookup_key: lookup_key.to_string(),
|
lookup_key: lookup_key.to_string(),
|
||||||
};
|
};
|
||||||
|
|||||||
@ -16,7 +16,6 @@ pub use self::operations::{
|
|||||||
};
|
};
|
||||||
use self::{
|
use self::{
|
||||||
flows::{ConstructFlowSpecificData, Feature},
|
flows::{ConstructFlowSpecificData, Feature},
|
||||||
helpers::{filter_by_constraints, validate_payment_list_request},
|
|
||||||
operations::{BoxedOperation, Operation},
|
operations::{BoxedOperation, Operation},
|
||||||
};
|
};
|
||||||
use super::errors::StorageErrorExt;
|
use super::errors::StorageErrorExt;
|
||||||
@ -573,10 +572,10 @@ pub async fn list_payments(
|
|||||||
merchant: storage::MerchantAccount,
|
merchant: storage::MerchantAccount,
|
||||||
constraints: api::PaymentListConstraints,
|
constraints: api::PaymentListConstraints,
|
||||||
) -> RouterResponse<api::PaymentListResponse> {
|
) -> RouterResponse<api::PaymentListResponse> {
|
||||||
validate_payment_list_request(&constraints)?;
|
helpers::validate_payment_list_request(&constraints)?;
|
||||||
let merchant_id = &merchant.merchant_id;
|
let merchant_id = &merchant.merchant_id;
|
||||||
let payment_intent =
|
let payment_intent =
|
||||||
filter_by_constraints(db, &constraints, merchant_id, merchant.storage_scheme)
|
helpers::filter_by_constraints(db, &constraints, merchant_id, merchant.storage_scheme)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| err.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound))?;
|
.map_err(|err| err.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound))?;
|
||||||
|
|
||||||
|
|||||||
@ -531,14 +531,17 @@ pub(crate) async fn call_payment_method(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn client_secret_auth(
|
pub(crate) fn client_secret_auth<P>(
|
||||||
payload: api::PaymentsRequest,
|
payload: P,
|
||||||
auth_type: &services::api::MerchantAuthentication,
|
auth_type: &services::api::MerchantAuthentication,
|
||||||
) -> RouterResult<api::PaymentsRequest> {
|
) -> RouterResult<P>
|
||||||
|
where
|
||||||
|
P: services::Authenticate,
|
||||||
|
{
|
||||||
match auth_type {
|
match auth_type {
|
||||||
services::MerchantAuthentication::PublishableKey => {
|
services::MerchantAuthentication::PublishableKey => {
|
||||||
payload
|
payload
|
||||||
.client_secret
|
.get_client_secret()
|
||||||
.check_value_present("client_secret")
|
.check_value_present("client_secret")
|
||||||
.change_context(errors::ApiErrorResponse::MissingRequiredField {
|
.change_context(errors::ApiErrorResponse::MissingRequiredField {
|
||||||
field_name: "client_secret".to_owned(),
|
field_name: "client_secret".to_owned(),
|
||||||
@ -546,7 +549,7 @@ pub(crate) fn client_secret_auth(
|
|||||||
Ok(payload)
|
Ok(payload)
|
||||||
}
|
}
|
||||||
services::api::MerchantAuthentication::ApiKey => {
|
services::api::MerchantAuthentication::ApiKey => {
|
||||||
if payload.client_secret.is_some() {
|
if payload.get_client_secret().is_some() {
|
||||||
Err(report!(errors::ApiErrorResponse::InvalidRequestData {
|
Err(report!(errors::ApiErrorResponse::InvalidRequestData {
|
||||||
message: "client_secret is not a valid parameter".to_owned(),
|
message: "client_secret is not a valid parameter".to_owned(),
|
||||||
}))
|
}))
|
||||||
@ -1178,3 +1181,56 @@ pub fn generate_mandate(
|
|||||||
(_, _) => None,
|
(_, _) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A function to manually authenticate the client secret
|
||||||
|
pub(crate) fn authenticate_client_secret(
|
||||||
|
request_client_secret: Option<&String>,
|
||||||
|
payment_intent_client_secret: Option<&String>,
|
||||||
|
) -> Result<(), errors::ApiErrorResponse> {
|
||||||
|
match (request_client_secret, payment_intent_client_secret) {
|
||||||
|
(Some(req_cs), Some(pi_cs)) => utils::when(
|
||||||
|
req_cs.ne(pi_cs),
|
||||||
|
Err(errors::ApiErrorResponse::ClientSecretInvalid),
|
||||||
|
),
|
||||||
|
_ => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A function to perform database lookup and then verify the client secret
|
||||||
|
pub(crate) async fn verify_client_secret(
|
||||||
|
db: &dyn StorageInterface,
|
||||||
|
storage_scheme: storage_enums::MerchantStorageScheme,
|
||||||
|
client_secret: Option<String>,
|
||||||
|
merchant_id: &str,
|
||||||
|
) -> error_stack::Result<(), errors::ApiErrorResponse> {
|
||||||
|
match client_secret {
|
||||||
|
None => Ok(()),
|
||||||
|
Some(cs) => {
|
||||||
|
let payment_id = cs.split('_').take(2).collect::<Vec<&str>>().join("_");
|
||||||
|
|
||||||
|
let payment_intent = db
|
||||||
|
.find_payment_intent_by_payment_id_merchant_id(
|
||||||
|
&payment_id,
|
||||||
|
merchant_id,
|
||||||
|
storage_scheme,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.change_context(errors::ApiErrorResponse::PaymentNotFound)?;
|
||||||
|
|
||||||
|
authenticate_client_secret(Some(&cs), payment_intent.client_secret.as_ref())
|
||||||
|
.map_err(|err| err.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_authenticate_client_secret() {
|
||||||
|
let req_cs = Some("1".to_string());
|
||||||
|
let pi_cs = Some("2".to_string());
|
||||||
|
assert!(authenticate_client_secret(req_cs.as_ref(), pi_cs.as_ref()).is_err())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -61,13 +61,10 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
|||||||
error.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)
|
error.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Some(ref req_cs) = request.client_secret {
|
helpers::authenticate_client_secret(
|
||||||
if let Some(ref pi_cs) = payment_intent.client_secret {
|
request.client_secret.as_ref(),
|
||||||
if req_cs.ne(pi_cs) {
|
payment_intent.client_secret.as_ref(),
|
||||||
return Err(report!(errors::ApiErrorResponse::ClientSecretInvalid));
|
)?;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let browser_info = request
|
let browser_info = request
|
||||||
.browser_info
|
.browser_info
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use error_stack::{report, ResultExt};
|
use error_stack::ResultExt;
|
||||||
use router_derive::PaymentOperation;
|
use router_derive::PaymentOperation;
|
||||||
use router_env::{instrument, tracing};
|
use router_env::{instrument, tracing};
|
||||||
|
|
||||||
@ -73,11 +73,10 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsSessionRequest>
|
|||||||
|
|
||||||
let amount = payment_intent.amount.into();
|
let amount = payment_intent.amount.into();
|
||||||
|
|
||||||
if let Some(ref payment_intent_client_secret) = payment_intent.client_secret {
|
helpers::authenticate_client_secret(
|
||||||
if request.client_secret.ne(payment_intent_client_secret) {
|
Some(&request.client_secret),
|
||||||
return Err(report!(errors::ApiErrorResponse::ClientSecretInvalid));
|
payment_intent.client_secret.as_ref(),
|
||||||
}
|
)?;
|
||||||
}
|
|
||||||
|
|
||||||
let shipping_address = helpers::get_address_for_payment_request(
|
let shipping_address = helpers::get_address_for_payment_request(
|
||||||
db,
|
db,
|
||||||
|
|||||||
@ -85,13 +85,10 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
|||||||
error.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)
|
error.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Some(ref req_cs) = request.client_secret {
|
helpers::authenticate_client_secret(
|
||||||
if let Some(ref pi_cs) = payment_intent.client_secret {
|
request.client_secret.as_ref(),
|
||||||
if req_cs.ne(pi_cs) {
|
payment_intent.client_secret.as_ref(),
|
||||||
return Err(report!(errors::ApiErrorResponse::ClientSecretInvalid));
|
)?;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let shipping_address = helpers::get_address_for_payment_request(
|
let shipping_address = helpers::get_address_for_payment_request(
|
||||||
db,
|
db,
|
||||||
|
|||||||
@ -10,6 +10,7 @@ use crate::{
|
|||||||
errors::{http_not_implemented, BachResult},
|
errors::{http_not_implemented, BachResult},
|
||||||
payment_methods::cards,
|
payment_methods::cards,
|
||||||
},
|
},
|
||||||
|
services,
|
||||||
services::api,
|
services::api,
|
||||||
types::api::payment_methods::{self, PaymentMethodId},
|
types::api::payment_methods::{self, PaymentMethodId},
|
||||||
};
|
};
|
||||||
@ -44,14 +45,20 @@ pub async fn list_payment_method_api(
|
|||||||
json_payload: web::Query<payment_methods::ListPaymentMethodRequest>,
|
json_payload: web::Query<payment_methods::ListPaymentMethodRequest>,
|
||||||
) -> HttpResponse {
|
) -> HttpResponse {
|
||||||
//let merchant_id = merchant_id.into_inner();
|
//let merchant_id = merchant_id.into_inner();
|
||||||
|
let (payload, auth_type) =
|
||||||
|
match api::get_auth_type_and_check_client_secret(&req, json_payload.into_inner()) {
|
||||||
|
Ok(values) => values,
|
||||||
|
Err(err) => return api::log_and_return_error_response(err),
|
||||||
|
};
|
||||||
|
|
||||||
api::server_wrap(
|
api::server_wrap(
|
||||||
&state,
|
&state,
|
||||||
&req,
|
&req,
|
||||||
json_payload.into_inner(),
|
payload,
|
||||||
|state, merchant_account, req| {
|
|state, merchant_account, req| {
|
||||||
cards::list_payment_methods(&*state.store, merchant_account, req)
|
cards::list_payment_methods(&*state.store, merchant_account, req)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
auth_type,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@ -65,6 +72,13 @@ pub async fn list_customer_payment_method_api(
|
|||||||
json_payload: web::Query<payment_methods::ListPaymentMethodRequest>,
|
json_payload: web::Query<payment_methods::ListPaymentMethodRequest>,
|
||||||
) -> HttpResponse {
|
) -> HttpResponse {
|
||||||
let customer_id = customer_id.into_inner().0;
|
let customer_id = customer_id.into_inner().0;
|
||||||
|
|
||||||
|
let auth_type =
|
||||||
|
match services::authenticate_eph_key(&req, &*state.store, customer_id.clone()).await {
|
||||||
|
Ok(auth_type) => auth_type,
|
||||||
|
Err(err) => return api::log_and_return_error_response(err),
|
||||||
|
};
|
||||||
|
|
||||||
api::server_wrap(
|
api::server_wrap(
|
||||||
&state,
|
&state,
|
||||||
&req,
|
&req,
|
||||||
@ -72,7 +86,7 @@ pub async fn list_customer_payment_method_api(
|
|||||||
|state, merchant_account, _| {
|
|state, merchant_account, _| {
|
||||||
cards::list_customer_payment_method(state, merchant_account, &customer_id)
|
cards::list_customer_payment_method(state, merchant_account, &customer_id)
|
||||||
},
|
},
|
||||||
api::MerchantAuthentication::ApiKey,
|
auth_type,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
@ -586,10 +586,13 @@ pub async fn authenticate_connector<'a>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_auth_type_and_check_client_secret(
|
pub(crate) fn get_auth_type_and_check_client_secret<P>(
|
||||||
req: &actix_web::HttpRequest,
|
req: &actix_web::HttpRequest,
|
||||||
payload: types::api::PaymentsRequest,
|
payload: P,
|
||||||
) -> RouterResult<(types::api::PaymentsRequest, MerchantAuthentication)> {
|
) -> RouterResult<(P, MerchantAuthentication)>
|
||||||
|
where
|
||||||
|
P: Authenticate,
|
||||||
|
{
|
||||||
let auth_type = get_auth_type(req)?;
|
let auth_type = get_auth_type(req)?;
|
||||||
Ok((
|
Ok((
|
||||||
payments::helpers::client_secret_auth(payload, &auth_type)?,
|
payments::helpers::client_secret_auth(payload, &auth_type)?,
|
||||||
@ -701,6 +704,22 @@ pub trait ConnectorRedirectResponse {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Authenticate {
|
||||||
|
fn get_client_secret(&self) -> Option<&String>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Authenticate for api_models::payments::PaymentsRequest {
|
||||||
|
fn get_client_secret(&self) -> Option<&String> {
|
||||||
|
self.client_secret.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Authenticate for api_models::payment_methods::ListPaymentMethodRequest {
|
||||||
|
fn get_client_secret(&self) -> Option<&String> {
|
||||||
|
self.client_secret.as_ref()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build_redirection_form(form: &RedirectForm) -> maud::Markup {
|
pub fn build_redirection_form(form: &RedirectForm) -> maud::Markup {
|
||||||
use maud::PreEscaped;
|
use maud::PreEscaped;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user