Skip to main content
You are a coding agent migrating a merchant codebase from @payrails/web-sdk 5.x to 6.x. This runbook tells you how to detect what needs migrating, route each finding to the right instructions, execute the changes, and verify the result. The detailed before/after for every breaking change lives in the migration guide — this document routes you through it; it does not repeat it. If you are a human, read the migration guide directly.

Ground rules

  • Detect, don’t assume. Determine the installed SDK version and the APIs actually used from the codebase — not from what the user or this document’s age implies.
  • The installed package is the contract. When this runbook or any doc disagrees with the TypeScript types shipped in the installed @payrails/web-sdk, the types win. Never invent an API: before writing a call you have not seen in the codebase, confirm it exists in the package’s .d.ts or in the reference docs.
  • Minimal diffs. Change only what the migration requires. Do not refactor, rename, or restyle surrounding code.
  • Preserve behavior. Every v5 callback’s logic must land in an equivalent v6 handler — count the callbacks you removed and the listeners you added, and reconcile any difference.
  • Escalate, don’t skip. Anything in the escalate to a human list must be reported, not silently dropped.

Phase 0: Detect

  1. Read the installed version of @payrails/web-sdk from the lockfile (or node_modules/@payrails/web-sdk/package.json; fall back to the package.json range).
  2. Route:
    • 5.x — run the full migration below.
    • 6.x — a migration may have been left incomplete. Run Phase 1 anyway; fix whatever it still finds.
    • 4.x or older — stop and escalate; this runbook only covers 5 → 6.
    • Not installed / loaded from a script tag — stop and escalate; this runbook covers the npm package only.

Phase 1: Inventory

First scope the search: limit every pattern below to files that import or reference @payrails/web-sdk, plus the local modules that build option objects for its calls. Names like onChange, onFocus, or onSuccess are ubiquitous in frontend code — unscoped matches outside the SDK integration are false positives, not work items. Search the scoped files for each pattern (also match minor formatting variants). Every hit is a work item; the section column links to the instructions. Do not flag these — they are unchanged or correct in v6:
  • styles on standalone googlePayButton / applePayButton / paypalButton (provider chrome), and under paymentMethodsConfiguration.<method>.styles.
  • events: { onClientInitialized } at Payrails.init — the one surviving bag callback (the handler body may still need item 4).
  • Existing .on(...) subscriptions, setSavedInstrument, setState, payrails.api(...), translations, fonts.
Also check the deployment configuration: if the site sets a Content-Security-Policy, assets.payrails.io must be allowed in script-src and style-src. You usually cannot change this yourself — escalate it.

Phase 2: Execute

Work in this order; run the project’s type-check after each step so regressions localize to the step that caused them.
  1. Upgrade the dependency to @payrails/web-sdk@6 with the project’s package manager.
  2. Make init awaited (inventory 1): add await, propagate async up through the callers, and add rejection handling for PAYRAILS_INIT_FAILED where other init errors are handled. In SSR frameworks, ensure the call runs only in the browser (guide §1).
  3. Delete the CSS import (inventory 2) and any bundler config that referenced it.
  4. Delete preloadCardForm() calls (inventory 3).
  5. Update onClientInitialized handler bodies (inventory 4): the argument is the plain response object; helper calls move to the payrails instance per guide §3.
  6. Replace event bags with .on() (inventory 5–7) using the mapping tables in guide §4. Three semantic traps — a mechanical rename is NOT enough:
    • Boolean-return gates (onRequestStart, onButtonClicked, onDeliveryAddressChanged) must call event.preventDefault(); a thrown error no longer blocks the payment.
    • Payment-outcome listeners are session-wide. If the page mounts more than one payment element, add event.paymentMethodCode / event.action filters to reproduce the old per-element behavior.
    • failed payloads carry the error in event.data (e.data?.code), not at the top level.
  7. Replace availability callbacks (inventory 8) with await button.isAvailable (guide §5).
  8. Migrate styling (inventory 9–10) to appearance using the per-element mapping tables in guide §6. Translate each v5 style key via the tables; do not guess selectors. Watch the three special cases: drop-in wallet-button chrome moves to paymentMethodsConfiguration.<method>.styles, Revolut Pay uses revolutOptions, the Lean dialog uses dialogCustomization.
  9. Clean up types (inventory 11) per guide §7.

Phase 3: Verify

  1. Re-run the Phase 1 inventory. Items 1–11 must return no unmigrated hits (modulo the do-not-flag list).
  2. Type-check and build the project; both must pass.
  3. Runtime smoke test, if you can run the app: load the checkout page and confirm Payrails.init resolves (bundle and stylesheet load from assets.payrails.io), the payment elements render styled, and no PAYRAILS_INIT_FAILED error appears in the console.
  4. Report to the human: version migrated from/to, work items found and fixed per inventory row, behavior-affecting choices you made (e.g. where you added paymentMethodCode filters), and every escalation item below that applies.

Escalate to a human

Report these instead of deciding yourself:
  • CSP changes — assets.payrails.io in script-src/style-src is usually infrastructure config outside the repo.
  • Visual sign-off — v6 ships a redesign (guide §8); a human must approve the new look and any re-created custom styling.
  • Real payment verification — completing a test payment in the TEST environment, 3DS challenges, wallet sheets, and session-expiry refresh need a human (or explicit instruction) to exercise.
  • Ambiguous event logic — if a v5 callback’s body encoded per-element assumptions you cannot confidently reproduce with filters, show both versions and ask.

Reference map


Last modified on September 30, 2026