| name | add-payment-method |
| description | Adds payment method support (Card, Wallet, Bank Transfer, UPI, BNPL, etc.) to an existing connector in the connector-service (UCS) Rust codebase. Modifies the Authorize flow transformers to handle new payment method data types. Use when a connector exists with Authorize flow but needs to support additional payment methods.
|
| license | Apache-2.0 |
| compatibility | Requires Rust toolchain with cargo. Linux or macOS. |
| metadata | {"author":"parallal","version":"2.0","domain":"payment-connectors"} |
Add Payment Method
Overview
Adds payment method support to an existing connector's Authorize flow.
MANDATORY SUBAGENT DELEGATION: You are the orchestrator. You MUST delegate every step
to a subagent using the prompts in references/subagent-prompts.md. Do NOT implement
code, run tests, or review quality yourself. Spawn subagents and coordinate their outputs.
Inputs: connector name + payment methods to add (e.g., "add Apple Pay and Google Pay to AcmePay")
Output: payment methods implemented, tested, quality-reviewed
Prerequisite: connector must have Authorize flow implemented
Payment Method Categories
| Category | PaymentMethodData Variant | Pattern File |
|---|
| Card | PaymentMethodData::Card(card) | references/payment-method-patterns/card.md |
| Wallet | PaymentMethodData::Wallet(wallet) | references/payment-method-patterns/wallet.md |
| BankTransfer | PaymentMethodData::BankTransfer(bt) (Box) | references/payment-method-patterns/bank-transfer.md |
| BankDebit | PaymentMethodData::BankDebit(bd) | references/payment-method-patterns/bank-debit.md |
| BankRedirect | PaymentMethodData::BankRedirect(br) | references/payment-method-patterns/bank-redirect.md |
| UPI | PaymentMethodData::Upi(upi) | references/payment-method-patterns/upi.md |
| BNPL | PaymentMethodData::PayLater(pl) | references/payment-method-patterns/bnpl.md |
| Crypto | PaymentMethodData::Crypto(crypto) | references/payment-method-patterns/crypto.md |
| GiftCard | PaymentMethodData::GiftCard(gc) (Box) | references/payment-method-patterns/gift-card.md |
| MobilePayment | PaymentMethodData::MobilePayment(mp) | references/payment-method-patterns/mobile-payment.md |
| Reward | PaymentMethodData::Reward | references/payment-method-patterns/reward.md |
Full PM name → category mapping: references/category-mapping.md
Critical Rules
- Never use catch-all
_ to silently drop payment methods -- always return IntegrationError::NotImplemented
- Each payment method gets its own explicit match arm
BankTransferData and GiftCardData are Box-wrapped -- use .deref()
- Wallet sub-variants (ApplePay, GooglePay, etc.) each need separate nested match arms
- Validate required fields with
missing_field_err
- Use
get_unimplemented_payment_method_error_message("ConnectorName") for error messages
Workflow: Orchestrator Sequence
Full subagent prompts: references/subagent-prompts.md
Step 1: Analysis & Category Resolution (Subagent)
Subagent prompt: references/subagent-prompts.md → Subagent 1
Inputs: connector_name, requested_payment_methods
What it does:
- Verifies connector exists and has Authorize flow
- Reads tech spec for PM-specific API requirements
- Maps each PM to its
PaymentMethodData category (via references/category-mapping.md)
- Identifies which PMs are already supported
- Checks if Refund/Capture flows need PM-specific changes
Outputs: category mapping per PM, existing PMs, implementation plan
Gates:
- If tech spec missing → invoke the
generate-tech-spec skill first. Do NOT proceed without it.
- If Authorize flow missing → invoke the
add-connector-flow skill to add Authorize first.
Step 2: Payment Method Implementation (MANDATORY subagent per PM or category)
CRITICAL: You MUST delegate implementation to a subagent. Do NOT implement code yourself.
Read the subagent prompt from references/subagent-prompts.md → Subagent 2, fill in the
variables ({ConnectorName}, {PaymentMethod}, {Category}, pattern file path), and spawn a subagent.
For multiple PMs in the same category (e.g., Apple Pay + Google Pay = both Wallet), you may
use one subagent for the whole category.
Per-category patterns: references/payment-method-patterns/{category}.md
Each PM subagent:
- Reads the category pattern file
- Finds the
match payment_method_data block in the Authorize TryFrom
- Adds match arm for the new PM variant
- Extracts fields, builds connector request
- Handles unsupported sub-variants with
NotImplemented
- Propagates to Refund/Capture if needed
- Runs
cargo build --package connector-integration
Step 3: gRPC Testing (MANDATORY subagent)
CRITICAL: You MUST delegate testing to a subagent. Do NOT run grpcurl yourself.
Subagent prompt: references/subagent-prompts.md → Subagent 3
Testing guide: references/grpc-testing-guide.md
Tests Authorize with each new payment method via grpcurl. The payment_method field
in the grpcurl request changes per PM type:
| PM | grpcurl payment_method field |
|---|
| Card | {"card": {"card_number": {"value":"4111..."}, ...}} |
| Apple Pay | {"wallet": {"apple_pay_third_party_sdk": {"payment_data":"..."}}} |
| Google Pay | {"wallet": {"google_pay": {"tokenization_data":{"token":"..."}}}} |
| UPI | {"upi": {"upi_collect": {"vpa_id":{"value":"test@upi"}}}} |
| ACH | {"bank_debit": {"ach": {"account_number":{"value":"..."}, ...}}} |
Also tests Refund/Capture with new PMs if those flows were modified.
Step 4: Quality Review (MANDATORY subagent)
CRITICAL: You MUST delegate quality review to a subagent. Do NOT review yourself.
Subagent prompt: references/subagent-prompts.md → Subagent 4
Checks:
- Each PM has explicit match arm (no silent drops)
- Unsupported variants return
NotImplemented with connector name
- Required fields validated with
missing_field_err
- Box-wrapped types properly
.deref()'d
cargo build passes clean
PaymentMethodData Match Pattern
The central pattern for all PM handling is a match on PaymentMethodData inside the
Authorize flow's TryFrom. This is the comprehensive pattern:
let payment_method_data = &item.router_data.request.payment_method_data;
match payment_method_data {
PaymentMethodData::Card(card) => {
let card_number = card.card_number.clone();
let expiry_month = card.card_exp_month.clone();
let cvc = card.card_cvc.clone();
Ok(ConnectorPaymentsRequest { payment_type: "card", card_number, ... })
},
PaymentMethodData::Wallet(wallet_data) => match wallet_data {
WalletData::ApplePayThirdPartySdk(apple_pay) => {
let token = apple_pay.payment_data.clone()
.ok_or_else(missing_field_err("apple_pay.payment_data"))?;
Ok(ConnectorPaymentsRequest { payment_type: "applepay", token, ... })
},
WalletData::GooglePay(google_pay) => {
let token = google_pay.tokenization_data.token.clone();
Ok(ConnectorPaymentsRequest { payment_type: "googlepay", token, ... })
},
_ => Err(errors::IntegrationError::NotImplemented(
utils::get_unimplemented_payment_method_error_message("ConnectorName", Default::default()),
).into()),
},
PaymentMethodData::BankTransfer(bt) => match bt.deref() {
BankTransferData::SepaBankTransfer { .. } => { ... },
_ => Err(errors::IntegrationError::NotImplemented(..., Default::default()).into()),
},
PaymentMethodData::BankDebit(bd) => match bd {
BankDebitData::SepaBankDebit { iban, .. } => { ... },
_ => Err(errors::IntegrationError::NotImplemented(..., Default::default()).into()),
},
PaymentMethodData::Upi(upi) => match upi {
UpiData::UpiCollect(c) => {
let vpa = c.vpa_id.clone().ok_or_else(missing_field_err("vpa_id"))?;
Ok(ConnectorPaymentsRequest { payment_type: "upi_collect", vpa, ... })
},
_ => Err(errors::IntegrationError::NotImplemented(..., Default::default()).into()),
},
PaymentMethodData::PayLater(pl) => match pl {
PayLaterData::KlarnaRedirect { .. } => { ... },
_ => Err(errors::IntegrationError::NotImplemented(..., Default::default()).into()),
},
_ => Err(errors::IntegrationError::NotImplemented(
utils::get_unimplemented_payment_method_error_message("ConnectorName", Default::default()),
).into()),
}
Key rules:
- Outer match dispatches on
PaymentMethodData variants
- Categories with sub-types need nested match (Wallet, BankTransfer, BankDebit, UPI, BNPL)
BankTransferData and GiftCardData are Box-wrapped → .deref()
- Every level ends with catch-all returning
NotImplemented
Reward is a unit variant with no inner data
Reference Index
| Path | Contents |
|---|
references/subagent-prompts.md | Full prompts for all 4 subagents |
references/category-mapping.md | PM name → PaymentMethodData variant mapping |
references/grpc-testing-guide.md | grpcurl templates, test validation, testing subagent prompt |
references/macro-reference.md | Connector macro system reference |
references/type-system.md | RouterDataV2, type system reference |
references/payment-method-patterns/card.md | Card payment patterns |
references/payment-method-patterns/wallet.md | Wallet (Apple Pay, Google Pay) patterns |
references/payment-method-patterns/bank-transfer.md | Bank transfer patterns |
references/payment-method-patterns/bank-debit.md | Bank debit (ACH, SEPA DD) patterns |
references/payment-method-patterns/bank-redirect.md | Bank redirect (iDEAL, Sofort) patterns |
references/payment-method-patterns/upi.md | UPI Collect/Intent patterns |
references/payment-method-patterns/bnpl.md | BNPL (Klarna, Afterpay) patterns |
references/payment-method-patterns/crypto.md | Cryptocurrency patterns |
references/payment-method-patterns/gift-card.md | Gift card patterns |
references/payment-method-patterns/mobile-payment.md | Mobile/carrier billing patterns |
references/payment-method-patterns/reward.md | Reward/loyalty points patterns |