Skip to content

Feat/react native sdk - #53

Merged
aguilar1x merged 27 commits into
PACTO-LAT:mainfrom
KevinLatino:feat/react-native-sdk
Jul 29, 2026
Merged

Feat/react native sdk#53
aguilar1x merged 27 commits into
PACTO-LAT:mainfrom
KevinLatino:feat/react-native-sdk

Conversation

@KevinLatino

@KevinLatino KevinLatino commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a React Native SDK to Pacto Connect — a WebView-hosted checkout, deep-link return handling, and an escrow event hook, all reusing @pacto-connect/core's existing handshake/session model instead of reimplementing the checkout UI natively.

  • packages/connect-react-native (new): PactoCheckoutSheet (Modal + WebView, the RN counterpart to mountFrame() in @pacto-connect/elements), a webview-bridge layer that translates the existing postMessage bridge protocol onto WebView's one-way JS-string channel while preserving origin validation, usePactoDeepLink (custom-scheme + universal-link return handling via Linking, warm and cold-start), and usePactoEscrowEvents (SSE when ReadableStream is available, a documented polling fallback when it isn't — plus AppState-aware reconnect on foreground and transparent PactoSession.refresh() before expiry, since mobile sessions live far longer than a web checkout tab).
  • Universal links: buildAppleAppSiteAssociation / buildAndroidAssetLinks generate the two platform verification file bodies, wired into apps/example-rn/app.json's associatedDomains/intentFilters — a custom scheme still works out of the box with no hosting required.
  • apps/example-rn (new): a real Expo app exercising the package end-to-end (checkout sheet, deep-link return, escrow hook).
  • Docs: new @pacto-connect/react-native API reference (generated), a Security guide section covering the WebView bridge's origin model and universal-link setup, README/CI updated to include the new package.
  • Incidental fix: apps/docs's lockfile was missing styled-jsx/@next/env (pre-existing, unrelated to this change) and silently broke next build — pinned styled-jsx so the whole workspace builds again.

Why this shape

The security model matters more here than in a typical wrapper: a WebView has no MessageEvent.origin, so onMessage payloads are validated against the WebView's current page URL instead, using the same isOriginAllowed allow-list the DOM bridge already uses. parentOrigin is pointed at the checkout page's own origin rather than an app scheme, because a same-window postMessage is only delivered when the target origin matches the receiving window's — there is no real parent window inside a WebView. External navigation (bank/3-D Secure redirects) is handed off to the system browser via onShouldStartLoadWithRequest rather than loaded inside the captive WebView. No merchant secret key is ever a prop on any exported component or hook — only publishableKey, matching the web SDKs.

Acceptance criteria coverage

  • A bare RN app can trigger a checkout, complete it in the embedded WebView, and receive an escrow-status callback in JS (onComplete/onDispute on PactoCheckoutSheet, demonstrated in apps/example-rn/App.tsx).
  • Deep-link / universal-link handling for returning from an external payment step (usePactoDeepLink + real associatedDomains/intentFilters config, not just a custom scheme).
  • Escrow event subscription surfaced via a React Native hook, reusing connect-core's SSE client where the platform allows, with a documented polling fallback where it doesn't (usePactoEscrowEvents).
  • No merchant secret key is ever bundled into the mobile app — verified by a test asserting the WebView URL never contains an sk_ value regardless of input.
  • Not run against a real iOS/Android simulator in this environment (no Xcode/Android SDK available) — apps/example-rn type-checks and builds cleanly; running it live in Expo Go/a simulator is the one thing I couldn't verify myself.

Test plan

npm run check # biome — 0 errors, whole workspace
npm run type-check # turbo — 11/11 packages
npm run build # turbo — 6/6 packages, apps/docs builds incl. new API reference page
npm run test # turbo — 9/9 packages, 387 tests total, 0 regressions

Closes #38

…cto-connect

Regenerating from a fork (or any checkout whose git 'origin' doesn't
resolve to this repo) rewrote every 'Defined in' link and made the
docs-freshness CI check fail on an unrelated diff. Also regenerates
react-native.mdx, which had drifted from the export-order change in
the preceding biome format commit.
@aguilar1x aguilar1x assigned aguilar1x and KevinLatino and unassigned aguilar1x Jul 29, 2026

@aguilar1x aguilar1x left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm!

@aguilar1x
aguilar1x merged commit 2587d00 into PACTO-LAT:main Jul 29, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(mobile): @pacto-connect/react-native SDK for embedded checkout in mobile apps

2 participants