# Adyen Salesforce Commerce Cloud Payment Authorization and Capture Flow Explained

> Understand the Adyen Salesforce Commerce Cloud payment authorization and capture flow. Learn how Adyen synchronizes order status and manages payments seamlessly.

- Repository: [Adyen/adyen-salesforce-commerce-cloud](https://github.com/adyen/adyen-salesforce-commerce-cloud)
- Tags: how-to-guide
- Published: 2026-02-23

---

**The Adyen Salesforce Commerce Cloud cartridge creates an order at checkout, immediately authorizes payment instruments via HookMgr hooks, and later reconciles order status through Adyen webhooks that can restore cancelled orders to Paid status upon successful capture.**

The payment authorization and capture flow in the Adyen Salesforce Commerce Cloud integration orchestrates real-time payment validation and asynchronous settlement reconciliation. This article examines the complete transaction lifecycle within the `adyen/adyen-salesforce-commerce-cloud` repository, tracing how checkout controllers, authorization helpers, and webhook handlers collaborate to manage payment state.

## Checkout and Order Creation

The flow begins when a shopper proceeds to checkout in a Salesforce Commerce Cloud storefront.

1. The **SFRA controller** `placeOrder` validates the basket and calculates totals.

2. It creates a **Dw Order** via `COHelpers.createOrder`.

3. Immediately after creation, the order is passed to the Adyen-specific helper:

```javascript
// Inside placeOrder.js
var handlePaymentResult = adyenHelpers.handlePayments(order);

```

*Source:* [`src/cartridges/int_adyen_SFRA/cartridge/controllers/middlewares/checkout_services/placeOrder.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_SFRA/cartridge/controllers/middlewares/checkout_services/placeOrder.js)

## Payment Authorization Process

### Delegating to handlePayments

The `handlePayments` function in [`authorizationHelper.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/authorizationHelper.js) acts as the entry point for payment processing. It validates the order total and delegates to `getPayments` if payment instruments exist.

```javascript
function handlePayments(order) {
  if (order.totalNetPrice === 0.0) {
    return {};
  }
  if (order.paymentInstruments.length) {
    return getPayments(order);
  }
  Transaction.wrap(() => {
    OrderMgr.failOrder(order, true);
  });
  return { error: true };
}

```

*Source:* [`src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/authorizationHelper.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/authorizationHelper.js)

### Authorizing Each Payment Instrument

The `getPayments` function iterates over every **PaymentInstrument** attached to the order. For each instrument, it:

1. Retrieves the **payment processor** via `PaymentMgr.getPaymentMethod`.
2. Constructs a dynamic hook name: `app.payment.processor.<processorId>`.
3. Executes the hook's `Authorize` method via **HookMgr**.

```javascript
const hookName = `app.payment.processor.${pProcessor.ID.toLowerCase()}`;
const customAuthorizeHook = () =>
  HookMgr.callHook(hookName, 'Authorize', order, pInstrument, pProcessor);
return HookMgr.hasHook(hookName) ? customAuthorizeHook()
                                  : HookMgr.callHook('app.payment.processor.default', 'Authorize');

```

*Source:* [`src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/getPayments.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/getPayments.js)

If authorization succeeds, the **PSP reference** is stored on the instrument's transaction. If `authorizationResult.error` is truthy, the order is immediately failed via `OrderMgr.failOrder`.

### Custom Authorization Hooks

Merchants can implement **custom authorization logic** by creating a hook file named `app.payment.processor.<processorId>.js`. When present, `getPayments` automatically invokes this hook instead of the default processor, enabling bespoke validation or routing logic for specific payment methods.

## Post-Authorization Order Placement

When `handlePayments` returns without error, the `placeOrder` controller continues:

- If the shopper used **Adyen gift cards**, the main payment instrument amount is adjusted and additional gift-card instruments are created.
- The controller returns a success JSON response, allowing the shopper to proceed to order confirmation.

If any error occurs during authorization, the order is failed, basket data is cleared, and the shopper is redirected to a payment-error page.

## Payment Capture via Webhook

### Handling the CAPTURE Event

When Adyen settles the payment (after 3-D Secure or offline capture), it sends a **CAPTURE** webhook to the Salesforce Commerce Cloud instance. The webhook is routed to the `handle` function in [`CAPTURE.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/CAPTURE.js).

```javascript
function handle({ order, customObj }) {
  if (isWebhookSuccessful(customObj) &&
      order.status.value === Order.ORDER_STATUS_CANCELLED) {
    order.setPaymentStatus(Order.PAYMENT_STATUS_PAID);
    order.setExportStatus(Order.EXPORT_STATUS_READY);
    order.setConfirmationStatus(Order.CONFIRMATION_STATUS_CONFIRMED);
    OrderMgr.undoCancelOrder(order);
    AdyenLogs.info_log(
      `Undo failed capture, Order ${order.orderNo} updated to status PAID.`,
    );
  }
}

```

*Source:* [`src/cartridges/int_adyen_webhooks/cartridge/eventHandlers/CAPTURE.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_webhooks/cartridge/eventHandlers/CAPTURE.js)

### Restoring Cancelled Orders

A critical feature of the capture flow is **order restoration**. If an order was previously **CANCELLED** (often due to a failed capture attempt or fraud review), the `CAPTURE` handler:

1. Sets the payment status to **PAID**.
2. Sets the export status to **READY**.
3. Sets the confirmation status to **CONFIRMED**.
4. Calls `OrderMgr.undoCancelOrder(order)` to restore the order to active status.

This ensures that delayed captures or retry scenarios do not result in lost revenue due to stuck order states.

## Key Source Files

| Purpose | File Path |
|---------|-----------|
| Checkout controller that creates the order and starts authorization | [`src/cartridges/int_adyen_SFRA/cartridge/controllers/middlewares/checkout_services/placeOrder.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_SFRA/cartridge/controllers/middlewares/checkout_services/placeOrder.js) |
| Helper that delegates to `getPayments` | [`src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/authorizationHelper.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/authorizationHelper.js) |
| Core authorization logic per payment instrument | [`src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/getPayments.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_SFRA/cartridge/adyen/utils/getPayments.js) |
| Webhook handler for successful authorisation | [`src/cartridges/int_adyen_webhooks/cartridge/eventHandlers/AUTHORISATION.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_webhooks/cartridge/eventHandlers/AUTHORISATION.js) |
| Webhook handler for capture events | [`src/cartridges/int_adyen_webhooks/cartridge/eventHandlers/CAPTURE.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_webhooks/cartridge/eventHandlers/CAPTURE.js) |
| Utility that validates webhook success | [`src/cartridges/int_adyen_SFRA/cartridge/utils/webhookUtils.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_SFRA/cartridge/utils/webhookUtils.js) |
| Logging helper used throughout the flow | [`src/cartridges/int_adyen_SFRA/cartridge/adyen/logs/adyenCustomLogs.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/src/cartridges/int_adyen_SFRA/cartridge/adyen/logs/adyenCustomLogs.js) |

## Summary

- The **payment authorization and capture flow** begins when [`placeOrder.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/placeOrder.js) creates a Salesforce Commerce Cloud order and invokes `authorizationHelper.handlePayments`.
- **Authorization** occurs via [`getPayments.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/getPayments.js), which iterates over payment instruments and executes custom or default HookMgr hooks to validate payment with Adyen.
- Successful authorization stores the **PSP reference** and marks the order as *Paid*; failures trigger `OrderMgr.failOrder` to cancel the transaction.
- **Capture** is handled asynchronously by the [`CAPTURE.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/CAPTURE.js) webhook handler, which can restore previously cancelled orders to *Paid* status using `OrderMgr.undoCancelOrder`.

## Frequently Asked Questions

### What happens if payment authorization fails during checkout?

If the `Authorize` hook returns an error or the Adyen API declines the payment, [`getPayments.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/getPayments.js) detects the `authorizationResult.error` flag and immediately calls `OrderMgr.failOrder(order, true)` within a transaction wrapper. This cancels the order, clears the basket, and redirects the shopper to a payment-error page.

### How does the CAPTURE webhook handle previously cancelled orders?

The [`CAPTURE.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/CAPTURE.js) handler checks if `order.status.value === Order.ORDER_STATUS_CANCELLED`. When true, it executes `OrderMgr.undoCancelOrder(order)` to restore the order, then sets `PAYMENT_STATUS_PAID`, `EXPORT_STATUS_READY`, and `CONFIRMATION_STATUS_CONFIRMED`. This ensures delayed captures or retry scenarios do not leave orders in a terminal cancelled state.

### Can I implement custom authorization logic for specific payment methods?

Yes. The [`getPayments.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/getPayments.js) utility dynamically constructs a hook name using `app.payment.processor.${pProcessor.ID.toLowerCase()}`. If you create a custom hook file matching this naming convention (e.g., [`app.payment.processor.mycustom.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/app.payment.processor.mycustom.js)), the cartridge will invoke your `Authorize` function instead of the default processor, allowing bespoke validation or routing logic.

### What is the difference between the AUTHORISATION and CAPTURE webhooks?

The **AUTHORISATION** webhook ([`AUTHORISATION.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/AUTHORISATION.js)) fires immediately after Adyen approves the payment, handling duplicate callbacks, partial payments, and fraud statuses to finalize the order as *Paid*. The **CAPTURE** webhook ([`CAPTURE.js`](https://github.com/adyen/adyen-salesforce-commerce-cloud/blob/main/CAPTURE.js)) fires later when funds are actually settled, primarily handling order restoration for previously cancelled orders and ensuring the final payment status reflects successful settlement.