feat: api contract change for wallet (#628)

This commit is contained in:
Sangamesh Kulkarni
2023-02-27 17:38:40 +05:30
committed by GitHub
parent 060c54193e
commit ff86417eee
20 changed files with 1176 additions and 477 deletions

View File

@ -78,7 +78,7 @@ impl TryFrom<refunds::RefundResponse> for StripeCreateRefundResponse {
payment_intent: res.payment_id,
status: res.status.into(),
created: res.created_at.map(|t| t.assume_utc().unix_timestamp()),
metadata: res.metadata.unwrap_or(serde_json::json!({})),
metadata: res.metadata.unwrap_or_else(|| serde_json::json!({})),
})
}
}

View File

@ -1,18 +1,16 @@
use base64::Engine;
use error_stack::ResultExt;
use masking::PeekInterface;
use reqwest::Url;
use serde::{Deserialize, Serialize};
use crate::{
connector::utils::{self, PaymentsRequestData},
connector::utils::PaymentsRequestData,
consts,
core::errors,
pii::{self, Email, Secret},
services,
types::{
self,
api::{self, enums as api_enums},
storage::enums as storage_enums,
},
types::{self, api, storage::enums as storage_enums},
};
// Adyen Types Definition
@ -339,7 +337,6 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for AdyenPaymentRequest {
get_paylater_specific_payment_data(item)
}
storage_models::enums::PaymentMethod::Wallet => get_wallet_specific_payment_data(item),
_ => Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into()),
}
}
}
@ -480,29 +477,34 @@ fn get_payment_method_data(
};
Ok(AdyenPaymentMethod::AdyenCard(adyen_card))
}
api::PaymentMethodData::Wallet(ref wallet_data) => match wallet_data.issuer_name {
api_enums::WalletIssuer::GooglePay => {
api::PaymentMethodData::Wallet(ref wallet_data) => match wallet_data {
api_models::payments::WalletData::GooglePay(data) => {
let gpay_data = AdyenGPay {
payment_type: PaymentType::Googlepay,
google_pay_token: wallet_data
.token
.clone()
.ok_or_else(utils::missing_field_err("token"))?,
google_pay_token: data.tokenization_data.token.to_owned(),
};
Ok(AdyenPaymentMethod::Gpay(gpay_data))
}
api_enums::WalletIssuer::ApplePay => {
api_models::payments::WalletData::ApplePay(data) => {
let apple_pay_data = AdyenApplePay {
payment_type: PaymentType::Applepay,
apple_pay_token: wallet_data
.token
.clone()
.ok_or_else(utils::missing_field_err("token"))?,
apple_pay_token:
consts::BASE64_ENGINE.encode(
common_utils::ext_traits::Encode::<
api_models::payments::ApplepayPaymentData,
>::encode_to_string_of_json(
&data.payment_data
)
.change_context(errors::ConnectorError::RequestEncodingFailed)?,
),
};
Ok(AdyenPaymentMethod::ApplePay(apple_pay_data))
}
api_enums::WalletIssuer::Paypal => {
api_models::payments::WalletData::PaypalSdk(_) => {
Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into())
}
api_models::payments::WalletData::PaypalRedirect(_) => {
let wallet = AdyenPaypal {
payment_type: PaymentType::Paypal,
};

View File

@ -171,7 +171,7 @@ impl<F>
Ok(Self {
response: Ok(types::PaymentsResponseData::SessionResponse {
session_token: {
api_models::payments::SessionToken::Applepay(Box::new(
api_models::payments::SessionToken::ApplePay(Box::new(
payments::ApplepaySessionTokenResponse {
session_token_data: applepay_session.into(),
payment_request_data: payment_request.into(),

View File

@ -1,6 +1,5 @@
use api_models::payments;
use base64::Engine;
use error_stack::ResultExt;
use masking::Secret;
use serde::{Deserialize, Serialize};
@ -8,7 +7,6 @@ use crate::{
consts,
core::errors,
types::{self, api, storage::enums},
utils::OptionExt,
};
#[derive(Default, Debug, Serialize, Eq, PartialEq)]
@ -111,12 +109,12 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for BraintreePaymentsRequest {
})),
api::PaymentMethodData::Wallet(ref wallet_data) => {
Ok(PaymentMethodType::PaymentMethodNonce(Nonce {
payment_method_nonce: wallet_data
.token
.to_owned()
.get_required_value("token")
.change_context(errors::ConnectorError::RequestEncodingFailed)
.attach_printable("No token passed")?,
payment_method_nonce: match wallet_data {
api_models::payments::WalletData::PaypalSdk(wallet_data) => {
Ok(wallet_data.token.to_owned())
}
_ => Err(errors::ConnectorError::InvalidWallet),
}?,
}))
}
_ => Err(errors::ConnectorError::NotImplemented(format!(

View File

@ -8,7 +8,6 @@ use crate::{
core::errors,
pii::{self, Secret},
types::{self, api, storage::enums},
utils::OptionExt,
};
const WALLET_IDENTIFIER: &str = "PBL";
@ -78,33 +77,29 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PayuPaymentsRequest {
cvv: ccard.card_cvc,
}),
}),
api::PaymentMethodData::Wallet(wallet_data) => match wallet_data.issuer_name {
api_models::enums::WalletIssuer::GooglePay => Ok(PayuPaymentMethod {
api::PaymentMethodData::Wallet(wallet_data) => match wallet_data {
api_models::payments::WalletData::GooglePay(data) => Ok(PayuPaymentMethod {
pay_method: PayuPaymentMethodData::Wallet({
PayuWallet {
value: PayuWalletCode::Ap,
wallet_type: WALLET_IDENTIFIER.to_string(),
authorization_code: consts::BASE64_ENGINE.encode(
wallet_data
.token
.get_required_value("token")
.change_context(errors::ConnectorError::RequestEncodingFailed)
.attach_printable("No token passed")?,
),
authorization_code: consts::BASE64_ENGINE
.encode(data.tokenization_data.token),
}
}),
}),
api_models::enums::WalletIssuer::ApplePay => Ok(PayuPaymentMethod {
api_models::payments::WalletData::ApplePay(data) => Ok(PayuPaymentMethod {
pay_method: PayuPaymentMethodData::Wallet({
PayuWallet {
value: PayuWalletCode::Jp,
wallet_type: WALLET_IDENTIFIER.to_string(),
authorization_code: consts::BASE64_ENGINE.encode(
wallet_data
.token
.get_required_value("token")
.change_context(errors::ConnectorError::RequestEncodingFailed)
.attach_printable("No token passed")?,
common_utils::ext_traits::Encode::<
api_models::payments::ApplepayPaymentData,
>::encode_to_string_of_json(
&data.payment_data
)
.change_context(errors::ConnectorError::RequestEncodingFailed)?,
),
}
}),

View File

@ -1,3 +1,4 @@
use base64::Engine;
use error_stack::{IntoReport, ResultExt};
use serde::{Deserialize, Serialize};
use url::Url;
@ -66,7 +67,7 @@ pub struct RapydWallet {
#[serde(rename = "type")]
payment_type: String,
#[serde(rename = "details")]
apple_pay_token: Option<String>,
token: Option<String>,
}
impl TryFrom<&types::PaymentsAuthorizeRouterData> for RapydPaymentsRequest {
@ -104,14 +105,23 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for RapydPaymentsRequest {
})
}
api_models::payments::PaymentMethodData::Wallet(ref wallet_data) => {
let digital_wallet = match wallet_data.issuer_name {
api_models::enums::WalletIssuer::GooglePay => Some(RapydWallet {
let digital_wallet = match wallet_data {
api_models::payments::WalletData::GooglePay(data) => Some(RapydWallet {
payment_type: "google_pay".to_string(),
apple_pay_token: wallet_data.token.to_owned(),
token: Some(data.tokenization_data.token.to_owned()),
}),
api_models::enums::WalletIssuer::ApplePay => Some(RapydWallet {
api_models::payments::WalletData::ApplePay(data) => Some(RapydWallet {
payment_type: "apple_pay".to_string(),
apple_pay_token: wallet_data.token.to_owned(),
token: Some(
consts::BASE64_ENGINE.encode(
common_utils::ext_traits::Encode::<
api_models::payments::ApplepayPaymentData,
>::encode_to_string_of_json(
&data.payment_data
)
.change_context(errors::ConnectorError::RequestEncodingFailed)?,
),
),
}),
_ => None,
};

View File

@ -1,12 +1,13 @@
use base64::Engine;
use common_utils::errors::CustomResult;
use error_stack::ResultExt;
use storage_models::enums;
use super::{requests::*, response::*};
use crate::{
consts,
core::errors,
types::{self, api},
utils::OptionExt,
};
fn fetch_payment_instrument(
@ -21,26 +22,27 @@ fn fetch_payment_instrument(
card_number: card.card_number,
..CardPayment::default()
})),
api::PaymentMethodData::Wallet(wallet) => match wallet.issuer_name {
api_models::enums::WalletIssuer::ApplePay => {
Ok(PaymentInstrument::Applepay(WalletPayment {
payment_type: PaymentType::Applepay,
wallet_token: wallet
.token
.get_required_value("token")
.change_context(errors::ConnectorError::RequestEncodingFailed)
.attach_printable("No token passed")?,
api::PaymentMethodData::Wallet(wallet) => match wallet {
api_models::payments::WalletData::GooglePay(data) => {
Ok(PaymentInstrument::Googlepay(WalletPayment {
payment_type: PaymentType::Googlepay,
wallet_token: data.tokenization_data.token,
..WalletPayment::default()
}))
}
api_models::enums::WalletIssuer::GooglePay => {
Ok(PaymentInstrument::Googlepay(WalletPayment {
payment_type: PaymentType::Googlepay,
wallet_token: wallet
.token
.get_required_value("token")
.change_context(errors::ConnectorError::RequestEncodingFailed)
.attach_printable("No token passed")?,
api_models::payments::WalletData::ApplePay(data) => {
Ok(PaymentInstrument::Applepay(WalletPayment {
payment_type: PaymentType::Applepay,
wallet_token:
consts::BASE64_ENGINE.encode(
common_utils::ext_traits::Encode::<
api_models::payments::ApplepayPaymentData,
>::encode_to_string_of_json(
&data.payment_data
)
.change_context(errors::ConnectorError::RequestEncodingFailed)?,
),
..WalletPayment::default()
}))
}

View File

@ -234,6 +234,8 @@ pub enum ConnectorError {
FailedToObtainPreferredConnector,
#[error("An invalid connector name was provided")]
InvalidConnectorName,
#[error("An invalid Wallet was used")]
InvalidWallet,
#[error("Failed to handle connector response")]
ResponseHandlingFailed,
#[error("Missing required field: {field_name}")]

View File

@ -1,5 +1,3 @@
use std::str::FromStr;
use common_utils::generate_id_with_default_len;
use error_stack::{IntoReport, ResultExt};
use masking::PeekInterface;
@ -103,8 +101,7 @@ impl Vaultable for api::Card {
impl Vaultable for api::WalletData {
fn get_value1(&self, _customer_id: Option<String>) -> CustomResult<String, errors::VaultError> {
let value1 = api::TokenizedWalletValue1 {
issuer: self.issuer_name.to_string(),
token: self.token.clone(),
data: self.to_owned(),
};
utils::Encode::<api::TokenizedWalletValue1>::encode_to_string_of_json(&value1)
@ -134,13 +131,7 @@ impl Vaultable for api::WalletData {
.change_context(errors::VaultError::ResponseDeserializationFailed)
.attach_printable("Could not deserialize into wallet data value2")?;
let wallet = Self {
issuer_name: api::enums::WalletIssuer::from_str(&value1.issuer)
.into_report()
.change_context(errors::VaultError::ResponseDeserializationFailed)
.attach_printable("Invalid issuer name when deserializing wallet data")?,
token: value1.token,
};
let wallet = value1.data;
let supp_data = SupplementaryVaultData {
customer_id: value2.customer_id,

View File

@ -91,7 +91,7 @@ fn create_gpay_session_token(
let response_router_data = types::PaymentsSessionRouterData {
response: Ok(types::PaymentsResponseData::SessionResponse {
session_token: payment_types::SessionToken::Gpay(Box::new(
session_token: payment_types::SessionToken::GooglePay(Box::new(
payment_types::GpaySessionTokenResponse {
merchant_info: gpay_data.data.merchant_info,
allowed_payment_methods: gpay_data.data.allowed_payment_methods,

View File

@ -721,18 +721,19 @@ pub async fn make_pm_data<'a, F: Clone, R>(
payment_data.payment_attempt.payment_method =
Some(storage_enums::PaymentMethod::Wallet);
// TODO: Remove redundant update from wallets.
if wallet_data.token.is_some() {
let updated_pm = api::PaymentMethodData::Wallet(wallet_data);
vault::Vault::store_payment_method_data_in_locker(
state,
Some(token),
&updated_pm,
payment_data.payment_intent.customer_id.to_owned(),
)
.await?;
Some(updated_pm)
} else {
pm
match wallet_data {
api_models::payments::WalletData::PaypalRedirect(_) => pm,
_ => {
let updated_pm = api::PaymentMethodData::Wallet(wallet_data);
vault::Vault::store_payment_method_data_in_locker(
state,
Some(token),
&updated_pm,
payment_data.payment_intent.customer_id.to_owned(),
)
.await?;
Some(updated_pm)
}
}
}

View File

@ -124,6 +124,8 @@ Never share your secret api keys. Keep them guarded and secure.
crate::types::api::payment_methods::CardDetailFromLocker,
crate::types::api::payment_methods::CardDetail,
api_models::customers::CustomerResponse,
api_models::admin::AcceptedCountries,
api_models::admin::AcceptedCurrencies,
api_models::enums::RoutingAlgorithm,
api_models::enums::PaymentMethod,
api_models::enums::PaymentMethodType,
@ -133,17 +135,19 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::enums::CaptureMethod,
api_models::enums::FutureUsage,
api_models::enums::AuthenticationType,
api_models::enums::WalletIssuer,
api_models::enums::Connector,
api_models::enums::PaymentMethod,
api_models::enums::SupportedWallets,
api_models::enums::PaymentMethodIssuerCode,
api_models::enums::MandateStatus,
api_models::enums::PaymentExperience,
api_models::enums::BankNames,
api_models::admin::PaymentConnectorCreate,
api_models::admin::PaymentMethodsEnabled,
api_models::payments::AddressDetails,
api_models::payments::Address,
api_models::payments::BankRedirectData,
api_models::payments::BankRedirectBilling,
api_models::payments::OrderDetails,
api_models::payments::NextActionType,
api_models::payments::Metadata,
@ -172,6 +176,9 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::payments::ApplePaySessionResponse,
api_models::payments::ApplePayPaymentRequest,
api_models::payments::AmountInfo,
api_models::payments::GpayWalletData,
api_models::payments::PayPalWalletData,
api_models::payments::PaypalRedirection,
api_models::payments::GpayMerchantInfo,
api_models::payments::GpayAllowedPaymentMethods,
api_models::payments::GpayAllowedMethodsParameters,
@ -182,6 +189,12 @@ Never share your secret api keys. Keep them guarded and secure.
api_models::payments::KlarnaSessionTokenResponse,
api_models::payments::PaypalSessionTokenResponse,
api_models::payments::ApplepaySessionTokenResponse,
api_models::payments::GpayTokenizationData,
api_models::payments::GpayPaymentMethodInfo,
api_models::payments::ApplePayWalletData,
api_models::payments::ApplepayPaymentData,
api_models::payments::ApplepayHeader,
api_models::payments::ApplepayPaymentMethod,
api_models::payments::PaymentsCancelRequest,
api_models::payments::PaymentListConstraints,
api_models::payments::PaymentListResponse,