Migrate from iFrame to the React Native Checkout SDK

Replace React Native WebView-based Spreedly iFrame or Express payment collection with the React Native Checkout SDK.

Move from Spreedly’s web iFrame, hosted fields SDK, or a WebView-wrapped web checkout to @spreedly/react-native-checkout while preserving your backend transaction flow.

Use this guide when you are replacing either of these React Native payment collection patterns:

  • Path A: Spreedly iFrame or Express checkout running in a WebView inside your React Native app.
  • Path B: A shared web checkout that your mobile team is replacing with native React Native screens.

Both paths converge on the React Native Checkout SDK. Start with Upgrading your checkout experience if you need the cross-platform migration plan or the detailed Web iFrame to Web Checkout SDK migration path. If you are already on @spreedly/react-native-checkout and upgrading between major versions, see v0-to-v1 migration instead.

Further reading

What you gain

The React Native Checkout SDK replaces WebView-based payment flows with native payment collection and SDK-owned secure inputs.

  • Native secure fields with SPLTextField and optional Express Checkout bottom sheet.
  • Server-side signed authentication with no Spreedly API secret on device.
  • Reduced PCI scope because sensitive card data never enters merchant JavaScript state.
  • 3D Secure support, including Forter global and gateway-specific flows.
  • Alternative payment method support, including Stripe APM and Braintree APM packages.
  • Offsite payment support for methods such as PayPal, Pix, Boleto, EBANX, and more.
  • CVV recaching for saved cards.
  • Screen capture protection with ScreenSecurity.
  • Built-in telemetry with sensitive values sanitized.

Compatibility

Confirm your app meets these requirements before migrating.

RequirementVersion
React Native0.79.0 or later
React18.2 or later
Android minSdk26 or later
iOS15.1 or later with Xcode 15 or later

Install the package that matches the payment capabilities you need.

PackagePurpose
@spreedly/react-native-checkoutCore package for SpreedlyCore, SPLTextField, Express Checkout, 3DS, offsite payments, and recaching.
@spreedly/react-native-checkout-stripe-apmStripe PaymentSheet support for payment methods such as iDEAL, Bancontact, EPS, P24, and SEPA.
@spreedly/react-native-checkout-braintree-apmBraintree PayPal and Venmo support.

Architectural differences

AreaWeb iFrame SDKReact Native Checkout SDK
UIDOM iframes and CSS through APIs such as setStyleNative SPLTextField components and optional PaymentBottomSheet
InitializationSpreedly.init(environmentKey, { …, numberEl, cvvEl })SpreedlyCore.initSdk(options) with no DOM container IDs
AuthenticationOften mixed into page configurationServer-generated signed parameters per session: nonce, signature, certificateToken, and timestamp
Multiple formsnew SpreedlyPaymentFrame() per formOne initSdk per active checkout session; multiple SPLTextField components represent one form
ResultsGlobal events such as paymentMethod, errors, and recachePromises, mapPaymentResult, and SpreedlyEventEmitter for sheet, 3DS, recache, and offsite events
StylingArbitrary CSS per fieldCustomThemeConfig tokens; no CSS
PCI handlingMerchant page wraps iframesCard number, CVV, and expiry are collected only through SPLTextField; no mobile setValue equivalent

Prerequisites

  1. Create a backend endpoint that returns fresh SDK authentication parameters for each checkout session.
  2. Keep your Spreedly API secret on your backend.
  3. Confirm your existing backend can process Spreedly payment method tokens from the React Native SDK.
  4. Configure access to the @spreedly packages your app needs.
  5. Confirm the app builds on iOS and Android before replacing your checkout screen.

Step 1: Implement server-side authentication

The web iFrame often mixed environment keys and signing material into page configuration. On React Native, your backend must mint fresh signed parameters for each checkout session.

Important: Call initSdk once per active checkout. Multiple SPLTextField views on one screen are one form, not separate iFrame instances. Never hardcode signing material. See Integration Guide — Authentication parameters.

const authParams = await fetchAuthParams();

await SpreedlyCore.initSdk({
  token: authParams.certificateToken,
  nonce: authParams.nonce,
  signature: authParams.signature,
  certificateToken: authParams.certificateToken,
  timestamp: String(authParams.timestamp),
  environmentKey: 'your_environment_key',
  forterSiteId: '', // optional
});

