Skip to content

feat(core): send customer date of birth to UCS as a typed field - #13973

Open
shuklatushar226 wants to merge 1 commit into
mainfrom
feat/customer-dob-to-ucs
Open

feat(core): send customer date of birth to UCS as a typed field#13973
shuklatushar226 wants to merge 1 commit into
mainfrom
feat/customer-dob-to-ucs

Conversation

@shuklatushar226

@shuklatushar226 shuklatushar226 commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Type of Change

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

Description

Ilixium requires customer.dateOfBirth on every card authorisation. It is a UCS-only connector, and because the UCS payment model had nowhere to put a date of birth, the connector read one out of the merchant's free-form payment metadata blob under ilixium_date_of_birth.

The pieces to fix this already exist on both sides. #13870 added customer.date_of_birth to the payment request and carried it to RouterData::customer_date_of_birth, which Checkout and WorldpayXML already consume on the direct path. connector-service #2188 added Customer.date_of_birth to the gRPC contract. Only the join was missing — every payments_grpc::Customer we build left the field unset.

  • Bump unified-connector-service-{client,cards} to 2026.09.01.0, the first release carrying Customer.date_of_birth. The proto diff is additive, but these literals are exhaustive, so the new AFT and payout fields are filled in too. They stay None: Hyperswitch's AFT support runs on the direct connector path today, and routing it through UCS is separate work.
  • to_grpc_customer_date_of_birth maps RouterData::customer_date_of_birth to the ISO-8601 string the contract asks for, mirroring to_grpc_customer_document_details, and is applied at all 16 Customer construction sites plus the payouts ForeignFrom. date_of_birth_to_string in api_models::customers is the single place that encodes time::Date for the wire; only the Ilixium transformer knows the ddmmyyyy shape the processor wants.
  • Ilixium's required fields gain customer.date_of_birth (FieldType::UserDateOfBirth) so the SDK collects it from the shopper, and move from non_mandate to common. non_mandate is merged only when the payment is not customer-initiated, so a save-card or setup_future_usage = off_session payment was collecting none of Ilixium's required fields at all.

Additional Changes

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

Dependency tags only: crates/{external_services,router,hyperswitch_interfaces}/Cargo.toml. No API-contract or schema change — customer.date_of_birth on the payment request already shipped in #13870.

Motivation and Context

Closes #13977.

Sourcing a date of birth from an opaque metadata key means no validation, no prompting in the SDK, and PII travelling outside the typed customer object. This moves it onto the customer object the shopper actually fills in.

Pairs with juspay/hyperswitch-prism#2211, which plumbs Customer.date_of_birth into PaymentsAuthorizeData and switches Ilixium off the metadata path.

How did you test it?

Unit test ilixium_collects_date_of_birth_on_every_card_payment asserts customer.date_of_birth is in Ilixium's common bucket (the only one merged for both customer-initiated and one-off payments) with FieldType::UserDateOfBirth, and that mandate/non_mandate are empty.

cargo clippy -p router --features v1 -- -D warnings              # exit 0
cargo check -p router --no-default-features --features "release,v2,redis-rs"  # exit 0
cargo test -p payment_methods ilixium_collects_date_of_birth     # 1 passed

Cypress: cypress-tests/cypress/e2e/configs/Payment/Ilixium.js now sends customer: { date_of_birth: "1990-01-01" } instead of metadata.ilixium_date_of_birth.

⚠️ Merge order and merchant impact

Ship this before juspay/hyperswitch-prism#2211. This PR only starts sending the field, which the current UCS release ignores — harmless. The prism PR changes where Ilixium reads from, so deployed first it would leave Ilixium with no date of birth at all.

Merchants passing ilixium_date_of_birth in metadata must move to customer.date_of_birth; the metadata key stops being read once the prism side ships. Worth a release note.

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

🤖 Generated with Claude Code

https://claude.ai/code/session_015KgmRmPj7PmQQLF1pPsRPf

Ilixium requires `customer.dateOfBirth` on every card authorisation. It is a
UCS-only connector, and because the UCS payment model had nowhere to put a date
of birth, the connector read one out of the merchant's free-form payment
`metadata` blob under `ilixium_date_of_birth`. That means no validation, no
prompting in the SDK, and PII travelling in an opaque JSON object.

The pieces to fix it already exist on both sides. #13870 added
`customer.date_of_birth` to the payment request and carried it through to
`RouterData::customer_date_of_birth`, which the Checkout and WorldpayXML
integrations already consume on the direct path. connector-service #2188 added
`Customer.date_of_birth` to the gRPC contract. Only the join was missing: every
`payments_grpc::Customer` this file builds left the field unset.

- Bump `unified-connector-service-{client,cards}` to 2026.09.01.0, the first
  release carrying `Customer.date_of_birth`. The proto diff is additive, but
  these literals are exhaustive, so the new AFT and payout fields are filled in
  as well. They stay `None`: Hyperswitch's own AFT support runs on the direct
  connector path today, and routing it through UCS is separate work.
- `to_grpc_customer_date_of_birth` maps `RouterData::customer_date_of_birth` to
  the ISO-8601 string the contract asks for, mirroring
  `to_grpc_customer_document_details`, and is applied at every construction
  site. `date_of_birth_to_string` in `api_models::customers` is the one place
  that encodes `time::Date` for the wire; only the Ilixium transformer knows
  the `ddmmyyyy` shape the processor actually wants.
- Ilixium's required fields gain `customer.date_of_birth`
  (`FieldType::UserDateOfBirth`) so the SDK collects it, and move from
  `non_mandate` to `common`. `non_mandate` is merged only when the payment is
  not customer-initiated, so a save-card or `setup_future_usage = off_session`
  payment was collecting none of Ilixium's required fields at all.

Merchants passing `ilixium_date_of_birth` in `metadata` must move to
`customer.date_of_birth`; the metadata key stops being read once the
corresponding UCS release ships. Ship this before that one, or Ilixium loses
its only source of a date of birth.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015KgmRmPj7PmQQLF1pPsRPf
@shuklatushar226
shuklatushar226 requested review from a team as code owners September 1, 2026 21:15
@semanticdiff-com

semanticdiff-com Bot commented Sep 1, 2026

Copy link
Copy Markdown

Review changes with  SemanticDiff

Changed Files
File Status
  crates/payment_methods/src/configs/payment_connector_required_fields.rs  1% smaller
  Cargo.lock Unsupported file format
  crates/api_models/src/customers.rs  0% smaller
  crates/external_services/Cargo.toml Unsupported file format
  crates/hyperswitch_interfaces/Cargo.toml Unsupported file format
  crates/router/Cargo.toml Unsupported file format
  crates/router/src/core/unified_connector_service/transformers.rs  0% smaller
  cypress-tests/cypress/e2e/configs/Payment/Ilixium.js  0% smaller
  cypress-tests/cypress/e2e/configs/Payment/Utils.js  0% smaller

@shuklatushar226 shuklatushar226 added the S-test-ready Status: This PR is ready for cypress-tests label Sep 1, 2026
@github-actions github-actions Bot removed the S-test-ready Status: This PR is ready for cypress-tests label Sep 1, 2026
@shuklatushar226 shuklatushar226 added the S-test-ready Status: This PR is ready for cypress-tests label Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-test-ready Status: This PR is ready for cypress-tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Send customer date of birth to UCS as a typed field instead of via payment metadata

1 participant