feat(single_use): add extra fields in Mandate table and MandateData [Blocked on #61] (#66)

This commit is contained in:
Nishant Joshi
2022-12-09 17:18:12 +05:30
committed by GitHub
parent 9710af1e56
commit 2aef3bccfb
9 changed files with 81 additions and 45 deletions

View File

@ -128,6 +128,21 @@ impl PaymentsAuthorizeRouterData {
)
.await
.change_context(errors::ApiErrorResponse::MandateNotFound)?;
let mandate = match mandate.mandate_type {
storage_enums::MandateType::SingleUse => state
.store
.update_mandate_by_merchant_id_mandate_id(
&resp.merchant_id,
mandate_id,
storage::MandateUpdate::StatusUpdate {
mandate_status: storage_enums::MandateStatus::Revoked,
},
)
.await
.change_context(errors::ApiErrorResponse::MandateNotFound),
storage_enums::MandateType::MultiUse => Ok(mandate),
}?;
resp.payment_method_id = Some(mandate.payment_method_id);
}
None => {
@ -173,19 +188,32 @@ impl PaymentsAuthorizeRouterData {
match (self.request.setup_mandate_details.clone(), customer) {
(Some(data), Some(cus)) => {
let mandate_id = utils::generate_id(consts::ID_LENGTH, "man");
Some(storage::MandateNew {
mandate_id,
customer_id: cus.customer_id.clone(),
merchant_id: self.merchant_id.clone(),
payment_method_id,
mandate_status: storage_enums::MandateStatus::Active,
mandate_type: storage_enums::MandateType::MultiUse,
customer_ip_address: data.customer_acceptance.get_ip_address().map(Secret::new),
customer_user_agent: data.customer_acceptance.get_user_agent(),
customer_accepted_at: Some(data.customer_acceptance.get_accepted_at()),
..Default::default() // network_transaction_id: Option<String>,
// previous_transaction_id: Option<String>,
// created_at: Option<PrimitiveDateTime>,
// The construction of the mandate new must be visible
let mut new_mandate = storage::MandateNew::default();
new_mandate
.set_mandate_id(mandate_id)
.set_customer_id(cus.customer_id.clone())
.set_merchant_id(self.merchant_id.clone())
.set_payment_method_id(payment_method_id)
.set_mandate_status(storage_enums::MandateStatus::Active)
.set_customer_ip_address(
data.customer_acceptance.get_ip_address().map(Secret::new),
)
.set_customer_user_agent(data.customer_acceptance.get_user_agent())
.set_customer_accepted_at(Some(data.customer_acceptance.get_accepted_at()));
Some(match data.mandate_type {
api::MandateType::SingleUse(data) => new_mandate
.set_single_use_amount(Some(data.amount))
.set_single_use_currency(Some(data.currency))
.set_mandate_type(storage_enums::MandateType::SingleUse)
.to_owned(),
api::MandateType::MultiUse => new_mandate
.set_mandate_type(storage_enums::MandateType::MultiUse)
.to_owned(),
})
}
(_, _) => None,

View File

@ -139,6 +139,11 @@ pub async fn get_token_for_recurring_mandate(
.await
.map_err(|error| error.to_not_found_response(errors::ApiErrorResponse::MandateNotFound))?;
utils::when(
mandate.mandate_status != storage_enums::MandateStatus::Active,
Err(errors::ApiErrorResponse::MandateNotFound),
)?;
let customer = req.customer_id.clone().get_required_value("customer_id")?;
let payment_method_id = {

View File

@ -137,7 +137,6 @@ where
payment_data.payment_attempt,
payment_data.payment_intent,
payment_data.refunds,
payment_data.mandate_id,
payment_data.payment_method_data,
customer,
auth_flow,
@ -198,7 +197,6 @@ pub fn payments_to_payments_response<R, Op>(
payment_attempt: storage::PaymentAttempt,
payment_intent: storage::PaymentIntent,
refunds: Vec<storage::Refund>,
mandate_id: Option<String>,
payment_method_data: Option<api::PaymentMethod>,
customer: Option<storage::Customer>,
auth_flow: services::AuthFlow,
@ -216,6 +214,7 @@ where
.as_ref()
.get_required_value("currency")?
.to_string();
let mandate_id = payment_attempt.mandate_id.clone();
let refunds_response = if refunds.is_empty() {
None
} else {

View File

@ -14,6 +14,7 @@ use super::app::AppState;
use crate::{
core::{errors::http_not_implemented, payments},
services::api,
types::api::{
enums as api_enums,
payments::{
@ -21,7 +22,7 @@ use crate::{
PaymentsRequest, PaymentsRetrieveRequest,
},
Authorize, Capture, PSync, PaymentRetrieveBody, PaymentsResponse, PaymentsStartRequest,
Verify, VerifyRequest, VerifyResponse, Void,
Verify, VerifyResponse, Void,
}, // FIXME imports
};
@ -110,33 +111,6 @@ pub async fn payments_start(
.await
}
#[allow(dead_code)]
#[instrument(skip(state), fields(flow = ?Flow::ValidatePaymentMethod))]
pub async fn validate_pm(
state: web::Data<AppState>,
req: HttpRequest,
json_payload: web::Json<VerifyRequest>,
) -> HttpResponse {
let payload = json_payload.into_inner();
api::server_wrap(
&state,
&req,
payload,
|state, merchant_account, req| {
payments::payments_core::<Verify, VerifyResponse, _, _, _>(
state,
merchant_account,
payments::PaymentMethodValidate,
req,
api::AuthFlow::Merchant,
payments::CallConnectorAction::Trigger,
)
},
api::MerchantAuthentication::ApiKey,
)
.await
}
#[instrument(skip(state), fields(flow = ?Flow::PaymentsRetrieve))]
// #[get("/{payment_id}")]
pub async fn payments_retrieve(

View File

@ -127,6 +127,8 @@ diesel::table! {
network_transaction_id -> Nullable<Varchar>,
previous_transaction_id -> Nullable<Varchar>,
created_at -> Timestamp,
single_use_amount -> Nullable<Int4>,
single_use_currency -> Nullable<Currency>,
}
}

View File

@ -7,7 +7,7 @@ use crate::{
core::errors,
pii,
services::api,
types::{self, api as api_types, api::enums as api_enums},
types::{self, api as api_types, api::enums as api_enums, storage},
utils::custom_serde,
};
@ -126,6 +126,14 @@ pub enum MandateTxnType {
#[serde(deny_unknown_fields)]
pub struct MandateData {
pub customer_acceptance: CustomerAcceptance,
pub mandate_type: MandateType,
}
#[derive(Default, Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone)]
pub enum MandateType {
SingleUse(storage::SingleUseMandate),
#[default]
MultiUse,
}
#[derive(Default, Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone)]

View File

@ -24,9 +24,13 @@ pub struct Mandate {
pub network_transaction_id: Option<String>,
pub previous_transaction_id: Option<String>,
pub created_at: PrimitiveDateTime,
pub single_use_amount: Option<i32>,
pub single_use_currency: Option<storage_enums::Currency>,
}
#[derive(Clone, Debug, Default, Insertable, router_derive::DebugAsDisplay)]
#[derive(
router_derive::Setter, Clone, Debug, Default, Insertable, router_derive::DebugAsDisplay,
)]
#[diesel(table_name = mandate)]
pub struct MandateNew {
pub mandate_id: String,
@ -41,6 +45,8 @@ pub struct MandateNew {
pub network_transaction_id: Option<String>,
pub previous_transaction_id: Option<String>,
pub created_at: Option<PrimitiveDateTime>,
pub single_use_amount: Option<i32>,
pub single_use_currency: Option<storage_enums::Currency>,
}
#[derive(Debug)]
@ -50,6 +56,12 @@ pub enum MandateUpdate {
},
}
#[derive(Clone, Eq, PartialEq, Copy, Debug, Default, serde::Serialize, serde::Deserialize)]
pub struct SingleUseMandate {
pub amount: i32,
pub currency: storage_enums::Currency,
}
#[derive(Clone, Debug, Default, AsChangeset, router_derive::DebugAsDisplay)]
#[diesel(table_name = mandate)]
pub(super) struct MandateUpdateInternal {