mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-02 21:07:58 +08:00
fix(connector): [braintree] add 3ds redirection error mapping and metadata validation (#2552)
This commit is contained in:
@ -1496,10 +1496,45 @@ impl services::ConnectorRedirectResponse for Braintree {
|
|||||||
fn get_flow_type(
|
fn get_flow_type(
|
||||||
&self,
|
&self,
|
||||||
_query_params: &str,
|
_query_params: &str,
|
||||||
_json_payload: Option<serde_json::Value>,
|
json_payload: Option<serde_json::Value>,
|
||||||
_action: services::PaymentAction,
|
action: services::PaymentAction,
|
||||||
) -> CustomResult<payments::CallConnectorAction, errors::ConnectorError> {
|
) -> CustomResult<payments::CallConnectorAction, errors::ConnectorError> {
|
||||||
Ok(payments::CallConnectorAction::Trigger)
|
match action {
|
||||||
|
services::PaymentAction::PSync => match json_payload {
|
||||||
|
Some(payload) => {
|
||||||
|
let redirection_response:braintree_graphql_transformers::BraintreeRedirectionResponse = serde_json::from_value(payload)
|
||||||
|
.into_report()
|
||||||
|
.change_context(
|
||||||
|
errors::ConnectorError::MissingConnectorRedirectionPayload {
|
||||||
|
field_name: "redirection_response",
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
let braintree_payload =
|
||||||
|
serde_json::from_str::<
|
||||||
|
braintree_graphql_transformers::BraintreeThreeDsErrorResponse,
|
||||||
|
>(&redirection_response.authentication_response);
|
||||||
|
let (error_code, error_message) = match braintree_payload {
|
||||||
|
Ok(braintree_response_payload) => (
|
||||||
|
braintree_response_payload.code,
|
||||||
|
braintree_response_payload.message,
|
||||||
|
),
|
||||||
|
Err(_) => (
|
||||||
|
consts::NO_ERROR_CODE.to_string(),
|
||||||
|
redirection_response.authentication_response,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
Ok(payments::CallConnectorAction::StatusUpdate {
|
||||||
|
status: enums::AttemptStatus::AuthenticationFailed,
|
||||||
|
error_code: Some(error_code),
|
||||||
|
error_message: Some(error_message),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
None => Ok(payments::CallConnectorAction::Avoid),
|
||||||
|
},
|
||||||
|
services::PaymentAction::CompleteAuthorize => {
|
||||||
|
Ok(payments::CallConnectorAction::Trigger)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use common_utils::pii;
|
||||||
use error_stack::{IntoReport, ResultExt};
|
use error_stack::{IntoReport, ResultExt};
|
||||||
use masking::{ExposeInterface, Secret};
|
use masking::{ExposeInterface, Secret};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -77,8 +78,19 @@ pub enum BraintreePaymentsRequest {
|
|||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct BraintreeMeta {
|
pub struct BraintreeMeta {
|
||||||
merchant_account_id: Option<Secret<String>>,
|
merchant_account_id: Secret<String>,
|
||||||
merchant_config_currency: Option<types::storage::enums::Currency>,
|
merchant_config_currency: types::storage::enums::Currency,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&Option<pii::SecretSerdeValue>> for BraintreeMeta {
|
||||||
|
type Error = error_stack::Report<errors::ConnectorError>;
|
||||||
|
fn try_from(meta_data: &Option<pii::SecretSerdeValue>) -> Result<Self, Self::Error> {
|
||||||
|
let metadata: Self = utils::to_connector_meta_from_secret::<Self>(meta_data.clone())
|
||||||
|
.change_context(errors::ConnectorError::InvalidConfig {
|
||||||
|
field_name: "merchant connector account metadata",
|
||||||
|
})?;
|
||||||
|
Ok(metadata)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
@ -96,10 +108,13 @@ impl TryFrom<&BraintreeRouterData<&types::PaymentsAuthorizeRouterData>>
|
|||||||
item: &BraintreeRouterData<&types::PaymentsAuthorizeRouterData>,
|
item: &BraintreeRouterData<&types::PaymentsAuthorizeRouterData>,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
let metadata: BraintreeMeta =
|
let metadata: BraintreeMeta =
|
||||||
utils::to_connector_meta_from_secret(item.router_data.connector_meta_data.clone())?;
|
utils::to_connector_meta_from_secret(item.router_data.connector_meta_data.clone())
|
||||||
|
.change_context(errors::ConnectorError::InvalidConfig {
|
||||||
|
field_name: "merchant connector account metadata",
|
||||||
|
})?;
|
||||||
utils::validate_currency(
|
utils::validate_currency(
|
||||||
item.router_data.request.currency,
|
item.router_data.request.currency,
|
||||||
metadata.merchant_config_currency,
|
Some(metadata.merchant_config_currency),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
match item.router_data.request.payment_method_data.clone() {
|
match item.router_data.request.payment_method_data.clone() {
|
||||||
@ -140,26 +155,28 @@ impl TryFrom<&BraintreeRouterData<&types::PaymentsCompleteAuthorizeRouterData>>
|
|||||||
fn try_from(
|
fn try_from(
|
||||||
item: &BraintreeRouterData<&types::PaymentsCompleteAuthorizeRouterData>,
|
item: &BraintreeRouterData<&types::PaymentsCompleteAuthorizeRouterData>,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
match item.router_data.request.payment_method_data.clone() {
|
match item.router_data.payment_method {
|
||||||
Some(api::PaymentMethodData::Card(_)) => {
|
api_models::enums::PaymentMethod::Card => {
|
||||||
Ok(Self::Card(CardPaymentRequest::try_from(item)?))
|
Ok(Self::Card(CardPaymentRequest::try_from(item)?))
|
||||||
}
|
}
|
||||||
Some(api_models::payments::PaymentMethodData::CardRedirect(_))
|
api_models::enums::PaymentMethod::CardRedirect
|
||||||
| Some(api_models::payments::PaymentMethodData::Wallet(_))
|
| api_models::enums::PaymentMethod::PayLater
|
||||||
| Some(api_models::payments::PaymentMethodData::PayLater(_))
|
| api_models::enums::PaymentMethod::Wallet
|
||||||
| Some(api_models::payments::PaymentMethodData::BankRedirect(_))
|
| api_models::enums::PaymentMethod::BankRedirect
|
||||||
| Some(api_models::payments::PaymentMethodData::BankDebit(_))
|
| api_models::enums::PaymentMethod::BankTransfer
|
||||||
| Some(api_models::payments::PaymentMethodData::BankTransfer(_))
|
| api_models::enums::PaymentMethod::Crypto
|
||||||
| Some(api_models::payments::PaymentMethodData::Crypto(_))
|
| api_models::enums::PaymentMethod::BankDebit
|
||||||
| Some(api_models::payments::PaymentMethodData::MandatePayment)
|
| api_models::enums::PaymentMethod::Reward
|
||||||
| Some(api_models::payments::PaymentMethodData::Reward)
|
| api_models::enums::PaymentMethod::Upi
|
||||||
| Some(api_models::payments::PaymentMethodData::Upi(_))
|
| api_models::enums::PaymentMethod::Voucher
|
||||||
| Some(api_models::payments::PaymentMethodData::Voucher(_))
|
| api_models::enums::PaymentMethod::GiftCard => {
|
||||||
| Some(api_models::payments::PaymentMethodData::GiftCard(_))
|
Err(errors::ConnectorError::NotImplemented(
|
||||||
| None => Err(errors::ConnectorError::NotImplemented(
|
utils::get_unimplemented_payment_method_error_message(
|
||||||
utils::get_unimplemented_payment_method_error_message("complete authorize flow"),
|
"complete authorize flow",
|
||||||
)
|
),
|
||||||
.into()),
|
)
|
||||||
|
.into())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -249,7 +266,6 @@ impl<F>
|
|||||||
*client_token_data,
|
*client_token_data,
|
||||||
item.data.get_payment_method_token()?,
|
item.data.get_payment_method_token()?,
|
||||||
item.data.request.payment_method_data.clone(),
|
item.data.request.payment_method_data.clone(),
|
||||||
item.data.request.amount,
|
|
||||||
)?),
|
)?),
|
||||||
mandate_reference: None,
|
mandate_reference: None,
|
||||||
connector_metadata: None,
|
connector_metadata: None,
|
||||||
@ -428,7 +444,6 @@ impl<F>
|
|||||||
*client_token_data,
|
*client_token_data,
|
||||||
item.data.get_payment_method_token()?,
|
item.data.get_payment_method_token()?,
|
||||||
item.data.request.payment_method_data.clone(),
|
item.data.request.payment_method_data.clone(),
|
||||||
item.data.request.amount,
|
|
||||||
)?),
|
)?),
|
||||||
mandate_reference: None,
|
mandate_reference: None,
|
||||||
connector_metadata: None,
|
connector_metadata: None,
|
||||||
@ -586,11 +601,14 @@ impl<F> TryFrom<BraintreeRouterData<&types::RefundsRouterData<F>>> for Braintree
|
|||||||
item: BraintreeRouterData<&types::RefundsRouterData<F>>,
|
item: BraintreeRouterData<&types::RefundsRouterData<F>>,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
let metadata: BraintreeMeta =
|
let metadata: BraintreeMeta =
|
||||||
utils::to_connector_meta_from_secret(item.router_data.connector_meta_data.clone())?;
|
utils::to_connector_meta_from_secret(item.router_data.connector_meta_data.clone())
|
||||||
|
.change_context(errors::ConnectorError::InvalidConfig {
|
||||||
|
field_name: "merchant connector account metadata",
|
||||||
|
})?;
|
||||||
|
|
||||||
utils::validate_currency(
|
utils::validate_currency(
|
||||||
item.router_data.request.currency,
|
item.router_data.request.currency,
|
||||||
metadata.merchant_config_currency,
|
Some(metadata.merchant_config_currency),
|
||||||
)?;
|
)?;
|
||||||
let query = REFUND_TRANSACTION_MUTATION.to_string();
|
let query = REFUND_TRANSACTION_MUTATION.to_string();
|
||||||
let variables = BraintreeRefundVariables {
|
let variables = BraintreeRefundVariables {
|
||||||
@ -598,11 +616,7 @@ impl<F> TryFrom<BraintreeRouterData<&types::RefundsRouterData<F>>> for Braintree
|
|||||||
transaction_id: item.router_data.request.connector_transaction_id.clone(),
|
transaction_id: item.router_data.request.connector_transaction_id.clone(),
|
||||||
refund: RefundInputData {
|
refund: RefundInputData {
|
||||||
amount: item.amount,
|
amount: item.amount,
|
||||||
merchant_account_id: metadata.merchant_account_id.ok_or(
|
merchant_account_id: metadata.merchant_account_id,
|
||||||
errors::ConnectorError::MissingRequiredField {
|
|
||||||
field_name: "merchant_account_id",
|
|
||||||
},
|
|
||||||
)?,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -695,9 +709,16 @@ pub struct BraintreeRSyncRequest {
|
|||||||
impl TryFrom<&types::RefundSyncRouterData> for BraintreeRSyncRequest {
|
impl TryFrom<&types::RefundSyncRouterData> for BraintreeRSyncRequest {
|
||||||
type Error = error_stack::Report<errors::ConnectorError>;
|
type Error = error_stack::Report<errors::ConnectorError>;
|
||||||
fn try_from(item: &types::RefundSyncRouterData) -> Result<Self, Self::Error> {
|
fn try_from(item: &types::RefundSyncRouterData) -> Result<Self, Self::Error> {
|
||||||
let metadata: BraintreeMeta =
|
let metadata: BraintreeMeta = utils::to_connector_meta_from_secret(
|
||||||
utils::to_connector_meta_from_secret(item.connector_meta_data.clone())?;
|
item.connector_meta_data.clone(),
|
||||||
utils::validate_currency(item.request.currency, metadata.merchant_config_currency)?;
|
)
|
||||||
|
.change_context(errors::ConnectorError::InvalidConfig {
|
||||||
|
field_name: "merchant connector account metadata",
|
||||||
|
})?;
|
||||||
|
utils::validate_currency(
|
||||||
|
item.request.currency,
|
||||||
|
Some(metadata.merchant_config_currency),
|
||||||
|
)?;
|
||||||
let refund_id = item.request.get_connector_refund_id()?;
|
let refund_id = item.request.get_connector_refund_id()?;
|
||||||
let query = format!("query {{ search {{ refunds(input: {{ id: {{is: \"{}\"}} }}, first: 1) {{ edges {{ node {{ id status createdAt amount {{ value currencyCode }} orderId }} }} }} }} }}",refund_id);
|
let query = format!("query {{ search {{ refunds(input: {{ id: {{is: \"{}\"}} }}, first: 1) {{ edges {{ node {{ id status createdAt amount {{ value currencyCode }} orderId }} }} }} }} }}",refund_id);
|
||||||
|
|
||||||
@ -1250,6 +1271,13 @@ pub struct BraintreeThreeDsResponse {
|
|||||||
pub liability_shift_possible: bool,
|
pub liability_shift_possible: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct BraintreeThreeDsErrorResponse {
|
||||||
|
pub code: String,
|
||||||
|
pub message: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct BraintreeRedirectionResponse {
|
pub struct BraintreeRedirectionResponse {
|
||||||
pub authentication_response: String,
|
pub authentication_response: String,
|
||||||
@ -1263,11 +1291,7 @@ impl TryFrom<BraintreeMeta> for BraintreeClientTokenRequest {
|
|||||||
variables: VariableClientTokenInput {
|
variables: VariableClientTokenInput {
|
||||||
input: InputClientTokenData {
|
input: InputClientTokenData {
|
||||||
client_token: ClientTokenInput {
|
client_token: ClientTokenInput {
|
||||||
merchant_account_id: metadata.merchant_account_id.ok_or(
|
merchant_account_id: metadata.merchant_account_id,
|
||||||
errors::ConnectorError::MissingRequiredField {
|
|
||||||
field_name: "merchant_account_id",
|
|
||||||
},
|
|
||||||
)?,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1304,11 +1328,7 @@ impl
|
|||||||
},
|
},
|
||||||
transaction: TransactionBody {
|
transaction: TransactionBody {
|
||||||
amount: item.amount.to_owned(),
|
amount: item.amount.to_owned(),
|
||||||
merchant_account_id: metadata.merchant_account_id.ok_or(
|
merchant_account_id: metadata.merchant_account_id,
|
||||||
errors::ConnectorError::MissingRequiredField {
|
|
||||||
field_name: "merchant_account_id",
|
|
||||||
},
|
|
||||||
)?,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1324,10 +1344,13 @@ impl TryFrom<&BraintreeRouterData<&types::PaymentsCompleteAuthorizeRouterData>>
|
|||||||
item: &BraintreeRouterData<&types::PaymentsCompleteAuthorizeRouterData>,
|
item: &BraintreeRouterData<&types::PaymentsCompleteAuthorizeRouterData>,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> Result<Self, Self::Error> {
|
||||||
let metadata: BraintreeMeta =
|
let metadata: BraintreeMeta =
|
||||||
utils::to_connector_meta_from_secret(item.router_data.connector_meta_data.clone())?;
|
utils::to_connector_meta_from_secret(item.router_data.connector_meta_data.clone())
|
||||||
|
.change_context(errors::ConnectorError::InvalidConfig {
|
||||||
|
field_name: "merchant connector account metadata",
|
||||||
|
})?;
|
||||||
utils::validate_currency(
|
utils::validate_currency(
|
||||||
item.router_data.request.currency,
|
item.router_data.request.currency,
|
||||||
metadata.merchant_config_currency,
|
Some(metadata.merchant_config_currency),
|
||||||
)?;
|
)?;
|
||||||
let payload_data =
|
let payload_data =
|
||||||
utils::PaymentsCompleteAuthorizeRequestData::get_redirect_response_payload(
|
utils::PaymentsCompleteAuthorizeRequestData::get_redirect_response_payload(
|
||||||
@ -1360,11 +1383,7 @@ impl TryFrom<&BraintreeRouterData<&types::PaymentsCompleteAuthorizeRouterData>>
|
|||||||
payment_method_id: three_ds_data.nonce,
|
payment_method_id: three_ds_data.nonce,
|
||||||
transaction: TransactionBody {
|
transaction: TransactionBody {
|
||||||
amount: item.amount.to_owned(),
|
amount: item.amount.to_owned(),
|
||||||
merchant_account_id: metadata.merchant_account_id.ok_or(
|
merchant_account_id: metadata.merchant_account_id,
|
||||||
errors::ConnectorError::MissingRequiredField {
|
|
||||||
field_name: "merchant_account_id",
|
|
||||||
},
|
|
||||||
)?,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1376,7 +1395,6 @@ fn get_braintree_redirect_form(
|
|||||||
client_token_data: ClientTokenResponse,
|
client_token_data: ClientTokenResponse,
|
||||||
payment_method_token: types::PaymentMethodToken,
|
payment_method_token: types::PaymentMethodToken,
|
||||||
card_details: api_models::payments::PaymentMethodData,
|
card_details: api_models::payments::PaymentMethodData,
|
||||||
amount: i64,
|
|
||||||
) -> Result<services::RedirectForm, error_stack::Report<errors::ConnectorError>> {
|
) -> Result<services::RedirectForm, error_stack::Report<errors::ConnectorError>> {
|
||||||
Ok(services::RedirectForm::Braintree {
|
Ok(services::RedirectForm::Braintree {
|
||||||
client_token: client_token_data
|
client_token: client_token_data
|
||||||
@ -1409,7 +1427,6 @@ fn get_braintree_redirect_form(
|
|||||||
errors::ConnectorError::NotImplemented("given payment method".to_owned()),
|
errors::ConnectorError::NotImplemented("given payment method".to_owned()),
|
||||||
)?,
|
)?,
|
||||||
},
|
},
|
||||||
amount,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,6 +3,7 @@ use common_utils::{
|
|||||||
crypto::{generate_cryptographically_secure_random_string, OptionalSecretValue},
|
crypto::{generate_cryptographically_secure_random_string, OptionalSecretValue},
|
||||||
date_time,
|
date_time,
|
||||||
ext_traits::{AsyncExt, ConfigExt, Encode, ValueExt},
|
ext_traits::{AsyncExt, ConfigExt, Encode, ValueExt},
|
||||||
|
pii,
|
||||||
};
|
};
|
||||||
use data_models::MerchantStorageScheme;
|
use data_models::MerchantStorageScheme;
|
||||||
use error_stack::{report, FutureExt, ResultExt};
|
use error_stack::{report, FutureExt, ResultExt};
|
||||||
@ -656,15 +657,26 @@ pub async fn create_payment_connector(
|
|||||||
expected_format: "auth_type and api_key".to_string(),
|
expected_format: "auth_type and api_key".to_string(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
validate_auth_type(req.connector_name, &auth).map_err(|err| {
|
validate_auth_and_metadata_type(req.connector_name, &auth, &req.metadata).map_err(|err| {
|
||||||
if err.current_context() == &errors::ConnectorError::InvalidConnectorName {
|
match *err.current_context() {
|
||||||
err.change_context(errors::ApiErrorResponse::InvalidRequestData {
|
errors::ConnectorError::InvalidConnectorName => {
|
||||||
message: "The connector name is invalid".to_string(),
|
err.change_context(errors::ApiErrorResponse::InvalidRequestData {
|
||||||
})
|
message: "The connector name is invalid".to_string(),
|
||||||
} else {
|
})
|
||||||
err.change_context(errors::ApiErrorResponse::InvalidRequestData {
|
}
|
||||||
message: "The auth type is invalid for the connector".to_string(),
|
errors::ConnectorError::InvalidConfig { field_name } => {
|
||||||
})
|
err.change_context(errors::ApiErrorResponse::InvalidRequestData {
|
||||||
|
message: format!("The {} is invalid", field_name),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
errors::ConnectorError::FailedToObtainAuthType => {
|
||||||
|
err.change_context(errors::ApiErrorResponse::InvalidRequestData {
|
||||||
|
message: "The auth type is invalid for the connector".to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => err.change_context(errors::ApiErrorResponse::InvalidRequestData {
|
||||||
|
message: "The request body is invalid".to_string(),
|
||||||
|
}),
|
||||||
}
|
}
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
@ -1250,9 +1262,10 @@ pub async fn update_business_profile(
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn validate_auth_type(
|
pub(crate) fn validate_auth_and_metadata_type(
|
||||||
connector_name: api_models::enums::Connector,
|
connector_name: api_models::enums::Connector,
|
||||||
val: &types::ConnectorAuthType,
|
val: &types::ConnectorAuthType,
|
||||||
|
connector_meta_data: &Option<pii::SecretSerdeValue>,
|
||||||
) -> Result<(), error_stack::Report<errors::ConnectorError>> {
|
) -> Result<(), error_stack::Report<errors::ConnectorError>> {
|
||||||
use crate::connector::*;
|
use crate::connector::*;
|
||||||
|
|
||||||
@ -1302,6 +1315,9 @@ pub(crate) fn validate_auth_type(
|
|||||||
}
|
}
|
||||||
api_enums::Connector::Braintree => {
|
api_enums::Connector::Braintree => {
|
||||||
braintree::transformers::BraintreeAuthType::try_from(val)?;
|
braintree::transformers::BraintreeAuthType::try_from(val)?;
|
||||||
|
braintree::braintree_graphql_transformers::BraintreeMeta::try_from(
|
||||||
|
connector_meta_data,
|
||||||
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
api_enums::Connector::Cashtocode => {
|
api_enums::Connector::Cashtocode => {
|
||||||
|
|||||||
@ -178,6 +178,8 @@ pub enum ConnectorError {
|
|||||||
message: String,
|
message: String,
|
||||||
connector: &'static str,
|
connector: &'static str,
|
||||||
},
|
},
|
||||||
|
#[error("Invalid Configuration")]
|
||||||
|
InvalidConfig { field_name: &'static str },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
|||||||
@ -703,7 +703,6 @@ pub enum RedirectForm {
|
|||||||
client_token: String,
|
client_token: String,
|
||||||
card_token: String,
|
card_token: String,
|
||||||
bin: String,
|
bin: String,
|
||||||
amount: i64,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1262,7 +1261,6 @@ pub fn build_redirection_form(
|
|||||||
client_token,
|
client_token,
|
||||||
card_token,
|
card_token,
|
||||||
bin,
|
bin,
|
||||||
amount,
|
|
||||||
} => {
|
} => {
|
||||||
maud::html! {
|
maud::html! {
|
||||||
(maud::DOCTYPE)
|
(maud::DOCTYPE)
|
||||||
@ -1270,7 +1268,7 @@ pub fn build_redirection_form(
|
|||||||
head {
|
head {
|
||||||
meta name="viewport" content="width=device-width, initial-scale=1";
|
meta name="viewport" content="width=device-width, initial-scale=1";
|
||||||
(PreEscaped(r#"<script src="https://js.braintreegateway.com/web/3.97.1/js/three-d-secure.js"></script>"#))
|
(PreEscaped(r#"<script src="https://js.braintreegateway.com/web/3.97.1/js/three-d-secure.js"></script>"#))
|
||||||
(PreEscaped(r#"<script src="https://js.braintreegateway.com/web/3.97.1/js/hosted-fields.js"></script>"#))
|
// (PreEscaped(r#"<script src="https://js.braintreegateway.com/web/3.97.1/js/hosted-fields.js"></script>"#))
|
||||||
|
|
||||||
}
|
}
|
||||||
body style="background-color: #ffffff; padding: 20px; font-family: Arial, Helvetica, Sans-Serif;" {
|
body style="background-color: #ffffff; padding: 20px; font-family: Arial, Helvetica, Sans-Serif;" {
|
||||||
@ -1318,15 +1316,26 @@ pub fn build_redirection_form(
|
|||||||
}}
|
}}
|
||||||
}},
|
}},
|
||||||
onLookupComplete: function(data, next) {{
|
onLookupComplete: function(data, next) {{
|
||||||
console.log(\"onLookup Complete\", data);
|
// console.log(\"onLookup Complete\", data);
|
||||||
next();
|
next();
|
||||||
}}
|
}}
|
||||||
}},
|
}},
|
||||||
function(err, payload) {{
|
function(err, payload) {{
|
||||||
if(err) {{
|
if(err) {{
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
var f = document.createElement('form');
|
||||||
|
f.action=window.location.pathname.replace(/payments\\/redirect\\/(\\w+)\\/(\\w+)\\/\\w+/, \"payments/$1/$2/redirect/response/braintree\");
|
||||||
|
var i = document.createElement('input');
|
||||||
|
i.type = 'hidden';
|
||||||
|
f.method='POST';
|
||||||
|
i.name = 'authentication_response';
|
||||||
|
i.value = JSON.stringify(err);
|
||||||
|
f.appendChild(i);
|
||||||
|
f.body = JSON.stringify(err);
|
||||||
|
document.body.appendChild(f);
|
||||||
|
f.submit();
|
||||||
}} else {{
|
}} else {{
|
||||||
console.log(payload);
|
// console.log(payload);
|
||||||
var f = document.createElement('form');
|
var f = document.createElement('form');
|
||||||
f.action=window.location.pathname.replace(/payments\\/redirect\\/(\\w+)\\/(\\w+)\\/\\w+/, \"payments/$1/$2/redirect/complete/braintree\");
|
f.action=window.location.pathname.replace(/payments\\/redirect\\/(\\w+)\\/(\\w+)\\/\\w+/, \"payments/$1/$2/redirect/complete/braintree\");
|
||||||
var i = document.createElement('input');
|
var i = document.createElement('input');
|
||||||
|
|||||||
Reference in New Issue
Block a user