High Wire Payments

Drop-in & wallets

Understand gateway-selected layouts, wallet setup, and styling in Payment SDK 0.7.0.

Gateway-selected layouts

Call hw.mount() once for the whole checkout. The gateway session decides its layout; there are no individual wallet or drop-in controllers in 0.7.0.

LayoutParts added in orderrequiresSubmit
card_and_walletsApple Pay, Google Pay, cardtrue
card_onlyCardtrue
drop_in, form with its own buttonApple Pay when offered, then drop-in formfalse
drop_in, form that uses your Pay buttonDrop-in formtrue

The layout and available methods are configured for your HighWire account. When the session includes a method list, a method absent from that list gets no slot. When the list is omitted, card_and_wallets offers wallet slots; browser and device availability determine whether they show. Show your Pay button only when checkout.requiresSubmit is true; a drop-in form with its own payment button takes the payment there. Handle every method through onProcessing, onResult, and onError; see Integration.

The CDN build includes the wallet loader. Wallet components run on your page; the card field and drop-in run inside HighWire frames. Availability also depends on browser, device, and account configuration. An unavailable wallet can stay hidden without reporting an error.

Drop-in forms that use your Pay button

Some account configurations use a drop-in form without a payment button of its own. The form takes cards only: the shopper enters the card in it, and your page supplies the email, the billing details and the Pay button:

  • Enable your Pay button while onAvailabilityChange reports true. Call checkout.submit({ customerEmail, billingAddress }) with the full billing address: at least the name, a two-letter country and the postalCode. The SDK checks the name and country; the form validates the rest of the address for that country and rejects one without a postal code. customerPhone is not sent.
  • HighWire checks the email before the card is charged. A payment takes up to 3 different emails, so the shopper can correct one. Without customerEmail, submit() uses the email of the payment's last declined attempt; before any decline it rejects HW_INCOMPLETE.
  • onProcessing('dropIn') fires when submit() sends a new submission, while HighWire checks the email. submit() resolves succeeded, pending or declined. After a decline with retryable: true the shopper can try another card; retryable: false ends the checkout.
  • Refused card details, billing address or email, a fourth email on the same payment, and a submission HighWire did not take reject HW_INCOMPLETE with recovery correct.
  • When HighWire denies the email, submit() rejects HW_DECLINED with recovery recheck. A changed email or save box that HighWire refuses while the payment is in progress rejects HW_TOKENIZE_IN_PROGRESS with recovery recheck. Both keep the payment, because an earlier attempt may still capture: a later submit() only reads its status, for up to 3 minutes, and the checkout takes no other payment. Check it on your server before starting another checkout.
  • Errors carry recovery. After an unknown outcome, another submit() only checks the original payment, and checkout.recheck() checks it without submitting.
  • With savePaymentMethodForFutureUse: true, the form shows an unticked save box under the card fields. Only the shopper's tick saves the card, under the email submit() sends; a succeeded result then carries customerId and paymentMethodId. It never carries maskedCard.
  • The form shows the payment provider's buyer terms under the card fields and runs card verification itself. Closing its verification dialog keeps the attempt and offers to finish verification. A verification step can also take the shopper's tab to another page and back to a HighWire return page; your page then loses its state, so settle the order from your server's view of the payment.

The Plain HTML and React / Next.js guides show complete controls, billing fields included, that work for this form and every other layout.

Collect the billing address in the form

Mount with billingAddressForm: 'full' to have the shopper enter the billing address in the drop-in form instead of on your page. submit() then takes the email alone:

const checkout = await hw.mount({
  container: '#payment',
  amount: 2999,
  currency: 'usd',
  billingAddressForm: 'full',
  // …your callbacks, unchanged
});

// From your Pay button, enabled while onAvailabilityChange reports true:
await checkout.submit({ customerEmail: 'shopper@example.com' });
  • submit() takes no billingAddress. Passing one, even {}, rejects HW_UNSUPPORTED with recovery correct before anything is sent.
  • When the form's fields are incomplete, submit() rejects HW_INCOMPLETE with recovery correct and sends nothing. The form may not mark the missing field, so ask the shopper to check both the card and the billing fields.
  • The address stays inside the form. Neither the SDK nor the payment status returns it, and it cannot be prefilled.
  • The form grows taller as the shopper adds address lines. Do not cap the container's height.
  • Only a drop-in form that uses your Pay button supports 'full', and the checkout's form is known only once mount() has created the payment. When a 'full' mount rejects HW_UNSUPPORTED, mount again with 'none' and show your own billing fields: the same payment is reused. To switch modes on a mounted checkout, unmount() it and mount again.
  • When HighWire's service cannot show the billing fields, the failure arrives after mount() resolved: onError receives HW_UNSUPPORTED with recovery unavailable, and onReady never fires.