Your server should expose an endpoint (for example /api/v1/auth/params) that returns nonce, signature, certificateToken, and timestamp. Never generate the HMAC signature in client-side code.

shield

Never include your Spreedly API secret in React Native JavaScript, native Android code, native iOS code, app resources, or compiled configuration.


Step 2: Remove legacy WebView / iFrame integration

Path A (WebView): Remove the WebView payment screen, JavaScript bridge (postMessage, injectJavaScript), iFrame script tags (spreedly.js, express checkout scripts), and DOM container wiring.

Path B (greenfield): Retire shared web checkout URLs or embedded HTML used only for mobile parity.

Search your codebase for:

  • addJavascriptInterface / react-native-webview handlers that tokenize cards
  • Hardcoded Spreedly environment secrets in the app (move signing to the server)

Step 3: Install the React Native SDK

  1. Configure GitHub Packages for @spreedly (read:packages PAT).
  2. yarn add @spreedly/react-native-checkout (and optional APM packages).
  3. Complete iOS (init_spreedly_checkout_pods) and Android (spreedly_github_setup.gradle, Kotlin 2.3 pins).

Full steps: Integration Guide (sections 1–6).


Step 4: Migrate payment flows

Express Checkout (pre-built bottom sheet)

Replaces web Express / sourceSet channel flows:

  • Subscribe to SpreedlyEventTypes.PAYMENT_BOTTOM_SHEET_RESULT
  • Call SpreedlyCore.paymentBottomSheet(options) when the user taps Pay
  • On iOS you may embed PaymentBottomSheet declaratively

See Integration Guide — Show a payment UI and Express Checkout Guide.

Hosted Fields (custom form)

Replaces iFrame number/CVV/expiry containers:

  • Mount SPLTextField per field type
  • Validate with areAllFieldsValid, tokenize with createCreditCard

See Hosted Fields Guide.

ACH bank account (preview — not yet released)

The web iFrame SDK has no bank-account hosted fields or tokenize API. ACH may exist in the React Native package before GA — it is in the code but not ready for release. Do not integrate ACH in production until Spreedly announces GA. Preview-only details: ACH Bank Account Guide.

Key PCI change: no raw card data in merchant code

Card number, CVV, and expiry must use SPLTextField. There is no setValue equivalent on mobile (PCI). Field callbacks expose a merchant-safe IIN prefix (6–8 digits) on CARD fields only — not full PAN or CVV. OS autofill is controlled with enableAutofill. See Security.


API mapping tables

Use the tables below to find the React Native equivalent for each iFrame call you use today.

Status legend

StatusMeaning
DirectUse the listed RN API for the same intent
Different modelSupported on RN; behavior, shape, or wiring differs — follow What to do
Not available on mobileOmitted on purpose (architecture or PCI)
Web onlyNo mobile equivalent — redesign UX
RN onlyAvailable on RN but not in the web iFrame SDK

Core and lifecycle

iFrame API / patternReact Native equivalentStatusWhat to doSee also
Spreedly.init(environmentKey, options)SpreedlyCore.initSdk(options)DirectPass server-issued signing fields + environmentKey. initSdk returns Promise<void>; await it or gate UI until it resolves before mounting fields.Integration Guide — Initialize
Spreedly.reload() / unload() + re-init()SpreedlyCore.resetPaymentState() + initSdk when neededDifferent modelNo DOM remount. Clear hosted state with resetPaymentState. When signing or environment changes, fetch new params and call initSdk again. You may change React key on SPLTextField when remounting UI.Hosted Fields — resetPaymentState
Spreedly.resetFields()SpreedlyCore.resetPaymentState()Different modelresetPaymentState also clears validation display and hosted PAN/CVV display state, not only field text.Hosted Fields — resetPaymentState
Spreedly.removeHandlers() / off(...)SpreedlyEventEmitter subscription .remove() + React useEffect cleanupDirectUnsubscribe when screens unmount. Avoid duplicate listeners across navigation.Integration Guide — Events
new SpreedlyPaymentFrame() (multiple forms)One initSdk; multiple SPLTextField = one formNot available on mobileDo not run concurrent isolated payment frames. Serialize checkouts or use one screen per session.Single SDK instance
ready event / Spreedly.isLoadedSpreedlyCore.isSdkInitialized() + component mountDifferent modelNo ready event. Await isSdkInitialized() or mount fields after init completes.Hosted Fields — areAllFieldsValid

