Skip to content

Support region-specific live endpoints for Checkout and PAL (data-region routing) #1651

@thomasc-adyen

Description

@thomasc-adyen

Summary

The library has no way to route Checkout / PAL live traffic (e.g. /payments, /payments/details) to a non-EU data region (AU, US, APSE). Today the region-aware hostname (-live-au, -live-us, -live-apse) is only supported for the Terminal Cloud API via RegionEnum. For Checkout and PAL the live hostname is a string literal in Service.createBaseUrl, so merchants operating on a non-EU data region are forced to resort to custom HTTP clients or subclassing to rewrite URLs.

Impact

Merchants on AU / US / APSE data regions hit 3DS2 / data-region errors such as:

DS2 integration error, subsequent request received in different data region than the region that initiated the 3DS2 transaction

This happens because 3DS is authenticated on the correct regional infrastructure (e.g. AU), but the follow-up /payments (or /payments/details) call made via the library goes to the EU host ({prefix}-checkout-live.adyenpayments.com) since that is the only hostname the library can produce.

Current behavior

src/config.ts only exposes region for Terminal API:

export enum RegionEnum {
    EU = "EU",
    AU = "AU",
    US = "US",
    APSE = "APSE"
}

export const TERMINAL_API_ENDPOINTS_MAP: Record<RegionEnum, string> = {
    [RegionEnum.EU]: TERMINAL_API_ENDPOINT_LIVE,
    [RegionEnum.AU]: TERMINAL_API_ENDPOINT_AU_LIVE,
    [RegionEnum.US]: TERMINAL_API_ENDPOINT_US_LIVE,
    [RegionEnum.APSE]: TERMINAL_API_ENDPOINT_APSE_LIVE
};

src/service.ts#createBaseUrl hard-codes the Checkout and PAL live hosts:

if (url.includes("pal-")) {
    if (!config.liveEndpointUrlPrefix) {
        throw new Error("Live endpoint URL prefix must be provided for LIVE environment.");
    }
    return url.replace("https://pal-test.adyen.com/pal/servlet/",
        `https://${this.client.config.liveEndpointUrlPrefix}-pal-live.adyenpayments.com/pal/servlet/`);
}

if (url.includes("checkout-")) {
    if (!config.liveEndpointUrlPrefix) {
        throw new Error("Live endpoint URL prefix must be provided for LIVE environment.");
    }
    if (url.includes("/possdk/v68")) {
        return url.replace("https://checkout-test.adyen.com/",
            `https://${this.client.config.liveEndpointUrlPrefix}-checkout-live.adyenpayments.com/`);
    }
    return url.replace("https://checkout-test.adyen.com/",
        `https://${this.client.config.liveEndpointUrlPrefix}-checkout-live.adyenpayments.com/checkout/`);
}

There is no configuration option that causes the -live suffix to become -live-au / -live-us / -live-apse, so merchants cannot target a non-EU data region through the supported API.

Reproduction

  1. Configure a Client for an AU merchant account:
    const client = new Client(new Config({
      apiKey: "...",
      environment: EnvironmentEnum.LIVE,
      liveEndpointUrlPrefix: "{AU_PREFIX}",
    }));
  2. Complete a 3DS2 authentication (which lands on AU).
  3. Call checkout.PaymentsApi.paymentsDetails(...) via the library.
  4. The library issues the request to https://{AU_PREFIX}-checkout-live.adyenpayments.com/checkout/... (EU) instead of https://{AU_PREFIX}-checkout-live-au.adyenpayments.com/checkout/....
  5. Adyen returns the data-region-mismatch error shown above.

Expected behavior

Merchants should be able to declare their data region on the Config object and have the library build the correct regional hostname for Checkout and PAL (not only Terminal API). For example:

new Config({
  apiKey: "...",
  environment: EnvironmentEnum.LIVE,
  liveEndpointUrlPrefix: "{PREFIX}",
  region: RegionEnum.AU, // routes Checkout / PAL to {PREFIX}-checkout-live-au.adyenpayments.com, etc.
});

Proposed fix

  1. Reuse the existing RegionEnum (already EU/AU/US/APSE) for Checkout/PAL routing as well, or introduce a dedicated liveEndpointRegion field on Config if a separate concept is preferred.
  2. In Service.createBaseUrl, derive a -live{regionSuffix} value ("", "-au", "-us", "-apse") from config.region and use it when building the pal-live / checkout-live hosts.
  3. Preserve backwards compatibility: no region set (or EU) must keep producing the current -checkout-live.adyenpayments.com / -pal-live.adyenpayments.com hosts.
  4. Add unit tests in src/__tests__/service.spec.ts covering each region for both pal- and checkout- (including the /possdk/v68 branch).

Current workaround

Inject a custom HTTP client into the Client constructor and rewrite the URL before it is sent, e.g.:

class AuRoutingClient extends HttpURLConnectionClient {
  request(endpoint: string, ...rest: any[]) {
    const regional = endpoint
      .replace("-checkout-live.adyenpayments.com", "-checkout-live-au.adyenpayments.com")
      .replace("-pal-live.adyenpayments.com",      "-pal-live-au.adyenpayments.com");
    return super.request(regional, ...rest);
  }
}

This works but is brittle (depends on internal URL shapes) and should not be required for a first-class supported feature.

Environment

  • @adyen/api-library current main
  • Node.js (all supported versions)

Additional context

RegionEnum already exists for Terminal API in src/config.ts, so much of the scaffolding is in place — this issue is about extending the same concept to Checkout/PAL live endpoint construction in src/service.ts.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions