Embedded Adyen checkout must be enabled for your project by Firmhouse. Contact us before implementing it. This guide covers initial checkout payments, not recurring invoice payments or changing an existing customer’s payment method.
Before you start
- Follow Create a storefront app to create a cart, add products or a plan, and collect customer details.
- Connect Adyen, including the client key and a working, HMAC-verified webhook to Firmhouse. Configure test and live accounts separately.
- In your own Adyen Customer Area, add your storefront’s exact origin to the API credential’s allowed origins. A local development origin and a staging domain need their own entries. Configuring the Firmhouse hosted checkout origin does not authorize your storefront.
- Configure payment methods and country-specific availability in Adyen. In Firmhouse, leave all payment methods unselected to use Adyen’s available methods supported by Sessions, or select methods to narrow that result. Complete wallet requirements for your storefront domain, including Apple Pay domain registration and applicable Google Pay configuration. These settings belong to your Adyen account; Firmhouse cannot configure your domains through the checkout API.
- Install Adyen Web and its stylesheet using Adyen’s Sessions integration guide.
Authenticate the cart
Send GraphQL requests tohttps://portal.firmhouse.com/graphql with:
errors and mutation payload errors before using a response. Mutation payload errors provide attribute and message. Top-level GraphQL errors provide message and may include path or extensions; do not assume they have an attribute. Do not depend on a dedicated checkout error code.
1. Finalise the cart
After saving the shopper’s details and cart contents, call:
Retain the returned
payment.token with the current cart. If finalisation succeeds without a payment, no payment is required: follow the returned returnUrl instead of creating an Adyen session.
2. Create or reuse the payment session
sessionData as opaque; Firmhouse supplies the amount, currency, payment reference, and line items. Configure Adyen Web with the returned client key, environment, locale, country, amount: { value: amountCents, currency }, and session: { id: sessionId, sessionData }. Pass amountCents directly in minor units, without dividing by 100, so Drop-in displays the correct payment total. Map cardConfiguration to Drop-in’s card configuration, googlePayConfiguration (when present) to Google Pay’s configuration, and paypalConfiguration to PayPal’s configuration. Keep these settings aligned with Firmhouse rather than hardcoding different cardholder-name or payment-storage behavior.
You can request the session again when reopening the normal payment page for the same eligible, unchanged payment. Firmhouse reuses an unexpired session and creates a fresh session when the stored session expires. Use expiresAt; the default Adyen lifetime is about one hour from creation, not from the shopper’s most recent page load. Session expiry alone does not currently move the Firmhouse payment to EXPIRED.
Mount Drop-in once per active session. Avoid duplicate mounts from frontend renders. Do not also open the hosted paymentUrl for that payment: embedded Sessions and hosted payment processing are mutually exclusive once a flow has started. Handle a flow-conflict error rather than attempting to bypass it with another cart.
3. Handle normal entry and redirect returns
Your checkout page has two entry modes:- Normal entry: restore the cart and current payment token, check its status if an attempt already exists, and create or reuse a session when payment is still needed.
- Adyen redirect return: when the URL contains
sessionIdandredirectResult, restore the original attempt and let Adyen Web complete that session. Do not finalise again or create a replacement session before handling the redirect.
sessionId and submit the redirectResult through submitDetails. See Adyen’s redirect instructions. Afterwards, check Firmhouse’s payment status below. Do not treat the redirect parameters as proof of payment.
4. Confirm payment through Firmhouse
Adyen sends payment notifications directly to Firmhouse. Browser callbacks such asonPaymentCompleted are useful for showing progress, but they are not the authority for confirming the order.
An existing
successUrl is not itself proof of success. Read it from the status response after confirming payment. For an order-backed checkout it includes order_id and order_value, preserving your existing query parameters, so your confirmation page can record the purchase. order_value is a decimal amount, for example 123.45, not an integer number of cents. Deduplicate purchase analytics by order ID.
Retries and cart changes
For a refused payment on an unchanged cart, requestcreateAdyenPaymentSession again with the same payment token. Firmhouse permits eligible failed initial payments to reopen, reusing an active session or obtaining a fresh one after expiry. It rejects already settled or abandoned payments. A slow or unknown payment outcome is not a refusal: check status before retrying.
When the shopper edits their cart or details after opening payment:
- Stop using the current Drop-in and save the edits on the same cart.
- Call
createSubscriptionFromCartagain, using the same cart authentication and your checkout URLs. - Check errors, then use the returned payment token for the session request and all subsequent status polling. Mount Drop-in with that session.
Optional: explicitly abandon a checkout
Most integrations do not need a separate abandonment call. When shoppers edit the same cart and you finalise it again, Firmhouse handles abandonment and replacement automatically when needed. UseabandonAdyenCheckout when your integration deliberately discards a checkout or creates a separate replacement cart. For a separate replacement cart, successfully abandon the original first using its own cart authentication:
Late payments on abandoned checkouts
The following applies whether Firmhouse automatically abandons an attempt during same-cart replacement or your integration explicitly abandons it. Abandonment is recorded in Firmhouse; it does not immediately invalidate the old Adyen session. If a successful authorisation arrives for an abandoned attempt, Firmhouse requests cancellation or refund asynchronously. The trigger is the payment notification, not a timer after session expiry. Funds may be held temporarily, and reversal requests can fail or need attention.
The portal retains abandoned payment and reversal history for investigation, including an abandoned checkout detail page for draft checkouts. This does not activate the abandoned subscription. An unused session can expire without a payment notification; do not expect a refund or an automatic terminal Firmhouse status for every unused attempt.