Hosted field UI

PRETTY is not iframe prettyFormat. On the web, prettyFormat keeps grouped digits visible when the field loses focus. On React Native, PRETTY applies blur masking (last-four style) when unfocused while masked. For digits that stay visible like iframe prettyFormat, use PLAIN. For full bullets on every digit, use MASKED or toggleMask().

iFrame API / patternReact Native equivalentStatusWhat to doSee also
setLabel(type, text)SPLTextField prop labelDirectRequired on every field. Acts as in-field placeholder/caption (prop name is label, not placeholder).Hosted Fields — props
setTitle(type, text)SPLTextField prop titleDifferent modeliOS only — visible text above the field. On Android, use label only.Hosted Fields — props
setPlaceholder(type, text)SPLTextField prop labelDirectRN does not expose a separate placeholder prop.Hosted Fields — props
setStyle(type, css)Web onlyNo arbitrary CSS on mobile. Use theme / darkTheme or SpreedlyCore.setGlobalTheme.Theme Guide, Styling from iFrame
setStyle('placeholder', css)theme.placeholderColor (optional) + labelWeb onlyPseudo-element CSS does not apply. Map placeholder color via theme tokens where supported.Theme Guide
setFieldType(type, 'number' | 'text' | 'tel')SPLTextField formFieldTypeDifferent modelKeyboard layout follows formFieldType. RN does not expose keyboardType or textContentType.Hosted Fields — keyboard
setInputMode(type, mode)(defaults from formFieldType)Different modelNot merchant-configurable on RN. Use FormFieldTypes (CARD, CVV, etc.).Hosted Fields — keyboard
setNumberFormat(format)SpreedlyCore.setNumberFormat(format)DirectHeadless CARD/CVV always follow singleton display state. Express sheet initial format: paymentBottomSheet({ cardNumberFormat }) / PaymentBottomSheet.Hosted Fields — PAN display
toggleMask()SpreedlyCore.toggleMask()DirectToggles global PAN/CVV mask when fields observe display state. Read state with getHostedCardDisplayState().Hosted Fields — PAN display
transferFocus(field)SPLTextField prop shouldFocusDirectSet shouldFocus={true} to request focus on mount for that field.Hosted Fields — props
setRequiredAttribute(type, required)SPLTextField prop isRequiredDirectDefault true. Use ValidationManager for form-level gating in React.Integration Guide
toggleAutoComplete()SPLTextField prop enableAutofillDirectDefault true. Express: paymentBottomSheet({ enableAutofill }) / PaymentBottomSheet.Hosted and Express capabilities
setValue(type, value)Not available on mobilePCI — no programmatic PAN/CVV. Cardholder entry (and OS autofill when enabled) only.No setValue

Per-field lifecycle: forceMaskOnLifecycleStop on SPLTextField — see Hosted Fields Guide.

Validation and field events

iFrame API / patternReact Native equivalentStatusWhat to doSee also
Spreedly.validate()SpreedlyCore.areAllFieldsValid(fieldTypes)DirectPass the same FormFieldTypes strings you mount. Returns Promise<boolean>. Call on submit, not every render.Hosted Fields — areAllFieldsValid
validation event / fieldEventSPLTextField onFieldStateChangeHostedFieldStatePayloadDifferent modelPCI-safe payload: scheme, lengths, validity, focus, mask flags — not raw card data or full iFrame inputProperties.Hosted Fields — field state
inputProperties.cardTypeHostedFieldStatePayload.cardSchemeDirectUse for brand icons and UX hints.Hosted Fields — props
validNumber / validCvv in validation payloadonValidationChange(isValid) per fieldDirectBoolean per field; combine with ValidationManager for submit button state.Hosted Fields — props
numberLength / cvvLengthHostedFieldStatePayload.numberLength / cvvLengthDirectEmitted via onFieldStateChange when available.Hosted Fields — props
inputProperties.iin (live while typing)HostedFieldStatePayload.iin (6/8-digit prefix on CARD)DirectMerchant-safe prefix only — not full PAN. After tokenization, use issuerIdentificationNumber on payment method API models.Hosted Fields — field state
fieldEvent focus / bluronFocusChanged(focused) + onFieldStateChange (FOCUS / BLUR)DirectUse either or both depending on UX needs.Hosted Fields — props
fieldEvent input (per keystroke)onFieldStateChange with eventType: 'INPUT'DirectDo not log payloads.Hosted Fields
fieldEvent tab / enter / escapeSPLTextField imeAction + onImeActionDifferent modelMobile uses IME Next / Done; no DOM Escape.Hosted Fields — props
fieldEvent mouseover / mouseoutWeb onlyTouch platforms; use focus/highlight in your RN layout instead.

