Changelog (iOS SDK)

Changelog for the Rainforest iOS SDK versions

Version 0.6.0 (released 8/14/2026) [BETA]

Breaking changes

  • presentPayin() no longer throws the underlying card reader provider's raw error type for reader errors it doesn't explicitly recognize
    • Every such error is now wrapped as RainforestError.error(.cardReader, ...) before being thrown
    • Attempting to read a card during an active phone call (readNotAllowedDuringCall) now throws a specific, actionable error — RainforestError.error(.cardReader, "Cannot process payments while on a call") — instead of a generic "unknown card reader error"

Version 0.5.5 (released 8/10/2026) [BETA]

Additions

  • More reliable recovery from noReaderSession/readerSessionExpired/readerTokenExpired errors — the SDK now calls resume() to re-arm the physical card reader during recovery, instead of only reconfiguring its credentials
  • SDK/provider initialization now surfaces structured, specific errors instead of a generic failure message when the underlying Tap to Pay provider fails to start up

Version 0.5.4 (released 7/23/2026) [BETA]

Additions

  • cancelPresented() now also aborts an in-flight card-read transaction on the reader itself if presentPayin() hasn't started polling yet, instead of only cancelling server-side. If you relied on the reader continuing to wait for a tap after calling cancelPresented() mid-presentPayin(), that no longer happens.

Version 0.5.3

No official release


Version 0.5.2 (released 7/22/2026) [BETA]

Breaking changes

  • presentPayin() (and the shared prepare/resume data-load path) now actively triggers the OS location-permission prompt if permission hasn't been granted yet, instead of immediately throwing RainforestError.missingPermission. The same error still throws if permission is denied, but a permission dialog can now appear mid-call.

Version 0.5.1 (released 7/6/2026) [BETA]

Additions

  • Minimum deployment target lowered to iOS 17.4 (from 17.6), and the Tap to Pay provider dependency is now lazy-loaded at runtime — this is what enables a Compat build of the SDK for apps that still need to support pre-17.4 devices
  • MerchantData / MerchantAddress fields (address, merchant ID, name, MCC, etc.) are now actually public and readable — previously the structs were public but their fields weren't

Version 0.5.0 (released 6/30/2026) [BETA]

Breaking changes

  • The per-call deviceRegistrationId overloads of setup(), prepare(), presentPayin(), resume(), cancelPresented(), and clientMetadata() (deprecated in 0.4.2) are removed. deviceRegistrationId must now be supplied once, at construction.

Additions

  • New "Auto mode" — RainforestPay.TapToPhoneAuto(environment:sessionKey:deviceRegistrationId:) async throws -> TapToPhoneCoreProtocol. Manages the prepare/resume lifecycle automatically (background prepare loop, auto-resume on foreground); you just call presentPayin(payinConfigId:) when needed.
  • RainforestPay.setupTapToPhone(environment:sessionKey:deviceRegistrationId:) async throws -> SetupResult — one-shot convenience that creates an instance and calls setup().
  • updateSessionKey(_:) — rotate a session key on a live instance without tearing it down and recreating it.
  • prepare(), resume(), and presentPayin() now guard against overlapping calls on the same instance instead of racing, throwing new RainforestError.prepareInFlight / .resumeInFlight / .presentPayinInFlight cases
  • New RainforestErrorCode.invalidSessionKey and RainforestEvent.invalidSessionKey / .prepareSucceeded / .prepareFailed(String) cases, surfaced by Auto mode's background prepare loop

Version 0.4.2 (released 6/10/2026) [BETA]

Breaking changes

  • RainforestPayStub removed entirely — no replacement stub ships in the SDK
  • RainforestEvent.attempted now fires when the card read actually completes on the reader, not when presentPayin() is first called. If you used .attempted as a "user started a tap" signal, it now fires later — and not at all if the tap never completes.
  • prepare() and presentPayin() can now throw RainforestError.missingPermission for location, not just setup() — for example, if permission is revoked after setup() already succeeded
  • setup() behavior changed substantially: it no longer short-circuits on repeat calls, and now checks whether the merchant's Tap to Pay terms have been accepted before proceeding
  • Reader-session errors no longer get case-specific auto-recovery; every PaymentCardReaderSession.ReadError case now uniformly throws RainforestError.error(.cardReaderSession, "Reader session failed. Prepare the SDK to create new session.")

