feat(connector): [Paybox] add paybox connector (#5575)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Kiran Kumar
2024-08-14 20:01:22 +05:30
committed by GitHub
parent 8fa51b7b1c
commit e4f4fbafe6
17 changed files with 977 additions and 197 deletions

View File

@ -3577,6 +3577,7 @@
"noon",
"nuvei",
"opennode",
"paybox",
"payme",
"payone",
"paypal",
@ -15493,6 +15494,7 @@
"noon",
"nuvei",
"opennode",
"paybox",
"payme",
"payone",
"paypal",

View File

@ -8055,6 +8055,7 @@
"noon",
"nuvei",
"opennode",
"paybox",
"payme",
"payone",
"paypal",
@ -20765,6 +20766,7 @@
"noon",
"nuvei",
"opennode",
"paybox",
"payme",
"payone",
"paypal",

View File

@ -70,7 +70,7 @@ noon.key_mode = "Live"
nuvei.base_url = "https://ppp-test.nuvei.com/"
opayo.base_url = "https://pi-live.sagepay.com/"
opennode.base_url = "https://api.opennode.com"
paybox.base_url = "https://preprod-ppps.paybox.com/PPPS.php"
paybox.base_url = "https://ppps.paybox.com/PPPS.php"
payeezy.base_url = "https://api.payeezy.com/"
payme.base_url = "https://live.payme.io/"
payone.base_url = "https://payment.payone.com/"

View File

@ -116,7 +116,7 @@ pub enum Connector {
Nuvei,
// Opayo, added as template code for future usage
Opennode,
// Paybox, added as template code for future usage
Paybox,
// Payeezy, As psync and rsync are not supported by this connector, it is added as template code for future usage
Payme,
Payone,
@ -244,7 +244,7 @@ impl Connector {
| Self::Nexinets
| Self::Nuvei
| Self::Opennode
// | Self::Paybox added as template code for future usage
| Self::Paybox
| Self::Payme
| Self::Payone
| Self::Paypal

View File

@ -229,7 +229,7 @@ pub enum RoutableConnectors {
// Opayo, added as template code for future usage
Opennode,
// Payeezy, As psync and rsync are not supported by this connector, it is added as template code for future usage
// Paybox, added as template code for future usage
Paybox,
Payme,
Payone,
Paypal,

View File

@ -175,7 +175,7 @@ pub struct ConnectorConfig {
pub nmi: Option<ConnectorTomlConfig>,
pub noon: Option<ConnectorTomlConfig>,
pub nuvei: Option<ConnectorTomlConfig>,
// pub paybox: Option<ConnectorTomlConfig>, added for future usage
pub paybox: Option<ConnectorTomlConfig>,
pub payme: Option<ConnectorTomlConfig>,
#[cfg(feature = "payouts")]
pub payone_payout: Option<ConnectorTomlConfig>,
@ -323,6 +323,7 @@ impl ConnectorConfig {
Connector::Nmi => Ok(connector_data.nmi),
Connector::Noon => Ok(connector_data.noon),
Connector::Nuvei => Ok(connector_data.nuvei),
Connector::Paybox => Ok(connector_data.paybox),
Connector::Payme => Ok(connector_data.payme),
Connector::Payone => Err("Use get_payout_connector_config".to_string()),
Connector::Paypal => Ok(connector_data.paypal),
@ -363,7 +364,6 @@ impl ConnectorConfig {
#[cfg(feature = "dummy_connector")]
Connector::DummyConnector7 => Ok(connector_data.paypal_test),
Connector::Netcetera => Ok(connector_data.netcetera),
// Connector::Paybox => Ok(connector_data.paybox), added for future usage
}
}
}

View File

@ -3803,6 +3803,46 @@ key1="Public Api Key"
api_key = "Passcode"
key1 = "datatrans MerchantId"
[paybox]
[[paybox.credit]]
payment_method_type = "Mastercard"
[[paybox.credit]]
payment_method_type = "Visa"
[[paybox.credit]]
payment_method_type = "Interac"
[[paybox.credit]]
payment_method_type = "AmericanExpress"
[[paybox.credit]]
payment_method_type = "JCB"
[[paybox.credit]]
payment_method_type = "DinersClub"
[[paybox.credit]]
payment_method_type = "Discover"
[[paybox.credit]]
payment_method_type = "CartesBancaires"
[[paybox.credit]]
payment_method_type = "UnionPay"
[[paybox.debit]]
payment_method_type = "Mastercard"
[[paybox.debit]]
payment_method_type = "Visa"
[[paybox.debit]]
payment_method_type = "Interac"
[[paybox.debit]]
payment_method_type = "AmericanExpress"
[[paybox.debit]]
payment_method_type = "JCB"
[[paybox.debit]]
payment_method_type = "DinersClub"
[[paybox.debit]]
payment_method_type = "Discover"
[[paybox.debit]]
payment_method_type = "CartesBancaires"
[paybox.connector_auth.SignatureKey]
api_key="SITE Key"
key1="Rang Identifier"
api_secret="CLE Secret"
[wellsfargo]
[[wellsfargo.credit]]
payment_method_type = "Mastercard"

View File

@ -2680,6 +2680,46 @@ key1 = "Merchant ID"
api_key="Private Api Key"
key1="Public Api Key"
[paybox]
[[paybox.credit]]
payment_method_type = "Mastercard"
[[paybox.credit]]
payment_method_type = "Visa"
[[paybox.credit]]
payment_method_type = "Interac"
[[paybox.credit]]
payment_method_type = "AmericanExpress"
[[paybox.credit]]
payment_method_type = "JCB"
[[paybox.credit]]
payment_method_type = "DinersClub"
[[paybox.credit]]
payment_method_type = "Discover"
[[paybox.credit]]
payment_method_type = "CartesBancaires"
[[paybox.credit]]
payment_method_type = "UnionPay"
[[paybox.debit]]
payment_method_type = "Mastercard"
[[paybox.debit]]
payment_method_type = "Visa"
[[paybox.debit]]
payment_method_type = "Interac"
[[paybox.debit]]
payment_method_type = "AmericanExpress"
[[paybox.debit]]
payment_method_type = "JCB"
[[paybox.debit]]
payment_method_type = "DinersClub"
[[paybox.debit]]
payment_method_type = "Discover"
[[paybox.debit]]
payment_method_type = "CartesBancaires"
[paybox.connector_auth.SignatureKey]
api_key="SITE Key"
key1="Rang Identifier"
api_secret="CLE Secret"
[datatrans]
[[datatrans.credit]]
payment_method_type = "Mastercard"

View File

@ -3796,6 +3796,46 @@ key1="Public Api Key"
api_key = "Passcode"
key1 = "datatrans MerchantId"
[paybox]
[[paybox.credit]]
payment_method_type = "Mastercard"
[[paybox.credit]]
payment_method_type = "Visa"
[[paybox.credit]]
payment_method_type = "Interac"
[[paybox.credit]]
payment_method_type = "AmericanExpress"
[[paybox.credit]]
payment_method_type = "JCB"
[[paybox.credit]]
payment_method_type = "DinersClub"
[[paybox.credit]]
payment_method_type = "Discover"
[[paybox.credit]]
payment_method_type = "CartesBancaires"
[[paybox.credit]]
payment_method_type = "UnionPay"
[[paybox.debit]]
payment_method_type = "Mastercard"
[[paybox.debit]]
payment_method_type = "Visa"
[[paybox.debit]]
payment_method_type = "Interac"
[[paybox.debit]]
payment_method_type = "AmericanExpress"
[[paybox.debit]]
payment_method_type = "JCB"
[[paybox.debit]]
payment_method_type = "DinersClub"
[[paybox.debit]]
payment_method_type = "Discover"
[[paybox.debit]]
payment_method_type = "CartesBancaires"
[paybox.connector_auth.SignatureKey]
api_key="SITE Key"
key1="Rang Identifier"
api_secret="CLE Secret"
[wellsfargo]
[[wellsfargo.credit]]
payment_method_type = "Mastercard"

View File

@ -1,5 +1,6 @@
pub mod transformers;
use common_enums::enums;
use common_utils::types::{AmountConvertor, MinorUnit, MinorUnitForConnector};
use error_stack::{report, ResultExt};
use masking::ExposeInterface;
@ -8,6 +9,7 @@ use transformers as paybox;
use super::utils::{self as connector_utils};
use crate::{
configs::settings,
connector::utils,
core::errors::{self, CustomResult},
events::connector_api_logs::ConnectorEvent,
headers,
@ -49,6 +51,10 @@ impl api::Refund for Paybox {}
impl api::RefundExecute for Paybox {}
impl api::RefundSync for Paybox {}
impl api::PaymentToken for Paybox {}
impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsResponseData>
for Paybox
{
}
impl
ConnectorIntegration<
@ -57,7 +63,6 @@ impl
types::PaymentsResponseData,
> for Paybox
{
// Not Implemented (R)
}
impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Paybox
@ -66,15 +71,13 @@ where
{
fn build_headers(
&self,
req: &types::RouterData<Flow, Request, Response>,
_req: &types::RouterData<Flow, Request, Response>,
_connectors: &settings::Connectors,
) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
let mut header = vec![(
let header = vec![(
headers::CONTENT_TYPE.to_string(),
self.get_content_type().to_string().into(),
)];
let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
header.append(&mut api_key);
Ok(header)
}
}
@ -84,15 +87,8 @@ impl ConnectorCommon for Paybox {
"paybox"
}
// fn get_currency_unit(&self) -> api::CurrencyUnit {
// // todo!()
// // TODO! Check connector documentation, on which unit they are processing the currency.
// // If the connector accepts amount in lower unit ( i.e cents for USD) then return api::CurrencyUnit::Minor,
// // if connector accepts amount in base unit (i.e dollars for USD) then return api::CurrencyUnit::Base
// }
fn common_get_content_type(&self) -> &'static str {
"application/json"
"application/x-www-form-urlencoded"
}
fn base_url<'a>(&self, connectors: &'a settings::Connectors) -> &'a str {
@ -107,7 +103,7 @@ impl ConnectorCommon for Paybox {
.change_context(errors::ConnectorError::FailedToObtainAuthType)?;
Ok(vec![(
headers::AUTHORIZATION.to_string(),
auth.api_key.expose().into_masked(),
auth.cle.expose().into_masked(),
)])
}
@ -136,13 +132,24 @@ impl ConnectorCommon for Paybox {
}
impl ConnectorValidation for Paybox {
//TODO: implement functions when support enabled
fn validate_capture_method(
&self,
capture_method: Option<enums::CaptureMethod>,
_pmt: Option<enums::PaymentMethodType>,
) -> CustomResult<(), errors::ConnectorError> {
let capture_method = capture_method.unwrap_or_default();
match capture_method {
enums::CaptureMethod::Automatic | enums::CaptureMethod::Manual => Ok(()),
enums::CaptureMethod::ManualMultiple | enums::CaptureMethod::Scheduled => Err(
utils::construct_not_implemented_error_report(capture_method, self.id()),
),
}
}
}
impl ConnectorIntegration<api::Session, types::PaymentsSessionData, types::PaymentsResponseData>
for Paybox
{
//TODO: implement sessions flow
}
impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, types::AccessToken>
@ -158,7 +165,6 @@ impl
> for Paybox
{
}
impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::PaymentsResponseData>
for Paybox
{
@ -177,9 +183,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
fn get_url(
&self,
_req: &types::PaymentsAuthorizeRouterData,
_connectors: &settings::Connectors,
connectors: &settings::Connectors,
) -> CustomResult<String, errors::ConnectorError> {
Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
Ok(self.base_url(connectors).to_string())
}
fn get_request_body(
@ -195,7 +201,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
let connector_router_data = paybox::PayboxRouterData::from((amount, req));
let connector_req = paybox::PayboxPaymentsRequest::try_from(&connector_router_data)?;
Ok(RequestContent::Json(Box::new(connector_req)))
Ok(RequestContent::FormUrlEncoded(Box::new(connector_req)))
}
fn build_request(
@ -210,9 +216,6 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
self, req, connectors,
)?)
.attach_default_headers()
.headers(types::PaymentsAuthorizeType::get_headers(
self, req, connectors,
)?)
.set_body(types::PaymentsAuthorizeType::get_request_body(
self, req, connectors,
)?)
@ -226,10 +229,7 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
event_builder: Option<&mut ConnectorEvent>,
res: Response,
) -> CustomResult<types::PaymentsAuthorizeRouterData, errors::ConnectorError> {
let response: paybox::PayboxPaymentsResponse = res
.response
.parse_struct("Paybox PaymentsAuthorizeResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
let response: paybox::PayboxResponse = paybox::parse_url_encoded_to_struct(res.response)?;
event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);
types::RouterData::try_from(types::ResponseRouterData {
@ -262,13 +262,20 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
fn get_content_type(&self) -> &'static str {
self.common_get_content_type()
}
fn get_request_body(
&self,
req: &types::PaymentsSyncRouterData,
_connectors: &settings::Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let connector_req = paybox::PayboxPSyncRequest::try_from(req)?;
Ok(RequestContent::FormUrlEncoded(Box::new(connector_req)))
}
fn get_url(
&self,
_req: &types::PaymentsSyncRouterData,
_connectors: &settings::Connectors,
connectors: &settings::Connectors,
) -> CustomResult<String, errors::ConnectorError> {
Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
Ok(self.base_url(connectors).to_string())
}
fn build_request(
@ -278,10 +285,12 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
Ok(Some(
services::RequestBuilder::new()
.method(services::Method::Get)
.method(services::Method::Post)
.url(&types::PaymentsSyncType::get_url(self, req, connectors)?)
.attach_default_headers()
.headers(types::PaymentsSyncType::get_headers(self, req, connectors)?)
.set_body(types::PaymentsSyncType::get_request_body(
self, req, connectors,
)?)
.build(),
))
}
@ -292,10 +301,8 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
event_builder: Option<&mut ConnectorEvent>,
res: Response,
) -> CustomResult<types::PaymentsSyncRouterData, errors::ConnectorError> {
let response: paybox::PayboxPaymentsResponse = res
.response
.parse_struct("paybox PaymentsSyncResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
let response: paybox::PayboxSyncResponse =
paybox::parse_url_encoded_to_struct(res.response)?;
event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);
types::RouterData::try_from(types::ResponseRouterData {
@ -332,17 +339,25 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
fn get_url(
&self,
_req: &types::PaymentsCaptureRouterData,
_connectors: &settings::Connectors,
connectors: &settings::Connectors,
) -> CustomResult<String, errors::ConnectorError> {
Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
Ok(self.base_url(connectors).to_string())
}
fn get_request_body(
&self,
_req: &types::PaymentsCaptureRouterData,
req: &types::PaymentsCaptureRouterData,
_connectors: &settings::Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into())
let amount = connector_utils::convert_amount(
self.amount_converter,
req.request.minor_amount_to_capture,
req.request.currency,
)?;
let connector_router_data = paybox::PayboxRouterData::from((amount, req));
let connector_req = paybox::PayboxCaptureRequest::try_from(&connector_router_data)?;
Ok(RequestContent::FormUrlEncoded(Box::new(connector_req)))
}
fn build_request(
@ -355,9 +370,6 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
.method(services::Method::Post)
.url(&types::PaymentsCaptureType::get_url(self, req, connectors)?)
.attach_default_headers()
.headers(types::PaymentsCaptureType::get_headers(
self, req, connectors,
)?)
.set_body(types::PaymentsCaptureType::get_request_body(
self, req, connectors,
)?)
@ -371,10 +383,9 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
event_builder: Option<&mut ConnectorEvent>,
res: Response,
) -> CustomResult<types::PaymentsCaptureRouterData, errors::ConnectorError> {
let response: paybox::PayboxPaymentsResponse = res
.response
.parse_struct("Paybox PaymentsCaptureResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
let response: paybox::PayboxCaptureResponse =
paybox::parse_url_encoded_to_struct(res.response)?;
event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);
types::RouterData::try_from(types::ResponseRouterData {
@ -393,11 +404,6 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
}
}
impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsResponseData>
for Paybox
{
}
impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsResponseData> for Paybox {
fn get_headers(
&self,
@ -414,9 +420,9 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
fn get_url(
&self,
_req: &types::RefundsRouterData<api::Execute>,
_connectors: &settings::Connectors,
connectors: &settings::Connectors,
) -> CustomResult<String, errors::ConnectorError> {
Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
Ok(self.base_url(connectors).to_string())
}
fn get_request_body(
@ -432,7 +438,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
let connector_router_data = paybox::PayboxRouterData::from((refund_amount, req));
let connector_req = paybox::PayboxRefundRequest::try_from(&connector_router_data)?;
Ok(RequestContent::Json(Box::new(connector_req)))
Ok(RequestContent::FormUrlEncoded(Box::new(connector_req)))
}
fn build_request(
@ -444,9 +450,6 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
.method(services::Method::Post)
.url(&types::RefundExecuteType::get_url(self, req, connectors)?)
.attach_default_headers()
.headers(types::RefundExecuteType::get_headers(
self, req, connectors,
)?)
.set_body(types::RefundExecuteType::get_request_body(
self, req, connectors,
)?)
@ -460,10 +463,7 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
event_builder: Option<&mut ConnectorEvent>,
res: Response,
) -> CustomResult<types::RefundsRouterData<api::Execute>, errors::ConnectorError> {
let response: paybox::RefundResponse =
res.response
.parse_struct("paybox RefundResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
let response: paybox::PayboxResponse = paybox::parse_url_encoded_to_struct(res.response)?;
event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);
types::RouterData::try_from(types::ResponseRouterData {
@ -498,9 +498,18 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
fn get_url(
&self,
_req: &types::RefundSyncRouterData,
_connectors: &settings::Connectors,
connectors: &settings::Connectors,
) -> CustomResult<String, errors::ConnectorError> {
Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into())
Ok(self.base_url(connectors).to_string())
}
fn get_request_body(
&self,
req: &types::RefundSyncRouterData,
_connectors: &settings::Connectors,
) -> CustomResult<RequestContent, errors::ConnectorError> {
let connector_req = paybox::PayboxRsyncRequest::try_from(req)?;
Ok(RequestContent::FormUrlEncoded(Box::new(connector_req)))
}
fn build_request(
@ -510,10 +519,9 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
Ok(Some(
services::RequestBuilder::new()
.method(services::Method::Get)
.method(services::Method::Post)
.url(&types::RefundSyncType::get_url(self, req, connectors)?)
.attach_default_headers()
.headers(types::RefundSyncType::get_headers(self, req, connectors)?)
.set_body(types::RefundSyncType::get_request_body(
self, req, connectors,
)?)
@ -527,10 +535,8 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
event_builder: Option<&mut ConnectorEvent>,
res: Response,
) -> CustomResult<types::RefundSyncRouterData, errors::ConnectorError> {
let response: paybox::RefundResponse = res
.response
.parse_struct("paybox RefundSyncResponse")
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
let response: paybox::PayboxSyncResponse =
paybox::parse_url_encoded_to_struct(res.response)?;
event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);
types::RouterData::try_from(types::ResponseRouterData {

View File

@ -1,14 +1,17 @@
use common_utils::types::MinorUnit;
use bytes::Bytes;
use common_utils::{date_time::DateFormat, errors::CustomResult, types::MinorUnit};
use error_stack::ResultExt;
use hyperswitch_connectors::utils::CardData;
use hyperswitch_domain_models::router_data::ConnectorAuthType;
use masking::Secret;
use serde::{Deserialize, Serialize};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use crate::{
connector::utils::PaymentsAuthorizeRequestData,
connector::utils,
core::errors,
types::{self, api, domain, storage::enums},
};
//TODO: Fill the struct with respective fields
pub struct PayboxRouterData<T> {
pub amount: MinorUnit, // The type of amount that a connector accepts, for example, String, i64, f64, etc.
pub router_data: T,
@ -16,7 +19,6 @@ pub struct PayboxRouterData<T> {
impl<T> From<(MinorUnit, T)> for PayboxRouterData<T> {
fn from((amount, item): (MinorUnit, T)) -> Self {
//Todo : use utils to convert the amount to the type of amount that a connector accepts
Self {
amount,
router_data: item,
@ -24,20 +26,294 @@ impl<T> From<(MinorUnit, T)> for PayboxRouterData<T> {
}
}
//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Serialize, PartialEq)]
const AUTH_REQUEST: &str = "00001";
const CAPTURE_REQUEST: &str = "00002";
const AUTH_AND_CAPTURE_REQUEST: &str = "00003";
const SYNC_REQUEST: &str = "00017";
const REFUND_REQUEST: &str = "00014";
const SUCCESS_CODE: &str = "00000";
const VERSION_PAYBOX: &str = "00104";
const PAY_ORIGIN_INTERNET: &str = "024";
type Error = error_stack::Report<errors::ConnectorError>;
#[derive(Debug, Serialize, Eq, PartialEq)]
pub struct PayboxPaymentsRequest {
amount: MinorUnit,
card: PayboxCard,
#[serde(rename = "DATEQ")]
pub date: String,
#[serde(rename = "TYPE")]
pub transaction_type: String,
#[serde(rename = "NUMQUESTION")]
pub paybox_request_number: String,
#[serde(rename = "MONTANT")]
pub amount: MinorUnit,
#[serde(rename = "REFERENCE")]
pub description_reference: String,
#[serde(rename = "VERSION")]
pub version: String,
#[serde(rename = "DEVISE")]
pub currency: String,
#[serde(rename = "PORTEUR")]
pub card_number: cards::CardNumber,
#[serde(rename = "DATEVAL")]
pub expiration_date: Secret<String>,
#[serde(rename = "CVV")]
pub cvv: Secret<String>,
#[serde(rename = "ACTIVITE")]
pub activity: String,
#[serde(rename = "SITE")]
pub site: Secret<String>,
#[serde(rename = "RANG")]
pub rank: Secret<String>,
#[serde(rename = "CLE")]
pub key: Secret<String>,
}
#[derive(Default, Debug, Serialize, Eq, PartialEq)]
pub struct PayboxCard {
number: cards::CardNumber,
expiry_month: Secret<String>,
expiry_year: Secret<String>,
cvc: Secret<String>,
complete: bool,
#[derive(Debug, Serialize, Eq, PartialEq)]
pub struct PayboxCaptureRequest {
#[serde(rename = "DATEQ")]
pub date: String,
#[serde(rename = "TYPE")]
pub transaction_type: String,
#[serde(rename = "NUMQUESTION")]
pub paybox_request_number: String,
#[serde(rename = "MONTANT")]
pub amount: MinorUnit,
#[serde(rename = "REFERENCE")]
pub reference: String,
#[serde(rename = "VERSION")]
pub version: String,
#[serde(rename = "DEVISE")]
pub currency: String,
#[serde(rename = "SITE")]
pub site: Secret<String>,
#[serde(rename = "RANG")]
pub rank: Secret<String>,
#[serde(rename = "CLE")]
pub key: Secret<String>,
#[serde(rename = "NUMTRANS")]
pub transaction_number: String,
#[serde(rename = "NUMAPPEL")]
pub paybox_order_id: String,
}
impl TryFrom<&PayboxRouterData<&types::PaymentsCaptureRouterData>> for PayboxCaptureRequest {
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
item: &PayboxRouterData<&types::PaymentsCaptureRouterData>,
) -> Result<Self, Self::Error> {
let auth_data: PayboxAuthType =
PayboxAuthType::try_from(&item.router_data.connector_auth_type)
.change_context(errors::ConnectorError::FailedToObtainAuthType)?;
let currency = diesel_models::enums::Currency::iso_4217(&item.router_data.request.currency)
.to_string();
let paybox_meta_data: PayboxMeta =
utils::to_connector_meta(item.router_data.request.connector_meta.clone())?;
let format_time = common_utils::date_time::format_date(
common_utils::date_time::now(),
DateFormat::YYYYMMDDHHmmss,
)
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
Ok(Self {
date: format_time.clone(),
transaction_type: CAPTURE_REQUEST.to_string(),
paybox_request_number: get_paybox_request_number()?,
version: VERSION_PAYBOX.to_string(),
currency,
site: auth_data.site,
rank: auth_data.rang,
key: auth_data.cle,
transaction_number: paybox_meta_data.connector_request_id,
paybox_order_id: item.router_data.request.connector_transaction_id.clone(),
amount: item.amount,
reference: item.router_data.connector_request_reference_id.to_string(),
})
}
}
#[derive(Debug, Serialize, Eq, PartialEq)]
pub struct PayboxRsyncRequest {
#[serde(rename = "DATEQ")]
pub date: String,
#[serde(rename = "TYPE")]
pub transaction_type: String,
#[serde(rename = "NUMQUESTION")]
pub paybox_request_number: String,
#[serde(rename = "VERSION")]
pub version: String,
#[serde(rename = "SITE")]
pub site: Secret<String>,
#[serde(rename = "RANG")]
pub rank: Secret<String>,
#[serde(rename = "CLE")]
pub key: Secret<String>,
#[serde(rename = "NUMTRANS")]
pub transaction_number: String,
#[serde(rename = "NUMAPPEL")]
pub paybox_order_id: String,
}
impl TryFrom<&types::RefundSyncRouterData> for PayboxRsyncRequest {
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(item: &types::RefundSyncRouterData) -> Result<Self, Self::Error> {
let auth_data: PayboxAuthType = PayboxAuthType::try_from(&item.connector_auth_type)
.change_context(errors::ConnectorError::FailedToObtainAuthType)?;
let format_time = common_utils::date_time::format_date(
common_utils::date_time::now(),
DateFormat::YYYYMMDDHHmmss,
)
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
Ok(Self {
date: format_time.clone(),
transaction_type: SYNC_REQUEST.to_string(),
paybox_request_number: get_paybox_request_number()?,
version: VERSION_PAYBOX.to_string(),
site: auth_data.site,
rank: auth_data.rang,
key: auth_data.cle,
transaction_number: item
.request
.connector_refund_id
.clone()
.ok_or(errors::ConnectorError::RequestEncodingFailed)?,
paybox_order_id: item.request.connector_transaction_id.clone(),
})
}
}
#[derive(Debug, Serialize, Eq, PartialEq)]
pub struct PayboxPSyncRequest {
#[serde(rename = "DATEQ")]
pub date: String,
#[serde(rename = "TYPE")]
pub transaction_type: String,
#[serde(rename = "NUMQUESTION")]
pub paybox_request_number: String,
#[serde(rename = "VERSION")]
pub version: String,
#[serde(rename = "SITE")]
pub site: Secret<String>,
#[serde(rename = "RANG")]
pub rank: Secret<String>,
#[serde(rename = "CLE")]
pub key: Secret<String>,
#[serde(rename = "NUMTRANS")]
pub transaction_number: String,
#[serde(rename = "NUMAPPEL")]
pub paybox_order_id: String,
}
impl TryFrom<&types::PaymentsSyncRouterData> for PayboxPSyncRequest {
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(item: &types::PaymentsSyncRouterData) -> Result<Self, Self::Error> {
let auth_data: PayboxAuthType = PayboxAuthType::try_from(&item.connector_auth_type)
.change_context(errors::ConnectorError::FailedToObtainAuthType)?;
let format_time = common_utils::date_time::format_date(
common_utils::date_time::now(),
DateFormat::YYYYMMDDHHmmss,
)
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
let paybox_meta_data: PayboxMeta =
utils::to_connector_meta(item.request.connector_meta.clone())?;
Ok(Self {
date: format_time.clone(),
transaction_type: SYNC_REQUEST.to_string(),
paybox_request_number: get_paybox_request_number()?,
version: VERSION_PAYBOX.to_string(),
site: auth_data.site,
rank: auth_data.rang,
key: auth_data.cle,
transaction_number: paybox_meta_data.connector_request_id,
paybox_order_id: item
.request
.connector_transaction_id
.get_connector_transaction_id()
.change_context(errors::ConnectorError::MissingConnectorTransactionID)?,
})
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct PayboxMeta {
pub connector_request_id: String,
}
#[derive(Debug, Serialize, Eq, PartialEq)]
pub struct PayboxRefundRequest {
#[serde(rename = "DATEQ")]
pub date: String,
#[serde(rename = "TYPE")]
pub transaction_type: String,
#[serde(rename = "NUMQUESTION")]
pub paybox_request_number: String,
#[serde(rename = "MONTANT")]
pub amount: MinorUnit,
#[serde(rename = "VERSION")]
pub version: String,
#[serde(rename = "DEVISE")]
pub currency: String,
#[serde(rename = "SITE")]
pub site: Secret<String>,
#[serde(rename = "RANG")]
pub rank: Secret<String>,
#[serde(rename = "CLE")]
pub key: Secret<String>,
#[serde(rename = "NUMTRANS")]
pub transaction_number: String,
#[serde(rename = "NUMAPPEL")]
pub paybox_order_id: String,
}
impl TryFrom<&PayboxRouterData<&types::PaymentsAuthorizeRouterData>> for PayboxPaymentsRequest {
@ -47,16 +323,37 @@ impl TryFrom<&PayboxRouterData<&types::PaymentsAuthorizeRouterData>> for PayboxP
) -> Result<Self, Self::Error> {
match item.router_data.request.payment_method_data.clone() {
domain::PaymentMethodData::Card(req_card) => {
let card = PayboxCard {
number: req_card.card_number,
expiry_month: req_card.card_exp_month,
expiry_year: req_card.card_exp_year,
cvc: req_card.card_cvc,
complete: item.router_data.request.is_auto_capture()?,
};
let auth_data: PayboxAuthType =
PayboxAuthType::try_from(&item.router_data.connector_auth_type)
.change_context(errors::ConnectorError::FailedToObtainAuthType)?;
let transaction_type =
get_transaction_type(item.router_data.request.capture_method)?;
let currency =
diesel_models::enums::Currency::iso_4217(&item.router_data.request.currency)
.to_string();
let expiration_date =
req_card.get_card_expiry_month_year_2_digit_with_delimiter("".to_owned())?;
let format_time = common_utils::date_time::format_date(
common_utils::date_time::now(),
DateFormat::YYYYMMDDHHmmss,
)
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
Ok(Self {
date: format_time.clone(),
transaction_type,
paybox_request_number: get_paybox_request_number()?,
amount: item.amount,
card,
description_reference: item.router_data.connector_request_reference_id.clone(),
version: VERSION_PAYBOX.to_string(),
currency,
card_number: req_card.card_number,
expiration_date,
cvv: req_card.card_cvc,
activity: PAY_ORIGIN_INTERNET.to_string(),
site: auth_data.site,
rank: auth_data.rang,
key: auth_data.cle,
})
}
_ => Err(errors::ConnectorError::NotImplemented("Payment methods".to_string()).into()),
@ -64,31 +361,59 @@ impl TryFrom<&PayboxRouterData<&types::PaymentsAuthorizeRouterData>> for PayboxP
}
}
//TODO: Fill the struct with respective fields
// Auth Struct
pub struct PayboxAuthType {
pub(super) api_key: Secret<String>,
fn get_transaction_type(capture_method: Option<enums::CaptureMethod>) -> Result<String, Error> {
match capture_method {
Some(enums::CaptureMethod::Automatic) => Ok(AUTH_AND_CAPTURE_REQUEST.to_string()),
Some(enums::CaptureMethod::Manual) => Ok(AUTH_REQUEST.to_string()),
_ => Err(errors::ConnectorError::CaptureMethodNotSupported)?,
}
}
fn get_paybox_request_number() -> Result<String, Error> {
let time_stamp = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.ok()
.ok_or(errors::ConnectorError::RequestEncodingFailed)?
.as_millis()
.to_string();
// unix time (in milliseconds) has 13 digits.if we consider 8 digits(the number digits to make day deterministic) there is no collision in the paybox_request_number as it will reset the paybox_request_number for each day and paybox accepting maximum length is 10 so we gonna take 9 (13-9)
let request_number = time_stamp
.get(4..)
.ok_or(errors::ConnectorError::ParsingFailed)?;
Ok(request_number.to_string())
}
impl TryFrom<&types::ConnectorAuthType> for PayboxAuthType {
#[derive(Debug, Serialize, Eq, PartialEq)]
pub struct PayboxAuthType {
pub(super) site: Secret<String>,
pub(super) rang: Secret<String>,
pub(super) cle: Secret<String>,
}
impl TryFrom<&ConnectorAuthType> for PayboxAuthType {
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_owned(),
}),
_ => Err(errors::ConnectorError::FailedToObtainAuthType.into()),
fn try_from(auth_type: &ConnectorAuthType) -> Result<Self, Self::Error> {
if let ConnectorAuthType::SignatureKey {
api_key,
key1,
api_secret,
} = auth_type
{
Ok(Self {
site: api_key.to_owned(),
rang: key1.to_owned(),
cle: api_secret.to_owned(),
})
} else {
Err(errors::ConnectorError::FailedToObtainAuthType)?
}
}
}
// PaymentsResponse
//TODO: Append the remaining status flags
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum PayboxPaymentStatus {
Succeeded,
Failed,
#[default]
Processing,
}
@ -102,44 +427,234 @@ impl From<PayboxPaymentStatus> for enums::AttemptStatus {
}
}
//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PayboxPaymentsResponse {
status: PayboxPaymentStatus,
id: String,
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PayboxResponse {
#[serde(rename = "NUMTRANS")]
pub transaction_number: String,
#[serde(rename = "NUMAPPEL")]
pub paybox_order_id: String,
#[serde(rename = "CODEREPONSE")]
pub response_code: String,
#[serde(rename = "COMMENTAIRE")]
pub response_message: String,
}
pub fn parse_url_encoded_to_struct<T: DeserializeOwned>(
query_bytes: Bytes,
) -> CustomResult<T, errors::ConnectorError> {
let (cow, _, _) = encoding_rs::ISO_8859_10.decode(&query_bytes);
serde_qs::from_str::<T>(cow.as_ref()).change_context(errors::ConnectorError::ParsingFailed)
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum PayboxStatus {
#[serde(rename = "Remboursé")]
Refunded,
#[serde(rename = "Annulé")]
Cancelled,
#[serde(rename = "Autorisé")]
Authorised,
#[serde(rename = "Capturé")]
Captured,
#[serde(rename = "Refusé")]
Rejected,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PayboxSyncResponse {
#[serde(rename = "NUMTRANS")]
pub transaction_number: String,
#[serde(rename = "NUMAPPEL")]
pub paybox_order_id: String,
#[serde(rename = "CODEREPONSE")]
pub response_code: String,
#[serde(rename = "COMMENTAIRE")]
pub response_message: String,
#[serde(rename = "STATUS")]
pub status: PayboxStatus,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct PayboxCaptureResponse {
#[serde(rename = "NUMTRANS")]
pub transaction_number: String,
#[serde(rename = "NUMAPPEL")]
pub paybox_order_id: String,
#[serde(rename = "CODEREPONSE")]
pub response_code: String,
#[serde(rename = "COMMENTAIRE")]
pub response_message: String,
}
impl<F, T>
TryFrom<types::ResponseRouterData<F, PayboxPaymentsResponse, T, types::PaymentsResponseData>>
TryFrom<types::ResponseRouterData<F, PayboxCaptureResponse, T, types::PaymentsResponseData>>
for types::RouterData<F, T, types::PaymentsResponseData>
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
item: types::ResponseRouterData<F, PayboxPaymentsResponse, T, types::PaymentsResponseData>,
item: types::ResponseRouterData<F, PayboxCaptureResponse, T, types::PaymentsResponseData>,
) -> Result<Self, Self::Error> {
Ok(Self {
status: enums::AttemptStatus::from(item.response.status),
let response = item.response.clone();
let status = get_status_of_request(response.response_code.clone());
match status {
true => Ok(Self {
status: enums::AttemptStatus::Pending,
response: Ok(types::PaymentsResponseData::TransactionResponse {
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
resource_id: types::ResponseId::ConnectorTransactionId(
response.paybox_order_id,
),
redirection_data: None,
mandate_reference: None,
connector_metadata: None,
connector_metadata: Some(serde_json::json!(PayboxMeta {
connector_request_id: response.transaction_number.clone()
})),
network_txn_id: None,
connector_response_reference_id: None,
incremental_authorization_allowed: None,
charge_id: None,
}),
amount_captured: None,
..item.data
}),
false => Ok(Self {
response: Err(types::ErrorResponse {
code: response.response_code.clone(),
message: response.response_message.clone(),
reason: Some(response.response_message),
status_code: item.http_code,
attempt_status: None,
connector_transaction_id: Some(item.response.transaction_number),
}),
..item.data
}),
}
}
}
impl<F, T> TryFrom<types::ResponseRouterData<F, PayboxResponse, T, types::PaymentsResponseData>>
for types::RouterData<F, T, types::PaymentsResponseData>
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
item: types::ResponseRouterData<F, PayboxResponse, T, types::PaymentsResponseData>,
) -> Result<Self, Self::Error> {
let response = item.response.clone();
let status = get_status_of_request(response.response_code.clone());
match status {
true => Ok(Self {
response: Ok(types::PaymentsResponseData::TransactionResponse {
resource_id: types::ResponseId::ConnectorTransactionId(
response.paybox_order_id,
),
redirection_data: None,
mandate_reference: None,
connector_metadata: Some(serde_json::json!(PayboxMeta {
connector_request_id: response.transaction_number.clone()
})),
network_txn_id: None,
connector_response_reference_id: None,
incremental_authorization_allowed: None,
charge_id: None,
}),
..item.data
})
}),
false => Ok(Self {
response: Err(types::ErrorResponse {
code: response.response_code.clone(),
message: response.response_message.clone(),
reason: Some(response.response_message),
status_code: item.http_code,
attempt_status: None,
connector_transaction_id: Some(item.response.transaction_number),
}),
..item.data
}),
}
}
}
//TODO: Fill the struct with respective fields
// REFUND :
// Type definition for RefundRequest
#[derive(Default, Debug, Serialize)]
pub struct PayboxRefundRequest {
pub amount: MinorUnit,
impl<F, T> TryFrom<types::ResponseRouterData<F, PayboxSyncResponse, T, types::PaymentsResponseData>>
for types::RouterData<F, T, types::PaymentsResponseData>
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
item: types::ResponseRouterData<F, PayboxSyncResponse, T, types::PaymentsResponseData>,
) -> Result<Self, Self::Error> {
let response = item.response.clone();
let status = get_status_of_request(response.response_code.clone());
let connector_payment_status = item.response.status;
match status {
true => Ok(Self {
status: enums::AttemptStatus::from(connector_payment_status),
response: Ok(types::PaymentsResponseData::TransactionResponse {
resource_id: types::ResponseId::ConnectorTransactionId(
response.paybox_order_id,
),
redirection_data: None,
mandate_reference: None,
connector_metadata: Some(serde_json::json!(PayboxMeta {
connector_request_id: response.transaction_number.clone()
})),
network_txn_id: None,
connector_response_reference_id: None,
incremental_authorization_allowed: None,
charge_id: None,
}),
..item.data
}),
false => Ok(Self {
response: Err(types::ErrorResponse {
code: response.response_code.clone(),
message: response.response_message.clone(),
reason: Some(response.response_message),
status_code: item.http_code,
attempt_status: None,
connector_transaction_id: Some(item.response.transaction_number),
}),
..item.data
}),
}
}
}
impl From<PayboxStatus> for common_enums::RefundStatus {
fn from(item: PayboxStatus) -> Self {
match item {
PayboxStatus::Refunded => Self::Success,
PayboxStatus::Cancelled
| PayboxStatus::Authorised
| PayboxStatus::Captured
| PayboxStatus::Rejected => Self::Failure,
}
}
}
impl From<PayboxStatus> for enums::AttemptStatus {
fn from(item: PayboxStatus) -> Self {
match item {
PayboxStatus::Cancelled => Self::Voided,
PayboxStatus::Authorised => Self::Authorized,
PayboxStatus::Captured | PayboxStatus::Refunded => Self::Charged,
PayboxStatus::Rejected => Self::Failure,
}
}
}
fn get_status_of_request(item: String) -> bool {
item == *SUCCESS_CODE
}
impl<F> TryFrom<&PayboxRouterData<&types::RefundsRouterData<F>>> for PayboxRefundRequest {
@ -147,68 +662,44 @@ impl<F> TryFrom<&PayboxRouterData<&types::RefundsRouterData<F>>> for PayboxRefun
fn try_from(
item: &PayboxRouterData<&types::RefundsRouterData<F>>,
) -> Result<Self, Self::Error> {
let auth_data: PayboxAuthType =
PayboxAuthType::try_from(&item.router_data.connector_auth_type)
.change_context(errors::ConnectorError::FailedToObtainAuthType)?;
let currency = diesel_models::enums::Currency::iso_4217(&item.router_data.request.currency)
.to_string();
let format_time = common_utils::date_time::format_date(
common_utils::date_time::now(),
DateFormat::YYYYMMDDHHmmss,
)
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
let paybox_meta_data: PayboxMeta =
utils::to_connector_meta(item.router_data.request.connector_metadata.clone())?;
Ok(Self {
amount: item.amount.to_owned(),
date: format_time.clone(),
transaction_type: REFUND_REQUEST.to_string(),
paybox_request_number: get_paybox_request_number()?,
version: VERSION_PAYBOX.to_string(),
currency,
site: auth_data.site,
rank: auth_data.rang,
key: auth_data.cle,
transaction_number: paybox_meta_data.connector_request_id,
paybox_order_id: item.router_data.request.connector_transaction_id.clone(),
amount: item.amount,
})
}
}
// Type definition for Refund Response
#[allow(dead_code)]
#[derive(Debug, Serialize, Default, Deserialize, Clone)]
pub enum RefundStatus {
Succeeded,
Failed,
#[default]
Processing,
}
impl From<RefundStatus> for enums::RefundStatus {
fn from(item: RefundStatus) -> Self {
match item {
RefundStatus::Succeeded => Self::Success,
RefundStatus::Failed => Self::Failure,
RefundStatus::Processing => Self::Pending,
//TODO: Review mapping
}
}
}
//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct RefundResponse {
id: String,
status: RefundStatus,
}
impl TryFrom<types::RefundsResponseRouterData<api::Execute, RefundResponse>>
for types::RefundsRouterData<api::Execute>
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
item: types::RefundsResponseRouterData<api::Execute, RefundResponse>,
) -> Result<Self, Self::Error> {
Ok(Self {
response: Ok(types::RefundsResponseData {
connector_refund_id: item.response.id.to_string(),
refund_status: enums::RefundStatus::from(item.response.status),
}),
..item.data
})
}
}
impl TryFrom<types::RefundsResponseRouterData<api::RSync, RefundResponse>>
impl TryFrom<types::RefundsResponseRouterData<api::RSync, PayboxSyncResponse>>
for types::RefundsRouterData<api::RSync>
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
item: types::RefundsResponseRouterData<api::RSync, RefundResponse>,
item: types::RefundsResponseRouterData<api::RSync, PayboxSyncResponse>,
) -> Result<Self, Self::Error> {
Ok(Self {
response: Ok(types::RefundsResponseData {
connector_refund_id: item.response.id.to_string(),
connector_refund_id: item.response.transaction_number,
refund_status: enums::RefundStatus::from(item.response.status),
}),
..item.data
@ -216,8 +707,23 @@ impl TryFrom<types::RefundsResponseRouterData<api::RSync, RefundResponse>>
}
}
//TODO: Fill the struct with respective fields
#[derive(Default, Debug, Serialize, Deserialize, PartialEq)]
impl TryFrom<types::RefundsResponseRouterData<api::Execute, PayboxResponse>>
for types::RefundsRouterData<api::Execute>
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
item: types::RefundsResponseRouterData<api::Execute, PayboxResponse>,
) -> Result<Self, Self::Error> {
Ok(Self {
response: Ok(types::RefundsResponseData {
connector_refund_id: item.response.transaction_number,
refund_status: common_enums::RefundStatus::Pending,
}),
..item.data
})
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct PayboxErrorResponse {
pub status_code: u16,
pub code: String,

View File

@ -1434,7 +1434,10 @@ impl<'a> ConnectorAuthTypeAndMetadataValidation<'a> {
opennode::transformers::OpennodeAuthType::try_from(self.auth_type)?;
Ok(())
}
// api_enums::Connector::Paybox => todo!(), added for future usage
api_enums::Connector::Paybox => {
paybox::transformers::PayboxAuthType::try_from(self.auth_type)?;
Ok(())
}
api_enums::Connector::Payme => {
payme::transformers::PaymeAuthType::try_from(self.auth_type)?;
Ok(())

View File

@ -420,7 +420,9 @@ impl ConnectorData {
enums::Connector::Opennode => {
Ok(ConnectorEnum::Old(Box::new(&connector::Opennode)))
}
// enums::Connector::Paybox => Ok(ConnectorEnum::Old(Box::new(connector::Paybox::new()))), // added for future use
enums::Connector::Paybox => {
Ok(ConnectorEnum::Old(Box::new(connector::Paybox::new())))
}
// "payeezy" => Ok(ConnectorIntegrationEnum::Old(Box::new(&connector::Payeezy)), As psync and rsync are not supported by this connector, it is added as template code for future usage
enums::Connector::Payme => {
Ok(ConnectorEnum::Old(Box::new(connector::Payme::new())))

View File

@ -271,7 +271,7 @@ impl ForeignTryFrom<api_enums::Connector> for common_enums::RoutableConnectors {
api_enums::Connector::Noon => Self::Noon,
api_enums::Connector::Nuvei => Self::Nuvei,
api_enums::Connector::Opennode => Self::Opennode,
// api_enums::Connector::Paybox => Self::Paybox, added for future usage
api_enums::Connector::Paybox => Self::Paybox,
api_enums::Connector::Payme => Self::Payme,
api_enums::Connector::Payone => Self::Payone,
api_enums::Connector::Paypal => Self::Paypal,

View File

@ -14,6 +14,7 @@ function normalise(input) {
const exceptions = {
bankofamerica: "Bank of America",
cybersource: "Cybersource",
paybox: "Paybox",
paypal: "Paypal",
wellsfargo: "Wellsfargo",
// Add more known exceptions here

View File

@ -0,0 +1,136 @@
const successfulNo3DSCardDetails = {
card_number: "1111222233334444",
card_exp_month: "05",
card_exp_year: "27",
card_holder_name: "joseph Doe",
card_cvc: "222",
};
export const connectorDetails = {
card_pm: {
PaymentIntent: {
Request: {
payment_method: "card",
payment_method_data: {
card: successfulNo3DSCardDetails,
},
currency: "EUR",
customer_acceptance: null,
setup_future_usage: "on_session",
},
Response: {
status: 200,
body: {
status: "requires_payment_method",
},
},
},
No3DSManualCapture: {
Request: {
payment_method: "card",
payment_method_data: {
card: successfulNo3DSCardDetails,
},
customer_acceptance: null,
setup_future_usage: "on_session",
},
Response: {
status: 200,
body: {
status: "processing",
},
},
},
No3DSAutoCapture: {
Request: {
payment_method: "card",
payment_method_data: {
card: successfulNo3DSCardDetails,
},
customer_acceptance: null,
setup_future_usage: "on_session",
},
Response: {
status: 200,
body: {
status: "processing",
},
},
},
Capture: {
Request: {
payment_method: "card",
payment_method_data: {
card: successfulNo3DSCardDetails,
},
customer_acceptance: null,
},
Response: {
status: 200,
body: {
status: "processing",
amount: 6500,
amount_capturable: 6500,
amount_received: null,
},
},
},
PartialCapture: {
Request: {},
Response: {
status: 200,
body: {
status: "processing",
amount: 6500,
amount_capturable: 6500,
amount_received: null,
},
},
},
Refund: {
Request: {
payment_method: "card",
payment_method_data: {
card: successfulNo3DSCardDetails,
},
customer_acceptance: null,
},
Response: {
status: 200,
body: {
status: "pending",
},
},
},
PartialRefund: {
Request: {
payment_method: "card",
payment_method_data: {
card: successfulNo3DSCardDetails,
},
customer_acceptance: null,
},
Response: {
status: 200,
body: {
status: "pending",
},
},
},
SyncRefund: {
Request: {
payment_method: "card",
payment_method_data: {
card: successfulNo3DSCardDetails,
},
customer_acceptance: null,
},
Response: {
status: 200,
body: {
status: "succeeded",
},
},
},
},
};

View File

@ -10,6 +10,7 @@ import { connectorDetails as datatransConnectorDetails } from "./Datatrans.js";
import { connectorDetails as iatapayConnectorDetails } from "./Iatapay.js";
import { connectorDetails as itaubankConnectorDetails } from "./ItauBank.js";
import { connectorDetails as nmiConnectorDetails } from "./Nmi.js";
import { connectorDetails as payboxConnectorDetails } from "./Paybox.js";
import { connectorDetails as paypalConnectorDetails } from "./Paypal.js";
import { connectorDetails as stripeConnectorDetails } from "./Stripe.js";
import { connectorDetails as trustpayConnectorDetails } from "./Trustpay.js";
@ -24,6 +25,7 @@ const connectorDetails = {
iatapay: iatapayConnectorDetails,
itaubank: itaubankConnectorDetails,
nmi: nmiConnectorDetails,
paybox: payboxConnectorDetails,
paypal: paypalConnectorDetails,
stripe: stripeConnectorDetails,
trustpay: trustpayConnectorDetails,