Skip to content

fix(connector): stop cashtocode, tokenio and zen declaring manual capture - #14315

Open
abhisheksharma2411 wants to merge 1 commit into
juspay:mainfrom
abhisheksharma2411:fix/false-manual-capture-declarations
Open

abhisheksharma2411 wants to merge 1 commit into
juspay:mainfrom
abhisheksharma2411:fix/false-manual-capture-declarations

Conversation

@abhisheksharma2411

Copy link
Copy Markdown

Type of Change

  • Bugfix

Description

Three connectors advertise a capture method they cannot perform. Each lists CaptureMethod::Manual in supported_capture_methods while its ConnectorIntegration<Capture, ..>::build_request returns FlowNotSupported:

connector Capture flow declares Manual
cashtocode Err(FlowNotSupported { flow: "Capture" }) yes
tokenio Err(FlowNotSupported { flow: "Capture" }) yes
zen Err(FlowNotSupported { flow: "Capture" }) yes

validate_connector_against_payment_request decides purely on membership of that list:

payment_method_type_info.supported_capture_methods.contains(&capture_method)

So a manual-capture payment passes validation, authorizes, and then cannot be captured. The failure arrives after the customer has already paid, instead of when the request is validated — which is the wrong end of the transaction for a capability error.

SequentialAutomatic is kept for all three, for the same reason as #14292: a charge never reports Authorized, so no follow-up capture call is made for it.

How this was found

Reviewing #14292, which fixes exactly this for Coinbase. Scanning the connector directory for the same shape — a Capture impl returning FlowNotSupported alongside a CaptureMethod::Manual declaration — returned four connectors: coinbase (covered by #14292), and these three. That is the complete set; every other connector whose Capture flow is unsupported already omits Manual.

Credit to @errmakov for #14292 — this is that fix applied to the rest of the set, deliberately mirroring its shape rather than inventing a different one.

Testing

Each connector gets the regression test from #14292, asserting through validate_connector_against_payment_request rather than reading the constant, so the guard survives a refactor of the list:

running 6 tests
test connectors::cashtocode::tests::rejects_manual_capture_because_capture_flow_is_not_supported ... ok
test connectors::tokenio::tests::rejects_manual_capture_because_capture_flow_is_not_supported ... ok
test connectors::zen::tests::rejects_manual_capture_because_capture_flow_is_not_supported ... ok
test connectors::*::tests::accepts_automatic_and_sequential_automatic_capture ... ok
test result: ok. 6 passed; 0 failed

Watched them fail first. Re-adding CaptureMethod::Manual to all three lists:

test result: FAILED. 3 passed; 3 failed

so each test fails for its own connector rather than passing on someone else's behaviour.

cargo fmt --all -- --check clean, cargo clippy -p hyperswitch_connectors --features "v1,payouts,frm,revenue_recovery" clean.

Not included

No change to the webhook-flow declarations. #14292 also drops EventClass::Refunds for Coinbase; I checked these three separately and did not find the same mismatch, so that half is deliberately not copied across.

…ture

All three list `CaptureMethod::Manual` in `supported_capture_methods`
while their `ConnectorIntegration<Capture, ..>::build_request` returns
`FlowNotSupported`. `validate_connector_against_payment_request` checks
membership of that list, so a manual-capture payment is accepted at
authorization and then cannot be captured — the failure lands after the
customer has already paid, rather than when the request is validated.

`SequentialAutomatic` stays for all three: a charge never reports
`Authorized`, so no follow-up capture call is made for it.

Same defect and the same fix as juspay#14292 for Coinbase, found by scanning
for connectors whose Capture flow is `FlowNotSupported` but which still
advertise Manual. Those four were the complete set.

Each connector gets the regression test from juspay#14292, asserting through
`validate_connector_against_payment_request` rather than reading the
constant, so re-adding Manual to the list fails rather than passing.
@abhisheksharma2411
abhisheksharma2411 requested a review from a team as a code owner September 18, 2026 21:45
@semanticdiff-com

semanticdiff-com Bot commented Sep 18, 2026

Copy link
Copy Markdown

Review changes with  SemanticDiff

Changed Files
File Status
  crates/hyperswitch_connectors/src/connectors/cashtocode.rs  2% smaller
  crates/hyperswitch_connectors/src/connectors/zen.rs  2% smaller
  crates/hyperswitch_connectors/src/connectors/tokenio.rs  2% smaller

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.

1 participant