fix(payouts): route merchant-authentication (access-token) calls through the payout connector#13150
fix(payouts): route merchant-authentication (access-token) calls through the payout connector#13150gopikrishna000 wants to merge 3 commits into
Conversation
…ugh the payout connector During the merchant-authentication (access-token) flow, the access-token gateway unconditionally used the payment gRPC header builder (x-connector) and a payment reference, even when the caller was a payout. For payout access-token calls this selected the payment connector variant and carried a placeholder payment reference instead of the real payout reference. Make the access-token path payout-aware: - external_services: add create_access_token_for_payouts, which uses build_unified_connector_service_grpc_headers_for_payouts (x-payout-connector). - gateway: when router_data.payout_id is set, build the payout reference and resource ids and call the payout sibling. Payments and the existing payout_transfer/payout_get paths are untouched.
Changed Files
|
| /// Performs Create Access Token Granular for payouts | ||
| /// | ||
| /// Identical to [`Self::create_access_token`] but attaches the payout connector | ||
| /// header (`x-payout-connector`) so the merchant-authentication flow resolves the | ||
| /// payout connector variant instead of the payment one. | ||
| pub async fn create_access_token_for_payouts( | ||
| &self, | ||
| create_access_token_request: payments_grpc::MerchantAuthenticationServiceCreateServerAuthenticationTokenRequest, | ||
| connector_auth_metadata: ConnectorAuthMetadata, | ||
| grpc_headers: GrpcHeadersUcs, | ||
| ) -> UnifiedConnectorServiceResult< | ||
| tonic::Response< | ||
| payments_grpc::MerchantAuthenticationServiceCreateServerAuthenticationTokenResponse, | ||
| >, | ||
| > { | ||
| let mut request = tonic::Request::new(create_access_token_request); | ||
| let connector_name = connector_auth_metadata.connector_name.clone(); | ||
| let metadata = build_unified_connector_service_grpc_headers_for_payouts( | ||
| connector_auth_metadata, | ||
| grpc_headers, | ||
| )?; | ||
| *request.metadata_mut() = metadata; | ||
|
|
||
| self.merchant_authentication_service_client | ||
| .clone() | ||
| .create_server_authentication_token(request) | ||
| .await | ||
| .map_err(|error| { | ||
| error_stack::Report::new(UnifiedConnectorServiceError::from_grpc_error( | ||
| &error, | ||
| &connector_name, | ||
| )) | ||
| }) | ||
| .inspect_err(|error| { | ||
| logger::error!( | ||
| grpc_error=?error, | ||
| method="create_server_authentication_token_for_payouts", | ||
| connector_name=?connector_name, | ||
| "UCS create server authentication token gRPC call failed" | ||
| ) | ||
| }) | ||
| } |
There was a problem hiding this comment.
the only difference between create_access_token_for_payouts and create_access_token is the metadata creation. so instead of duplicating the whole logic in create_access_token we can pass a field indicating payments or payouts, based on that we can create the metadata
There was a problem hiding this comment.
Done in d417197 — collapsed create_access_token_for_payouts into create_access_token with an is_payout flag that selects the payout vs payment header builder; both call sites updated (gateway passes is_payout, the payments/relay path passes false).
|
Both Add |
Review Findings[should-fix] Code duplication in access token methodsThe new [should-fix]
|
…stead of a payout sibling Address review: collapse create_access_token_for_payouts into create_access_token via an is_payout flag that selects the payout vs payment gRPC header builder, removing the duplicated function body.
|
The logic at lines 102-170 detects payout flow using Consider using a more explicit flow discriminator or validating that |
|
In The addition of pub async fn create_access_token(
&self,
...
is_payout: bool, // What does true mean again?
)If more connector types are added (payouts, fraud_check, identity, etc.), this becomes an unmaintainable series of booleans. Fix: Use an enum to make call sites self-documenting: pub enum ConnectorType {
Payment,
Payout,
}
// Call site becomes:
create_access_token(..., ConnectorType::Payout) |
|
💡 Consider consolidating payout detection logic The |
|
The .inspect_err(|err| logger::warn!(...))
.ok()
.map(...)Invalid Consider failing fast with a proper error instead of continuing with |
Summary
During the merchant-authentication (access-token) flow, the access-token gateway unconditionally used the payment gRPC header builder (
x-connector) and a payment reference — even when the caller was a payout. For payout access-token calls this selected the payment connector variant and carried a placeholder payment reference instead of the real payout reference, even thoughrouter_data.payout_idis available on the access-tokenRouterData(preserved throughrouter_data_type_conversion).What this does
Makes the access-token path payout-aware:
external_services— addscreate_access_token_for_payouts, a sibling ofcreate_access_tokenthat usesbuild_unified_connector_service_grpc_headers_for_payouts(x-payout-connector).access_token_gateway.rs) — whenrouter_data.payout_idis set, builds the payout reference (UcsReferenceId::Payout) and resource id (UcsResourceId::PayoutAttempt) and dispatches to the payout sibling, following the existingpayouts/gateway/*pattern. The payment path and the existingpayout_transfer/payout_getpaths are untouched.Result
Payout access-token calls now select the payout connector variant, run its auth implementation, and carry the real payout reference.
Companion change
Pairs with the connector-side implementation of the Itaú payout merchant-auth flow: juspay/hyperswitch-prism#1806