Apple Pay setup

  1. Ask HighWire to register your checkout domain for Apple Pay and provide the required domain-association file.
  2. Serve the file unchanged at https://your-domain/.well-known/apple-developer-merchantid-domain-association, as plain text, with no extension or redirect.
  3. Request that URL and verify it returns the file, rather than your site's HTML fallback.
  4. Confirm domain verification with HighWire before enabling Apple Pay in production.

Apple Pay renders over HTTPS in Safari. Elsewhere, its slot stays hidden or data-hw-empty without calling onError. A checkout inside a third-party iframe also needs Safari 17 or later, allow="payment" on that iframe, and both domains registered.

Google Pay needs no domain-association file. Its sheet shows the merchant name from the session.

Styling and accessibility hooks

HookMeaning
data-hw-layout on the containerCurrent layout name.
data-hw-slot="applePay", "googlePay", "card", "dropIn"Direct child slots appended after any existing children. Reorder with flex/grid order.
hidden on a wallet slotWallet unavailable or retired after expiry. Do not override it with a display rule on the slot.
data-hw-emptySlot currently draws nothing. Collapse spacing, rather than hiding the slot.
inert, aria-disabled="true" on wallet/drop-in slotsPayment in progress or a card-confirm answer still unknown. A drop-in form that uses your Pay button is also locked until it can take a submission, and while a submission runs or its outcome is unknown, except while the form shows a verification step.
data-hw-processing on the containerMethod being confirmed, from onProcessing until result or error. An error with recovery wait leaves it in place.
#payment { display: flex; flex-direction: column; position: relative; }
#payment > [data-hw-slot] { margin-bottom: 12px; }
#payment > [data-hw-empty] { margin-bottom: 0; }
#payment > [data-hw-slot="card"] { order: -1; }
#payment[data-hw-processing]::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgb(255 255 255 / .7);
}

Never set display: none on an empty slot: it can no longer measure itself and may never recover. Use an accessible status message alongside a visual processing overlay.

Drop-in theming and overlay behavior depend on your account configuration. Confirm supported behavior with HighWire and test the configured checkout in your page layout. HighWire's card 3-D Secure dialog opens above the page.

unmount() removes slots and data-hw-processing, and restores the container's original data-hw-layout. A checkout that ends removes its slots automatically.

Session lifetime

Payment sessions expire. When the SDK reports HW_SESSION_EXPIRED, stop using that checkout and reconcile its payment on your server before creating a replacement. The payment may have completed even when the page did not receive a final answer.

Use the shared result-handling rules for every method. Browser results guide the UI; fulfillment requires server verification.

Content Security Policy

Allow the SDK script, gateway requests, and HighWire frames. Wallet and device-screening components also run on the merchant page. Obtain the required account-specific sandbox and production allowlists from HighWire before enforcing CSP.

DirectiveStarting allowance
script-src'self' and https://cdn.highwirepayments.com/sdk/, plus the wallet and screening script origins supplied by HighWire.
frame-srcYour configured HighWire field origin, plus wallet, screening, and verification origins from the account allowlist.
connect-src'self' and your HighWire gateway origin, plus the wallet and screening endpoints from the account allowlist.

These starting allowances are not a complete policy. Ask HighWire for the origins that apply to your enabled methods and environment. Do not substitute broad hosting-domain wildcards. External merchant integration files work with 'self'; inline scripts need a nonce or hash. Wallet components can use inline style attributes; if you restrict styles, test the required style-src or style-src-attr allowances with HighWire in report-only mode.

3-D Secure requires frame-src and, when set, form-action to allow the HighWire gateway and verification pages. Issuer origins vary by card: a fixed list can block challenges. Test the necessary allowances on your checkout route; some integrations need https: for those two directives to support issuer handoffs.

Run Content-Security-Policy-Report-Only through card, wallet, device screening, and challenge flows, then confirm observed origins with HighWire before enforcement. Also check default-src, img-src, and other restricted directives.

Keep the CDN allowance scoped to /sdk/ or the exact file. SRI verifies the script tag you provide; it does not secure every script allowed by your policy.

Blocked wallet scripts leave those wallets unavailable while card or drop-in payment can continue.

On this page