Skip to content

Conversation

@siaass842
Copy link

@siaass842 siaass842 commented Nov 5, 2025

Description

Added CA certificate support for API calls in the Archipel connector, following the pattern from hyperswitch PR #8128. This enables one-way TLS
authentication with custom CA certificates for the Archipel connector.

Changes made:

  1. ConnectorIntegrationV2 Trait (backend/interfaces/src/connector_integration_v2.rs)

    • Added get_ca_certificate() method to the trait interface
    • Updated build_request_v2() to call .add_ca_certificate_pem()
  2. Archipel Connector (backend/connector-integration/src/connectors/archipel.rs)

    • Implemented get_ca_cert() helper function to extract CA certificate from auth
    • Overrode get_ca_certificate() method to return the CA certificate from auth details
  3. HTTP Client (backend/external-services/src/service.rs)

    • Updated create_client() function to support three modes:
      • Mutual TLS (client cert + key)
      • One-way TLS (CA cert only) - NEW
      • Default client (no certificates)
    • Handles PEM parsing and escaped newline characters
  4. Archipel Auth Type (already existed in transformers.rs)

    • Uses existing ca_certificate field in ArchipelAuthType
    • Extracts CA cert from ConnectorAuthType::HeaderKey { api_key }

Motivation and Context

The Archipel connector requires custom CA certificate support for secure communication with their API endpoints. This allows the connector to authenticate the server using a custom CA certificate, which
is essential for environments with self-signed or internal CA certificates.

This implementation follows the established pattern from the hyperswitch repository to maintain consistency across the codebase.

Type of Change

  • New feature (non-breaking change which adds functionality)
  • Refactoring (non-breaking change which does not add functionality)

Additional Changes

  • This PR modifies the API contract
  • This PR modifies application configuration/environment variables

How did you test it?

  • Successfully built the entire workspace with cargo build --workspace
  • No compilation errors or warnings related to the changes
  • Code follows the same pattern as the reference implementation in hyperswitch

Manual Testing Required:

To fully test this feature, the following steps should be performed:

  1. Configure the Archipel connector with a CA certificate in PEM format via the HeaderKey auth type
  2. Make API calls to the Archipel connector
  3. Verify that the custom CA certificate is properly used for TLS verification
  4. Confirm successful API communication with endpoints using custom CA certificates

Files Modified:

  • backend/interfaces/src/connector_integration_v2.rs:211-220 - Added get_ca_certificate() method
  • backend/interfaces/src/connector_integration_v2.rs:108 - Added .add_ca_certificate_pem() call
  • backend/connector-integration/src/connectors/archipel.rs:34 - Added Secret import
  • backend/connector-integration/src/connectors/archipel.rs:168-177 - Added get_ca_cert() helper
  • backend/connector-integration/src/connectors/archipel.rs:779-784 - Overrode get_ca_certificate()
  • backend/external-services/src/service.rs:741-788 - Implemented CA cert support in HTTP client

