mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 01:27:31 +08:00
feat(connector): add payment create, sync, capture, refund, void, rsync support for globalpay (#322)
This commit is contained in:
15
Cargo.lock
generated
15
Cargo.lock
generated
@ -378,6 +378,19 @@ dependencies = [
|
||||
"futures-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-compression"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a"
|
||||
dependencies = [
|
||||
"flate2",
|
||||
"futures-core",
|
||||
"memchr",
|
||||
"pin-project-lite",
|
||||
"tokio",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-stream"
|
||||
version = "0.3.3"
|
||||
@ -3044,6 +3057,7 @@ version = "0.11.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c"
|
||||
dependencies = [
|
||||
"async-compression",
|
||||
"base64 0.13.1",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
@ -3067,6 +3081,7 @@ dependencies = [
|
||||
"serde_urlencoded",
|
||||
"tokio",
|
||||
"tokio-native-tls",
|
||||
"tokio-util 0.7.4",
|
||||
"tower-service",
|
||||
"url",
|
||||
"wasm-bindgen",
|
||||
|
||||
@ -37,8 +37,8 @@ locker_decryption_key1 = ""
|
||||
locker_decryption_key2 = ""
|
||||
|
||||
[connectors.supported]
|
||||
wallets = ["klarna", "braintree", "applepay"]
|
||||
cards = ["stripe", "adyen", "authorizedotnet", "checkout", "braintree", "aci", "shift4", "cybersource", "worldpay"]
|
||||
wallets = ["klarna","braintree","applepay"]
|
||||
cards = ["stripe","adyen","authorizedotnet","checkout","braintree","aci","shift4","cybersource", "worldpay", "globalpay"]
|
||||
|
||||
[refund]
|
||||
max_attempts = 10
|
||||
@ -80,6 +80,9 @@ base_url = "https://api.shift4.com/"
|
||||
[connectors.worldpay]
|
||||
base_url = "http://localhost:9090/"
|
||||
|
||||
[connectors.globalpay]
|
||||
base_url = "https://apis.sandbox.globalpay.com/ucp/"
|
||||
|
||||
[scheduler]
|
||||
stream = "SCHEDULER_STREAM"
|
||||
consumer_group = "SCHEDULER_GROUP"
|
||||
|
||||
@ -140,10 +140,13 @@ base_url = "https://api.shift4.com/"
|
||||
[connectors.worldpay]
|
||||
base_url = "https://try.access.worldpay.com/"
|
||||
|
||||
[connectors.globalpay]
|
||||
base_url = "https://apis.sandbox.globalpay.com/ucp/"
|
||||
|
||||
# This data is used to call respective connectors for wallets and cards
|
||||
[connectors.supported]
|
||||
wallets = ["klarna", "braintree", "applepay"]
|
||||
cards = ["stripe", "adyen", "authorizedotnet", "checkout", "braintree", "cybersource"]
|
||||
cards = ["stripe", "adyen", "authorizedotnet", "checkout", "braintree", "cybersource", "shift4", "worldpay", "globalpay"]
|
||||
|
||||
# Scheduler settings provides a point to modify the behaviour of scheduler flow.
|
||||
# It defines the the streams/queues name and configuration as well as event selection variables
|
||||
|
||||
@ -89,6 +89,9 @@ base_url = "https://api.shift4.com/"
|
||||
[connectors.worldpay]
|
||||
base_url = "https://try.access.worldpay.com/"
|
||||
|
||||
[connectors.globalpay]
|
||||
base_url = "https://apis.sandbox.globalpay.com/ucp/"
|
||||
|
||||
[connectors.supported]
|
||||
wallets = ["klarna", "braintree", "applepay"]
|
||||
cards = ["stripe", "adyen", "authorizedotnet", "checkout", "braintree", "shift4", "cybersource", "worldpay"]
|
||||
cards = ["stripe", "adyen", "authorizedotnet", "checkout", "braintree", "shift4", "cybersource", "worldpay", "globalpay"]
|
||||
|
||||
@ -53,7 +53,10 @@ impl ConnectorCommon for {{project-name | downcase | pascal_case}} {
|
||||
}
|
||||
|
||||
fn get_auth_header(&self,_auth_type:&types::ConnectorAuthType)-> CustomResult<Vec<(String,String)>,errors::ConnectorError> {
|
||||
todo!()
|
||||
let auth: {{project-name | downcase | pascal_case}}::{{project-name | downcase | pascal_case}}AuthType = auth_type
|
||||
.try_into()
|
||||
.change_context(errors::ConnectorError::FailedToObtainAuthType)?;
|
||||
Ok(vec![(headers::AUTHORIZATION.to_string(), auth.api_key)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,14 +89,14 @@ impl
|
||||
{
|
||||
fn get_headers(
|
||||
&self,
|
||||
_req: &types::PaymentsSyncRouterData,
|
||||
_connectors: &settings::Connectors,
|
||||
req: &types::PaymentsSyncRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
|
||||
todo!()
|
||||
self.build_headers(req, connectors)
|
||||
}
|
||||
|
||||
fn get_content_type(&self) -> &'static str {
|
||||
todo!()
|
||||
self.common_get_content_type()
|
||||
}
|
||||
|
||||
fn get_url(
|
||||
@ -109,14 +112,20 @@ impl
|
||||
_req: &types::PaymentsSyncRouterData,
|
||||
_connectors: &settings::Connectors,
|
||||
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
|
||||
todo!()
|
||||
Ok(Some(
|
||||
services::RequestBuilder::new()
|
||||
.method(services::Method::Get)
|
||||
.url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
|
||||
.headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
|
||||
.build(),
|
||||
))
|
||||
}
|
||||
|
||||
fn get_error_response(
|
||||
&self,
|
||||
_res: Bytes,
|
||||
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
||||
todo!()
|
||||
self.build_error_response(res)
|
||||
}
|
||||
|
||||
fn handle_response(
|
||||
@ -124,7 +133,17 @@ impl
|
||||
_data: &types::PaymentsSyncRouterData,
|
||||
_res: Response,
|
||||
) -> CustomResult<types::PaymentsSyncRouterData, errors::ConnectorError> {
|
||||
todo!()
|
||||
logger::debug!(payment_sync_response=?res);
|
||||
let response: {{project-name | downcase}}:: {{project-name | downcase | pascal_case}}PaymentsResponse = res
|
||||
.response
|
||||
.parse_struct("{{project-name | downcase}} PaymentsResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
types::RouterData::try_from(types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
})
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,13 +158,21 @@ impl
|
||||
{
|
||||
fn get_headers(
|
||||
&self,
|
||||
_req: &types::PaymentsCaptureRouterData,
|
||||
_connectors: &settings::Connectors,
|
||||
req: &types::PaymentsCaptureRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
|
||||
todo!()
|
||||
self.build_headers(req, connectors)
|
||||
}
|
||||
|
||||
fn get_content_type(&self) -> &'static str {
|
||||
self.common_get_content_type()
|
||||
}
|
||||
|
||||
fn get_url(
|
||||
&self,
|
||||
_req: &types::PaymentsCaptureRouterData,
|
||||
_connectors: &settings::Connectors,
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@ -161,7 +188,15 @@ impl
|
||||
_req: &types::PaymentsCaptureRouterData,
|
||||
_connectors: &settings::Connectors,
|
||||
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
|
||||
todo!()
|
||||
Ok(Some(
|
||||
services::RequestBuilder::new()
|
||||
.method(services::Method::Post)
|
||||
.url(&types::PaymentsCaptureType::get_url(self, req, connectors)?)
|
||||
.headers(types::PaymentsCaptureType::get_headers(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.build(),
|
||||
))
|
||||
}
|
||||
|
||||
fn handle_response(
|
||||
@ -169,22 +204,25 @@ impl
|
||||
_data: &types::PaymentsCaptureRouterData,
|
||||
_res: Response,
|
||||
) -> CustomResult<types::PaymentsCaptureRouterData, errors::ConnectorError> {
|
||||
todo!()
|
||||
let response: {{project-name | downcase }}::{{project-name | downcase | pascal_case}}PaymentsResponse = res
|
||||
.response
|
||||
.parse_struct("{{project-name | downcase | pascal_case}} PaymentsResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
logger::debug!({{project-name | downcase}}payments_create_response=?response);
|
||||
types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
}
|
||||
|
||||
fn get_url(
|
||||
&self,
|
||||
_req: &types::PaymentsCaptureRouterData,
|
||||
_connectors: &settings::Connectors,
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
todo!()
|
||||
.try_into()
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
}
|
||||
|
||||
fn get_error_response(
|
||||
&self,
|
||||
_res: Bytes,
|
||||
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
||||
todo!()
|
||||
self.build_error_response(res)
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,12 +246,12 @@ impl
|
||||
types::PaymentsAuthorizeData,
|
||||
types::PaymentsResponseData,
|
||||
> for {{project-name | downcase | pascal_case}} {
|
||||
fn get_headers(&self, _req: &types::PaymentsAuthorizeRouterData,_connectors: &settings::Connectors,) -> CustomResult<Vec<(String, String)>,errors::ConnectorError> {
|
||||
todo!()
|
||||
fn get_headers(&self, req: &types::PaymentsAuthorizeRouterData, connectors: &settings::Connectors,) -> CustomResult<Vec<(String, String)>,errors::ConnectorError> {
|
||||
self.build_headers(req, connectors)
|
||||
}
|
||||
|
||||
fn get_content_type(&self) -> &'static str {
|
||||
todo!()
|
||||
self.common_get_content_type()
|
||||
}
|
||||
|
||||
fn get_url(&self, _req: &types::PaymentsAuthorizeRouterData, _connectors: &settings::Connectors,) -> CustomResult<String,errors::ConnectorError> {
|
||||
@ -226,6 +264,25 @@ impl
|
||||
Ok(Some({{project-name | downcase}}_req))
|
||||
}
|
||||
|
||||
fn build_request(
|
||||
&self,
|
||||
req: &types::PaymentsAuthorizeRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
|
||||
Ok(Some(
|
||||
services::RequestBuilder::new()
|
||||
.method(services::Method::Post)
|
||||
.url(&types::PaymentsAuthorizeType::get_url(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.headers(types::PaymentsAuthorizeType::get_headers(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
|
||||
.build(),
|
||||
))
|
||||
}
|
||||
|
||||
fn handle_response(
|
||||
&self,
|
||||
data: &types::PaymentsAuthorizeRouterData,
|
||||
@ -242,8 +299,8 @@ impl
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
}
|
||||
|
||||
fn get_error_response(&self, _res: Bytes) -> CustomResult<ErrorResponse,errors::ConnectorError> {
|
||||
todo!()
|
||||
fn get_error_response(&self, res: Bytes) -> CustomResult<ErrorResponse,errors::ConnectorError> {
|
||||
self.build_error_response(res)
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,12 +314,12 @@ impl
|
||||
types::RefundsData,
|
||||
types::RefundsResponseData,
|
||||
> for {{project-name | downcase | pascal_case}} {
|
||||
fn get_headers(&self, _req: &types::RefundsRouterData<api::Execute>,_connectors: &settings::Connectors,) -> CustomResult<Vec<(String,String)>,errors::ConnectorError> {
|
||||
todo!()
|
||||
fn get_headers(&self, req: &types::RefundsRouterData<api::Execute>, connectors: &settings::Connectors,) -> CustomResult<Vec<(String,String)>,errors::ConnectorError> {
|
||||
self.build_headers(req, connectors)
|
||||
}
|
||||
|
||||
fn get_content_type(&self) -> &'static str {
|
||||
todo!()
|
||||
self.common_get_content_type()
|
||||
}
|
||||
|
||||
fn get_url(&self, _req: &types::RefundsRouterData<api::Execute>, _connectors: &settings::Connectors,) -> CustomResult<String,errors::ConnectorError> {
|
||||
@ -300,25 +357,40 @@ impl
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
}
|
||||
|
||||
fn get_error_response(&self, _res: Bytes) -> CustomResult<ErrorResponse,errors::ConnectorError> {
|
||||
todo!()
|
||||
fn get_error_response(&self, res: Bytes) -> CustomResult<ErrorResponse,errors::ConnectorError> {
|
||||
self.build_error_response(res)
|
||||
}
|
||||
}
|
||||
|
||||
impl
|
||||
ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponseData> for {{project-name | downcase | pascal_case}} {
|
||||
fn get_headers(&self, _req: &types::RefundSyncRouterData,_connectors: &settings::Connectors,) -> CustomResult<Vec<(String, String)>,errors::ConnectorError> {
|
||||
todo!()
|
||||
fn get_headers(&self, req: &types::RefundSyncRouterData,connectors: &settings::Connectors,) -> CustomResult<Vec<(String, String)>,errors::ConnectorError> {
|
||||
self.build_headers(req, connectors)
|
||||
}
|
||||
|
||||
fn get_content_type(&self) -> &'static str {
|
||||
todo!()
|
||||
self.common_get_content_type()
|
||||
}
|
||||
|
||||
fn get_url(&self, _req: &types::RefundSyncRouterData,_connectors: &settings::Connectors,) -> CustomResult<String,errors::ConnectorError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn build_request(
|
||||
&self,
|
||||
req: &types::RefundSyncRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
|
||||
Ok(Some(
|
||||
services::RequestBuilder::new()
|
||||
.method(services::Method::Get)
|
||||
.url(&types::RefundSyncType::get_url(self, req, connectors)?)
|
||||
.headers(types::RefundSyncType::get_headers(self, req, connectors)?)
|
||||
.body(types::RefundSyncType::get_request_body(self, req)?)
|
||||
.build(),
|
||||
))
|
||||
}
|
||||
|
||||
fn handle_response(
|
||||
&self,
|
||||
data: &types::RefundSyncRouterData,
|
||||
@ -335,8 +407,8 @@ impl
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
}
|
||||
|
||||
fn get_error_response(&self, _res: Bytes) -> CustomResult<ErrorResponse,errors::ConnectorError> {
|
||||
todo!()
|
||||
fn get_error_response(&self, res: Bytes) -> CustomResult<ErrorResponse,errors::ConnectorError> {
|
||||
self.build_error_response(res)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -82,11 +82,10 @@ async fn should_refund_succeeded_payment() {
|
||||
let response = connector.make_payment(None).await;
|
||||
|
||||
//try refund for previous payment
|
||||
if let Some(transaction_id) = utils::get_connector_transaction_id(response) {
|
||||
let transaction_id = utils::get_connector_transaction_id(response).unwrap();
|
||||
let response = connector.refund_payment(transaction_id, None).await;
|
||||
assert_eq!(
|
||||
response.response.unwrap().refund_status,
|
||||
enums::RefundStatus::Success,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,9 +36,9 @@ pub enum {{project-name | downcase | pascal_case}}PaymentStatus {
|
||||
impl From<{{project-name | downcase | pascal_case}}PaymentStatus> for enums::AttemptStatus {
|
||||
fn from(item: {{project-name | downcase | pascal_case}}PaymentStatus) -> Self {
|
||||
match item {
|
||||
{{project-name | downcase | pascal_case}}PaymentStatus::Succeeded => enums::AttemptStatus::Charged,
|
||||
{{project-name | downcase | pascal_case}}PaymentStatus::Failed => enums::AttemptStatus::Failure,
|
||||
{{project-name | downcase | pascal_case}}PaymentStatus::Processing => enums::AttemptStatus::Authorizing,
|
||||
{{project-name | downcase | pascal_case}}PaymentStatus::Succeeded => Self::Charged,
|
||||
{{project-name | downcase | pascal_case}}PaymentStatus::Failed => Self::Failure,
|
||||
{{project-name | downcase | pascal_case}}PaymentStatus::Processing => Self::Authorizing,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -47,10 +47,19 @@ impl From<{{project-name | downcase | pascal_case}}PaymentStatus> for enums::Att
|
||||
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
|
||||
pub struct {{project-name | downcase | pascal_case}}PaymentsResponse {}
|
||||
|
||||
impl TryFrom<types::PaymentsResponseRouterData<{{project-name | downcase | pascal_case}}PaymentsResponse>> for types::PaymentsAuthorizeRouterData {
|
||||
impl<F,T> TryFrom<types::ResponseRouterData<F, {{project-name | downcase | pascal_case}}PaymentsResponse, T, types::PaymentsResponseData>> for types::RouterData<F, T, types::PaymentsResponseData> {
|
||||
type Error = error_stack::Report<errors::ParsingError>;
|
||||
fn try_from(_item: types::PaymentsResponseRouterData<{{project-name | downcase | pascal_case}}PaymentsResponse>) -> Result<Self,Self::Error> {
|
||||
todo!()
|
||||
fn try_from(item: types::ResponseRouterData<F, {{project-name | downcase | pascal_case}}PaymentsResponse, T, types::PaymentsResponseData>) -> Result<Self,Self::Error> {
|
||||
Ok(Self {
|
||||
status: enums::AttemptStatus::from(item.response.status),
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
}),
|
||||
..item.data
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -503,6 +503,7 @@ pub enum Connector {
|
||||
Cybersource,
|
||||
#[default]
|
||||
Dummy,
|
||||
Globalpay,
|
||||
Klarna,
|
||||
Shift4,
|
||||
Stripe,
|
||||
|
||||
@ -53,7 +53,7 @@ nanoid = "0.4.0"
|
||||
num_cpus = "1.15.0"
|
||||
once_cell = "1.17.0"
|
||||
rand = "0.8.5"
|
||||
reqwest = { version = "0.11.13", features = ["json", "native-tls"] }
|
||||
reqwest = { version = "0.11.13", features = ["json", "native-tls", "gzip"] }
|
||||
ring = "0.16.20"
|
||||
serde = { version = "1.0.152", features = ["derive"] }
|
||||
serde_json = "1.0.91"
|
||||
|
||||
@ -135,6 +135,7 @@ pub struct Connectors {
|
||||
pub shift4: ConnectorParams,
|
||||
pub stripe: ConnectorParams,
|
||||
pub supported: SupportedConnectors,
|
||||
pub globalpay: ConnectorParams,
|
||||
pub worldpay: ConnectorParams,
|
||||
pub applepay: ConnectorParams,
|
||||
}
|
||||
|
||||
@ -5,13 +5,15 @@ pub mod authorizedotnet;
|
||||
pub mod braintree;
|
||||
pub mod checkout;
|
||||
pub mod cybersource;
|
||||
pub mod globalpay;
|
||||
pub mod klarna;
|
||||
pub mod shift4;
|
||||
pub mod stripe;
|
||||
pub mod utils;
|
||||
pub mod worldpay;
|
||||
|
||||
pub use self::{
|
||||
aci::Aci, adyen::Adyen, applepay::Applepay, authorizedotnet::Authorizedotnet,
|
||||
braintree::Braintree, checkout::Checkout, cybersource::Cybersource, klarna::Klarna,
|
||||
shift4::Shift4, stripe::Stripe, worldpay::Worldpay,
|
||||
braintree::Braintree, checkout::Checkout, cybersource::Cybersource, globalpay::Globalpay,
|
||||
klarna::Klarna, shift4::Shift4, stripe::Stripe, worldpay::Worldpay,
|
||||
};
|
||||
|
||||
605
crates/router/src/connector/globalpay.rs
Normal file
605
crates/router/src/connector/globalpay.rs
Normal file
@ -0,0 +1,605 @@
|
||||
mod requests;
|
||||
mod response;
|
||||
mod transformers;
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
use bytes::Bytes;
|
||||
use error_stack::{IntoReport, ResultExt};
|
||||
|
||||
use self::{
|
||||
requests::GlobalpayPaymentsRequest, response::GlobalpayPaymentsResponse,
|
||||
transformers as globalpay,
|
||||
};
|
||||
use crate::{
|
||||
configs::settings,
|
||||
core::{
|
||||
errors::{self, CustomResult},
|
||||
payments,
|
||||
},
|
||||
headers, logger,
|
||||
services::{self, ConnectorIntegration},
|
||||
types::{
|
||||
self,
|
||||
api::{self, ConnectorCommon, ConnectorCommonExt},
|
||||
ErrorResponse, Response,
|
||||
},
|
||||
utils::{self, BytesExt},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Globalpay;
|
||||
|
||||
impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Globalpay
|
||||
where
|
||||
Self: ConnectorIntegration<Flow, Request, Response>,
|
||||
{
|
||||
fn build_headers(
|
||||
&self,
|
||||
req: &types::RouterData<Flow, Request, Response>,
|
||||
_connectors: &settings::Connectors,
|
||||
) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
|
||||
let mut headers = vec![
|
||||
(
|
||||
headers::CONTENT_TYPE.to_string(),
|
||||
self.get_content_type().to_string(),
|
||||
),
|
||||
("X-GP-Version".to_string(), "2021-03-22".to_string()),
|
||||
];
|
||||
let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
|
||||
headers.append(&mut api_key);
|
||||
Ok(headers)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConnectorCommon for Globalpay {
|
||||
fn id(&self) -> &'static str {
|
||||
"globalpay"
|
||||
}
|
||||
|
||||
fn common_get_content_type(&self) -> &'static str {
|
||||
"application/json"
|
||||
}
|
||||
|
||||
fn base_url<'a>(&self, connectors: &'a settings::Connectors) -> &'a str {
|
||||
connectors.globalpay.base_url.as_ref()
|
||||
}
|
||||
|
||||
fn get_auth_header(
|
||||
&self,
|
||||
auth_type: &types::ConnectorAuthType,
|
||||
) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
|
||||
let auth: globalpay::GlobalpayAuthType = auth_type
|
||||
.try_into()
|
||||
.change_context(errors::ConnectorError::FailedToObtainAuthType)?;
|
||||
Ok(vec![(headers::AUTHORIZATION.to_string(), auth.api_key)])
|
||||
}
|
||||
|
||||
fn build_error_response(
|
||||
&self,
|
||||
res: Bytes,
|
||||
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
||||
let response: globalpay::GlobalpayErrorResponse = res
|
||||
.parse_struct("Globalpay ErrorResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
|
||||
Ok(ErrorResponse {
|
||||
code: response.error_code,
|
||||
message: response.detailed_error_description,
|
||||
reason: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl api::Payment for Globalpay {}
|
||||
|
||||
impl api::PreVerify for Globalpay {}
|
||||
impl ConnectorIntegration<api::Verify, types::VerifyRequestData, types::PaymentsResponseData>
|
||||
for Globalpay
|
||||
{
|
||||
}
|
||||
|
||||
impl api::PaymentVoid for Globalpay {}
|
||||
|
||||
impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsResponseData>
|
||||
for Globalpay
|
||||
{
|
||||
fn get_headers(
|
||||
&self,
|
||||
req: &types::PaymentsCancelRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
|
||||
self.build_headers(req, connectors)
|
||||
}
|
||||
|
||||
fn get_content_type(&self) -> &'static str {
|
||||
self.common_get_content_type()
|
||||
}
|
||||
|
||||
fn get_url(
|
||||
&self,
|
||||
req: &types::PaymentsCancelRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
Ok(format!(
|
||||
"{}/transactions/{}/reversal",
|
||||
self.base_url(connectors),
|
||||
req.request.connector_transaction_id
|
||||
))
|
||||
}
|
||||
|
||||
fn build_request(
|
||||
&self,
|
||||
req: &types::PaymentsCancelRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
|
||||
Ok(Some(
|
||||
services::RequestBuilder::new()
|
||||
.method(services::Method::Post)
|
||||
.url(&types::PaymentsVoidType::get_url(self, req, connectors)?)
|
||||
.headers(types::PaymentsVoidType::get_headers(self, req, connectors)?)
|
||||
.body(types::PaymentsVoidType::get_request_body(self, req)?)
|
||||
.build(),
|
||||
))
|
||||
}
|
||||
|
||||
fn get_request_body(
|
||||
&self,
|
||||
req: &types::PaymentsCancelRouterData,
|
||||
) -> CustomResult<Option<String>, errors::ConnectorError> {
|
||||
let globalpay_req = utils::Encode::<GlobalpayPaymentsRequest>::convert_and_encode(req)
|
||||
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
|
||||
Ok(Some(globalpay_req))
|
||||
}
|
||||
|
||||
fn handle_response(
|
||||
&self,
|
||||
data: &types::PaymentsCancelRouterData,
|
||||
res: Response,
|
||||
) -> CustomResult<types::PaymentsCancelRouterData, errors::ConnectorError> {
|
||||
let response: GlobalpayPaymentsResponse = res
|
||||
.response
|
||||
.parse_struct("Globalpay PaymentsResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
logger::debug!(globalpaypayments_create_response=?response);
|
||||
types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
}
|
||||
.try_into()
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
}
|
||||
|
||||
fn get_error_response(
|
||||
&self,
|
||||
res: Bytes,
|
||||
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
||||
self.build_error_response(res)
|
||||
}
|
||||
}
|
||||
|
||||
impl api::PaymentSync for Globalpay {}
|
||||
impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>
|
||||
for Globalpay
|
||||
{
|
||||
fn get_headers(
|
||||
&self,
|
||||
req: &types::PaymentsSyncRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
|
||||
self.build_headers(req, connectors)
|
||||
}
|
||||
|
||||
fn get_content_type(&self) -> &'static str {
|
||||
self.common_get_content_type()
|
||||
}
|
||||
|
||||
fn get_url(
|
||||
&self,
|
||||
req: &types::PaymentsSyncRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
Ok(format!(
|
||||
"{}transactions/{}",
|
||||
self.base_url(connectors),
|
||||
req.request
|
||||
.connector_transaction_id
|
||||
.get_connector_transaction_id()
|
||||
.change_context(errors::ConnectorError::MissingConnectorTransactionID)?
|
||||
))
|
||||
}
|
||||
|
||||
fn build_request(
|
||||
&self,
|
||||
req: &types::PaymentsSyncRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
|
||||
Ok(Some(
|
||||
services::RequestBuilder::new()
|
||||
.method(services::Method::Get)
|
||||
.url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
|
||||
.headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
|
||||
.build(),
|
||||
))
|
||||
}
|
||||
|
||||
fn get_error_response(
|
||||
&self,
|
||||
res: Bytes,
|
||||
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
||||
self.build_error_response(res)
|
||||
}
|
||||
|
||||
fn handle_response(
|
||||
&self,
|
||||
data: &types::PaymentsSyncRouterData,
|
||||
res: Response,
|
||||
) -> CustomResult<types::PaymentsSyncRouterData, errors::ConnectorError> {
|
||||
logger::debug!(payment_sync_response=?res);
|
||||
let response: GlobalpayPaymentsResponse = res
|
||||
.response
|
||||
.parse_struct("globalpay PaymentsResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
types::RouterData::try_from(types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
})
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
}
|
||||
}
|
||||
|
||||
impl api::PaymentCapture for Globalpay {}
|
||||
impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::PaymentsResponseData>
|
||||
for Globalpay
|
||||
{
|
||||
fn get_headers(
|
||||
&self,
|
||||
req: &types::PaymentsCaptureRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
|
||||
self.build_headers(req, connectors)
|
||||
}
|
||||
|
||||
fn get_content_type(&self) -> &'static str {
|
||||
self.common_get_content_type()
|
||||
}
|
||||
|
||||
fn get_url(
|
||||
&self,
|
||||
req: &types::PaymentsCaptureRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
Ok(format!(
|
||||
"{}/transactions/{}/capture",
|
||||
self.base_url(connectors),
|
||||
req.request.connector_transaction_id
|
||||
))
|
||||
}
|
||||
|
||||
fn get_request_body(
|
||||
&self,
|
||||
req: &types::PaymentsCaptureRouterData,
|
||||
) -> CustomResult<Option<String>, errors::ConnectorError> {
|
||||
let globalpay_req = utils::Encode::<GlobalpayPaymentsRequest>::convert_and_encode(req)
|
||||
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
|
||||
Ok(Some(globalpay_req))
|
||||
}
|
||||
|
||||
fn build_request(
|
||||
&self,
|
||||
req: &types::PaymentsCaptureRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
|
||||
Ok(Some(
|
||||
services::RequestBuilder::new()
|
||||
.method(services::Method::Post)
|
||||
.url(&types::PaymentsCaptureType::get_url(self, req, connectors)?)
|
||||
.headers(types::PaymentsCaptureType::get_headers(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.body(types::PaymentsCaptureType::get_request_body(self, req)?)
|
||||
.build(),
|
||||
))
|
||||
}
|
||||
|
||||
fn handle_response(
|
||||
&self,
|
||||
data: &types::PaymentsCaptureRouterData,
|
||||
res: Response,
|
||||
) -> CustomResult<types::PaymentsCaptureRouterData, errors::ConnectorError> {
|
||||
let response: GlobalpayPaymentsResponse = res
|
||||
.response
|
||||
.parse_struct("Globalpay PaymentsResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
logger::debug!(globalpaypayments_create_response=?response);
|
||||
types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
}
|
||||
.try_into()
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
}
|
||||
|
||||
fn get_error_response(
|
||||
&self,
|
||||
res: Bytes,
|
||||
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
||||
self.build_error_response(res)
|
||||
}
|
||||
}
|
||||
|
||||
impl api::PaymentSession for Globalpay {}
|
||||
|
||||
impl ConnectorIntegration<api::Session, types::PaymentsSessionData, types::PaymentsResponseData>
|
||||
for Globalpay
|
||||
{
|
||||
}
|
||||
|
||||
impl api::PaymentAuthorize for Globalpay {}
|
||||
|
||||
impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::PaymentsResponseData>
|
||||
for Globalpay
|
||||
{
|
||||
fn get_headers(
|
||||
&self,
|
||||
req: &types::PaymentsAuthorizeRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
|
||||
self.build_headers(req, connectors)
|
||||
}
|
||||
|
||||
fn get_content_type(&self) -> &'static str {
|
||||
self.common_get_content_type()
|
||||
}
|
||||
|
||||
fn get_url(
|
||||
&self,
|
||||
_req: &types::PaymentsAuthorizeRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
Ok(format!("{}transactions", self.base_url(connectors)))
|
||||
}
|
||||
|
||||
fn get_request_body(
|
||||
&self,
|
||||
req: &types::PaymentsAuthorizeRouterData,
|
||||
) -> CustomResult<Option<String>, errors::ConnectorError> {
|
||||
let globalpay_req = utils::Encode::<GlobalpayPaymentsRequest>::convert_and_encode(req)
|
||||
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
|
||||
Ok(Some(globalpay_req))
|
||||
}
|
||||
|
||||
fn build_request(
|
||||
&self,
|
||||
req: &types::PaymentsAuthorizeRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
|
||||
Ok(Some(
|
||||
services::RequestBuilder::new()
|
||||
.method(services::Method::Post)
|
||||
.url(&types::PaymentsAuthorizeType::get_url(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.headers(types::PaymentsAuthorizeType::get_headers(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.body(types::PaymentsAuthorizeType::get_request_body(self, req)?)
|
||||
.build(),
|
||||
))
|
||||
}
|
||||
|
||||
fn handle_response(
|
||||
&self,
|
||||
data: &types::PaymentsAuthorizeRouterData,
|
||||
res: Response,
|
||||
) -> CustomResult<types::PaymentsAuthorizeRouterData, errors::ConnectorError> {
|
||||
let response: GlobalpayPaymentsResponse = res
|
||||
.response
|
||||
.parse_struct("Globalpay PaymentsResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
logger::debug!(globalpaypayments_create_response=?response);
|
||||
types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
}
|
||||
.try_into()
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
}
|
||||
|
||||
fn get_error_response(
|
||||
&self,
|
||||
res: Bytes,
|
||||
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
||||
self.build_error_response(res)
|
||||
}
|
||||
}
|
||||
|
||||
impl api::Refund for Globalpay {}
|
||||
impl api::RefundExecute for Globalpay {}
|
||||
impl api::RefundSync for Globalpay {}
|
||||
|
||||
impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsResponseData>
|
||||
for Globalpay
|
||||
{
|
||||
fn get_headers(
|
||||
&self,
|
||||
req: &types::RefundsRouterData<api::Execute>,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
|
||||
self.build_headers(req, connectors)
|
||||
}
|
||||
|
||||
fn get_content_type(&self) -> &'static str {
|
||||
self.common_get_content_type()
|
||||
}
|
||||
|
||||
fn get_url(
|
||||
&self,
|
||||
req: &types::RefundsRouterData<api::Execute>,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
Ok(format!(
|
||||
"{}transactions/{}/refund",
|
||||
self.base_url(connectors),
|
||||
req.request.connector_transaction_id
|
||||
))
|
||||
}
|
||||
|
||||
fn get_request_body(
|
||||
&self,
|
||||
req: &types::RefundsRouterData<api::Execute>,
|
||||
) -> CustomResult<Option<String>, errors::ConnectorError> {
|
||||
let globalpay_req =
|
||||
utils::Encode::<requests::GlobalpayRefundRequest>::convert_and_encode(req)
|
||||
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
|
||||
Ok(Some(globalpay_req))
|
||||
}
|
||||
|
||||
fn build_request(
|
||||
&self,
|
||||
req: &types::RefundsRouterData<api::Execute>,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
|
||||
let request = services::RequestBuilder::new()
|
||||
.method(services::Method::Post)
|
||||
.url(&types::RefundExecuteType::get_url(self, req, connectors)?)
|
||||
.headers(types::RefundExecuteType::get_headers(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.body(types::RefundExecuteType::get_request_body(self, req)?)
|
||||
.build();
|
||||
Ok(Some(request))
|
||||
}
|
||||
|
||||
fn handle_response(
|
||||
&self,
|
||||
data: &types::RefundsRouterData<api::Execute>,
|
||||
res: Response,
|
||||
) -> CustomResult<types::RefundsRouterData<api::Execute>, errors::ConnectorError> {
|
||||
logger::debug!(target: "router::connector::globalpay", response=?res);
|
||||
let response: GlobalpayPaymentsResponse = res
|
||||
.response
|
||||
.parse_struct("globalpay RefundResponse")
|
||||
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
|
||||
types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
}
|
||||
.try_into()
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
}
|
||||
|
||||
fn get_error_response(
|
||||
&self,
|
||||
res: Bytes,
|
||||
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
||||
self.build_error_response(res)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponseData>
|
||||
for Globalpay
|
||||
{
|
||||
fn get_headers(
|
||||
&self,
|
||||
req: &types::RefundSyncRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
|
||||
self.build_headers(req, connectors)
|
||||
}
|
||||
|
||||
fn get_content_type(&self) -> &'static str {
|
||||
self.common_get_content_type()
|
||||
}
|
||||
|
||||
fn get_url(
|
||||
&self,
|
||||
req: &types::RefundSyncRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
Ok(format!(
|
||||
"{}transactions/{}",
|
||||
self.base_url(connectors),
|
||||
req.request.connector_transaction_id
|
||||
))
|
||||
}
|
||||
|
||||
fn build_request(
|
||||
&self,
|
||||
req: &types::RefundSyncRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
|
||||
Ok(Some(
|
||||
services::RequestBuilder::new()
|
||||
.method(services::Method::Get)
|
||||
.url(&types::RefundSyncType::get_url(self, req, connectors)?)
|
||||
.headers(types::RefundSyncType::get_headers(self, req, connectors)?)
|
||||
.body(types::RefundSyncType::get_request_body(self, req)?)
|
||||
.build(),
|
||||
))
|
||||
}
|
||||
|
||||
fn handle_response(
|
||||
&self,
|
||||
data: &types::RefundSyncRouterData,
|
||||
res: Response,
|
||||
) -> CustomResult<types::RefundSyncRouterData, errors::ConnectorError> {
|
||||
logger::debug!(target: "router::connector::globalpay", response=?res);
|
||||
let response: GlobalpayPaymentsResponse = res
|
||||
.response
|
||||
.parse_struct("globalpay RefundResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
}
|
||||
.try_into()
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
}
|
||||
|
||||
fn get_error_response(
|
||||
&self,
|
||||
res: Bytes,
|
||||
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
||||
self.build_error_response(res)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl api::IncomingWebhook for Globalpay {
|
||||
fn get_webhook_object_reference_id(
|
||||
&self,
|
||||
_body: &[u8],
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
Err(errors::ConnectorError::WebhooksNotImplemented).into_report()
|
||||
}
|
||||
|
||||
fn get_webhook_event_type(
|
||||
&self,
|
||||
_body: &[u8],
|
||||
) -> CustomResult<api::IncomingWebhookEvent, errors::ConnectorError> {
|
||||
Err(errors::ConnectorError::WebhooksNotImplemented).into_report()
|
||||
}
|
||||
|
||||
fn get_webhook_resource_object(
|
||||
&self,
|
||||
_body: &[u8],
|
||||
) -> CustomResult<serde_json::Value, errors::ConnectorError> {
|
||||
Err(errors::ConnectorError::WebhooksNotImplemented).into_report()
|
||||
}
|
||||
}
|
||||
|
||||
impl services::ConnectorRedirectResponse for Globalpay {
|
||||
fn get_flow_type(
|
||||
&self,
|
||||
_query_params: &str,
|
||||
) -> CustomResult<payments::CallConnectorAction, errors::ConnectorError> {
|
||||
Ok(payments::CallConnectorAction::Trigger)
|
||||
}
|
||||
}
|
||||
805
crates/router/src/connector/globalpay/requests.rs
Normal file
805
crates/router/src/connector/globalpay/requests.rs
Normal file
@ -0,0 +1,805 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Default, Serialize)]
|
||||
pub struct GlobalpayPaymentsRequest {
|
||||
/// A meaningful label for the merchant account set by Global Payments.
|
||||
pub account_name: String,
|
||||
/// The amount to transfer between Payer and Merchant for a SALE or a REFUND. It is always
|
||||
/// represented in the lowest denomiation of the related currency.
|
||||
pub amount: Option<String>,
|
||||
/// Indicates if the merchant would accept an authorization for an amount less than the
|
||||
/// requested amount. This is available for CP channel
|
||||
/// only where the balance not authorized can be processed again using a different card.
|
||||
pub authorization_mode: Option<AuthorizationMode>,
|
||||
/// Indicates whether the transaction is to be captured automatically, later or later using
|
||||
/// more than 1 partial capture.
|
||||
pub capture_mode: Option<CaptureMode>,
|
||||
/// The amount of the transaction that relates to cashback.It is always represented in the
|
||||
/// lowest denomiation of the related currency.
|
||||
pub cashback_amount: Option<String>,
|
||||
/// Describes whether the transaction was processed in a face to face(CP) scenario or a
|
||||
/// Customer Not Present (CNP) scenario.
|
||||
pub channel: Channel,
|
||||
/// The amount that reflects the charge the merchant applied to the transaction for availing
|
||||
/// of a more convenient purchase.It is always represented in the lowest denomiation of the
|
||||
/// related currency.
|
||||
pub convenience_amount: Option<String>,
|
||||
/// The country in ISO-3166-1(alpha-2 code) format.
|
||||
pub country: String,
|
||||
/// The currency of the amount in ISO-4217(alpha-3)
|
||||
pub currency: String,
|
||||
pub currency_conversion: Option<CurrencyConversion>,
|
||||
/// Merchant defined field to describe the transaction.
|
||||
pub description: Option<String>,
|
||||
pub device: Option<Device>,
|
||||
/// The amount of the gratuity for a transaction.It is always represented in the lowest
|
||||
/// denomiation of the related currency.
|
||||
pub gratuity_amount: Option<String>,
|
||||
/// Indicates whether the Merchant or the Payer initiated the creation of a transaction.
|
||||
pub initiator: Option<Initiator>,
|
||||
/// Indicates the source IP Address of the system used to create the transaction.
|
||||
pub ip_address: Option<String>,
|
||||
/// Indicates the language the transaction was executed in. In the format ISO-639-1 (alpha-2)
|
||||
/// or ISO-639-1 (alpha-2)_ISO-3166(alpha-2)
|
||||
pub language: Option<Language>,
|
||||
pub lodging: Option<Lodging>,
|
||||
/// Indicates to Global Payments where the merchant wants to receive notifications of certain
|
||||
/// events that occur on the Global Payments system.
|
||||
pub notifications: Option<Notifications>,
|
||||
pub order: Option<Order>,
|
||||
/// The merchant's payer reference for the transaction
|
||||
pub payer_reference: Option<String>,
|
||||
pub payment_method: PaymentMethod,
|
||||
/// Merchant defined field to reference the transaction.
|
||||
pub reference: String,
|
||||
/// A merchant defined reference for the location that created the transaction.
|
||||
pub site_reference: Option<String>,
|
||||
/// Stored data information used to create a transaction.
|
||||
pub stored_credential: Option<StoredCredential>,
|
||||
/// The amount that reflects the additional charge the merchant applied to the transaction
|
||||
/// for using a specific payment method.It is always represented in the lowest denomiation of
|
||||
/// the related currency.
|
||||
pub surcharge_amount: Option<String>,
|
||||
/// Indicates the total or expected total of captures that will executed against a
|
||||
/// transaction flagged as being captured multiple times.
|
||||
pub total_capture_count: Option<i64>,
|
||||
/// Describes whether the transaction is a SALE, that moves funds from Payer to Merchant, or
|
||||
/// a REFUND where funds move from Merchant to Payer.
|
||||
#[serde(rename = "type")]
|
||||
pub globalpay_payments_request_type: Option<GlobalpayPaymentsRequestType>,
|
||||
/// The merchant's user reference for the transaction. This represents the person who
|
||||
/// processed the transaction on the merchant's behalf like a clerk or cashier reference.
|
||||
pub user_reference: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CurrencyConversion {
|
||||
/// A unique identifier generated by Global Payments to identify the currency conversion. It
|
||||
/// can be used to reference a currency conversion when processing a sale or a refund
|
||||
/// transaction.
|
||||
pub id: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Device {
|
||||
pub capabilities: Option<Capabilities>,
|
||||
pub entry_modes: Option<Vec<Vec<DeviceEntryMode>>>,
|
||||
/// Describes whether a device prompts a payer for a gratuity when the payer is entering
|
||||
/// their payment method details to the device.
|
||||
pub gratuity_prompt_mode: Option<GratuityPromptMode>,
|
||||
/// Describes the receipts a device prints when processing a transaction.
|
||||
pub print_receipt_mode: Option<PrintReceiptMode>,
|
||||
/// The sequence number from the device used to align with processing platform.
|
||||
pub sequence_number: Option<String>,
|
||||
/// A unique identifier for the physical device. This value persists with the device even if
|
||||
/// it is repurposed.
|
||||
pub serial_number: Option<String>,
|
||||
/// The time from the device in ISO8601 format
|
||||
pub time: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Capabilities {
|
||||
pub authorization_modes: Option<Vec<AuthorizationMode>>,
|
||||
/// The number of lines that can be used to display information on the device.
|
||||
pub display_line_count: Option<f64>,
|
||||
pub enabled_response: Option<Vec<EnabledResponse>>,
|
||||
pub entry_modes: Option<Vec<CapabilitiesEntryMode>>,
|
||||
pub fraud: Option<Vec<AuthorizationMode>>,
|
||||
pub mobile: Option<Vec<Mobile>>,
|
||||
pub payer_verifications: Option<Vec<PayerVerification>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Lodging {
|
||||
/// A reference that identifies the booking reference for a lodging stay.
|
||||
pub booking_reference: Option<String>,
|
||||
/// The amount charged for one nights lodging.
|
||||
pub daily_rate_amount: Option<String>,
|
||||
/// A reference that identifies the booking reference for a lodging stay.
|
||||
pub date_checked_in: Option<String>,
|
||||
/// The check out date for a lodging stay.
|
||||
pub date_checked_out: Option<String>,
|
||||
/// The total number of days of the lodging stay.
|
||||
pub duration_days: Option<f64>,
|
||||
#[serde(rename = "lodging.charge_items")]
|
||||
pub lodging_charge_items: Option<Vec<LodgingChargeItem>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct LodgingChargeItem {
|
||||
pub payment_method_program_codes: Option<Vec<PaymentMethodProgramCode>>,
|
||||
/// A reference that identifies the charge item, such as a lodging folio number.
|
||||
pub reference: Option<String>,
|
||||
/// The total amount for the list of charge types for a charge item.
|
||||
pub total_amount: Option<String>,
|
||||
pub types: Option<Vec<TypeElement>>,
|
||||
}
|
||||
|
||||
/// Indicates to Global Payments where the merchant wants to receive notifications of certain
|
||||
/// events that occur on the Global Payments system.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Notifications {
|
||||
/// The merchant URL that will receive the notification when the customer has completed the
|
||||
/// authentication.
|
||||
pub challenge_return_url: Option<String>,
|
||||
/// The merchant URL that will receive the notification when the customer has completed the
|
||||
/// authentication when the authentication is decoupled and separate to the purchase.
|
||||
pub decoupled_challenge_return_url: Option<String>,
|
||||
/// The merchant URL to return the payer to, once the payer has completed payment using the
|
||||
/// payment method. This returns control of the payer's payment experience to the merchant.
|
||||
pub return_url: Option<String>,
|
||||
/// The merchant URL to notify the merchant of the latest status of the transaction.
|
||||
pub status_url: Option<String>,
|
||||
/// The merchant URL that will receive the notification when the 3DS ACS successfully gathers
|
||||
/// de ice informatiSon and tonotification_configurations.cordingly.
|
||||
pub three_ds_method_return_url: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Order {
|
||||
/// Merchant defined field common to all transactions that are part of the same order.
|
||||
pub reference: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
pub struct PaymentMethod {
|
||||
pub apm: Option<Apm>,
|
||||
pub authentication: Option<Authentication>,
|
||||
pub bank_transfer: Option<BankTransfer>,
|
||||
pub card: Option<Card>,
|
||||
pub digital_wallet: Option<DigitalWallet>,
|
||||
pub encryption: Option<Encryption>,
|
||||
/// Indicates how the payment method information was obtained by the Merchant for this
|
||||
/// transaction.
|
||||
pub entry_mode: PaymentMethodEntryMode,
|
||||
/// Indicates whether to execute the fingerprint signature functionality.
|
||||
pub fingerprint_mode: Option<FingerprintMode>,
|
||||
/// Specify the first name of the owner of the payment method.
|
||||
pub first_name: Option<String>,
|
||||
/// Unique Global Payments generated id used to reference a stored payment method on the
|
||||
/// Global Payments system. Often referred to as the payment method token. This value can be
|
||||
/// used instead of payment method details such as a card number and expiry date.
|
||||
pub id: Option<String>,
|
||||
/// Specify the surname of the owner of the payment method.
|
||||
pub last_name: Option<String>,
|
||||
/// The full name of the owner of the payment method.
|
||||
pub name: Option<String>,
|
||||
/// Contains the value a merchant wishes to appear on the payer's payment method statement
|
||||
/// for this transaction
|
||||
pub narrative: Option<String>,
|
||||
/// Indicates whether to store the card as part of a transaction.
|
||||
pub storage_mode: Option<CardStorageMode>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Apm {
|
||||
/// A string used to identify the payment method provider being used to execute this
|
||||
/// transaction.
|
||||
pub provider: Option<ApmProvider>,
|
||||
}
|
||||
|
||||
/// Information outlining the degree of authentication executed related to a transaction.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Authentication {
|
||||
/// Information outlining the degree of 3D Secure authentication executed.
|
||||
pub three_ds: Option<ThreeDs>,
|
||||
/// A message authentication code that is used to confirm the security and integrity of the
|
||||
/// messaging to Global Payments.
|
||||
pub mac: Option<String>,
|
||||
}
|
||||
|
||||
/// Information outlining the degree of 3D Secure authentication executed.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ThreeDs {
|
||||
/// The reference created by the 3DSecure Directory Server to identify the specific
|
||||
/// authentication attempt.
|
||||
pub ds_trans_reference: Option<String>,
|
||||
/// An indication of the degree of the authentication and liability shift obtained for this
|
||||
/// transaction. It is determined during the 3D Secure process. 2 or 1 for Mastercard
|
||||
/// indicates the merchant has a liability shift. 5 or 6 for Visa or Amex indicates the
|
||||
/// merchant has a liability shift. However for Amex if the payer is not enrolled the eci may
|
||||
/// still be 6 but liability shift has not bee achieved.
|
||||
pub eci: Option<String>,
|
||||
/// Indicates if any exemptions apply to this transaction.
|
||||
pub exempt_status: Option<ExemptStatus>,
|
||||
/// Indicates the version of 3DS
|
||||
pub message_version: Option<String>,
|
||||
/// The reference created by the 3DSecure provider to identify the specific authentication
|
||||
/// attempt.
|
||||
pub server_trans_reference: Option<String>,
|
||||
/// The authentication value created as part of the 3D Secure process.
|
||||
pub value: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct BankTransfer {
|
||||
/// The number or reference for the payer's bank account.
|
||||
pub account_number: Option<String>,
|
||||
pub bank: Option<Bank>,
|
||||
/// The number or reference for the check
|
||||
pub check_reference: Option<String>,
|
||||
/// The type of bank account associated with the payer's bank account.
|
||||
pub number_type: Option<NumberType>,
|
||||
/// Indicates how the transaction was authorized by the merchant.
|
||||
pub sec_code: Option<SecCode>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Bank {
|
||||
pub address: Option<Address>,
|
||||
/// The local identifier code for the bank.
|
||||
pub code: Option<String>,
|
||||
/// The name of the bank.
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Address {
|
||||
/// Merchant defined field common to all transactions that are part of the same order.
|
||||
pub city: Option<String>,
|
||||
/// The country in ISO-3166-1(alpha-2 code) format.
|
||||
pub country: Option<String>,
|
||||
/// First line of the address.
|
||||
pub line_1: Option<String>,
|
||||
/// Second line of the address.
|
||||
pub line_2: Option<String>,
|
||||
/// Third line of the address.
|
||||
pub line_3: Option<String>,
|
||||
/// The city or town of the address.
|
||||
pub postal_code: Option<String>,
|
||||
/// The state or region of the address. ISO 3166-2 minus the country code itself. For
|
||||
/// example, US Illinois = IL, or in the case of GB counties Wiltshire = WI or Aberdeenshire
|
||||
/// = ABD
|
||||
pub state: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
pub struct Card {
|
||||
/// The card providers description of their card product.
|
||||
pub account_type: Option<String>,
|
||||
/// Code generated when the card is successfully authorized.
|
||||
pub authcode: Option<String>,
|
||||
/// First line of the address associated with the card.
|
||||
pub avs_address: Option<String>,
|
||||
/// Postal code of the address associated with the card.
|
||||
pub avs_postal_code: Option<String>,
|
||||
/// The unique reference created by the brands/schemes to uniquely identify the transaction.
|
||||
pub brand_reference: Option<String>,
|
||||
/// Indicates if a fallback mechanism was used to obtain the card information when EMV/chip
|
||||
/// did not work as expected.
|
||||
pub chip_condition: Option<ChipCondition>,
|
||||
/// The numeric value printed on the physical card.
|
||||
pub cvv: String,
|
||||
/// Card Verification Value Indicator sent by the Merchant indicating the CVV
|
||||
/// availability.
|
||||
pub cvv_indicator: CvvIndicator,
|
||||
/// The 2 digit expiry date month of the card.
|
||||
pub expiry_month: String,
|
||||
/// The 2 digit expiry date year of the card.
|
||||
pub expiry_year: String,
|
||||
/// Indicates whether the card is a debit or credit card.
|
||||
pub funding: Option<Funding>,
|
||||
/// The the card account number used to authorize the transaction. Also known as PAN.
|
||||
pub number: String,
|
||||
/// Contains the pin block info, relating to the pin code the Payer entered.
|
||||
pub pin_block: Option<String>,
|
||||
/// The full card tag data for an EMV/chip card transaction.
|
||||
pub tag: Option<String>,
|
||||
/// Data from magnetic stripe of a card
|
||||
pub track: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct DigitalWallet {
|
||||
/// First line of the address associated with the card.
|
||||
pub avs_address: Option<String>,
|
||||
/// Postal code of the address associated with the card.
|
||||
pub avs_postal_code: Option<String>,
|
||||
/// The authentication value use to verify the validity of the digit wallet transaction.
|
||||
pub cryptogram: Option<String>,
|
||||
/// The numeric value printed on the physical card.
|
||||
pub cvv: Option<String>,
|
||||
/// Card Verification Value Indicator sent by the Merchant indicating the CVV
|
||||
/// availability.
|
||||
pub cvv_indicator: Option<CvvIndicator>,
|
||||
/// An indication of the degree of the authentication and liability shift obtained for this
|
||||
/// transaction. It is determined during the 3D Secure process. 2 or 1 for Mastercard
|
||||
/// indicates the merchant has a liability shift. 5 or 6 for Visa or Amex indicates the
|
||||
/// merchant has a liability shift. However for Amex if the payer is not enrolled the eci may
|
||||
/// still be 6 but liability shift has not bee achieved.
|
||||
pub eci: Option<String>,
|
||||
/// The 2 digit expiry date month of the card.
|
||||
pub expiry_month: Option<String>,
|
||||
/// The 2 digit expiry date year of the card.
|
||||
pub expiry_year: Option<String>,
|
||||
/// Identifies who provides the digital wallet for the Payer.
|
||||
pub provider: Option<DigitalWalletProvider>,
|
||||
/// A token that represents, or is the payment method, stored with the digital wallet.
|
||||
pub token: Option<String>,
|
||||
/// Indicates if the actual card number or a token is being used to process the
|
||||
/// transaction.
|
||||
pub token_format: Option<TokenFormat>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Encryption {
|
||||
/// The encryption info used when sending encrypted card data to Global Payments.
|
||||
pub info: Option<String>,
|
||||
/// The encryption method used when sending encrypted card data to Global Payments.
|
||||
pub method: Option<Method>,
|
||||
/// The version of encryption being used.
|
||||
pub version: Option<String>,
|
||||
}
|
||||
|
||||
/// Stored data information used to create a transaction.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct StoredCredential {
|
||||
/// Indicates the transaction processing model being executed when using stored
|
||||
/// credentials.
|
||||
pub model: Option<Model>,
|
||||
/// The reason stored credentials are being used to to create a transaction.
|
||||
pub reason: Option<Reason>,
|
||||
/// Indiciates the order of this transaction in the sequence of a planned repeating
|
||||
/// transaction processing model.
|
||||
pub sequence: Option<Sequence>,
|
||||
}
|
||||
|
||||
/// Indicates if the merchant would accept an authorization for an amount less than the
|
||||
/// requested amount. This is available for CP channel
|
||||
/// only where the balance not authorized can be processed again using a different card.
|
||||
///
|
||||
/// Describes the instruction a device can indicate to the clerk in the case of fraud.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum AuthorizationMode {
|
||||
/// Indicates merchant would accept an authorization for an amount less than the
|
||||
/// requested amount.
|
||||
/// pub example: PARTIAL
|
||||
///
|
||||
///
|
||||
/// Describes whether the device can process partial authorizations.
|
||||
Partial,
|
||||
}
|
||||
|
||||
/// Indicates whether the transaction is to be captured automatically, later or later using
|
||||
/// more than 1 partial capture.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum CaptureMode {
|
||||
/// If a transaction is authorized, funds will exchange between the payer and
|
||||
/// merchant automatically and as soon as possible.
|
||||
Auto,
|
||||
/// If a transaction is authorized, funds will not exchange between the payer and
|
||||
/// merchant automatically and will require a subsequent separate action to capture that
|
||||
/// transaction and start the funding process. Only one successful capture is permitted.
|
||||
Later,
|
||||
/// If a transaction is authorized, funds will not exchange between the payer
|
||||
/// and merchant automatically. One or more subsequent separate capture actions are required
|
||||
/// to capture that transaction in parts and start the funding process for the part captured.
|
||||
/// One or many successful capture are permitted once the total amount captured is within a
|
||||
/// range of the original authorized amount.'
|
||||
Multiple,
|
||||
}
|
||||
|
||||
/// Describes whether the transaction was processed in a face to face(CP) scenario or a
|
||||
/// Customer Not Present (CNP) scenario.
|
||||
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
pub enum Channel {
|
||||
#[default]
|
||||
#[serde(rename = "CNP")]
|
||||
/// A Customer NOT Present transaction is when the payer and the merchant are not
|
||||
/// together when exchanging payment method information to fulfill a transaction. e.g. a
|
||||
/// transaction executed from a merchant's website or over the phone
|
||||
CustomerNotPresent,
|
||||
#[serde(rename = "CP")]
|
||||
/// A Customer Present transaction is when the payer and the merchant are in direct
|
||||
/// face to face contact when exchanging payment method information to fulfill a transaction.
|
||||
/// e.g. in a store and paying at the counter that is attended by a clerk.
|
||||
CustomerPresent,
|
||||
}
|
||||
|
||||
/// Describes the data the device can handle when it receives a response for a card
|
||||
/// authorization.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum EnabledResponse {
|
||||
Avs,
|
||||
BrandReference,
|
||||
Cvv,
|
||||
MaskedNumberLast4,
|
||||
}
|
||||
|
||||
/// Describes the entry mode capabilities a device has.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum CapabilitiesEntryMode {
|
||||
Chip,
|
||||
Contactless,
|
||||
ContactlessSwipe,
|
||||
Manual,
|
||||
Swipe,
|
||||
}
|
||||
|
||||
/// Describes the mobile features a device has
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum Mobile {
|
||||
IntegratedCardReader,
|
||||
SeparateCardReader,
|
||||
}
|
||||
|
||||
/// Describes the capabilities a device has to verify a payer.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum PayerVerification {
|
||||
ContactlessSignature,
|
||||
PayerDevice,
|
||||
Pinpad,
|
||||
}
|
||||
|
||||
/// Describes the allowed entry modes to obtain payment method information from the payer as
|
||||
/// part of a transaction request.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum DeviceEntryMode {
|
||||
Chip,
|
||||
Contactless,
|
||||
Manual,
|
||||
Swipe,
|
||||
}
|
||||
|
||||
/// Describes whether a device prompts a payer for a gratuity when the payer is entering
|
||||
/// their payment method details to the device.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum GratuityPromptMode {
|
||||
NotRequired,
|
||||
Prompt,
|
||||
}
|
||||
|
||||
/// Describes the receipts a device prints when processing a transaction.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum PrintReceiptMode {
|
||||
Both,
|
||||
Merchant,
|
||||
None,
|
||||
Payer,
|
||||
}
|
||||
|
||||
/// Describes whether the transaction is a SALE, that moves funds from Payer to Merchant, or
|
||||
/// a REFUND where funds move from Merchant to Payer.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum GlobalpayPaymentsRequestType {
|
||||
/// indicates the movement, or the attempt to move, funds from merchant to the
|
||||
/// payer.
|
||||
Refund,
|
||||
/// indicates the movement, or the attempt to move, funds from payer to a
|
||||
/// merchant.
|
||||
Sale,
|
||||
}
|
||||
|
||||
/// Indicates whether the Merchant or the Payer initiated the creation of a transaction.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum Initiator {
|
||||
/// The transaction was initated by the merchant, who is getting paid by the
|
||||
/// payer.'
|
||||
Merchant,
|
||||
/// The transaction was initated by the customer who is paying the merchant.
|
||||
Payer,
|
||||
}
|
||||
|
||||
/// Indicates the language the transaction was executed in. In the format ISO-639-1 (alpha-2)
|
||||
/// or ISO-639-1 (alpha-2)_ISO-3166(alpha-2)
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum Language {
|
||||
#[serde(rename = "fr")]
|
||||
Fr,
|
||||
#[serde(rename = "fr_CA")]
|
||||
FrCa,
|
||||
#[serde(rename = "ISO-639(alpha-2)")]
|
||||
Iso639Alpha2,
|
||||
#[serde(rename = "ISO-639(alpha-2)_ISO-3166(alpha-2)")]
|
||||
Iso639alpha2Iso3166alpha2,
|
||||
}
|
||||
|
||||
/// Describes the payment method programs, typically run by card brands such as Amex, Visa
|
||||
/// and MC.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum PaymentMethodProgramCode {
|
||||
AssuredReservation,
|
||||
CardDeposit,
|
||||
Other,
|
||||
Purchase,
|
||||
}
|
||||
|
||||
/// Describes the types of charges associated with a transaction. This can be one or more
|
||||
/// than more charge type.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum TypeElement {
|
||||
GiftShop,
|
||||
Laundry,
|
||||
MiniBar,
|
||||
NoShow,
|
||||
Other,
|
||||
Phone,
|
||||
Restaurant,
|
||||
}
|
||||
|
||||
/// A string used to identify the payment method provider being used to execute this
|
||||
/// transaction.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum ApmProvider {
|
||||
Giropay,
|
||||
Ideal,
|
||||
Paypal,
|
||||
Sofort,
|
||||
Testpay,
|
||||
}
|
||||
|
||||
/// Indicates if any exemptions apply to this transaction.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum ExemptStatus {
|
||||
LowValue,
|
||||
ScaDelegation,
|
||||
SecureCorporatePayment,
|
||||
TransactionRiskAnalysis,
|
||||
TrustedMerchant,
|
||||
}
|
||||
|
||||
/// The type of bank account associated with the payer's bank account.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum NumberType {
|
||||
Checking,
|
||||
Savings,
|
||||
}
|
||||
|
||||
/// Indicates how the transaction was authorized by the merchant.
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum SecCode {
|
||||
/// Cash Concentration or Disbursement - Can be either a credit or debit application
|
||||
/// where funds are wither distributed or consolidated between corporate entities.
|
||||
#[serde(rename = "CCD")]
|
||||
CashConcentrationOrDisbursement,
|
||||
|
||||
/// Point of Sale Entry - Point of sale debit applications non-shared (POS)
|
||||
/// environment. These transactions are most often initiated by the consumer via a plastic
|
||||
/// access card. This is only support for normal ACH transactions
|
||||
#[serde(rename = "POP")]
|
||||
PointOfSaleEntry,
|
||||
/// Prearranged Payment and Deposits - used to credit or debit a consumer account.
|
||||
/// Popularity used for payroll direct deposits and pre-authorized bill payments.
|
||||
#[serde(rename = "PPD")]
|
||||
PrearrangedPaymentAndDeposits,
|
||||
/// Telephone-Initiated Entry - Used for the origination of a single entry debit
|
||||
/// transaction to a consumer's account pursuant to a verbal authorization obtained from the
|
||||
/// consumer via the telephone.
|
||||
#[serde(rename = "TEL")]
|
||||
TelephoneInitiatedEntry,
|
||||
/// Internet (Web)-Initiated Entry - Used for the origination of debit entries
|
||||
/// (either Single or Recurring Entry) to a consumer's account pursuant to a to an
|
||||
/// authorization that is obtained from the Receiver via the Internet.
|
||||
#[serde(rename = "WEB")]
|
||||
WebInitiatedEntry,
|
||||
}
|
||||
|
||||
/// Indicates if a fallback mechanism was used to obtain the card information when EMV/chip
|
||||
/// did not work as expected.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum ChipCondition {
|
||||
/// indicates the previous transaction with this card failed.
|
||||
PrevFailed,
|
||||
/// indicates the previous transaction with this card was a success.
|
||||
PrevSuccess,
|
||||
}
|
||||
|
||||
/// Card Verification Value Indicator sent by the Merchant indicating the CVV
|
||||
/// availability.
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum CvvIndicator {
|
||||
/// indicates the cvv is present but cannot be read.
|
||||
Illegible,
|
||||
/// indicates the cvv is not present on the card.
|
||||
NotPresent,
|
||||
#[default]
|
||||
/// indicates the cvv is present.
|
||||
Present,
|
||||
}
|
||||
|
||||
/// Indicates whether the card is a debit or credit card.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum Funding {
|
||||
/// indicates the card is an, Electronic Benefits Transfer, for cash
|
||||
/// benefits.
|
||||
CashBenefits,
|
||||
/// indicates the card is a credit card where the funds may be available on credit
|
||||
/// to the payer to fulfill the transaction amount.
|
||||
Credit,
|
||||
/// indicates the card is a debit card where the funds may be present in an account
|
||||
/// to fulfill the transaction amount.
|
||||
Debit,
|
||||
/// indicates the card is an, Electronic Benefits Transfer, for food stamps.
|
||||
FoodStamp,
|
||||
/// indicates the card is a prepaid card where the funds are loaded to the card
|
||||
/// account to fulfill the transaction amount. Unlike a debit card, a prepaid is not linked
|
||||
/// to a bank account.
|
||||
Prepaid,
|
||||
}
|
||||
|
||||
/// Identifies who provides the digital wallet for the Payer.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum DigitalWalletProvider {
|
||||
Applepay,
|
||||
PayByGoogle,
|
||||
}
|
||||
|
||||
/// Indicates if the actual card number or a token is being used to process the
|
||||
/// transaction.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum TokenFormat {
|
||||
/// The value in the digital wallet token field is a real card number
|
||||
/// (PAN)
|
||||
CardNumber,
|
||||
/// The value in the digital wallet token field is a temporary token in the
|
||||
/// format of a card number (PAN) but is not a real card number.
|
||||
CardToken,
|
||||
}
|
||||
|
||||
/// The encryption method used when sending encrypted card data to Global Payments.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum Method {
|
||||
Ksn,
|
||||
Ktb,
|
||||
}
|
||||
|
||||
/// Indicates how the payment method information was obtained by the Merchant for this
|
||||
/// transaction.
|
||||
#[derive(Debug, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum PaymentMethodEntryMode {
|
||||
/// A CP channel entry mode where the payment method information was obtained from a
|
||||
/// chip. E.g. card is inserted into a device to read the chip.
|
||||
Chip,
|
||||
/// A CP channel entry mode where the payment method information was
|
||||
/// obtained by bringing the payment method to close proximity of a device. E.g. tap a cardon
|
||||
/// or near a device to exchange card information.
|
||||
ContactlessChip,
|
||||
/// A CP channel entry mode where the payment method information was
|
||||
/// obtained by bringing the payment method to close proximity of a device and also swiping
|
||||
/// the card. E.g. tap a card on or near a device and swipe it through device to exchange
|
||||
/// card information
|
||||
ContactlessSwipe,
|
||||
#[default]
|
||||
/// A CNP channel entry mode where the payment method was obtained via a browser.
|
||||
Ecom,
|
||||
/// A CNP channel entry mode where the payment method was obtained via an
|
||||
/// application and applies to digital wallets only.
|
||||
InApp,
|
||||
/// A CNP channel entry mode where the payment method was obtained via postal mail.
|
||||
Mail,
|
||||
/// A CP channel entry mode where the payment method information was obtained by
|
||||
/// manually keying the payment method information into the device.
|
||||
Manual,
|
||||
/// A CNP channel entry mode where the payment method information was obtained over
|
||||
/// the phone or via postal mail.
|
||||
Moto,
|
||||
/// A CNP channel entry mode where the payment method was obtained over the
|
||||
/// phone.
|
||||
Phone,
|
||||
/// A CP channel entry mode where the payment method information was obtained from
|
||||
/// swiping a magnetic strip. E.g. card's magnetic strip is swiped through a device to read
|
||||
/// the card information.
|
||||
Swipe,
|
||||
}
|
||||
|
||||
/// Indicates whether to execute the fingerprint signature functionality.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum FingerprintMode {
|
||||
/// Always check and create the fingerprint value regardless of the result of the
|
||||
/// card authorization.
|
||||
Always,
|
||||
/// Always check and create the fingerprint value when the card authorization
|
||||
/// is successful.
|
||||
OnSuccess,
|
||||
}
|
||||
|
||||
/// Indicates whether to store the card as part of a transaction.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum CardStorageMode {
|
||||
/// /// The card information is always stored irrespective of whether the payment
|
||||
/// method authorization was successful or not.
|
||||
Always,
|
||||
/// The card information is only stored if the payment method authorization was
|
||||
/// successful.
|
||||
OnSuccess,
|
||||
}
|
||||
|
||||
/// Indicates the transaction processing model being executed when using stored
|
||||
/// credentials.
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum Model {
|
||||
/// The transaction is a repeat transaction initiated by the merchant and
|
||||
/// taken using the payment method stored with the merchant, as part of an agreed schedule of
|
||||
/// transactions and where the amount is known and agreed in advanced. For example the
|
||||
/// payment in full of a good in fixed installments over a defined period of time.'
|
||||
Installment,
|
||||
/// The transaction is a repeat transaction initiated by the merchant and taken
|
||||
/// using the payment method stored with the merchant, as part of an agreed schedule of
|
||||
/// transactions.
|
||||
Recurring,
|
||||
/// The transaction is a repeat transaction initiated by the merchant and
|
||||
/// taken using the payment method stored with the merchant, as part of an agreed schedule of
|
||||
/// transactions. The amount taken is based on the usage by the payer of the good or service.
|
||||
/// for example a monthly mobile phone bill.
|
||||
Subscription,
|
||||
/// the transaction is adhoc or unscheduled. For example a payer visiting a
|
||||
/// merchant to make purchase using the payment method stored with the merchant.
|
||||
Unscheduled,
|
||||
}
|
||||
|
||||
/// The reason stored credentials are being used to to create a transaction.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum Reason {
|
||||
Delayed,
|
||||
Incremental,
|
||||
NoShow,
|
||||
Reauthorization,
|
||||
Resubmission,
|
||||
}
|
||||
|
||||
/// Indiciates the order of this transaction in the sequence of a planned repeating
|
||||
/// transaction processing model.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum Sequence {
|
||||
First,
|
||||
Last,
|
||||
Subsequent,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Serialize)]
|
||||
pub struct GlobalpayRefundRequest {
|
||||
pub amount: String,
|
||||
}
|
||||
363
crates/router/src/connector/globalpay/response.rs
Normal file
363
crates/router/src/connector/globalpay/response.rs
Normal file
@ -0,0 +1,363 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::requests;
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct GlobalpayPaymentsResponse {
|
||||
/// A unique identifier for the merchant account set by Global Payments.
|
||||
pub account_id: Option<String>,
|
||||
/// A meaningful label for the merchant account set by Global Payments.
|
||||
pub account_name: Option<String>,
|
||||
/// Information about the Action executed.
|
||||
pub action: Option<Action>,
|
||||
/// The amount to transfer between Payer and Merchant for a SALE or a REFUND. It is always
|
||||
/// represented in the lowest denomiation of the related currency.
|
||||
pub amount: Option<String>,
|
||||
/// Indicates if the merchant would accept an authorization for an amount less than the
|
||||
/// requested amount. This is available for CP channel
|
||||
/// only where the balance not authorized can be processed again using a different card.
|
||||
pub authorization_mode: Option<requests::AuthorizationMode>,
|
||||
/// A Global Payments created reference that uniquely identifies the batch.
|
||||
pub batch_id: Option<String>,
|
||||
/// Indicates whether the transaction is to be captured automatically, later or later using
|
||||
/// more than 1 partial capture.
|
||||
pub capture_mode: Option<requests::CaptureMode>,
|
||||
/// Describes whether the transaction was processed in a face to face(CP) scenario or a
|
||||
/// Customer Not Present (CNP) scenario.
|
||||
pub channel: Option<requests::Channel>,
|
||||
/// The country in ISO-3166-1(alpha-2 code) format.
|
||||
pub country: Option<String>,
|
||||
/// The currency of the amount in ISO-4217(alpha-3)
|
||||
pub currency: Option<String>,
|
||||
/// Information relating to a currency conversion.
|
||||
pub currency_conversion: Option<requests::CurrencyConversion>,
|
||||
/// A unique identifier generated by Global Payments to identify the transaction.
|
||||
pub id: String,
|
||||
/// A unique identifier for the merchant set by Global Payments.
|
||||
pub merchant_id: Option<String>,
|
||||
/// A meaningful label for the merchant set by Global Payments.
|
||||
pub merchant_name: Option<String>,
|
||||
pub payment_method: Option<PaymentMethod>,
|
||||
/// Merchant defined field to reference the transaction.
|
||||
pub reference: Option<String>,
|
||||
/// Indicates where a transaction is in its lifecycle.
|
||||
pub status: GlobalpayPaymentStatus,
|
||||
/// Global Payments time indicating when the object was created in ISO-8601 format.
|
||||
pub time_created: Option<String>,
|
||||
/// Describes whether the transaction is a SALE, that moves funds from Payer to Merchant, or
|
||||
/// a REFUND where funds move from Merchant to Payer.
|
||||
#[serde(rename = "type")]
|
||||
pub globalpay_payments_response_type: Option<requests::GlobalpayPaymentsRequestType>,
|
||||
}
|
||||
|
||||
/// Information about the Action executed.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Action {
|
||||
/// The id of the app that was used to create the token.
|
||||
pub app_id: Option<String>,
|
||||
/// The name of the app the user gave to the application.
|
||||
pub app_name: Option<String>,
|
||||
/// A unique identifier for the object created by Global Payments. The first 3 characters
|
||||
/// identifies the resource an id relates to.
|
||||
pub id: Option<String>,
|
||||
/// The result of the action executed.
|
||||
pub result_code: Option<ResultCode>,
|
||||
/// Global Payments time indicating when the object was created in ISO-8601 format.
|
||||
pub time_created: Option<String>,
|
||||
/// Indicates the action taken.
|
||||
#[serde(rename = "type")]
|
||||
pub action_type: Option<String>,
|
||||
}
|
||||
|
||||
/// Information relating to a currency conversion.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct CurrencyConversion {
|
||||
/// The percentage commission taken for providing the currency conversion.
|
||||
pub commission_percentage: Option<String>,
|
||||
/// The exchange rate used to convert one currency to another.
|
||||
pub conversion_rate: Option<String>,
|
||||
/// The source of the base exchange rate was obtained to execute the currency conversion.
|
||||
pub exchange_rate_source: Option<String>,
|
||||
/// The time the base exchange rate was obtained from the source.
|
||||
pub exchange_source_time: Option<String>,
|
||||
/// The exchange rate used to convert one currency to another.
|
||||
pub margin_rate_percentage: Option<String>,
|
||||
/// The amount that will affect the payer's account.
|
||||
pub payer_amount: Option<String>,
|
||||
/// The currency of the amount that will affect the payer's account.
|
||||
pub payer_currency: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct PaymentMethod {
|
||||
/// Data associated with the response of an APM transaction.
|
||||
pub apm: Option<Apm>,
|
||||
/// Information outlining the degree of authentication executed related to a transaction.
|
||||
pub authentication: Option<Authentication>,
|
||||
pub bank_transfer: Option<BankTransfer>,
|
||||
pub card: Option<Card>,
|
||||
pub digital_wallet: Option<requests::DigitalWallet>,
|
||||
/// Indicates how the payment method information was obtained by the Merchant for this
|
||||
/// transaction.
|
||||
pub entry_mode: Option<requests::PaymentMethodEntryMode>,
|
||||
/// If enabled, this field contains the unique fingerprint signature for that payment method
|
||||
/// for that merchant. If the payment method is seen again this same value is generated. For
|
||||
/// cards the primary account number is checked only. The expiry date or the CVV is not used
|
||||
/// for this check.
|
||||
pub fingerprint: Option<String>,
|
||||
/// If enabled, this field indicates whether the payment method has been seen before or is
|
||||
/// new.
|
||||
/// * EXISTS - Indicates that the payment method was seen on the platform before by this
|
||||
/// merchant.
|
||||
/// * NEW - Indicates that the payment method was not seen on the platform before by this
|
||||
/// merchant.
|
||||
pub fingerprint_presence_indicator: Option<String>,
|
||||
/// Unique Global Payments generated id used to reference a stored payment method on the
|
||||
/// Global Payments system. Often referred to as the payment method token. This value can be
|
||||
/// used instead of payment method details such as a card number and expiry date.
|
||||
pub id: Option<String>,
|
||||
/// Result message from the payment method provider corresponding to the result code.
|
||||
pub message: Option<String>,
|
||||
/// Result code from the payment method provider.
|
||||
pub result: Option<String>,
|
||||
}
|
||||
|
||||
/// Data associated with the response of an APM transaction.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Apm {
|
||||
pub bank: Option<Bank>,
|
||||
/// A string generated by the payment method that represents to what degree the merchant is
|
||||
/// funded for the transaction.
|
||||
pub fund_status: Option<FundStatus>,
|
||||
pub mandate: Option<Mandate>,
|
||||
/// Indicates that a redirect to the payment method is not required. Some payment methods
|
||||
/// (for example, SEPA DirectDebit) provide the option to redirect the customer to a page to
|
||||
/// display additional information about the payment.
|
||||
pub optional_redirect: Option<f64>,
|
||||
/// A string used to identify the payment method provider being used to execute this
|
||||
/// transaction.
|
||||
pub provider: Option<ApmProvider>,
|
||||
/// A name of the payer from the payment method system.
|
||||
pub provider_payer_name: Option<String>,
|
||||
/// The time the payment method provider created the transaction at on their system.
|
||||
pub provider_time_created: Option<String>,
|
||||
/// The reference the payment method provider created for the transaction.
|
||||
pub provider_transaction_reference: Option<String>,
|
||||
/// URL to redirect the payer from the merchant's system to the payment method's system.
|
||||
pub redirect_url: Option<String>,
|
||||
/// A string generated by the payment method to represent the session created on the payment
|
||||
/// method's platform to facilitate the creation of a transaction.
|
||||
pub session_token: Option<String>,
|
||||
/// Indicates to instruct the payer to wait for an update at the time the transaction is
|
||||
/// being executed or that an update will be given later.
|
||||
pub wait_notification: Option<f64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Bank {
|
||||
/// The local identifier of the bank account.
|
||||
pub account_number: Option<String>,
|
||||
/// The local identifier of the bank.
|
||||
pub code: Option<String>,
|
||||
/// The international identifier of the bank account.
|
||||
pub iban: Option<String>,
|
||||
/// The international identifier code for the bank.
|
||||
pub identifier_code: Option<String>,
|
||||
/// The name assocaited with the bank account
|
||||
pub name: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Mandate {
|
||||
/// The reference to identify the mandate.
|
||||
pub code: Option<String>,
|
||||
}
|
||||
|
||||
/// Information outlining the degree of authentication executed related to a transaction.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Authentication {
|
||||
/// Information outlining the degree of 3D Secure authentication executed.
|
||||
pub three_ds: Option<ThreeDs>,
|
||||
}
|
||||
|
||||
/// Information outlining the degree of 3D Secure authentication executed.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ThreeDs {
|
||||
/// The result of the three_ds value validation by the brands or issuing bank.
|
||||
pub value_result: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct BankTransfer {
|
||||
/// The last 4 characters of the local reference for a bank account number.
|
||||
pub masked_number_last4: Option<String>,
|
||||
/// The name of the bank.
|
||||
pub name: Option<String>,
|
||||
/// The type of bank account associated with the payer's bank account.
|
||||
pub number_type: Option<NumberType>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Card {
|
||||
/// Code generated when the card is successfully authorized.
|
||||
pub authcode: Option<String>,
|
||||
/// The recommended AVS action to be taken by the agent processing the card transaction.
|
||||
pub avs_action: Option<String>,
|
||||
/// The result of the AVS address check.
|
||||
pub avs_address_result: Option<String>,
|
||||
/// The result of the AVS postal code check.
|
||||
pub avs_postal_code_result: Option<String>,
|
||||
/// Indicates the card brand that issued the card.
|
||||
pub brand: Option<Brand>,
|
||||
/// The unique reference created by the brands/schemes to uniquely identify the transaction.
|
||||
pub brand_reference: Option<String>,
|
||||
/// The time returned by the card brand indicating when the transaction was processed on
|
||||
/// their system.
|
||||
pub brand_time_reference: Option<String>,
|
||||
/// The result of the CVV check.
|
||||
pub cvv_result: Option<String>,
|
||||
/// Masked card number with last 4 digits showing.
|
||||
pub masked_number_last4: Option<String>,
|
||||
/// The result codes directly from the card issuer.
|
||||
pub provider: Option<ProviderClass>,
|
||||
/// The card EMV tag response data from the card issuer for a contactless or chip card
|
||||
/// transaction.
|
||||
pub tag_response: Option<String>,
|
||||
}
|
||||
|
||||
/// The result codes directly from the card issuer.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ProviderClass {
|
||||
/// The result code of the AVS address check from the card issuer.
|
||||
#[serde(rename = "card.provider.avs_address_result")]
|
||||
pub card_provider_avs_address_result: Option<String>,
|
||||
/// The result of the AVS postal code check from the card issuer..
|
||||
#[serde(rename = "card.provider.avs_postal_code_result")]
|
||||
pub card_provider_avs_postal_code_result: Option<String>,
|
||||
/// The result code of the AVS check from the card issuer.
|
||||
#[serde(rename = "card.provider.avs_result")]
|
||||
pub card_provider_avs_result: Option<String>,
|
||||
/// The result code of the CVV check from the card issuer.
|
||||
#[serde(rename = "card.provider.cvv_result")]
|
||||
pub card_provider_cvv_result: Option<String>,
|
||||
/// Result code from the card issuer.
|
||||
#[serde(rename = "card.provider.result")]
|
||||
pub card_provider_result: Option<String>,
|
||||
}
|
||||
|
||||
/// The result of the action executed.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum ResultCode {
|
||||
Declined,
|
||||
Success,
|
||||
}
|
||||
|
||||
/// A string generated by the payment method that represents to what degree the merchant is
|
||||
/// funded for the transaction.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum FundStatus {
|
||||
Missing,
|
||||
NotExpected,
|
||||
Received,
|
||||
Waiting,
|
||||
}
|
||||
|
||||
/// A string used to identify the payment method provider being used to execute this
|
||||
/// transaction.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum ApmProvider {
|
||||
Giropay,
|
||||
Ideal,
|
||||
Paypal,
|
||||
Sofort,
|
||||
Testpay,
|
||||
}
|
||||
|
||||
/// The type of bank account associated with the payer's bank account.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum NumberType {
|
||||
Checking,
|
||||
Savings,
|
||||
}
|
||||
|
||||
/// The recommended AVS action to be taken by the agent processing the card transaction.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum AvsAction {
|
||||
Accept,
|
||||
Decline,
|
||||
Prompt,
|
||||
}
|
||||
|
||||
/// The result of the AVS address check.
|
||||
///
|
||||
/// The result of the AVS postal code check.
|
||||
///
|
||||
/// The result of the CVV check.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum GlobalPayResult {
|
||||
Matched,
|
||||
NotChecked,
|
||||
NotMatched,
|
||||
}
|
||||
|
||||
/// Indicates the card brand that issued the card.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum Brand {
|
||||
Amex,
|
||||
Cup,
|
||||
Diners,
|
||||
Discover,
|
||||
Jcb,
|
||||
Mastercard,
|
||||
Visa,
|
||||
}
|
||||
|
||||
/// If enabled, this field indicates whether the payment method has been seen before or is
|
||||
/// new.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum FingerprintPresenceIndicator {
|
||||
/// Indicates that the payment method was seen on the platform before by this
|
||||
/// merchant.
|
||||
Exists,
|
||||
/// Indicates that the payment method was not seen on the platform before by this
|
||||
/// merchant.
|
||||
New,
|
||||
}
|
||||
|
||||
/// Indicates where a transaction is in its lifecycle.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum GlobalpayPaymentStatus {
|
||||
/// A Transaction has been successfully authorized and captured. The funding
|
||||
/// process will commence once the transaction remains in this status.
|
||||
Captured,
|
||||
/// A Transaction where the payment method provider declined the transfer of
|
||||
/// funds between the payer and the merchant.
|
||||
Declined,
|
||||
/// A Transaction where the funds have transferred between payer and merchant as
|
||||
/// expected.
|
||||
Funded,
|
||||
/// A Transaction has been successfully initiated. An update on its status is
|
||||
/// expected via a separate asynchronous notification to a webhook.
|
||||
Initiated,
|
||||
/// A Transaction has been sent to the payment method provider and are waiting
|
||||
/// for a result.
|
||||
Pending,
|
||||
/// A Transaction has been approved but a capture request is required to
|
||||
/// commence the movement of funds.
|
||||
Preauthorized,
|
||||
/// A Transaction where the funds were expected to transfer between payer and
|
||||
/// merchant but the transfer was rejected during the funding process. This rarely happens
|
||||
/// but when it does it is usually addressed by Global Payments operations.
|
||||
Rejected,
|
||||
/// A Transaction that had a status of PENDING, PREAUTHORIZED or CAPTURED has
|
||||
/// subsequently been reversed which voids/cancels a transaction before it is funded.
|
||||
Reversed,
|
||||
}
|
||||
188
crates/router/src/connector/globalpay/transformers.rs
Normal file
188
crates/router/src/connector/globalpay/transformers.rs
Normal file
@ -0,0 +1,188 @@
|
||||
use error_stack::ResultExt;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::{
|
||||
requests::{self, GlobalpayPaymentsRequest},
|
||||
response::{GlobalpayPaymentStatus, GlobalpayPaymentsResponse},
|
||||
};
|
||||
use crate::{
|
||||
connector::utils::{self, CardData, PaymentsRequestData},
|
||||
core::errors,
|
||||
types::{self, api, storage::enums},
|
||||
utils::OptionExt,
|
||||
};
|
||||
|
||||
impl TryFrom<&types::PaymentsAuthorizeRouterData> for GlobalpayPaymentsRequest {
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
|
||||
let metadata = item
|
||||
.connector_meta_data
|
||||
.to_owned()
|
||||
.get_required_value("connector_meta_data")
|
||||
.change_context(errors::ConnectorError::NoConnectorMetaData)?;
|
||||
let account_name = metadata
|
||||
.as_object()
|
||||
.and_then(|o| o.get("account_name"))
|
||||
.map(|o| o.to_string())
|
||||
.ok_or_else(utils::missing_field_err("connector_meta.account_name"))?;
|
||||
let card = item.get_card()?;
|
||||
Ok(Self {
|
||||
account_name,
|
||||
amount: Some(item.request.amount.to_string()),
|
||||
currency: item.request.currency.to_string(),
|
||||
reference: item.get_attempt_id()?,
|
||||
country: item.get_billing_country()?,
|
||||
capture_mode: item.request.capture_method.map(|f| match f {
|
||||
enums::CaptureMethod::Manual => requests::CaptureMode::Later,
|
||||
_ => requests::CaptureMode::Auto,
|
||||
}),
|
||||
payment_method: requests::PaymentMethod {
|
||||
card: Some(requests::Card {
|
||||
number: card.get_card_number(),
|
||||
expiry_month: card.get_card_expiry_month(),
|
||||
expiry_year: card.get_card_expiry_year_2_digit(),
|
||||
cvv: card.get_card_cvc(),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&types::PaymentsCaptureRouterData> for GlobalpayPaymentsRequest {
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(value: &types::PaymentsCaptureRouterData) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
amount: value
|
||||
.request
|
||||
.amount_to_capture
|
||||
.map(|amount| amount.to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&types::PaymentsCancelRouterData> for GlobalpayPaymentsRequest {
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(_value: &types::PaymentsCancelRouterData) -> Result<Self, Self::Error> {
|
||||
Ok(Self::default())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct GlobalpayAuthType {
|
||||
pub api_key: String,
|
||||
}
|
||||
|
||||
impl TryFrom<&types::ConnectorAuthType> for GlobalpayAuthType {
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(auth_type: &types::ConnectorAuthType) -> Result<Self, Self::Error> {
|
||||
match auth_type {
|
||||
types::ConnectorAuthType::HeaderKey { api_key } => Ok(Self {
|
||||
api_key: api_key.to_string(),
|
||||
}),
|
||||
_ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GlobalpayPaymentStatus> for enums::AttemptStatus {
|
||||
fn from(item: GlobalpayPaymentStatus) -> Self {
|
||||
match item {
|
||||
GlobalpayPaymentStatus::Captured | GlobalpayPaymentStatus::Funded => Self::Charged,
|
||||
GlobalpayPaymentStatus::Declined | GlobalpayPaymentStatus::Rejected => Self::Failure,
|
||||
GlobalpayPaymentStatus::Preauthorized => Self::Authorized,
|
||||
GlobalpayPaymentStatus::Reversed => Self::Voided,
|
||||
GlobalpayPaymentStatus::Initiated | GlobalpayPaymentStatus::Pending => Self::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GlobalpayPaymentStatus> for enums::RefundStatus {
|
||||
fn from(item: GlobalpayPaymentStatus) -> Self {
|
||||
match item {
|
||||
GlobalpayPaymentStatus::Captured | GlobalpayPaymentStatus::Funded => Self::Success,
|
||||
GlobalpayPaymentStatus::Declined | GlobalpayPaymentStatus::Rejected => Self::Failure,
|
||||
GlobalpayPaymentStatus::Initiated | GlobalpayPaymentStatus::Pending => Self::Pending,
|
||||
_ => Self::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, T>
|
||||
TryFrom<types::ResponseRouterData<F, GlobalpayPaymentsResponse, T, types::PaymentsResponseData>>
|
||||
for types::RouterData<F, T, types::PaymentsResponseData>
|
||||
{
|
||||
type Error = error_stack::Report<errors::ParsingError>;
|
||||
fn try_from(
|
||||
item: types::ResponseRouterData<
|
||||
F,
|
||||
GlobalpayPaymentsResponse,
|
||||
T,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
status: enums::AttemptStatus::from(item.response.status),
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
..item.data
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> TryFrom<&types::RefundsRouterData<F>> for requests::GlobalpayRefundRequest {
|
||||
type Error = error_stack::Report<errors::ParsingError>;
|
||||
fn try_from(item: &types::RefundsRouterData<F>) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
amount: item.request.refund_amount.to_string(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<types::RefundsResponseRouterData<api::Execute, GlobalpayPaymentsResponse>>
|
||||
for types::RefundExecuteRouterData
|
||||
{
|
||||
type Error = error_stack::Report<errors::ParsingError>;
|
||||
fn try_from(
|
||||
item: types::RefundsResponseRouterData<api::Execute, GlobalpayPaymentsResponse>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
response: Ok(types::RefundsResponseData {
|
||||
connector_refund_id: item.response.id,
|
||||
refund_status: enums::RefundStatus::from(item.response.status),
|
||||
}),
|
||||
..item.data
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<types::RefundsResponseRouterData<api::RSync, GlobalpayPaymentsResponse>>
|
||||
for types::RefundsRouterData<api::RSync>
|
||||
{
|
||||
type Error = error_stack::Report<errors::ParsingError>;
|
||||
fn try_from(
|
||||
item: types::RefundsResponseRouterData<api::RSync, GlobalpayPaymentsResponse>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
response: Ok(types::RefundsResponseData {
|
||||
connector_refund_id: item.response.id,
|
||||
refund_status: enums::RefundStatus::from(item.response.status),
|
||||
}),
|
||||
..item.data
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
|
||||
pub struct GlobalpayErrorResponse {
|
||||
pub error_code: String,
|
||||
pub detailed_error_code: String,
|
||||
pub detailed_error_description: String,
|
||||
}
|
||||
72
crates/router/src/connector/utils.rs
Normal file
72
crates/router/src/connector/utils.rs
Normal file
@ -0,0 +1,72 @@
|
||||
use crate::{
|
||||
core::errors,
|
||||
pii::PeekInterface,
|
||||
types::{self, api},
|
||||
};
|
||||
|
||||
pub fn missing_field_err(
|
||||
message: &str,
|
||||
) -> Box<dyn Fn() -> error_stack::Report<errors::ConnectorError> + '_> {
|
||||
Box::new(|| {
|
||||
errors::ConnectorError::MissingRequiredField {
|
||||
field_name: message.to_string(),
|
||||
}
|
||||
.into()
|
||||
})
|
||||
}
|
||||
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
pub trait PaymentsRequestData {
|
||||
fn get_attempt_id(&self) -> Result<String, Error>;
|
||||
fn get_billing_country(&self) -> Result<String, Error>;
|
||||
fn get_card(&self) -> Result<api::CCard, Error>;
|
||||
}
|
||||
|
||||
pub trait CardData {
|
||||
fn get_card_number(&self) -> String;
|
||||
fn get_card_expiry_month(&self) -> String;
|
||||
fn get_card_expiry_year(&self) -> String;
|
||||
fn get_card_expiry_year_2_digit(&self) -> String;
|
||||
fn get_card_cvc(&self) -> String;
|
||||
}
|
||||
impl CardData for api::CCard {
|
||||
fn get_card_number(&self) -> String {
|
||||
self.card_number.peek().clone()
|
||||
}
|
||||
fn get_card_expiry_month(&self) -> String {
|
||||
self.card_exp_month.peek().clone()
|
||||
}
|
||||
fn get_card_expiry_year(&self) -> String {
|
||||
self.card_exp_year.peek().clone()
|
||||
}
|
||||
fn get_card_expiry_year_2_digit(&self) -> String {
|
||||
let year = self.card_exp_year.peek().clone();
|
||||
year[year.len() - 2..].to_string()
|
||||
}
|
||||
fn get_card_cvc(&self) -> String {
|
||||
self.card_cvc.peek().clone()
|
||||
}
|
||||
}
|
||||
impl PaymentsRequestData for types::PaymentsAuthorizeRouterData {
|
||||
fn get_attempt_id(&self) -> Result<String, Error> {
|
||||
self.attempt_id
|
||||
.clone()
|
||||
.ok_or_else(missing_field_err("attempt_id"))
|
||||
}
|
||||
|
||||
fn get_billing_country(&self) -> Result<String, Error> {
|
||||
self.address
|
||||
.billing
|
||||
.clone()
|
||||
.and_then(|a| a.address)
|
||||
.and_then(|ad| ad.country)
|
||||
.ok_or_else(missing_field_err("billing.country"))
|
||||
}
|
||||
|
||||
fn get_card(&self) -> Result<api::CCard, Error> {
|
||||
match self.request.payment_method_data.clone() {
|
||||
api::PaymentMethod::Card(card) => Ok(card),
|
||||
_ => Err(missing_field_err("card")()),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -150,6 +150,7 @@ impl ConnectorData {
|
||||
"cybersource" => Ok(Box::new(&connector::Cybersource)),
|
||||
"shift4" => Ok(Box::new(&connector::Shift4)),
|
||||
"worldpay" => Ok(Box::new(&connector::Worldpay)),
|
||||
"globalpay" => Ok(Box::new(&connector::Globalpay)),
|
||||
_ => Err(report!(errors::UnexpectedError)
|
||||
.attach_printable(format!("invalid connector name: {connector_name}")))
|
||||
.change_context(errors::ConnectorError::InvalidConnectorName)
|
||||
|
||||
@ -6,6 +6,7 @@ pub(crate) struct ConnectorAuthentication {
|
||||
pub aci: Option<BodyKey>,
|
||||
pub authorizedotnet: Option<BodyKey>,
|
||||
pub checkout: Option<BodyKey>,
|
||||
pub globalpay: Option<HeaderKey>,
|
||||
pub shift4: Option<HeaderKey>,
|
||||
pub worldpay: Option<HeaderKey>,
|
||||
}
|
||||
|
||||
193
crates/router/tests/connectors/globalpay.rs
Normal file
193
crates/router/tests/connectors/globalpay.rs
Normal file
@ -0,0 +1,193 @@
|
||||
use std::{thread::sleep, time::Duration};
|
||||
|
||||
use futures::future::OptionFuture;
|
||||
use masking::Secret;
|
||||
use router::types::{
|
||||
self,
|
||||
api::{self},
|
||||
storage::enums,
|
||||
};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{
|
||||
connector_auth,
|
||||
utils::{self, ConnectorActions, PaymentInfo},
|
||||
};
|
||||
|
||||
struct Globalpay;
|
||||
impl ConnectorActions for Globalpay {}
|
||||
impl utils::Connector for Globalpay {
|
||||
fn get_data(&self) -> types::api::ConnectorData {
|
||||
use router::connector::Globalpay;
|
||||
types::api::ConnectorData {
|
||||
connector: Box::new(&Globalpay),
|
||||
connector_name: types::Connector::Globalpay,
|
||||
get_token: types::api::GetToken::Connector,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_auth_token(&self) -> types::ConnectorAuthType {
|
||||
types::ConnectorAuthType::from(
|
||||
connector_auth::ConnectorAuthentication::new()
|
||||
.globalpay
|
||||
.expect("Missing connector authentication configuration"),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_name(&self) -> String {
|
||||
"globalpay".to_string()
|
||||
}
|
||||
|
||||
fn get_connector_meta(&self) -> Option<serde_json::Value> {
|
||||
Some(json!({"account_name": "transaction_processing"}))
|
||||
}
|
||||
}
|
||||
|
||||
fn get_default_payment_info() -> Option<PaymentInfo> {
|
||||
Some(PaymentInfo {
|
||||
address: Some(types::PaymentAddress {
|
||||
billing: Some(api::Address {
|
||||
address: Some(api::AddressDetails {
|
||||
country: Some("US".to_string()),
|
||||
..Default::default()
|
||||
}),
|
||||
phone: None,
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
auth_type: None,
|
||||
})
|
||||
}
|
||||
|
||||
#[actix_web::test]
|
||||
async fn should_only_authorize_payment() {
|
||||
let response = Globalpay {}
|
||||
.authorize_payment(None, get_default_payment_info())
|
||||
.await;
|
||||
assert_eq!(response.status, enums::AttemptStatus::Authorized);
|
||||
}
|
||||
|
||||
#[actix_web::test]
|
||||
async fn should_authorize_and_capture_payment() {
|
||||
let response = Globalpay {}
|
||||
.make_payment(None, get_default_payment_info())
|
||||
.await;
|
||||
assert_eq!(response.status, enums::AttemptStatus::Charged);
|
||||
}
|
||||
|
||||
#[actix_web::test]
|
||||
async fn should_capture_already_authorized_payment() {
|
||||
let connector = Globalpay {};
|
||||
let authorize_response = connector
|
||||
.authorize_payment(None, get_default_payment_info())
|
||||
.await;
|
||||
assert_eq!(authorize_response.status, enums::AttemptStatus::Authorized);
|
||||
let txn_id = utils::get_connector_transaction_id(authorize_response);
|
||||
let response: OptionFuture<_> = txn_id
|
||||
.map(|transaction_id| async move {
|
||||
connector
|
||||
.capture_payment(transaction_id, None, get_default_payment_info())
|
||||
.await
|
||||
.status
|
||||
})
|
||||
.into();
|
||||
assert_eq!(response.await, Some(enums::AttemptStatus::Charged));
|
||||
}
|
||||
|
||||
#[actix_web::test]
|
||||
async fn should_sync_payment() {
|
||||
let connector = Globalpay {};
|
||||
let authorize_response = connector
|
||||
.authorize_payment(None, get_default_payment_info())
|
||||
.await;
|
||||
let txn_id = utils::get_connector_transaction_id(authorize_response);
|
||||
sleep(Duration::from_secs(5)); // to avoid 404 error as globalpay takes some time to process the new transaction
|
||||
let response = connector
|
||||
.sync_payment(
|
||||
Some(types::PaymentsSyncData {
|
||||
connector_transaction_id: router::types::ResponseId::ConnectorTransactionId(
|
||||
txn_id.unwrap(),
|
||||
),
|
||||
encoded_data: None,
|
||||
}),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
assert_eq!(response.status, enums::AttemptStatus::Authorized,);
|
||||
}
|
||||
|
||||
#[actix_web::test]
|
||||
async fn should_fail_payment_for_incorrect_cvc() {
|
||||
let response = Globalpay {}
|
||||
.make_payment(
|
||||
Some(types::PaymentsAuthorizeData {
|
||||
payment_method_data: types::api::PaymentMethod::Card(api::CCard {
|
||||
card_number: Secret::new("4024007134364842".to_string()),
|
||||
..utils::CCardType::default().0
|
||||
}),
|
||||
..utils::PaymentAuthorizeType::default().0
|
||||
}),
|
||||
get_default_payment_info(),
|
||||
)
|
||||
.await;
|
||||
let x = response.status;
|
||||
assert_eq!(x, enums::AttemptStatus::Failure);
|
||||
}
|
||||
|
||||
#[actix_web::test]
|
||||
async fn should_refund_succeeded_payment() {
|
||||
let connector = Globalpay {};
|
||||
//make a successful payment
|
||||
let response = connector
|
||||
.make_payment(None, get_default_payment_info())
|
||||
.await;
|
||||
|
||||
//try refund for previous payment
|
||||
let transaction_id = utils::get_connector_transaction_id(response).unwrap();
|
||||
let response = connector
|
||||
.refund_payment(transaction_id, None, get_default_payment_info())
|
||||
.await;
|
||||
assert_eq!(
|
||||
response.response.unwrap().refund_status,
|
||||
enums::RefundStatus::Success,
|
||||
);
|
||||
}
|
||||
|
||||
#[actix_web::test]
|
||||
async fn should_void_already_authorized_payment() {
|
||||
let connector = Globalpay {};
|
||||
let authorize_response = connector
|
||||
.authorize_payment(None, get_default_payment_info())
|
||||
.await;
|
||||
assert_eq!(authorize_response.status, enums::AttemptStatus::Authorized);
|
||||
let txn_id = utils::get_connector_transaction_id(authorize_response);
|
||||
let response: OptionFuture<_> = txn_id
|
||||
.map(|transaction_id| async move {
|
||||
connector
|
||||
.void_payment(transaction_id, None, None)
|
||||
.await
|
||||
.status
|
||||
})
|
||||
.into();
|
||||
assert_eq!(response.await, Some(enums::AttemptStatus::Voided));
|
||||
}
|
||||
|
||||
#[actix_web::test]
|
||||
async fn should_sync_refund() {
|
||||
let connector = Globalpay {};
|
||||
let response = connector
|
||||
.make_payment(None, get_default_payment_info())
|
||||
.await;
|
||||
let transaction_id = utils::get_connector_transaction_id(response).unwrap();
|
||||
connector
|
||||
.refund_payment(transaction_id.clone(), None, get_default_payment_info())
|
||||
.await;
|
||||
sleep(Duration::from_secs(5)); // to avoid 404 error as globalpay takes some time to process the new transaction
|
||||
let response = connector
|
||||
.sync_refund(transaction_id, None, get_default_payment_info())
|
||||
.await;
|
||||
assert_eq!(
|
||||
response.response.unwrap().refund_status,
|
||||
enums::RefundStatus::Success,
|
||||
);
|
||||
}
|
||||
@ -4,6 +4,7 @@ mod aci;
|
||||
mod authorizedotnet;
|
||||
mod checkout;
|
||||
mod connector_auth;
|
||||
mod globalpay;
|
||||
mod shift4;
|
||||
mod utils;
|
||||
mod worldpay;
|
||||
|
||||
@ -18,3 +18,6 @@ api_key = "Bearer MyApiKey"
|
||||
|
||||
[worldpay]
|
||||
api_key = "Bearer MyApiKey"
|
||||
|
||||
[globalpay]
|
||||
api_key = "Bearer MyApiKey"
|
||||
|
||||
@ -34,25 +34,28 @@ impl utils::Connector for Shift4 {
|
||||
|
||||
#[actix_web::test]
|
||||
async fn should_only_authorize_payment() {
|
||||
let response = Shift4 {}.authorize_payment(None).await;
|
||||
let response = Shift4 {}.authorize_payment(None, None).await;
|
||||
assert_eq!(response.status, enums::AttemptStatus::Authorized);
|
||||
}
|
||||
|
||||
#[actix_web::test]
|
||||
async fn should_authorize_and_capture_payment() {
|
||||
let response = Shift4 {}.make_payment(None).await;
|
||||
let response = Shift4 {}.make_payment(None, None).await;
|
||||
assert_eq!(response.status, enums::AttemptStatus::Charged);
|
||||
}
|
||||
|
||||
#[actix_web::test]
|
||||
async fn should_capture_already_authorized_payment() {
|
||||
let connector = Shift4 {};
|
||||
let authorize_response = connector.authorize_payment(None).await;
|
||||
let authorize_response = connector.authorize_payment(None, None).await;
|
||||
assert_eq!(authorize_response.status, enums::AttemptStatus::Authorized);
|
||||
let txn_id = utils::get_connector_transaction_id(authorize_response);
|
||||
let response: OptionFuture<_> = txn_id
|
||||
.map(|transaction_id| async move {
|
||||
connector.capture_payment(transaction_id, None).await.status
|
||||
connector
|
||||
.capture_payment(transaction_id, None, None)
|
||||
.await
|
||||
.status
|
||||
})
|
||||
.into();
|
||||
assert_eq!(response.await, Some(enums::AttemptStatus::Charged));
|
||||
@ -61,13 +64,16 @@ async fn should_capture_already_authorized_payment() {
|
||||
#[actix_web::test]
|
||||
async fn should_fail_payment_for_incorrect_cvc() {
|
||||
let response = Shift4 {}
|
||||
.make_payment(Some(types::PaymentsAuthorizeData {
|
||||
.make_payment(
|
||||
Some(types::PaymentsAuthorizeData {
|
||||
payment_method_data: types::api::PaymentMethod::Card(api::CCard {
|
||||
card_number: Secret::new("4024007134364842".to_string()),
|
||||
..utils::CCardType::default().0
|
||||
}),
|
||||
..utils::PaymentAuthorizeType::default().0
|
||||
}))
|
||||
}),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
let x = response.response.unwrap_err();
|
||||
assert_eq!(
|
||||
@ -80,11 +86,11 @@ async fn should_fail_payment_for_incorrect_cvc() {
|
||||
async fn should_refund_succeeded_payment() {
|
||||
let connector = Shift4 {};
|
||||
//make a successful payment
|
||||
let response = connector.make_payment(None).await;
|
||||
let response = connector.make_payment(None, None).await;
|
||||
|
||||
//try refund for previous payment
|
||||
if let Some(transaction_id) = utils::get_connector_transaction_id(response) {
|
||||
let response = connector.refund_payment(transaction_id, None).await;
|
||||
let response = connector.refund_payment(transaction_id, None, None).await;
|
||||
assert_eq!(
|
||||
response.response.unwrap().refund_status,
|
||||
enums::RefundStatus::Success,
|
||||
|
||||
@ -14,6 +14,15 @@ pub trait Connector {
|
||||
fn get_data(&self) -> types::api::ConnectorData;
|
||||
fn get_auth_token(&self) -> types::ConnectorAuthType;
|
||||
fn get_name(&self) -> String;
|
||||
fn get_connector_meta(&self) -> Option<serde_json::Value> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct PaymentInfo {
|
||||
pub address: Option<PaymentAddress>,
|
||||
pub auth_type: Option<enums::AuthenticationType>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
@ -21,29 +30,27 @@ pub trait ConnectorActions: Connector {
|
||||
async fn authorize_payment(
|
||||
&self,
|
||||
payment_data: Option<types::PaymentsAuthorizeData>,
|
||||
payment_info: Option<PaymentInfo>,
|
||||
) -> types::PaymentsAuthorizeRouterData {
|
||||
let integration = self.get_data().connector.get_connector_integration();
|
||||
let request = generate_data(
|
||||
self.get_name(),
|
||||
self.get_auth_token(),
|
||||
enums::AuthenticationType::NoThreeDs,
|
||||
let request = self.generate_data(
|
||||
payment_data.unwrap_or_else(|| types::PaymentsAuthorizeData {
|
||||
capture_method: Some(storage_models::enums::CaptureMethod::Manual),
|
||||
..PaymentAuthorizeType::default().0
|
||||
}),
|
||||
payment_info,
|
||||
);
|
||||
call_connector(request, integration).await
|
||||
}
|
||||
async fn make_payment(
|
||||
&self,
|
||||
payment_data: Option<types::PaymentsAuthorizeData>,
|
||||
payment_info: Option<PaymentInfo>,
|
||||
) -> types::PaymentsAuthorizeRouterData {
|
||||
let integration = self.get_data().connector.get_connector_integration();
|
||||
let request = generate_data(
|
||||
self.get_name(),
|
||||
self.get_auth_token(),
|
||||
enums::AuthenticationType::NoThreeDs,
|
||||
let request = self.generate_data(
|
||||
payment_data.unwrap_or_else(|| PaymentAuthorizeType::default().0),
|
||||
payment_info,
|
||||
);
|
||||
call_connector(request, integration).await
|
||||
}
|
||||
@ -51,13 +58,12 @@ pub trait ConnectorActions: Connector {
|
||||
async fn sync_payment(
|
||||
&self,
|
||||
payment_data: Option<types::PaymentsSyncData>,
|
||||
payment_info: Option<PaymentInfo>,
|
||||
) -> types::PaymentsSyncRouterData {
|
||||
let integration = self.get_data().connector.get_connector_integration();
|
||||
let request = generate_data(
|
||||
self.get_name(),
|
||||
self.get_auth_token(),
|
||||
enums::AuthenticationType::NoThreeDs,
|
||||
let request = self.generate_data(
|
||||
payment_data.unwrap_or_else(|| PaymentSyncType::default().0),
|
||||
payment_info,
|
||||
);
|
||||
call_connector(request, integration).await
|
||||
}
|
||||
@ -66,18 +72,17 @@ pub trait ConnectorActions: Connector {
|
||||
&self,
|
||||
transaction_id: String,
|
||||
payment_data: Option<types::PaymentsCaptureData>,
|
||||
payment_info: Option<PaymentInfo>,
|
||||
) -> types::PaymentsCaptureRouterData {
|
||||
let integration = self.get_data().connector.get_connector_integration();
|
||||
let request = generate_data(
|
||||
self.get_name(),
|
||||
self.get_auth_token(),
|
||||
enums::AuthenticationType::NoThreeDs,
|
||||
let request = self.generate_data(
|
||||
payment_data.unwrap_or(types::PaymentsCaptureData {
|
||||
amount_to_capture: Some(100),
|
||||
connector_transaction_id: transaction_id,
|
||||
currency: enums::Currency::USD,
|
||||
amount: 100,
|
||||
}),
|
||||
payment_info,
|
||||
);
|
||||
call_connector(request, integration).await
|
||||
}
|
||||
@ -86,16 +91,15 @@ pub trait ConnectorActions: Connector {
|
||||
&self,
|
||||
transaction_id: String,
|
||||
payment_data: Option<types::PaymentsCancelData>,
|
||||
payment_info: Option<PaymentInfo>,
|
||||
) -> types::PaymentsCancelRouterData {
|
||||
let integration = self.get_data().connector.get_connector_integration();
|
||||
let request = generate_data(
|
||||
self.get_name(),
|
||||
self.get_auth_token(),
|
||||
enums::AuthenticationType::NoThreeDs,
|
||||
let request = self.generate_data(
|
||||
payment_data.unwrap_or(types::PaymentsCancelData {
|
||||
connector_transaction_id: transaction_id,
|
||||
cancellation_reason: Some("Test cancellation".to_string()),
|
||||
}),
|
||||
payment_info,
|
||||
);
|
||||
call_connector(request, integration).await
|
||||
}
|
||||
@ -104,12 +108,10 @@ pub trait ConnectorActions: Connector {
|
||||
&self,
|
||||
transaction_id: String,
|
||||
payment_data: Option<types::RefundsData>,
|
||||
payment_info: Option<PaymentInfo>,
|
||||
) -> types::RefundExecuteRouterData {
|
||||
let integration = self.get_data().connector.get_connector_integration();
|
||||
let request = generate_data(
|
||||
self.get_name(),
|
||||
self.get_auth_token(),
|
||||
enums::AuthenticationType::NoThreeDs,
|
||||
let request = self.generate_data(
|
||||
payment_data.unwrap_or_else(|| types::RefundsData {
|
||||
amount: 100,
|
||||
currency: enums::Currency::USD,
|
||||
@ -119,6 +121,7 @@ pub trait ConnectorActions: Connector {
|
||||
connector_metadata: None,
|
||||
reason: None,
|
||||
}),
|
||||
payment_info,
|
||||
);
|
||||
call_connector(request, integration).await
|
||||
}
|
||||
@ -127,12 +130,10 @@ pub trait ConnectorActions: Connector {
|
||||
&self,
|
||||
transaction_id: String,
|
||||
payment_data: Option<types::RefundsData>,
|
||||
payment_info: Option<PaymentInfo>,
|
||||
) -> types::RefundSyncRouterData {
|
||||
let integration = self.get_data().connector.get_connector_integration();
|
||||
let request = generate_data(
|
||||
self.get_name(),
|
||||
self.get_auth_token(),
|
||||
enums::AuthenticationType::NoThreeDs,
|
||||
let request = self.generate_data(
|
||||
payment_data.unwrap_or_else(|| types::RefundsData {
|
||||
amount: 100,
|
||||
currency: enums::Currency::USD,
|
||||
@ -142,9 +143,42 @@ pub trait ConnectorActions: Connector {
|
||||
connector_metadata: None,
|
||||
reason: None,
|
||||
}),
|
||||
payment_info,
|
||||
);
|
||||
call_connector(request, integration).await
|
||||
}
|
||||
|
||||
fn generate_data<Flow, Req: From<Req>, Res>(
|
||||
&self,
|
||||
req: Req,
|
||||
info: Option<PaymentInfo>,
|
||||
) -> types::RouterData<Flow, Req, Res> {
|
||||
types::RouterData {
|
||||
flow: PhantomData,
|
||||
merchant_id: self.get_name(),
|
||||
connector: self.get_name(),
|
||||
payment_id: uuid::Uuid::new_v4().to_string(),
|
||||
attempt_id: Some(uuid::Uuid::new_v4().to_string()),
|
||||
status: enums::AttemptStatus::default(),
|
||||
router_return_url: None,
|
||||
auth_type: info
|
||||
.clone()
|
||||
.map_or(enums::AuthenticationType::NoThreeDs, |a| {
|
||||
a.auth_type
|
||||
.map_or(enums::AuthenticationType::NoThreeDs, |a| a)
|
||||
}),
|
||||
payment_method: enums::PaymentMethodType::Card,
|
||||
connector_auth_type: self.get_auth_token(),
|
||||
description: Some("This is a test".to_string()),
|
||||
return_url: None,
|
||||
request: req,
|
||||
response: Err(types::ErrorResponse::default()),
|
||||
payment_method_id: None,
|
||||
address: info.map_or(PaymentAddress::default(), |a| a.address.unwrap()),
|
||||
connector_meta_data: self.get_connector_meta(),
|
||||
amount_captured: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn call_connector<
|
||||
@ -268,31 +302,3 @@ pub fn get_connector_transaction_id(
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_data<Flow, Req: From<Req>, Res>(
|
||||
connector: String,
|
||||
connector_auth_type: types::ConnectorAuthType,
|
||||
auth_type: enums::AuthenticationType,
|
||||
req: Req,
|
||||
) -> types::RouterData<Flow, Req, Res> {
|
||||
types::RouterData {
|
||||
flow: PhantomData,
|
||||
merchant_id: connector.clone(),
|
||||
connector,
|
||||
payment_id: uuid::Uuid::new_v4().to_string(),
|
||||
attempt_id: Some(uuid::Uuid::new_v4().to_string()),
|
||||
status: enums::AttemptStatus::default(),
|
||||
router_return_url: None,
|
||||
auth_type,
|
||||
payment_method: enums::PaymentMethodType::Card,
|
||||
connector_auth_type,
|
||||
description: Some("This is a test".to_string()),
|
||||
return_url: None,
|
||||
request: req,
|
||||
response: Err(types::ErrorResponse::default()),
|
||||
payment_method_id: None,
|
||||
address: PaymentAddress::default(),
|
||||
connector_meta_data: None,
|
||||
amount_captured: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ impl utils::Connector for Worldpay {
|
||||
async fn should_authorize_card_payment() {
|
||||
let conn = Worldpay {};
|
||||
let _mock = conn.start_server(get_mock_config()).await;
|
||||
let response = conn.authorize_payment(None).await;
|
||||
let response = conn.authorize_payment(None, None).await;
|
||||
assert_eq!(response.status, enums::AttemptStatus::Authorized);
|
||||
assert_eq!(
|
||||
utils::get_connector_transaction_id(response),
|
||||
@ -62,13 +62,16 @@ async fn should_authorize_gpay_payment() {
|
||||
let conn = Worldpay {};
|
||||
let _mock = conn.start_server(get_mock_config()).await;
|
||||
let response = conn
|
||||
.authorize_payment(Some(types::PaymentsAuthorizeData {
|
||||
.authorize_payment(
|
||||
Some(types::PaymentsAuthorizeData {
|
||||
payment_method_data: types::api::PaymentMethod::Wallet(api::WalletData {
|
||||
issuer_name: api_enums::WalletIssuer::GooglePay,
|
||||
token: Some("someToken".to_string()),
|
||||
}),
|
||||
..utils::PaymentAuthorizeType::default().0
|
||||
}))
|
||||
}),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
assert_eq!(response.status, enums::AttemptStatus::Authorized);
|
||||
assert_eq!(
|
||||
@ -83,13 +86,16 @@ async fn should_authorize_applepay_payment() {
|
||||
let conn = Worldpay {};
|
||||
let _mock = conn.start_server(get_mock_config()).await;
|
||||
let response = conn
|
||||
.authorize_payment(Some(types::PaymentsAuthorizeData {
|
||||
.authorize_payment(
|
||||
Some(types::PaymentsAuthorizeData {
|
||||
payment_method_data: types::api::PaymentMethod::Wallet(api::WalletData {
|
||||
issuer_name: api_enums::WalletIssuer::ApplePay,
|
||||
token: Some("someToken".to_string()),
|
||||
}),
|
||||
..utils::PaymentAuthorizeType::default().0
|
||||
}))
|
||||
}),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
assert_eq!(response.status, enums::AttemptStatus::Authorized);
|
||||
assert_eq!(
|
||||
@ -103,12 +109,15 @@ async fn should_authorize_applepay_payment() {
|
||||
async fn should_capture_already_authorized_payment() {
|
||||
let connector = Worldpay {};
|
||||
let _mock = connector.start_server(get_mock_config()).await;
|
||||
let authorize_response = connector.authorize_payment(None).await;
|
||||
let authorize_response = connector.authorize_payment(None, None).await;
|
||||
assert_eq!(authorize_response.status, enums::AttemptStatus::Authorized);
|
||||
let txn_id = utils::get_connector_transaction_id(authorize_response);
|
||||
let response: OptionFuture<_> = txn_id
|
||||
.map(|transaction_id| async move {
|
||||
connector.capture_payment(transaction_id, None).await.status
|
||||
connector
|
||||
.capture_payment(transaction_id, None, None)
|
||||
.await
|
||||
.status
|
||||
})
|
||||
.into();
|
||||
assert_eq!(response.await, Some(enums::AttemptStatus::Charged));
|
||||
@ -120,12 +129,15 @@ async fn should_sync_payment() {
|
||||
let connector = Worldpay {};
|
||||
let _mock = connector.start_server(get_mock_config()).await;
|
||||
let response = connector
|
||||
.sync_payment(Some(types::PaymentsSyncData {
|
||||
.sync_payment(
|
||||
Some(types::PaymentsSyncData {
|
||||
connector_transaction_id: router::types::ResponseId::ConnectorTransactionId(
|
||||
"112233".to_string(),
|
||||
),
|
||||
encoded_data: None,
|
||||
}))
|
||||
}),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
assert_eq!(response.status, enums::AttemptStatus::Authorized,);
|
||||
}
|
||||
@ -135,13 +147,15 @@ async fn should_sync_payment() {
|
||||
async fn should_void_already_authorized_payment() {
|
||||
let connector = Worldpay {};
|
||||
let _mock = connector.start_server(get_mock_config()).await;
|
||||
let authorize_response = connector.authorize_payment(None).await;
|
||||
let authorize_response = connector.authorize_payment(None, None).await;
|
||||
assert_eq!(authorize_response.status, enums::AttemptStatus::Authorized);
|
||||
let txn_id = utils::get_connector_transaction_id(authorize_response);
|
||||
let response: OptionFuture<_> =
|
||||
txn_id
|
||||
let response: OptionFuture<_> = txn_id
|
||||
.map(|transaction_id| async move {
|
||||
connector.void_payment(transaction_id, None).await.status
|
||||
connector
|
||||
.void_payment(transaction_id, None, None)
|
||||
.await
|
||||
.status
|
||||
})
|
||||
.into();
|
||||
assert_eq!(response.await, Some(enums::AttemptStatus::Voided));
|
||||
@ -152,9 +166,11 @@ async fn should_void_already_authorized_payment() {
|
||||
async fn should_fail_capture_for_invalid_payment() {
|
||||
let connector = Worldpay {};
|
||||
let _mock = connector.start_server(get_mock_config()).await;
|
||||
let authorize_response = connector.authorize_payment(None).await;
|
||||
let authorize_response = connector.authorize_payment(None, None).await;
|
||||
assert_eq!(authorize_response.status, enums::AttemptStatus::Authorized);
|
||||
let response = connector.capture_payment("12345".to_string(), None).await;
|
||||
let response = connector
|
||||
.capture_payment("12345".to_string(), None, None)
|
||||
.await;
|
||||
let err = response.response.unwrap_err();
|
||||
assert_eq!(
|
||||
err.message,
|
||||
@ -169,11 +185,11 @@ async fn should_refund_succeeded_payment() {
|
||||
let connector = Worldpay {};
|
||||
let _mock = connector.start_server(get_mock_config()).await;
|
||||
//make a successful payment
|
||||
let response = connector.make_payment(None).await;
|
||||
let response = connector.make_payment(None, None).await;
|
||||
|
||||
//try refund for previous payment
|
||||
let transaction_id = utils::get_connector_transaction_id(response).unwrap();
|
||||
let response = connector.refund_payment(transaction_id, None).await;
|
||||
let response = connector.refund_payment(transaction_id, None, None).await;
|
||||
assert_eq!(
|
||||
response.response.unwrap().refund_status,
|
||||
enums::RefundStatus::Success,
|
||||
@ -185,7 +201,9 @@ async fn should_refund_succeeded_payment() {
|
||||
async fn should_sync_refund() {
|
||||
let connector = Worldpay {};
|
||||
let _mock = connector.start_server(get_mock_config()).await;
|
||||
let response = connector.sync_refund("654321".to_string(), None).await;
|
||||
let response = connector
|
||||
.sync_refund("654321".to_string(), None, None)
|
||||
.await;
|
||||
assert_eq!(
|
||||
response.response.unwrap().refund_status,
|
||||
enums::RefundStatus::Success,
|
||||
|
||||
@ -64,6 +64,18 @@ base_url = "http://stripe-mock:12111/"
|
||||
[connectors.braintree]
|
||||
base_url = "https://api.sandbox.braintreegateway.com/"
|
||||
|
||||
[connectors.cybersource]
|
||||
base_url = "https://apitest.cybersource.com/"
|
||||
|
||||
[connectors.shift4]
|
||||
base_url = "https://api.shift4.com/"
|
||||
|
||||
[connectors.worldpay]
|
||||
base_url = "https://try.access.worldpay.com/"
|
||||
|
||||
[connectors.globalpay]
|
||||
base_url = "https://apis.sandbox.globalpay.com/ucp/"
|
||||
|
||||
[connectors.applepay]
|
||||
base_url = "https://apple-pay-gateway.apple.com/"
|
||||
|
||||
@ -71,5 +83,5 @@ base_url = "https://apple-pay-gateway.apple.com/"
|
||||
base_url = "https://api-na.playground.klarna.com/"
|
||||
|
||||
[connectors.supported]
|
||||
wallets = ["klarna","braintree","applepay"]
|
||||
cards = ["stripe","adyen","authorizedotnet","checkout","braintree"]
|
||||
wallets = ["klarna", "braintree", "applepay"]
|
||||
cards = ["stripe", "adyen", "authorizedotnet", "checkout", "braintree", "cybersource", "shift4", "worldpay", "globalpay"]
|
||||
|
||||
@ -11,7 +11,7 @@ fi
|
||||
cd $SCRIPT/..
|
||||
# remove template files if already created for this connector
|
||||
rm -rf $conn/$pg $conn/$pg.rs
|
||||
git checkout $conn.rs $src/types/api.rs $src/configs/settings.rs config/Development.toml config/docker_compose.toml crates/api_models/src/enums.rs
|
||||
git checkout $conn.rs $src/types/api.rs $src/configs/settings.rs config/Development.toml config/docker_compose.toml config/config.example.toml loadtest/config/Development.toml crates/router/src/configs/defaults.toml crates/api_models/src/enums.rs
|
||||
# add enum for this connector in required places
|
||||
sed -i'' -e "s/pub use self::{/pub mod ${pg};\n\npub use self::{/" $conn.rs
|
||||
sed -i'' -e "s/};/${pg}::${pgc},\n};/" $conn.rs
|
||||
@ -21,9 +21,14 @@ sed -i'' -e "s/\[scheduler\]/[connectors.${pg}]\nbase_url = \"\"\n\n[scheduler]/
|
||||
sed -r -i'' -e "s/cards = \[(.*)\]/cards = [\1, \"${pg}\"]/" config/Development.toml
|
||||
sed -i'' -e "s/\[connectors.supported\]/[connectors.${pg}]\nbase_url = ""\n\n[connectors.supported]/" config/docker_compose.toml
|
||||
sed -r -i'' -e "s/cards = \[(.*)\]/cards = [\1, \"${pg}\"]/" config/docker_compose.toml
|
||||
sed -i'' -e "s/\[connectors.supported\]/[connectors.${pg}]\nbase_url = ""\n\n[connectors.supported]/" config/config.example.toml
|
||||
sed -r -i'' -e "s/cards = \[(.*)\]/cards = [\1, \"${pg}\"]/" config/config.example.toml
|
||||
sed -i'' -e "s/\[connectors.supported\]/[connectors.${pg}]\nbase_url = ""\n\n[connectors.supported]/" loadtest/config/Development.toml
|
||||
sed -r -i'' -e "s/cards = \[(.*)\]/cards = [\1, \"${pg}\"]/" loadtest/config/Development.toml
|
||||
sed -i'' -e "s/\[connectors.supported\]/[connectors.${pg}]\nbase_url = ""\n\n[connectors.supported]/" crates/router/src/configs/defaults.toml
|
||||
sed -i'' -e "s/Dummy,/Dummy,\n\t${pgc},/" crates/api_models/src/enums.rs
|
||||
# remove temporary files created in above step
|
||||
rm $conn.rs-e $src/types/api.rs-e $src/configs/settings.rs-e config/Development.toml-e config/docker_compose.toml-e crates/api_models/src/enums.rs-e
|
||||
rm $conn.rs-e $src/types/api.rs-e $src/configs/settings.rs-e config/Development.toml-e config/docker_compose.toml-e config/config.example.toml-e loadtest/config/Development.toml-e crates/router/src/configs/defaults.toml-e crates/api_models/src/enums.rs-e
|
||||
cd $conn/
|
||||
# generate template files for the connector
|
||||
cargo install cargo-generate
|
||||
|
||||
Reference in New Issue
Block a user