mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 04:04:55 +08:00
fix: fixes to surface level mandate issues (#180)
This commit is contained in:
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -916,9 +916,11 @@ dependencies = [
|
||||
name = "common_utils"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"bytes",
|
||||
"error-stack",
|
||||
"fake",
|
||||
"futures",
|
||||
"hex",
|
||||
"masking",
|
||||
"nanoid",
|
||||
|
||||
@ -130,6 +130,21 @@ pub enum MandateTxnType {
|
||||
RecurringMandateTxn,
|
||||
}
|
||||
|
||||
#[derive(Default, Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
pub struct MandateIds {
|
||||
pub mandate_id: String,
|
||||
pub connector_mandate_id: Option<String>,
|
||||
}
|
||||
|
||||
impl MandateIds {
|
||||
pub fn new(mandate_id: String) -> Self {
|
||||
Self {
|
||||
mandate_id,
|
||||
connector_mandate_id: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct MandateData {
|
||||
|
||||
@ -8,8 +8,10 @@ readme = "README.md"
|
||||
license = "Apache-2.0"
|
||||
|
||||
[dependencies]
|
||||
async-trait = "0.1.59"
|
||||
bytes = "1.3.0"
|
||||
error-stack = "0.2.4"
|
||||
futures = "0.3.25"
|
||||
hex = "0.4.3"
|
||||
nanoid = "0.4.0"
|
||||
once_cell = "1.16.0"
|
||||
|
||||
@ -277,3 +277,79 @@ impl<T> StringExt<T> for String {
|
||||
.attach_printable_lazy(|| format!("Unable to parse {type_name} from string"))
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Extending functionalities of Wrapper types for idiomatic
|
||||
///
|
||||
#[async_trait::async_trait]
|
||||
pub trait AsyncExt<A, B> {
|
||||
/// Output type of the map function
|
||||
type WrappedSelf<T>;
|
||||
///
|
||||
/// Extending map by allowing functions which are async
|
||||
///
|
||||
async fn async_map<F, Fut>(self, func: F) -> Self::WrappedSelf<B>
|
||||
where
|
||||
F: FnOnce(A) -> Fut + Send,
|
||||
Fut: futures::Future<Output = B> + Send;
|
||||
|
||||
///
|
||||
/// Extending the `and_then` by allowing functions which are async
|
||||
///
|
||||
async fn async_and_then<F, Fut>(self, func: F) -> Self::WrappedSelf<B>
|
||||
where
|
||||
F: FnOnce(A) -> Fut + Send,
|
||||
Fut: futures::Future<Output = Self::WrappedSelf<B>> + Send;
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<A: std::marker::Send, B, E: std::marker::Send> AsyncExt<A, B> for Result<A, E> {
|
||||
type WrappedSelf<T> = Result<T, E>;
|
||||
async fn async_and_then<F, Fut>(self, func: F) -> Self::WrappedSelf<B>
|
||||
where
|
||||
F: FnOnce(A) -> Fut + Send,
|
||||
Fut: futures::Future<Output = Self::WrappedSelf<B>> + Send,
|
||||
{
|
||||
match self {
|
||||
Ok(a) => func(a).await,
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
async fn async_map<F, Fut>(self, func: F) -> Self::WrappedSelf<B>
|
||||
where
|
||||
F: FnOnce(A) -> Fut + Send,
|
||||
Fut: futures::Future<Output = B> + Send,
|
||||
{
|
||||
match self {
|
||||
Ok(a) => Ok(func(a).await),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl<A: std::marker::Send, B> AsyncExt<A, B> for Option<A> {
|
||||
type WrappedSelf<T> = Option<T>;
|
||||
async fn async_and_then<F, Fut>(self, func: F) -> Self::WrappedSelf<B>
|
||||
where
|
||||
F: FnOnce(A) -> Fut + Send,
|
||||
Fut: futures::Future<Output = Self::WrappedSelf<B>> + Send,
|
||||
{
|
||||
match self {
|
||||
Some(a) => func(a).await,
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
async fn async_map<F, Fut>(self, func: F) -> Self::WrappedSelf<B>
|
||||
where
|
||||
F: FnOnce(A) -> Fut + Send,
|
||||
Fut: futures::Future<Output = B> + Send,
|
||||
{
|
||||
match self {
|
||||
Some(a) => Some(func(a).await),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,7 +90,6 @@ pub struct PaymentIntentRequest {
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||
pub struct SetupIntentRequest {
|
||||
pub statement_descriptor_suffix: Option<String>,
|
||||
#[serde(rename = "metadata[order_id]")]
|
||||
pub metadata_order_id: String,
|
||||
#[serde(rename = "metadata[txn_id]")]
|
||||
@ -98,7 +97,7 @@ pub struct SetupIntentRequest {
|
||||
#[serde(rename = "metadata[txn_uuid]")]
|
||||
pub metadata_txn_uuid: String,
|
||||
pub confirm: bool,
|
||||
pub setup_future_usage: Option<enums::FutureUsage>,
|
||||
pub usage: Option<enums::FutureUsage>,
|
||||
pub off_session: Option<bool>,
|
||||
#[serde(flatten)]
|
||||
pub payment_data: StripePaymentMethodData,
|
||||
@ -153,7 +152,12 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest {
|
||||
// let api::PaymentMethod::Card(a) = item.payment_method_data;
|
||||
|
||||
let (payment_data, mandate) = {
|
||||
match item.request.mandate_id.clone() {
|
||||
match item
|
||||
.request
|
||||
.mandate_id
|
||||
.clone()
|
||||
.and_then(|mandate_ids| mandate_ids.connector_mandate_id)
|
||||
{
|
||||
None => (
|
||||
Some(match item.request.payment_method_data {
|
||||
api::PaymentMethod::Card(ref ccard) => StripePaymentMethodData::Card({
|
||||
@ -257,9 +261,8 @@ impl TryFrom<&types::VerifyRouterData> for SetupIntentRequest {
|
||||
metadata_txn_id,
|
||||
metadata_txn_uuid,
|
||||
payment_data,
|
||||
statement_descriptor_suffix: item.request.statement_descriptor_suffix.clone(),
|
||||
off_session: item.request.off_session,
|
||||
setup_future_usage: item.request.setup_future_usage,
|
||||
usage: item.request.setup_future_usage,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,6 +93,7 @@ where
|
||||
{
|
||||
match resp.request.get_mandate_id() {
|
||||
Some(mandate_id) => {
|
||||
let mandate_id = &mandate_id.mandate_id;
|
||||
let mandate = state
|
||||
.store
|
||||
.find_mandate_by_merchant_id_mandate_id(resp.merchant_id.as_ref(), mandate_id)
|
||||
@ -157,7 +158,10 @@ where
|
||||
mandate_reference,
|
||||
) {
|
||||
resp.request
|
||||
.set_mandate_id(new_mandate_data.mandate_id.clone());
|
||||
.set_mandate_id(api_models::payments::MandateIds {
|
||||
mandate_id: new_mandate_data.mandate_id.clone(),
|
||||
connector_mandate_id: new_mandate_data.connector_mandate_id.clone(),
|
||||
});
|
||||
state
|
||||
.store
|
||||
.insert_mandate(new_mandate_data)
|
||||
@ -178,7 +182,7 @@ where
|
||||
pub trait MandateBehaviour {
|
||||
fn get_amount(&self) -> i64;
|
||||
fn get_setup_future_usage(&self) -> Option<storage_models::enums::FutureUsage>;
|
||||
fn get_mandate_id(&self) -> Option<&String>;
|
||||
fn set_mandate_id(&mut self, new_mandate_id: String);
|
||||
fn get_mandate_id(&self) -> Option<&api_models::payments::MandateIds>;
|
||||
fn set_mandate_id(&mut self, new_mandate_id: api_models::payments::MandateIds);
|
||||
fn get_payment_method_data(&self) -> api_models::payments::PaymentMethod;
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ pub mod transformers;
|
||||
|
||||
use std::{fmt::Debug, marker::PhantomData, time::Instant};
|
||||
|
||||
use common_utils::ext_traits::AsyncExt;
|
||||
use error_stack::{IntoReport, ResultExt};
|
||||
use futures::future::join_all;
|
||||
use router_env::{tracing, tracing::instrument};
|
||||
@ -61,6 +62,7 @@ where
|
||||
|
||||
// To perform router related operation for PaymentResponse
|
||||
PaymentResponse: Operation<F, FData>,
|
||||
FData: std::marker::Send,
|
||||
{
|
||||
let operation: BoxedOperation<F, Req> = Box::new(operation);
|
||||
|
||||
@ -181,6 +183,7 @@ pub async fn payments_core<F, Res, Req, Op, FData>(
|
||||
) -> RouterResponse<Res>
|
||||
where
|
||||
F: Send + Clone,
|
||||
FData: std::marker::Send,
|
||||
Op: Operation<F, Req> + Send + Sync + Clone,
|
||||
Req: Debug,
|
||||
Res: transformers::ToResponse<Req, PaymentData<F>, Op> + From<Req>,
|
||||
@ -194,7 +197,6 @@ where
|
||||
|
||||
// To perform router related operation for PaymentResponse
|
||||
PaymentResponse: Operation<F, FData>,
|
||||
// To create merchant response
|
||||
{
|
||||
let (payment_data, req, customer) = payments_operation_core(
|
||||
state,
|
||||
@ -313,7 +315,7 @@ where
|
||||
|
||||
// To create connector flow specific interface data
|
||||
PaymentData<F>: ConstructFlowSpecificData<F, Req, types::PaymentsResponseData>,
|
||||
types::RouterData<F, Req, types::PaymentsResponseData>: Feature<F, Req>,
|
||||
types::RouterData<F, Req, types::PaymentsResponseData>: Feature<F, Req> + Send,
|
||||
|
||||
// To construct connector flow specific api
|
||||
dyn api::Connector: services::api::ConnectorIntegration<F, Req, types::PaymentsResponseData>,
|
||||
@ -339,7 +341,8 @@ where
|
||||
)
|
||||
.await;
|
||||
|
||||
let response = helpers::amap(res, |response| async {
|
||||
let response = res
|
||||
.async_and_then(|response| async {
|
||||
let operation = helpers::response_operation::<F, Req>();
|
||||
let payment_data = operation
|
||||
.to_post_update_tracker()?
|
||||
@ -347,7 +350,7 @@ where
|
||||
db,
|
||||
payment_id,
|
||||
payment_data,
|
||||
Some(response),
|
||||
response,
|
||||
merchant_account.storage_scheme,
|
||||
)
|
||||
.await?;
|
||||
@ -457,8 +460,8 @@ where
|
||||
pub payment_attempt: storage::PaymentAttempt,
|
||||
pub connector_response: storage::ConnectorResponse,
|
||||
pub amount: api::Amount,
|
||||
pub mandate_id: Option<api_models::payments::MandateIds>,
|
||||
pub currency: storage_enums::Currency,
|
||||
pub mandate_id: Option<String>,
|
||||
pub setup_mandate: Option<api::MandateData>,
|
||||
pub address: PaymentAddress,
|
||||
pub token: Option<String>,
|
||||
|
||||
@ -111,7 +111,7 @@ impl mandate::MandateBehaviour for types::PaymentsAuthorizeData {
|
||||
fn get_amount(&self) -> i64 {
|
||||
self.amount
|
||||
}
|
||||
fn get_mandate_id(&self) -> Option<&String> {
|
||||
fn get_mandate_id(&self) -> Option<&api_models::payments::MandateIds> {
|
||||
self.mandate_id.as_ref()
|
||||
}
|
||||
fn get_payment_method_data(&self) -> api_models::payments::PaymentMethod {
|
||||
@ -120,7 +120,7 @@ impl mandate::MandateBehaviour for types::PaymentsAuthorizeData {
|
||||
fn get_setup_future_usage(&self) -> Option<storage_models::enums::FutureUsage> {
|
||||
self.setup_future_usage
|
||||
}
|
||||
fn set_mandate_id(&mut self, new_mandate_id: String) {
|
||||
fn set_mandate_id(&mut self, new_mandate_id: api_models::payments::MandateIds) {
|
||||
self.mandate_id = Some(new_mandate_id);
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,11 +98,11 @@ impl mandate::MandateBehaviour for types::VerifyRequestData {
|
||||
self.setup_future_usage
|
||||
}
|
||||
|
||||
fn get_mandate_id(&self) -> Option<&String> {
|
||||
fn get_mandate_id(&self) -> Option<&api_models::payments::MandateIds> {
|
||||
self.mandate_id.as_ref()
|
||||
}
|
||||
|
||||
fn set_mandate_id(&mut self, new_mandate_id: String) {
|
||||
fn set_mandate_id(&mut self, new_mandate_id: api_models::payments::MandateIds) {
|
||||
self.mandate_id = Some(new_mandate_id);
|
||||
}
|
||||
|
||||
|
||||
@ -390,7 +390,7 @@ pub fn verify_mandate_details(
|
||||
mandate
|
||||
.mandate_currency
|
||||
.map(|mandate_currency| mandate_currency.to_string() != request_currency)
|
||||
.unwrap_or(true),
|
||||
.unwrap_or(false),
|
||||
Err(report!(errors::ApiErrorResponse::MandateValidationFailed {
|
||||
reason: "cross currency mandates not supported".to_string()
|
||||
})),
|
||||
@ -471,17 +471,6 @@ where
|
||||
Box::new(PaymentResponse)
|
||||
}
|
||||
|
||||
pub async fn amap<A, B, E, F, Fut>(value: Result<A, E>, func: F) -> Result<B, E>
|
||||
where
|
||||
F: FnOnce(A) -> Fut,
|
||||
Fut: futures::Future<Output = Result<B, E>>,
|
||||
{
|
||||
match value {
|
||||
Ok(a) => func(a).await,
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
pub(crate) async fn call_payment_method(
|
||||
state: &AppState,
|
||||
|
||||
@ -164,7 +164,7 @@ pub trait PostUpdateTracker<F, D, R>: Send {
|
||||
db: &dyn StorageInterface,
|
||||
payment_id: &api::PaymentIdType,
|
||||
payment_data: D,
|
||||
response: Option<types::RouterData<F, R, PaymentsResponseData>>,
|
||||
response: types::RouterData<F, R, PaymentsResponseData>,
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> RouterResult<D>
|
||||
where
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use common_utils::ext_traits::AsyncExt;
|
||||
use error_stack::ResultExt;
|
||||
use masking::Secret;
|
||||
use router_derive::PaymentOperation;
|
||||
@ -182,6 +183,22 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
}
|
||||
}?;
|
||||
|
||||
let mandate_id = request
|
||||
.mandate_id
|
||||
.as_ref()
|
||||
.async_and_then(|mandate_id| async {
|
||||
let mandate = db
|
||||
.find_mandate_by_merchant_id_mandate_id(merchant_id, mandate_id)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::MandateNotFound);
|
||||
Some(mandate.map(|mandate_obj| api_models::payments::MandateIds {
|
||||
mandate_id: mandate_obj.mandate_id,
|
||||
connector_mandate_id: mandate_obj.connector_mandate_id,
|
||||
}))
|
||||
})
|
||||
.await
|
||||
.transpose()?;
|
||||
|
||||
let operation = payments::if_not_create_change_operation::<_, F>(
|
||||
is_update,
|
||||
payment_intent.status,
|
||||
@ -197,7 +214,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
payment_attempt,
|
||||
currency,
|
||||
amount,
|
||||
mandate_id: request.mandate_id.clone(),
|
||||
mandate_id,
|
||||
setup_mandate,
|
||||
token,
|
||||
address: PaymentAddress {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use async_trait::async_trait;
|
||||
use error_stack::{report, ResultExt};
|
||||
use error_stack::ResultExt;
|
||||
use router_derive;
|
||||
|
||||
use super::{Operation, PostUpdateTracker};
|
||||
@ -34,26 +34,21 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsAuthorizeData
|
||||
db: &dyn StorageInterface,
|
||||
payment_id: &api::PaymentIdType,
|
||||
mut payment_data: PaymentData<F>,
|
||||
response: Option<
|
||||
types::RouterData<F, types::PaymentsAuthorizeData, types::PaymentsResponseData>,
|
||||
router_data: types::RouterData<
|
||||
F,
|
||||
types::PaymentsAuthorizeData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> RouterResult<PaymentData<F>>
|
||||
where
|
||||
F: 'b + Send,
|
||||
{
|
||||
let router_data = response.ok_or(report!(errors::ApiErrorResponse::InternalServerError))?;
|
||||
payment_data.mandate_id = payment_data
|
||||
.mandate_id
|
||||
.or_else(|| router_data.request.mandate_id.clone());
|
||||
|
||||
payment_response_update_tracker(
|
||||
db,
|
||||
payment_id,
|
||||
payment_data,
|
||||
Some(router_data),
|
||||
storage_scheme,
|
||||
)
|
||||
payment_response_update_tracker(db, payment_id, payment_data, router_data, storage_scheme)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@ -65,9 +60,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsSyncData> for
|
||||
db: &dyn StorageInterface,
|
||||
payment_id: &api::PaymentIdType,
|
||||
payment_data: PaymentData<F>,
|
||||
response: Option<
|
||||
types::RouterData<F, types::PaymentsSyncData, types::PaymentsResponseData>,
|
||||
>,
|
||||
response: types::RouterData<F, types::PaymentsSyncData, types::PaymentsResponseData>,
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> RouterResult<PaymentData<F>>
|
||||
where
|
||||
@ -87,9 +80,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsSessionData>
|
||||
db: &dyn StorageInterface,
|
||||
payment_id: &api::PaymentIdType,
|
||||
payment_data: PaymentData<F>,
|
||||
response: Option<
|
||||
types::RouterData<F, types::PaymentsSessionData, types::PaymentsResponseData>,
|
||||
>,
|
||||
response: types::RouterData<F, types::PaymentsSessionData, types::PaymentsResponseData>,
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> RouterResult<PaymentData<F>>
|
||||
where
|
||||
@ -109,9 +100,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsCaptureData>
|
||||
db: &dyn StorageInterface,
|
||||
payment_id: &api::PaymentIdType,
|
||||
payment_data: PaymentData<F>,
|
||||
response: Option<
|
||||
types::RouterData<F, types::PaymentsCaptureData, types::PaymentsResponseData>,
|
||||
>,
|
||||
response: types::RouterData<F, types::PaymentsCaptureData, types::PaymentsResponseData>,
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> RouterResult<PaymentData<F>>
|
||||
where
|
||||
@ -129,9 +118,8 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsCancelData> f
|
||||
db: &dyn StorageInterface,
|
||||
payment_id: &api::PaymentIdType,
|
||||
payment_data: PaymentData<F>,
|
||||
response: Option<
|
||||
types::RouterData<F, types::PaymentsCancelData, types::PaymentsResponseData>,
|
||||
>,
|
||||
response: types::RouterData<F, types::PaymentsCancelData, types::PaymentsResponseData>,
|
||||
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> RouterResult<PaymentData<F>>
|
||||
where
|
||||
@ -148,16 +136,20 @@ impl<F: Clone> PostUpdateTracker<F, PaymentData<F>, types::VerifyRequestData> fo
|
||||
&'b self,
|
||||
db: &dyn StorageInterface,
|
||||
payment_id: &api::PaymentIdType,
|
||||
payment_data: PaymentData<F>,
|
||||
response: Option<
|
||||
types::RouterData<F, types::VerifyRequestData, types::PaymentsResponseData>,
|
||||
>,
|
||||
mut payment_data: PaymentData<F>,
|
||||
router_data: types::RouterData<F, types::VerifyRequestData, types::PaymentsResponseData>,
|
||||
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> RouterResult<PaymentData<F>>
|
||||
where
|
||||
F: 'b + Send,
|
||||
{
|
||||
payment_response_update_tracker(db, payment_id, payment_data, response, storage_scheme)
|
||||
payment_data.mandate_id = payment_data.mandate_id.or_else(|| {
|
||||
router_data.request.mandate_id.clone()
|
||||
// .map(api_models::payments::MandateIds::new)
|
||||
});
|
||||
|
||||
payment_response_update_tracker(db, payment_id, payment_data, router_data, storage_scheme)
|
||||
.await
|
||||
}
|
||||
}
|
||||
@ -166,11 +158,9 @@ async fn payment_response_update_tracker<F: Clone, T>(
|
||||
db: &dyn StorageInterface,
|
||||
_payment_id: &api::PaymentIdType,
|
||||
mut payment_data: PaymentData<F>,
|
||||
response: Option<types::RouterData<F, T, types::PaymentsResponseData>>,
|
||||
router_data: types::RouterData<F, T, types::PaymentsResponseData>,
|
||||
storage_scheme: enums::MerchantStorageScheme,
|
||||
) -> RouterResult<PaymentData<F>> {
|
||||
let router_data = response.ok_or(report!(errors::ApiErrorResponse::InternalServerError))?;
|
||||
|
||||
let (payment_attempt_update, connector_response_update) = match router_data.response.clone() {
|
||||
Err(err) => (
|
||||
Some(storage::PaymentAttemptUpdate::ErrorUpdate {
|
||||
@ -212,7 +202,10 @@ async fn payment_response_update_tracker<F: Clone, T>(
|
||||
authentication_type: None,
|
||||
payment_method_id: Some(router_data.payment_method_id),
|
||||
redirect: Some(redirect),
|
||||
mandate_id: payment_data.mandate_id.clone(),
|
||||
mandate_id: payment_data
|
||||
.mandate_id
|
||||
.clone()
|
||||
.map(|mandate| mandate.mandate_id),
|
||||
};
|
||||
|
||||
let connector_response_update = storage::ConnectorResponseUpdate::ResponseUpdate {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use common_utils::ext_traits::AsyncExt;
|
||||
use error_stack::{report, ResultExt};
|
||||
use masking::Secret;
|
||||
use router_derive::PaymentOperation;
|
||||
@ -126,6 +127,21 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
.attach_printable("Database error when finding connector response")
|
||||
})?;
|
||||
|
||||
let mandate_id = request
|
||||
.mandate_id
|
||||
.as_ref()
|
||||
.async_and_then(|mandate_id| async {
|
||||
let mandate = db
|
||||
.find_mandate_by_merchant_id_mandate_id(merchant_id, mandate_id)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::MandateNotFound);
|
||||
Some(mandate.map(|mandate_obj| api_models::payments::MandateIds {
|
||||
mandate_id: mandate_obj.mandate_id,
|
||||
connector_mandate_id: mandate_obj.connector_mandate_id,
|
||||
}))
|
||||
})
|
||||
.await
|
||||
.transpose()?;
|
||||
let next_operation: BoxedOperation<'a, F, api::PaymentsRequest> =
|
||||
if request.confirm.unwrap_or(false) {
|
||||
Box::new(operations::PaymentConfirm)
|
||||
@ -149,7 +165,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
payment_attempt,
|
||||
currency,
|
||||
amount,
|
||||
mandate_id: request.mandate_id.clone(),
|
||||
mandate_id,
|
||||
token,
|
||||
setup_mandate,
|
||||
address: PaymentAddress {
|
||||
|
||||
@ -197,7 +197,7 @@ where
|
||||
phone: customer
|
||||
.as_ref()
|
||||
.and_then(|cus| cus.phone.as_ref().map(|s| s.to_owned())),
|
||||
mandate_id: data.mandate_id,
|
||||
mandate_id: data.mandate_id.map(|mandate_ids| mandate_ids.mandate_id),
|
||||
payment_method: data
|
||||
.payment_attempt
|
||||
.payment_method
|
||||
@ -499,8 +499,8 @@ impl<F: Clone> TryFrom<PaymentData<F>> for types::VerifyRequestData {
|
||||
},
|
||||
statement_descriptor_suffix: payment_data.payment_intent.statement_descriptor_suffix,
|
||||
setup_future_usage: payment_data.payment_intent.setup_future_usage,
|
||||
mandate_id: payment_data.mandate_id.clone(),
|
||||
off_session: payment_data.mandate_id.as_ref().map(|_| true),
|
||||
mandate_id: payment_data.mandate_id.clone(),
|
||||
setup_mandate_details: payment_data.setup_mandate,
|
||||
})
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ pub struct PaymentsAuthorizeData {
|
||||
pub capture_method: Option<storage_enums::CaptureMethod>,
|
||||
// Mandates
|
||||
pub setup_future_usage: Option<storage_enums::FutureUsage>,
|
||||
pub mandate_id: Option<String>,
|
||||
pub mandate_id: Option<api_models::payments::MandateIds>,
|
||||
pub off_session: Option<bool>,
|
||||
pub setup_mandate_details: Option<payments::MandateData>,
|
||||
pub browser_info: Option<BrowserInformation>,
|
||||
@ -134,7 +134,7 @@ pub struct VerifyRequestData {
|
||||
pub payment_method_data: payments::PaymentMethod,
|
||||
pub confirm: bool,
|
||||
pub statement_descriptor_suffix: Option<String>,
|
||||
pub mandate_id: Option<String>,
|
||||
pub mandate_id: Option<api_models::payments::MandateIds>,
|
||||
pub setup_future_usage: Option<storage_enums::FutureUsage>,
|
||||
pub off_session: Option<bool>,
|
||||
pub setup_mandate_details: Option<payments::MandateData>,
|
||||
|
||||
Reference in New Issue
Block a user