Skip to main content
Take an ALLOW from Attesso and execute it on Worldline’s MyCheckout hosted payment page, then report the outcome. This is the Worldline recipe for the pattern in Bind an authorization to your PSP: authorize first, execute second, report finality. Attesso authorizes and records. Your backend calls Worldline to execute, then reports the outcome to Attesso. Attesso never calls Worldline. API host: https://api.preprod.connect.worldline-solutions.com for preproduction, https://api.connect.worldline-solutions.com for production. Hosted checkout runs on the Global Collect platform and every server request is HMAC-signed. Use the official SDK (connect-sdk-nodejs) instead of hand-rolling the signature. New to Attesso? The quickstart covers creating a workspace, a test key, and the approval trust this recipe assumes.

Create the hosted checkout

Create it from the same immutable proposed action you sent to /authorizations. Only call Worldline when the decision is ALLOW and can_execute is true.
One product in paymentProductFilters.restrictTo.products skips the payment product picker and lands on the card form. Two products show the picker. Redirect the payer to redirect.

Read the result

Worldline appends hostedCheckoutId and RETURNMAC to the return URL. The redirect is not proof. Read the session server-side:
Map the payment state, not the checkout state: PENDING_APPROVAL is the normal acceptance state for a card on a delayed capture merchant. Waiting for PAID leaves the loop hanging, because capture can settle minutes or days later.

Close the loop

  • Mandate revoked after the card was authorized. Void the payment with payments.cancel, assert CANCELLED, then close the Attesso side. payments.cancelapproval returns SET_PAYMENT_NOT_CANCELLABLE and is not a void.
  • Consumer cancels on the page. Create the session with returnCancelState: true. The checkout status becomes CANCELLED_BY_CONSUMER and no payment exists. Cancel the Attesso authorization.
  • The execution window closes first. Delete the hosted checkout (DELETE /v1/{merchantId}/hostedcheckouts/{hostedCheckoutId}, 204) before execute_before. A late commit is refused with 409 RESOURCE_STATE_CONFLICT; the authorization is already terminal.
  • Refunds. Only after capture. At PENDING_APPROVAL Worldline returns ORDER_WITHOUT_REFUNDABLE_PAYMENTS; at CAPTURE_REQUESTED it accepts a refund that sits REFUND_REQUESTED.

Reconcile a lost response

Create Hosted Checkout is not idempotent. The same X-GCS-Idempotence-Key creates a second session. One authorization means one create, and a create whose response was lost is not retried. Recover by merchant reference instead: the Worldline payment carries the merchantReference you set, and the webhook does too. Read the payment by id or match the reference in the payment list.

Webhooks

Worldline posts an event envelope with the full object: payment.created, payment.pending_approval, payment.capture_requested, payment.captured, payment.paid, payment.completed, payment.rejected, payment.cancelled, and the rest. Two headers carry the proof:
  • X-GCS-Signature: HMAC-SHA256 of the raw body, base64 encoded.
  • X-GCS-KeyId: the webhooks key used.
Verify the signature over the raw bytes before parsing. The SDK helper is connectSdk.webhooks.v1.init(store).unmarshal(rawBody, headers); the store only needs getSecretKey(keyId). Register the endpoint and its key in the Worldline Configuration Center. There is no API for it. The endpoint must answer a GET validation by echoing X-GCS-Webhooks-Endpoint-Verification, and a POST with 2xx within 10 seconds. Delivery is asynchronous. Do not use a webhook to drive the checkout UI. Poll Get hosted checkout on return and treat the webhook as later authority.

Limits, measured on preproduction (Oct 2026)

Test mode

Verified against Worldline preproduction:
  • 4012000033330026 (Visa, CVV 200): frictionless 3DS, then PENDING_APPROVAL with isAuthorized: true.
  • 4012009341147907 (Visa): an ACS challenge simulator, then REJECTED (statusCode 180, isAuthorized: false). Click Continue Transaction on the simulator to finish.
  • A documented challenge-success card (4839645466321180) was rejected as unsupported on the test merchant. Confirm enabled cards with Worldline.
  • payments.approve moves PENDING_APPROVAL to CAPTURE_REQUESTED. payments.capture is refused at both states with NOT_CAPTURABLE_STATUS.

Rehearsal

Three scripts in the Attesso repository drive and pin this recipe. They play the integrator; Attesso itself never calls executor APIs.
  • scripts/worldline-e2e.mjs: five phases against preproduction. Commit on an accepted card, cancel on a rejected one, revoke plus void, consumer cancel, and authorization expiry. Every Mandate and Authorization create is replayed under the same idempotency key first; the replay must return the same resource. Commit and cancellation are replayed the same way. It verifies each evidence bundle against the published keys, and self-tests the webhook verifier with the configured key (signed 200, tampered 401).
  • scripts/worldline-drive.mjs: runs the harness unattended. It plays the Attesso passkey approval with a virtual authenticator and the hosted card form with Playwright, including the ACS challenge simulator.
  • scripts/worldline-limits.mjs: re-checks the field limits and error codes in the table above. Exit 0 means the platform still behaves as documented.
Run them from a directory holding attesso-quickstart.json (the quickstart state file), with the Worldline credentials in the environment and PUBLIC_BASE_URL set to a public tunnel that forwards to the state file’s return port.