Additions

  • New factory overload, RainforestPay.TapToPhone(_:sessionKey:deviceRegistrationId:), binding deviceRegistrationId once at construction, plus matching parameter-less instance methods: setup(), prepare(), presentPayin(payinConfigId:), resume(), cancelPresented(), clientMetadata()
    • The old per-call deviceRegistrationId: overloads still work but are deprecated (removed in 0.5.0)
  • clientMetadata() async throws -> ClientMetadata — new method, returns { merchantTermsAccepted: Bool }
  • New RainforestErrorCode.usage case, thrown if you mix the two calling conventions above on the same instance
  • New RainforestEvent.configured case

Version 0.4.1 (released 5/5/2026) [BETA]

Breaking changes

  • presentPayin() and resume() no longer throw RainforestError.error(.notReady, ...) when prepare() hasn't been called yet or the session has expired — they now automatically call prepare() internally instead (with one retry). If your error handling was keyed on .notReady to drive your own prepare/retry flow, it will no longer trigger from this path.
  • presentPayin() now automatically calls resume() internally if the reader needs it, instead of immediately throwing RainforestError.error(.cardReaderSession, "Reader session paused. Resume the SDK to create new session.")

Version 0.4.0 (released 4/10/2026) [BETA]

Breaking changes

  • Fixed a heap-corruption crash caused by concurrent SDK instances. Instance creation is now serialized through an internal manager that reuses a matching existing instance, coalesces concurrent creation requests for the same environment/session, and tears down the previous instance before building a new one for a different environment/session.
  • RainforestPay.TapToPhone(_:sessionKey:) is now async throws (previously just throws) — add await at every call site
  • TapToPhoneProtocol gained a required teardown() async method, and instances no longer clean themselves up automatically on deinit — simply dropping a reference no longer performs cleanup; teardown() must be called (the SDK's own instance manager calls it for you when superseding an instance)

Additions

  • New RainforestErrorCode.initialize case, thrown in a specific instance-creation race edge case

Version 0.3.1 (released 3/21/2026) [BETA]

Breaking changes

  • The events property is replaced with a method: eventStream() -> AsyncStream<TapEvent>
    • This also fixes a bug where only the most recently obtained stream actually received events — multiple concurrent subscribers to eventStream() now each receive every event

Version 0.3.0 (released 3/12/2026) [BETA]

Breaking changes

  • RainforestPay.TapToPhone(_:sessionKey:) is now throws. It previously could not fail; it now throws if the underlying Tap to Pay provider fails to initialize, replacing what used to be a hard crash.

Version 0.2.1 (released 2/27/2026) [BETA]

Internal fix only — no consumer-facing changes.


Version 0.2.0 (released 2/24/2026) [BETA]

Breaking changes

  • presentPayin() now requires a prior successful setup()/prepare() — calling it without one now throws RainforestError.error(.notReady, "SDK not ready to present payin") instead of silently fetching what it needs on demand
  • Significantly expanded error-code mapping — many provider failure codes that used to fall through to RainforestErrorCode.unknown now map to a specific code (new cases: .appConfiguration, .authorization, .merchant, .missingPermission, .notReady, .service). If you pattern-match on error codes for these scenarios, expect different values than before.

Additions

  • New setup() method — TapToPhoneProtocol.setup(deviceRegistrationId:) async throws -> SetupResult. Checks device passcode/biometric and location permissions, requesting them if needed, before preparing the SDK for its first use.

Version 0.1.3 (released 2/1/2026) [BETA]

Build tooling fix only — no consumer-facing changes.


Version 0.1.2 (released 1/29/2026) [BETA]

Additions

  • .cardDetected, .cardReadSuccess, and .cardReadFailure events — declared since 0.1.0 but never actually delivered — now fire on the events stream

Version 0.1.1 (released 1/28/2026) [BETA]

Additions

  • .updateReaderProgress(Int) event — declared since 0.1.0 but never actually delivered — now fires on the events stream

Version 0.1.0 (released 1/21/2026) [BETA]

Initial release



Did this page help you?