Skip to content

fix(connector): [COINBASE] stop declaring manual capture and refunds webhook flow - #14292

Open
errmakov wants to merge 1 commit into
juspay:mainfrom
errmakov:fix/coinbase-declared-capabilities
Open

errmakov wants to merge 1 commit into
juspay:mainfrom
errmakov:fix/coinbase-declared-capabilities

Conversation

@errmakov

Copy link
Copy Markdown
Contributor

Type of Change

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

Description

The Coinbase connector specification declared capabilities that the connector does not implement, so GET /feature_matrix (and the connector docs generated from it) advertised them:

Declaration Before After Why
supported_capture_methods Automatic, Manual, SequentialAutomatic Automatic, SequentialAutomatic ConnectorIntegration<Capture> returns FlowNotSupported, so a manual capture can never be completed
COINBASE_SUPPORTED_WEBHOOK_FLOWS Payments, Refunds Payments Refunds are declared NotSupported, Execute returns FlowNotSupported, and get_webhook_event_type maps no refund event

Because the default ConnectorValidation::validate_connector_against_payment_request checks the requested capture method against supported_capture_methods, a Coinbase payment with capture_method: manual is now rejected up front with NotSupported, instead of being accepted and failing at capture time.

Why SequentialAutomatic is kept (the issue suggests removing it): should_initiate_capture_flow only chains a capture call when the attempt is Authorized, and only for Paybox. Coinbase's status mapping never produces Authorized (NewAuthenticationPending, Completed/ResolvedCharged), so for Coinbase SequentialAutomatic behaves exactly like Automatic and works today. Removing it would start rejecting requests that currently succeed. This matches cryptopay, which declares the same pair.

Additional Changes

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

Motivation and Context

Fixes #14277.

How did you test it?

Added unit tests in crates/hyperswitch_connectors/src/connectors/coinbase.rs that call validate_connector_against_payment_request for each capture method and check get_supported_webhook_flows.

cargo test -p hyperswitch_connectors --features v1,frm,payouts,revenue_recovery,dummy_connector --lib connectors::coinbase::tests

Tests against the old declarations (tests only):

test connectors::coinbase::tests::accepts_automatic_and_sequential_automatic_capture ... ok
test connectors::coinbase::tests::declares_only_payments_webhook_flow ... FAILED
test connectors::coinbase::tests::rejects_manual_capture_because_capture_flow_is_not_supported ... FAILED
  left: Some([Payments, Refunds])
 right: Some([Payments])
assertion failed: !validate_capture_method(CaptureMethod::Manual)
test result: FAILED. 1 passed; 2 failed; 0 ignored; 0 measured; 10 filtered out

With the fix:

test connectors::coinbase::tests::accepts_automatic_and_sequential_automatic_capture ... ok
test connectors::coinbase::tests::declares_only_payments_webhook_flow ... ok
test connectors::coinbase::tests::rejects_manual_capture_because_capture_flow_is_not_supported ... ok
test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 10 filtered out

Not tested against a live Coinbase account: the change only affects declarations and request validation, and no Coinbase API call changes.

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

…webhook flow

Coinbase has no capture API (the Capture flow returns FlowNotSupported)
and does not support refunds, but its connector specification declared
CaptureMethod::Manual and EventClass::Refunds. /feature_matrix and the
generated connector docs advertised both.

Keep SequentialAutomatic: a Coinbase charge never reports Authorized, so
should_initiate_capture_flow never chains a capture call for it and it
behaves like Automatic.

Add unit tests for capture method validation and declared webhook flows.

Fixes juspay#14277

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@errmakov
errmakov requested a review from a team as a code owner September 17, 2026 14:26
@semanticdiff-com

semanticdiff-com Bot commented Sep 17, 2026

Copy link
Copy Markdown

Review changes with  SemanticDiff

Changed Files
File Status
  crates/hyperswitch_connectors/src/connectors/coinbase.rs  2% smaller

@abhisheksharma2411 abhisheksharma2411 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Verified both removals against the connector rather than the description, and both are correct — this is removing capabilities the code cannot actually perform.

Manual capture. impl ConnectorIntegration<Capture, …> for Coinbase at L349 has a build_request that returns Err(FlowNotSupported) outright. So a merchant configuring manual capture on Coinbase got an accepted configuration and a runtime failure at capture time — after the customer had already paid. Moving that rejection to request validation is the right trade: in payments, failing at configuration beats failing mid-transaction.

Keeping SequentialAutomatic with the reasoning spelled out (a charge never reports Authorized, so no follow-up capture is ever attempted) is the detail that makes this safe to merge — that's the one that would have been easy to remove along with Manual and quietly break working integrations.

Refunds webhook. Also correct, and doubly so:

ConnectorIntegration<Execute, RefundsData, …>::build_request  ->  Err(FlowNotSupported)
get_webhook_event_type  ->  PaymentIntentSuccess | PaymentActionRequired
                            | PaymentIntentProcessing | EventNotSupported

The refund flow is unimplemented, and the webhook mapper cannot emit a single refund event — there is no IncomingWebhookEvent::Refund* anywhere in the connector. So EventClass::Refunds was advertising a webhook class that can never fire.

This looks like a small pattern rather than a one-off. Scanning for connectors whose Capture impl returns FlowNotSupported and which still name CaptureMethod::Manual:

cashtocode
coinbase     <- this PR
tokenio
zen

cashtocode has Manual sitting in its supported_capture_methods vector next to Automatic and SequentialAutomatic, same shape as Coinbase before this change. I haven't checked whether each of those three has the same runtime outcome — a couple may route capture differently — but they're worth a look, and the validate_capture_method test added here is exactly the guard that would pin them once checked. Happy to file an issue listing them if that's useful rather than expanding this PR.

The test is the right shape: asserting through validate_connector_against_payment_request rather than reading the constant means a future edit to the supported list has to confront it.

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.

[BUG] [Coinbase]: declares manual capture and a refunds webhook flow that the connector does not implement

2 participants