Tokenization

iFrame API / patternReact Native equivalentStatusWhat to doSee also
Spreedly.tokenizeCreditCard(options)SpreedlyCore.createCreditCard(options)DirectPromise-based. Requires formFieldTypes listing mounted hosted fields. Use mapPaymentResult for normalized outcomes.Integration Guide — API reference
setParam('allow_blank_name', …) / allow_expired_dateSpreedlyCore.setParam(ValidationParameter.ALLOW_BLANK_NAME | ALLOW_EXPIRED_DATE, value)DirectSame flags via ValidationParameter. Can also pass allowBlankName, allowExpiredDate on createCreditCard.Integration Guide — Global configuration
setParam('allow_blank_date', …)ValidationParameter.ALLOW_BLANK_DATE + create/sheet/recache optionsRN onlyUse allowBlankDate on createCreditCard, paymentBottomSheet, or recachePaymentMethod.Express Checkout
ALLOW_INTERNATIONAL_ZIP_CODESSpreedlyCore.setParam(ValidationParameter.ALLOW_INTERNATIONAL_ZIP_CODES, true)RN onlyMount FormFieldTypes.ZIP via SPLTextField or Express otherFields.Hosted and Express capabilities
Metadata + billing fields on tokenizecreateCreditCard({ metadata, additionalFields, fields, … })DirectNon-sensitive billing can use custom TextInput; sensitive fields stay in SPLTextField.Integration Guide
eligible_for_card_updatercreateCreditCard({ eligibleForCardUpdater: true })DirectOpt in only when your program expects Account Updater semantics.Hosted and Express capabilities
paymentMethod eventcreateCreditCard resolved promise + mapPaymentResultDifferent modelPrefer await/handle promise over global success listener. Bottom sheet uses SpreedlyEventTypes.PAYMENT_BOTTOM_SHEET_RESULT.Integration Guide — Events
errors eventcreateCreditCard rejection / status: 'failed' + FailureDetailsDifferent modelTyped validationErrors on failure. Do not log raw request bodies.Integration Guide

CVV recache

iFrame API / patternReact Native equivalentStatusWhat to doSee also
Spreedly.setRecache(...) + Spreedly.recache()SpreedlyCore.recachePaymentMethod(options)DirectSingle RN API bundles config + presentation.CVV Recaching Guide
recache eventSpreedlyEventEmitterSpreedlyEventTypes.RECACHE_RESULTDirectSubscribe before calling recachePaymentMethod. Payload type RecacheResult.CVV Recaching Guide
recacheReady eventDifferent modelNo separate ready event; invoke recachePaymentMethod when you are ready to show recache UI.CVV Recaching Guide

Global lifecycle events

iFrame API / patternReact Native equivalentStatusWhat to doSee also
ready eventSpreedlyCore.isSdkInitialized()Different modelSee Core table.
numberSet / cvvSet eventsonFieldStateChange (isEmpty, INPUT)Different modelDerive "field has content" from isEmpty and validation state.Hosted Fields
sourceSet (express channel)Web onlyWeb express channel only. On RN use paymentBottomSheet or embedded PaymentBottomSheet.Express Checkout
consoleError eventsetupGlobalErrorHandler / Datadog logging helpersDifferent modelUse logError, logException from @spreedly/react-native-checkout. Never log PAN/CVV.Central Logging Guide

3D Secure

iFrame API / patternReact Native equivalentStatusWhat to doSee also
3ds:status / managed challenge UISpreedlyCore.showThreeDSChallenge(managedOrderToken, transactionToken) + SpreedlyEventTypes.THREE_DS_CHALLENGE_RESULTDirectSubscribe to challenge result before showing UI. hideThreeDSChallenge() for edge dismissals.3DS Guide
Gateway-specific 3DS lifecycleGatewaySpecific3DS class + SpreedlyEventTypes.GATEWAY_SPECIFIC_3DS_*DirectinitializeGatewaySpecific3DSObservers(), startGatewaySpecific3DSFlow, finalizeGatewaySpecific3DSTransaction, cleanupGatewaySpecific3DSLifecycle.3DS Gateway Guide

Alternative payment methods (APM)

iFrame API / patternReact Native equivalentStatusWhat to doSee also
createStripePaymentElement / Stripe Payment ElementStripeAPM.presentCheckout(config) from @spreedly/react-native-checkout-stripe-apmDirectSeparate package. On iOS, dismiss → status: 'canceled'.Stripe APM Guide
createBraintreePaymentElementsBraintreeAPM.presentCheckout(config) from @spreedly/react-native-checkout-braintree-apmDirectpaymentType: paypal | venmo. Confirm nonce on backend via Spreedly /confirm.json.Braintree payment guide

Offsite payments and screen security

iFrame API / patternReact Native equivalentStatusWhat to doSee also
Offsite methods (PIX, Boleto, …)OffsitePayment + SpreedlyCore.submitOffsitePayment / presentOffsiteCheckout / handleOffsiteReturnRN onlyInitialize observer, submit config, handle return URL. Event: SpreedlyEventTypes.OFFSITE_PAYMENT_RESULT.Offsite payments guide
Screen capture preventionScreenSecurity utilitiesDifferent modelStronger on iOS; on Android combine with host app flags.Security Guide

Planned differences

Single SDK instance (not multi-form)

The web SDK supports new SpreedlyPaymentFrame() per form with isolated number/CVV iframes. On React Native, call SpreedlyCore.initSdk once per active checkout session; a second call replaces the active session. If you used multiple iFrame instances on one page, use one screen per checkout, or finish and resetPaymentState before starting another flow.

No setValue (programmatic PAN/CVV)

Web setValue(field, value) can inject card number or CVV into hosted inputs. React Native has no equivalent (PCI). Card number, CVV, and expiry must be entered in SPLTextField. OS autofill is controlled with enableAutofill.

Live IIN in field callbacks

onFieldStateChange / HostedFieldStatePayload.iin exposes a merchant-safe 6- or 8-digit prefix on CARD fields (iFrame parity). It is not the full PAN. For full BIN/IIN after tokenization, read issuerIdentificationNumber on the payment method from your backend.


Styling from iFrame setStyle

Web setStyle(type, css) injects arbitrary CSS (fonts, borders, ::placeholder).

Mobile hosted fields are native secure inputs, not HTML. Map design tokens instead:

iFrame approachReact Native approach
CSS on #card_numberSPLTextField theme / darkTheme (CustomThemeConfig)
Global themeSpreedlyCore.setGlobalTheme({ theme, darkTheme })
Placeholder textlabel prop (required)
Placeholder colorplaceholderColor in theme (where supported)
Express / sheet chromepaymentBottomSheet({ theme, darkTheme }) — see Theme Guide

Web-only / out of scope on mobile

These iFrame capabilities have no mobile equivalent and are not in the API tables above:

iFrame capabilityNotes
fraud:token (Forter JS callback)Web-only fraud integration path
Click to PayNot in RN core package
stripeRadar()Web-only

Verification checklist

  • No WebView payment code remaining (Path A): search for spreedly.js, addJavascriptInterface, and iFrame bridge handlers — zero results in payment flows
  • No API secret in app source: signing happens only on your server
  • SpreedlyCore.initSdk runs before any SPLTextField or Express Checkout UI mounts
  • Card, CVV, and expiry use SPLTextField only (no custom TextInput for PAN/CVV)
  • End-to-end test with card 4111111111111111; token sent to backend over HTTPS
  • Event listeners removed on screen unmount (SpreedlyEventEmitter subscriptions)

Getting help

TopicDocument
Install, auth, API referenceIntegration Guide
SPLTextField, PAN mask, validationHosted Fields Guide
ACH bank account (preview)ACH Bank Account Guide — not for production
Capability indexHosted and Express capabilities
ThemesTheme Guide
Express checkoutExpress Checkout Guide
CVV recacheCVV Recaching Guide
3DS3DS Guide · 3DS Gateway
Stripe / Braintree APMStripe APM · Braintree
OffsiteOffsite payments
Security / PCISecurity
TestingTesting Guide
TroubleshootingIntegration Guide — Troubleshooting
Spreedly Supportspreedly.com/support

Next steps



Did this page help you?