Skip to content

Conversation

@swetasharma03
Copy link
Contributor

@swetasharma03 swetasharma03 commented Jul 30, 2025

Type of Change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring
  • Dependency updates
  • Documentation
  • CI/CD

Description

BNPL flow added for affirm connector.
Only added mock server for affirm and not cypress because BNPL is currently not supported in cypress.

Additional Changes

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

Motivation and Context

How did you test it?

This is an alpha connector, also cypress doen't support pay_later PMs as of now.

Checklist

  • I formatted the code cargo +nightly fmt --all
  • I addressed lints thrown by cargo clippy
  • I reviewed the submitted code
  • I added unit tests for my changes where possible

@swetasharma03 swetasharma03 self-assigned this Jul 30, 2025
@swetasharma03 swetasharma03 requested a review from a team as a code owner July 30, 2025 06:13
@semanticdiff-com
Copy link

semanticdiff-com bot commented Jul 30, 2025

Review changes with  SemanticDiff

Changed Files
File Status
  crates/hyperswitch_connectors/src/default_implementations.rs  24% smaller
  crates/common_enums/src/connector_enums.rs  11% smaller
  crates/hyperswitch_connectors/src/connectors/affirm.rs  7% smaller
  crates/hyperswitch_connectors/src/connectors/affirm/transformers.rs  6% smaller
  api-reference/v1/openapi_spec_v1.json  0% smaller
  api-reference/v2/openapi_spec_v2.json  0% smaller
  config/config.example.toml Unsupported file format
  config/deployments/integration_test.toml Unsupported file format
  config/deployments/production.toml Unsupported file format
  config/deployments/sandbox.toml Unsupported file format
  config/development.toml Unsupported file format
  config/docker_compose.toml Unsupported file format
  crates/connector_configs/src/connector.rs  0% smaller
  crates/connector_configs/toml/development.toml Unsupported file format
  crates/connector_configs/toml/production.toml Unsupported file format
  crates/connector_configs/toml/sandbox.toml Unsupported file format
  crates/router/src/core/connector_validation.rs  0% smaller
  crates/router/src/types/api/connector_mapping.rs  0% smaller
  crates/router/src/types/api/feature_matrix.rs  0% smaller
  crates/router/src/types/connector_transformers.rs  0% smaller
  cypress-tests/cypress/e2e/configs/mock-server/Connectors/Affirm.ts  0% smaller
  cypress-tests/cypress/e2e/configs/mock-server/Creds.json  0% smaller
  cypress-tests/cypress/e2e/configs/mock-server/router.ts  0% smaller
  loadtest/config/development.toml Unsupported file format

@swetasharma03 swetasharma03 force-pushed the affirm-bnpl branch 10 times, most recently from 47866b1 to 21aa4e2 Compare July 31, 2025 07:58
Comment on lines 187 to 210
fn extract_metadata(raw: &Value) -> Option<Metadata> {
Some(Metadata {
shipping_type: get_str("shipping_type", raw),
entity_name: get_str("entity_name", raw),
platform_type: get_str("platform_type", raw),
platform_version: get_str("platform_version", raw),
platform_affirm: get_str("platform_affirm", raw),
webhook_session_id: get_str("webhook_session_id", raw),
mode: get_str("mode", raw),
customer: raw.get("customer").cloned(),
itinerary: raw.get("itinerary").and_then(|v| v.as_array().cloned()),
checkout_channel_type: get_str("checkout_channel_type", raw),
bopis: get_bool("BOPIS", raw),
})
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need all these values in metadata?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Metadata is an optional field in connector's API contract, I used HS metadata to populate these values. Should I remove this field?

Copy link
Contributor

Choose a reason for hiding this comment

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

remove the optional fields

Comment on lines 212 to 272
let billing = item
.router_data
.get_optional_billing()
.and_then(|billing_address| {
billing_address.address.as_ref().map(|address| Billing {
name: Name {
first: address.first_name.clone(),
last: address.last_name.clone(),
full: address.get_optional_full_name(),
},
address: Address {
line1: address.line1.clone(),
line2: address.line2.clone(),
city: address.city.clone(),
state: address.state.clone(),
zipcode: address.zip.clone(),
country: address.country,
},
phone_number: billing_address
.phone
.as_ref()
.and_then(|phone| phone.number.as_ref().cloned()),
email: billing_address.email.clone(),
})
});

let shipping = item
.router_data
.get_optional_shipping()
.and_then(|shipping_address| {
shipping_address.address.as_ref().map(|address| Shipping {
name: Name {
first: address.first_name.clone(),
last: address.last_name.clone(),
full: address.get_optional_full_name(),
},
address: Address {
line1: address.line1.clone(),
line2: address.line2.clone(),
city: address.city.clone(),
state: address.state.clone(),
zipcode: address.zip.clone(),
country: address.country,
},
phone_number: shipping_address
.phone
.as_ref()
.and_then(|phone| phone.number.as_ref().cloned()),
email: shipping_address.email.clone(),
})
});
Copy link
Contributor

Choose a reason for hiding this comment

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

If any of these fields is mandatory please add them in crates/payment_methods/src/configs/payment_connector_required_fields.rs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

use utils here

Copy link
Contributor

Choose a reason for hiding this comment

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

e.g. get_optional_billing_line1

AffirmEventType::ExpireAuthorization | AffirmEventType::ExpireConfirmation => {
Self::AuthorizationFailed
}
AffirmEventType::Refund | AffirmEventType::RefundVoided => Self::AutoRefunded,
Copy link
Contributor

@deepanshu-iiitu