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.
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 appendshostedCheckoutId and RETURNMAC to the return URL. The
redirect is not proof. Read the session server-side:
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, assertCANCELLED, then close the Attesso side.payments.cancelapprovalreturnsSET_PAYMENT_NOT_CANCELLABLEand is not a void. - Consumer cancels on the page. Create the session with
returnCancelState: true. The checkout status becomesCANCELLED_BY_CONSUMERand no payment exists. Cancel the Attesso authorization. - The execution window closes first. Delete the hosted checkout
(
DELETE /v1/{merchantId}/hostedcheckouts/{hostedCheckoutId}, 204) beforeexecute_before. A late commit is refused with 409RESOURCE_STATE_CONFLICT; the authorization is already terminal. - Refunds. Only after capture. At
PENDING_APPROVALWorldline returnsORDER_WITHOUT_REFUNDABLE_PAYMENTS; atCAPTURE_REQUESTEDit accepts a refund that sitsREFUND_REQUESTED.
Reconcile a lost response
Create Hosted Checkout is not idempotent. The sameX-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.
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, thenPENDING_APPROVALwithisAuthorized: true.4012009341147907(Visa): an ACS challenge simulator, thenREJECTED(statusCode180,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.approvemovesPENDING_APPROVALtoCAPTURE_REQUESTED.payments.captureis refused at both states withNOT_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.
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.
