Skip to main content

Extending to More Flows

YOu have implemmented the basic plumbing for routing payment processor agnostic APIs. All methods work the same way with the single interface regardless of which payment processor you use. That's the power you get with the library.

Beyond the basic authorization and capture, the library handles complex payment scenarios in a processor agnostic manner. This includes recurring payments, incremental authorization, void, reverse, refund and more.

Payment Flows Overview

Below are some sample use cases to try out quickly, followed by some real world scenarios.

FlowUse CaseKey Operations
Authorize + CaptureStandard e-commerceauthorize, capture
Authorize + VoidCancel pending orderauthorize, void
Automatic CaptureDigital goods, immediate chargeauthorize with AUTOMATIC
Incremental AuthorizationHotel check-in, car rentalauthorize, incrementalAuthorization
Partial CaptureMulti-shipment orderscapture with partial amount
RefundsCustomer returnsrefund
Reucrring PaymentsSaaS billing and rersetupMandate, charge

Incremental Authorization

Hotels and car rentals need to increase authorization amounts after the initial charge:

// 1. Initial authorization: $100 hold
const auth = await client.payments.authorize({
amount: { minorAmount: 10000, currency: Currency.USD },
captureMethod: CaptureMethod.MANUAL
});

// 2. Customer adds room service: increase hold to $150
const incremental = await client.payments.incrementalAuthorization({
paymentId: auth.paymentId,
additionalAmount: { minorAmount: 5000, currency: Currency.USD }
});

// 3. At checkout: capture final amount
await client.payments.capture({
paymentId: auth.paymentId,
amount: { minorAmount: 14750, currency: Currency.USD } // Actual amount
});

See: incrementalAuthorization API Reference

Subscription / Recurring Payments

Store a payment method and charge it later:

// 1. Set up mandate (store payment method)
const mandate = await client.payments.setupMandate({
customerId: 'cus_xyz789',
paymentMethod: { card: { ... } }
});

// 2. Charge the stored method monthly
const charge = await client.recurringPayments.charge({
mandateId: mandate.mandateId,
amount: { minorAmount: 2900, currency: Currency.USD }
});


See: [`setupMandate`](../../api-reference/services/payment-service/setup-recurring.md), [`charge`](../../api-reference/services/recurring-payment-service/charge.md), [`revoke`](../../api-reference/services/recurring-payment-service/revoke.md)


## Partial Capture

Capture less than authorized amount (multi-shipment orders):

```javascript
// Authorized $100
const auth = await client.payments.authorize({
amount: { minorAmount: 10000, currency: Currency.USD },
captureMethod: CaptureMethod.MANUAL
});

// First shipment: capture $40
await client.payments.capture({
paymentId: auth.paymentId,
amount: { minorAmount: 4000, currency: Currency.USD } // Partial
});

// Second shipment: capture remaining $60
await client.payments.capture({
paymentId: auth.paymentId,
amount: { minorAmount: 6000, currency: Currency.USD }
});

See: capture

Void (Cancel Authorization)

Release held funds without charging:

// Customer cancels order before shipment
await client.payments.void({
paymentId: auth.paymentId,
reason: 'Customer cancelled'
});
// Funds released immediately

See: void

Reverse (Refund Without Reference)

Refund when you only have the connector transaction ID:

await client.payments.reverse({
connectorTransactionId: 'pi_3MqSCR2eZvKYlo2C1',
amount: { minorAmount: 10000, currency: Currency.USD }
});

See: reverse

Webhook Handling

Process events from payment processors:

// Express route for webhooks
app.post('/webhooks', async (req, res) => {
const event = await client.events.handle({
payload: req.body,
signature: req.headers['stripe-signature'],
connector: Connector.STRIPE
});

switch (event.type) {
case 'payment.captured':
await fulfillOrder(event.paymentId);
break;
case 'payment.failed':
await notifyCustomer(event.paymentId);
break;
case 'refund.completed':
await updateInventory(event.refundId);
break;
}

res.sendStatus(200);
});

See: handle

Dispute Handling

When customers dispute charges:

// Accept the dispute (refund immediately)
await client.disputes.accept({
disputeId: 'dp_xyz789'
});

// Or defend with evidence
await client.disputes.defend({
disputeId: 'dp_xyz789'
});

await client.disputes.submitEvidence({
disputeId: 'dp_xyz789',
evidence: {
productDescription: 'Premium Widget',
customerCommunication: emailThread,
shippingReceipt: trackingNumber
}
});

See: accept, defend, submitEvidence

Next Steps