@siaass842 siaass842 requested review from a team as code owners November 5, 2025 12:22
@siaass842 siaass842 changed the title feat(archipel) add authorize flow feat(archipel): add authorize flow Nov 5, 2025
request: Request,
_flow_name: &str,
) -> CustomResult<Result<Response, Response>, ApiClientError> {
println!(">>> {:?}", request.body);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this.

Comment on lines 89 to 103
/// Represents details of a payment method.
#[derive(Debug, Clone)]
pub struct PaymentMethodDetails {
/// Indicates whether mandates are supported by this payment method.
pub mandates: common_enums::FeatureStatus,
/// Indicates whether refund is supported by this payment method.
pub refunds: common_enums::FeatureStatus,
/// List of supported capture methods
pub supported_capture_methods: Vec<common_enums::CaptureMethod>,
/// Payment method specific features
pub specific_features: Option<PaymentMethodSpecificFeatures>,
}

/// list of payment methods, payment method types and metadata related to them
pub type SupportedPaymentMethods = HashMap<common_enums::PaymentMethod, PaymentMethodTypeMetadata>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are these changes required?

use std::collections::HashMap;

use common_utils::Method;
use crate::types::{PaymentMethodSpecificFeatures, PaymentMethodTypeMetadata};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this required?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no removed

Cybersource, Dlocal, Elavon, Fiserv, Fiuu, Helcim, Mifinity, Nexinets, Noon, Novalnet, Paytm,
Payu, Phonepe, Placetopay, Rapyd, Razorpay, RazorpayV2, Stripe, Trustpay, Volt, Worldpay,
Xendit,
Xendit, Archipel
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maintain alphabetical order here

Comment on lines 1803 to 1815

pub enum PaymentMethodStatus {
Active,
Inactive,
Processing,
AwaitingData,
}

#[derive(Debug, Clone)]
pub enum FeatureStatus {
NotSupported,
Supported,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this required?

Comment on lines 186 to 192
pub fn connector_base_url_refunds<'a, F, Req, Res>(
&self,
req: &'a RouterDataV2<F, RefundFlowData, Req, Res>,
) -> &'a str {
&req.resource_common_data.connectors.archipel.base_url
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check if we can remove this function from here. This function should be included in refunds PR.

// TODO: Implement proper error response parsing
Ok(ErrorResponse {
status_code: res.status_code,
code: NO_ERROR_CODE.to_string(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check if code can be filled from the error response.

code: NO_ERROR_CODE.to_string(),
attempt_status: None,
connector_transaction_id: None,
message: NO_ERROR_MESSAGE.to_string(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check if message can be filled from the error response.

attempt_status: None,
connector_transaction_id: None,
message: NO_ERROR_MESSAGE.to_string(),
reason: None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check if reason can be filled from the error response.

@Anurag-05-prog
Copy link
Contributor

Resolve Merge Conflicts.

@Anurag-05-prog
Copy link
Contributor

Run cargo +nightly fmt --all

let capture_method = req
.request
.capture_method
.ok_or(errors::ConnectorError::CaptureMethodNotSupported)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use MissingRequiredField: capture_method here

build_env_specific_endpoint(self.connector_base_url_payments(req), &req.request.metadata)?;
match capture_method {
enums::CaptureMethod::Automatic | enums::CaptureMethod::SequentialAutomatic => {
println!("here");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this println line

utils::CardIssuer,
};
use error_stack::{ report};
// use hyperswitch_interfaces::{consts, errors};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this comment if it's not required

use serde_json::Value;

use crate::{
// connectors::archipel::ArchipelRouterData,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this comment if it's not required

Comment on lines 76 to 85
// impl TryFrom<&Option<pii::SecretSerdeValue>> for ArchipelConfigData {
// type Error = error_stack::Report<errors::ConnectorError>;
// fn try_from(connector_metadata: &Option<pii::SecretSerdeValue>) -> Result<Self, Self::Error> {
// let config_data = utils::to_connector_meta_from_secret::<Self>(connector_metadata.clone())
// .change_context(errors::ConnectorError::InvalidConnectorConfig {
// config: "metadata. Required fields: tenant_id, platform_url",
// })?;
// Ok(config_data)
// }
// }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this comment if it's not required

Comment on lines 95 to 106
// fn to_connector_meta(
// connector_meta: Option<Value>,
// ) -> CustomResult<ArchipelConfigData, ConnectorError> {
// Ok(connector_meta
// .map(|meta| {
// print!("meta value {:?}",meta);
// serde_json::from_value::<ArchipelConfigData>(meta)
// .map_err(|_| report!(errors::ConnectorError::InvalidDataFormat { field_name: "metadata" }))
// })
// .transpose()?
// .ok_or_else(|| ConnectorError::NoConnectorMetaData)?)
// }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this comment if it's not required

#[serde(rename_all = "camelCase")]
pub struct ArchipelOrderRequest {
amount: MinorUnit,
currency: String,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
currency: String,
currency: enums::Currency,

+ Serialize,
> {
card_data: ArchipelTokenizedCard<T>,
// wallet_information: ArchipelWalletInformation,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this line

AttemptStatus::AuthenticationFailed => Ok(Self::Verify),
AttemptStatus::Authorizing
| AttemptStatus::Authorized
| AttemptStatus::AuthorizationFailed => Ok(Self::Authorize),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why AuthorizationFailed is mapped with Authorize?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should it be cancel then ?

Comment on lines 505 to 508
amount: Option<i64>,
currency: Option<Currency>,
captured_amount: Option<i64>,
authorized_amount: Option<i64>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use MinorUnit instead of i64.

.router_data
.request
.capture_method
.ok_or_else(|| errors::ConnectorError::CaptureMethodNotSupported)?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use MissingRequiredField: capture_method here.

Comment on lines 402 to 404
AttemptStatus::Authorizing
| AttemptStatus::Authorized
| AttemptStatus::AuthorizationFailed => Ok(Self::Authorize),
| AttemptStatus::AuthorizationFailed => Ok(Self::Cancel),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check this status mapping

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants