Skip to content

feat(qwikcilver): add payment method eligibility check - #2135

Merged
Aishwariyaa-Anand merged 5 commits into
mainfrom
qwikcilver_eligibility
Aug 18, 2026
Merged

feat(qwikcilver): add payment method eligibility check#2135
Aishwariyaa-Anand merged 5 commits into
mainfrom
qwikcilver_eligibility

Conversation

@Aishwariyaa-Anand

Copy link
Copy Markdown
Contributor

Description

Adds PaymentMethodEligibility support for Qwikcilver, and a composite endpoint that bootstraps the connector's access token before calling it.

  • Qwikcilver eligibility flow (PaymentMethodService.Eligibility): performs the exact same wallet lookup Qwikcilver's GetPaymentMethod already does (GET /wallet/{wallet_number}, or by customer phone as a fallback), maps the wallet's status to ELIGIBLE (ACTIVE) / INELIGIBLE (INACTIVE), and returns the wallet's payment_method_details (balance, items) in the same response instead of a bare eligible/ineligible flag.
  • Shared proto/domain changes: added connector_payment_method_id to PaymentMethodServiceEligibilityRequest and payment_method_details to PaymentMethodServiceEligibilityResponse. Both are additive/optional, so the existing BNPL eligibility usage (Tamara) is unaffected.
  • Composite flow (CompositePaymentMethodService.Eligibility, POST /composite/payment_methods/eligibility): follows the same access-token-bootstrap + forward pattern as /composite/payment_methods/get — auto-bootstraps the connector's session token via MerchantAuthenticationService.CreateServerAuthenticationToken (only when the connector requires one and the caller hasn't already supplied one), splices the resulting token into the inner PaymentMethodService.Eligibility request via state.access_token, and forwards. This lets callers hit a single endpoint instead of manually calling /payments/server_authentication_token first.

Motivation and Context

Additional Changes

  • This PR modifies the API contract
    • crates/types-traits/grpc-api-types/proto/payment.proto (PaymentMethodServiceEligibilityRequest/Response)
    • crates/types-traits/grpc-api-types/proto/composite_services.proto (new CompositePaymentMethodService.Eligibility RPC)
    • crates/types-traits/grpc-api-types/proto/composite_payment.proto (new CompositePaymentMethodEligibilityRequest/Response messages)
  • This PR modifies application configuration/environment variables

How did you test it?

composite eligibility

curl --location 'http://localhost:8000/composite/payment_methods/eligibility' \
--header 'Content-Type: application/json' \
--header 'x-connector: qwikcilver' \
--header 'x-connector-config: {"config":{-}}}' \
--header 'x-merchant-id: JUSPAYUAT' \
--header 'x-tenant-id: public' \
--data '{
    "connector_payment_method_id": "4999771007702947",
    "amount": {
        "minor_amount": 1000,
        "currency": "USD"
    },
    "order_details": []
}
'

Response

{
    "access_token_response": {
        "access_token": "-",
        "token_type": "Bearer",
        "expires_in_seconds": 1200,
        "status": "OPERATION_STATUS_SUCCESS",
        "status_code": 200
    },
    "eligibility_response": {
        "eligibility": "ELIGIBLE",
        "status_code": 200,
        "raw_connector_request": "-",
        "raw_connector_response": "-",
        "typed_connector_response": "{\"Wallet\":{\"WalletNumber\":\"*** alloc::string::String ***\",\"ExternalWalletId\":\"*** alloc::string::String ***\",\"WalletPin\":\"*** alloc::string::String ***\",\"Status\":\"ACTIVE\",\"TrackData\":null,\"BarCode\":null,\"WalletProgramGroupName\":\"PAWC-AFG Payblue Wallet UAE\",\"WalletHolderName\":\"*** alloc::string::String ***\",\"Balance\":2339.68,\"Notes\":\"Wallet AFG\",\"Card\":null,\"Customer\":{\"CustomerType\":\"WALLETCUSTOMER\",\"Salutation\":\"MR\",\"Firstname\":\"*** alloc::string::String ***\",\"LastName\":\"*** alloc::string::String ***\",\"PhoneNumber\":\"*** alloc::string::String ***\",\"Email\":\"********@PINELABS.COM\",\"DOB\":\"*** alloc::string::String ***\",\"AddressLine1\":\"*** alloc::string::String ***\",\"AddressLine2\":\"*** alloc::string::String ***\",\"ExternalCustomerId\":null}},\"CurrentBatchNumber\":17732929,\"Notes\":\"Wallet AFG\",\"ApprovalCode\":\"147662602\",\"ResponseCode\":0,\"ResponseMessage\":\"Transaction successful.\",\"TransactionId\":1786716858212010000,\"TransactionType\":\"WALLET GET\",\"ErrorCode\":null,\"ErrorDescription\":null}",
        "response_headers": {
            "content-length": "1160",
            "connection": "keep-alive",
            "date": "Fri, 14 Aug 2026 14:14:18 GMT",
            "cache-control": "no-cache",
            "expires": "-1",
            "x-content-type-options": "nosniff",
            "access-control-allow-origin": "*",
            "access-control-expose-headers": "WWW-Authenticate",
            "pragma": "no-cache",
            "api-supported-versions": "2.0",
            "content-type": "application/json; charset=utf-8",
            "server": "Microsoft-IIS/10.0",
            "strict-transport-security": "Strict-Transport-Security: max-age=31536000; includeSubDomains"
        },
        "payment_method_details": {
            "details": {
                "Wallet": {
                    "wallet_account_id": "4999771007702947",
                    "wallet_pin": "",
                    "wallet_status": "ACTIVE_WALLET",
                    "wallet_holder_name": "MR. PRASHANT M",
                    "balance": 233968,
                    "product_id": "PAWC-AFG Payblue Wallet UAE",
                    "items": []
                }
            }
        }
    }
}

@Aishwariyaa-Anand Aishwariyaa-Anand self-assigned this Aug 14, 2026
@Aishwariyaa-Anand
Aishwariyaa-Anand requested review from a team as code owners August 14, 2026 15:25
hyperswitch-bot Bot and others added 2 commits August 14, 2026 15:46
Auto-applied by CI:
- cargo +nightly fmt --all
- make -C sdk generate (if applicable)
- make docs (if applicable)

This commit was automatically generated by GitHub Actions.
serde_json::to_string(&body).ok().map(Secret::new);
data.response = match body.response_code {
QWIKCILVER_SUCCESS_CODE => {
let currency = data.request.amount.currency;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

amount.currency is the order currency, but it drives convert_back on the wallet's balance. GetPaymentMethod (:1178) and CreatePaymentMethod (:1113) read the same envelope via currency_from_feature_data. A JPY order against the AED wallet from your repro turns 2339.68 into 2340 instead of 233968, so /get and /eligibility report different balances for one wallet.

Suggested change
let currency = data.request.amount.currency;
let currency =
currency_from_feature_data(data.request.connector_feature_data.as_ref());

Some(currency) at :1257 then becomes just currency.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this is not required in connector_feature_data, passing it in the amount field itself

} else {
(common_enums::EligibilityStatus::Unknown, None)
};
Ok(PaymentMethodEligibilityResponse {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Only amount.currency is read here — amount.minor_amount never enters the verdict, so an ACTIVE wallet with a zero balance comes back ELIGIBLE for any order total. Is that intended? For a stored-value instrument I'd expect the balance check to happen here rather than being left to the caller.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

we will only check for wallet eligibility and not amount cause the payment can also be performed via split payments

@Aishwariyaa-Anand
Aishwariyaa-Anand added this pull request to the merge queue Aug 18, 2026
Merged via the queue into main with commit 91d0a3d Aug 18, 2026
26 of 28 checks passed
@Aishwariyaa-Anand
Aishwariyaa-Anand deleted the qwikcilver_eligibility branch August 18, 2026 07:18
pixincreate added a commit that referenced this pull request Aug 19, 2026
…-response-parsing

* origin/main:
  feat(connector): [Trustly] Implementation (#2068)
  feat(connector): [ilixium] add Ilixium connector with all six core flows (#2125)
  chore(version): 2026.08.19.0
  feat(connector): Moneris Connector Integration (#2127)
  feat(shadow): add x-org-id header to outgoing shadow mode requests (#2148)
  chore(version): 2026.08.18.1
  feat(tamara): override prod with sbx url (#2147)
  docs(sdk/payout-service): add per-operation docs for java, node, pyth… (#2102)
  feat(qwikcilver): add payment method eligibility check (#2135)
  feat(connector): implement Authorize (Card, non-3DS + 3DS redirect), PSync, Capture, Void, Refund and RSync for citigate (#2124)
  chore(version): 2026.08.18.0
  feat(logs): euler-parity golden-line sources + mapping config (on #2075) (#2076)
  fix(sync): return merchant_transaction_id on failed payment sync response (#2141)
  feat(connector): [Truelayer] Implementation (#2047)
  refactor(deps): make log_utils optional and fix default log format visibility (#2137)
  fix(maya): capture missing response fields + surface raw connector response (#2134)
  chore(version): 2026.08.17.0
  feat(connector): [Truelayer] Add support for Returning Customer Flow (#1458)
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.

4 participants