pub mod transformers; use std::fmt::Debug; use error_stack::{ResultExt, IntoReport}; use masking::ExposeInterface; use crate::{ configs::settings, utils::{self, BytesExt}, core::{ errors::{self, CustomResult}, }, headers, services::{self, ConnectorIntegration, ConnectorValidation, request::{self, Mask}}, types::{ self, api::{self, ConnectorCommon, ConnectorCommonExt}, ErrorResponse, Response, } }; use transformers as {{project-name | downcase}}; #[derive(Debug, Clone)] pub struct {{project-name | downcase | pascal_case}}; impl api::Payment for {{project-name | downcase | pascal_case}} {} impl api::PaymentSession for {{project-name | downcase | pascal_case}} {} impl api::ConnectorAccessToken for {{project-name | downcase | pascal_case}} {} impl api::PreVerify for {{project-name | downcase | pascal_case}} {} impl api::PaymentAuthorize for {{project-name | downcase | pascal_case}} {} impl api::PaymentSync for {{project-name | downcase | pascal_case}} {} impl api::PaymentCapture for {{project-name | downcase | pascal_case}} {} impl api::PaymentVoid for {{project-name | downcase | pascal_case}} {} impl api::Refund for {{project-name | downcase | pascal_case}} {} impl api::RefundExecute for {{project-name | downcase | pascal_case}} {} impl api::RefundSync for {{project-name | downcase | pascal_case}} {} impl api::PaymentToken for {{project-name | downcase | pascal_case}} {} impl ConnectorIntegration< api::PaymentMethodToken, types::PaymentMethodTokenizationData, types::PaymentsResponseData, > for {{project-name | downcase | pascal_case}} { // Not Implemented (R) } impl ConnectorCommonExt for {{project-name | downcase | pascal_case}} where Self: ConnectorIntegration,{ fn build_headers( &self, req: &types::RouterData, _connectors: &settings::Connectors, ) -> CustomResult)>, errors::ConnectorError> { let mut header = vec![( headers::CONTENT_TYPE.to_string(), types::PaymentsAuthorizeType::get_content_type(self).to_string().into(), )]; let mut api_key = self.get_auth_header(&req.connector_auth_type)?; header.append(&mut api_key); Ok(header) } } impl ConnectorCommon for {{project-name | downcase | pascal_case}} { fn id(&self) -> &'static str { "{{project-name | downcase}}" } 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" } fn base_url<'a>(&self, connectors: &'a settings::Connectors) -> &'a str { connectors.{{project-name}}.base_url.as_ref() } fn get_auth_header(&self, auth_type:&types::ConnectorAuthType)-> CustomResult)>,errors::ConnectorError> { let auth = {{project-name | downcase}}::{{project-name | downcase | pascal_case}}AuthType::try_from(auth_type) .change_context(errors::ConnectorError::FailedToObtainAuthType)?; Ok(vec![(headers::AUTHORIZATION.to_string(), auth.api_key.expose().into_masked())]) } fn build_error_response( &self, res: Response, ) -> CustomResult { let response: {{project-name | downcase}}::{{project-name | downcase | pascal_case}}ErrorResponse = res .response .parse_struct("{{project-name | downcase | pascal_case}}ErrorResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; Ok(ErrorResponse { status_code: res.status_code, code: response.code, message: response.message, reason: response.reason, }) } } impl ConnectorValidation for {{project-name | downcase | pascal_case}} { //TODO: implement functions when support enabled } impl ConnectorIntegration< api::Session, types::PaymentsSessionData, types::PaymentsResponseData, > for {{project-name | downcase | pascal_case}} { //TODO: implement sessions flow } impl ConnectorIntegration for {{project-name | downcase | pascal_case}} { } impl ConnectorIntegration< api::Verify, types::VerifyRequestData, types::PaymentsResponseData, > for {{project-name | downcase | pascal_case}} { } impl ConnectorIntegration< api::Authorize, types::PaymentsAuthorizeData, types::PaymentsResponseData, > for {{project-name | downcase | pascal_case}} { fn get_headers(&self, req: &types::PaymentsAuthorizeRouterData, connectors: &settings::Connectors,) -> CustomResult)>,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 { Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) } fn get_request_body(&self, req: &types::PaymentsAuthorizeRouterData) -> CustomResult, errors::ConnectorError> { let connector_router_data = {{project-name | downcase}}::{{project-name | downcase | pascal_case}}RouterData::try_from(( &self.get_currency_unit(), req.request.currency, req.request.amount, req, ))?; let req_obj = {{project-name | downcase}}::{{project-name | downcase | pascal_case}}PaymentsRequest::try_from(&connector_router_data)?; let {{project-name | downcase}}_req = types::RequestBody::log_and_get_request_body(&req_obj, utils::Encode::<{{project-name | downcase}}::{{project-name | downcase | pascal_case}}PaymentsRequest>::encode_to_string_of_json) .change_context(errors::ConnectorError::RequestEncodingFailed)?; Ok(Some({{project-name | downcase}}_req)) } fn build_request( &self, req: &types::PaymentsAuthorizeRouterData, connectors: &settings::Connectors, ) -> CustomResult, errors::ConnectorError> { Ok(Some( services::RequestBuilder::new() .method(services::Method::Post) .url(&types::PaymentsAuthorizeType::get_url( self, req, connectors, )?) .attach_default_headers() .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 { let response: {{project-name | downcase}}::{{project-name | downcase | pascal_case}}PaymentsResponse = res.response.parse_struct("{{project-name | downcase | pascal_case}} PaymentsAuthorizeResponse").change_context(errors::ConnectorError::ResponseDeserializationFailed)?; types::RouterData::try_from(types::ResponseRouterData { response, data: data.clone(), http_code: res.status_code, }) } fn get_error_response(&self, res: Response) -> CustomResult { self.build_error_response(res) } } impl ConnectorIntegration for {{project-name | downcase | pascal_case}} { fn get_headers( &self, req: &types::PaymentsSyncRouterData, connectors: &settings::Connectors, ) -> CustomResult)>, 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 { Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) } fn build_request( &self, req: &types::PaymentsSyncRouterData, connectors: &settings::Connectors, ) -> CustomResult, errors::ConnectorError> { Ok(Some( services::RequestBuilder::new() .method(services::Method::Get) .url(&types::PaymentsSyncType::get_url(self, req, connectors)?) .attach_default_headers() .headers(types::PaymentsSyncType::get_headers(self, req, connectors)?) .build(), )) } fn handle_response( &self, data: &types::PaymentsSyncRouterData, res: Response, ) -> CustomResult { let response: {{project-name | downcase}}:: {{project-name | downcase | pascal_case}}PaymentsResponse = res .response .parse_struct("{{project-name | downcase}} PaymentsSyncResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; types::RouterData::try_from(types::ResponseRouterData { response, data: data.clone(), http_code: res.status_code, }) } fn get_error_response( &self, res: Response, ) -> CustomResult { self.build_error_response(res) } } impl ConnectorIntegration< api::Capture, types::PaymentsCaptureData, types::PaymentsResponseData, > for {{project-name | downcase | pascal_case}} { fn get_headers( &self, req: &types::PaymentsCaptureRouterData, connectors: &settings::Connectors, ) -> CustomResult)>, 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 { Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) } fn get_request_body( &self, _req: &types::PaymentsCaptureRouterData, ) -> CustomResult, errors::ConnectorError> { Err(errors::ConnectorError::NotImplemented("get_request_body method".to_string()).into()) } fn build_request( &self, req: &types::PaymentsCaptureRouterData, connectors: &settings::Connectors, ) -> CustomResult, errors::ConnectorError> { Ok(Some( services::RequestBuilder::new() .method(services::Method::Post) .url(&types::PaymentsCaptureType::get_url(self, req, connectors)?) .attach_default_headers() .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 { let response: {{project-name | downcase }}::{{project-name | downcase | pascal_case}}PaymentsResponse = res .response .parse_struct("{{project-name | downcase | pascal_case}} PaymentsCaptureResponse") .change_context(errors::ConnectorError::ResponseDeserializationFailed)?; types::RouterData::try_from(types::ResponseRouterData { response, data: data.clone(), http_code: res.status_code, }) } fn get_error_response( &self, res: Response, ) -> CustomResult { self.build_error_response(res) } } impl ConnectorIntegration< api::Void, types::PaymentsCancelData, types::PaymentsResponseData, > for {{project-name | downcase | pascal_case}} {} impl ConnectorIntegration< api::Execute, types::RefundsData, types::RefundsResponseData, > for {{project-name | downcase | pascal_case}} { fn get_headers(&self, req: &types::RefundsRouterData, connectors: &settings::Connectors,) -> CustomResult)>,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, _connectors: &settings::Connectors,) -> CustomResult { Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) } fn get_request_body(&self, req: &types::RefundsRouterData) -> CustomResult, errors::ConnectorError> { let connector_router_data = {{project-name | downcase}}::{{project-name | downcase | pascal_case}}RouterData::try_from(( &self.get_currency_unit(), req.request.currency, req.request.refund_amount, req, ))?; let req_obj = {{project-name | downcase}}::{{project-name | downcase | pascal_case}}RefundRequest::try_from(&connector_router_data)?; let {{project-name | downcase}}_req = types::RequestBody::log_and_get_request_body(&req_obj, utils::Encode::<{{project-name | downcase}}::{{project-name | downcase | pascal_case}}RefundRequest>::encode_to_string_of_json) .change_context(errors::ConnectorError::RequestEncodingFailed)?; Ok(Some({{project-name | downcase}}_req)) } fn build_request(&self, req: &types::RefundsRouterData, connectors: &settings::Connectors,) -> CustomResult,errors::ConnectorError> { let request = services::RequestBuilder::new() .method(services::Method::Post) .url(&types::RefundExecuteType::get_url(self, req, connectors)?) .attach_default_headers() .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, res: Response, ) -> CustomResult,errors::ConnectorError> { let response: {{project-name| downcase}}::RefundResponse = res.response.parse_struct("{{project-name | downcase}} RefundResponse").change_context(errors::ConnectorError::ResponseDeserializationFailed)?; types::RouterData::try_from(types::ResponseRouterData { response, data: data.clone(), http_code: res.status_code, }) } fn get_error_response(&self, res: Response) -> CustomResult { self.build_error_response(res) } } impl ConnectorIntegration for {{project-name | downcase | pascal_case}} { fn get_headers(&self, req: &types::RefundSyncRouterData,connectors: &settings::Connectors,) -> CustomResult)>,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 { Err(errors::ConnectorError::NotImplemented("get_url method".to_string()).into()) } fn build_request( &self, req: &types::RefundSyncRouterData, connectors: &settings::Connectors, ) -> CustomResult, errors::ConnectorError> { Ok(Some( services::RequestBuilder::new() .method(services::Method::Get) .url(&types::RefundSyncType::get_url(self, req, connectors)?) .attach_default_headers() .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 { let response: {{project-name | downcase}}::RefundResponse = res.response.parse_struct("{{project-name | downcase}} RefundSyncResponse").change_context(errors::ConnectorError::ResponseDeserializationFailed)?; types::RouterData::try_from(types::ResponseRouterData { response, data: data.clone(), http_code: res.status_code, }) } fn get_error_response(&self, res: Response) -> CustomResult { self.build_error_response(res) } } #[async_trait::async_trait] impl api::IncomingWebhook for {{project-name | downcase | pascal_case}} { fn get_webhook_object_reference_id( &self, _request: &api::IncomingWebhookRequestDetails<'_>, ) -> CustomResult { Err(errors::ConnectorError::WebhooksNotImplemented).into_report() } fn get_webhook_event_type( &self, _request: &api::IncomingWebhookRequestDetails<'_>, ) -> CustomResult { Err(errors::ConnectorError::WebhooksNotImplemented).into_report() } fn get_webhook_resource_object( &self, _request: &api::IncomingWebhookRequestDetails<'_>, ) -> CustomResult { Err(errors::ConnectorError::WebhooksNotImplemented).into_report() } }