feat(react-paypal-js): add v6 Local Payment Methods (LPM) React wrapper core#993
feat(react-paypal-js): add v6 Local Payment Methods (LPM) React wrapper core#993Mathanjeevika wants to merge 3 commits into
Conversation
…er core Adds the generic, registry-driven React wrapper for all 50 v6 Local Payment Methods, exposed via the ./sdk-v6/local-payment-methods subpath so the default @paypal/react-paypal-js export is unaffected. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: fc4705f The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
One thing we'll need to do is update the react-paypal-js README with integration code snippets and appropriate re-directs to integration resources (v6 sample integration repo or dev docs). |
| }, | ||
| estonia: { | ||
| component: "estoniabank-payments", | ||
| buttonTag: "estoniabank-button", |
There was a problem hiding this comment.
| buttonTag: "estoniabank-button", | |
| buttonTag: "estonia-button", |
| testBuyerCountry: "ID", | ||
| }, | ||
| thailandBanks: { | ||
| component: "thailandbanks-payments", |
There was a problem hiding this comment.
| component: "thailandbanks-payments", | |
| component: "thailand-banks-payments", |
| test("button tag derives from component name", () => { | ||
| // FIUU is the one exception: its SDK component is "fiuu-cash-payments" but | ||
| // the registered custom-element button tag is "fiuu-button". | ||
| const TAG_EXCEPTIONS: Record<string, string> = { | ||
| "fiuu-cash-payments": "fiuu-button", | ||
| }; | ||
| for (const config of Object.values(LPM_REGISTRY)) { | ||
| const expectedTag = | ||
| TAG_EXCEPTIONS[config.component] ?? | ||
| config.component.replace("-payments", "-button"); | ||
| expect(config.buttonTag).toBe(expectedTag); | ||
| } | ||
| }); |
There was a problem hiding this comment.
This test is using the registry's own component value to compute the expected tag, which is why it didn't catch the estonia button bug that I pointed out elsewhere. This needs an independent list, like checking if config.buttonTag is a key in SDKWebComponents.
| test("has exactly 50 LPM entries", () => { | ||
| expect(Object.keys(LPM_REGISTRY)).toHaveLength(50); | ||
| }); |
There was a problem hiding this comment.
What is the purpose of this test?
| /** | ||
| * Creates a stable SDK-iframe field component for a given field type. | ||
| * | ||
| * This is a module-level factory (not defined inside the hook render) so | ||
| * React concurrent-mode is fully safe and no ESLint suppression is required. | ||
| * The returned component is created once per `createEnhancedLPMHook` call via | ||
| * `useRef` and will not unmount/remount when the session changes — instead it | ||
| * uses a version counter driven by a pub/sub listener on `sessionListenersRef`. | ||
| */ |
There was a problem hiding this comment.
It looks like this implementation goes against the decision from the ADR to create an LPMSessionContext in place of the pub/sub listener set. Can you review the ADR decisions and update the implementation here?
| // Mount (or re-mount) the SDK iframe whenever the session version changes, | ||
| // i.e. whenever a new session becomes available via the pub/sub mechanism. | ||
| // sessionRef.current is accessed imperatively; fieldType is a stable | ||
| // closure variable from the factory — neither belongs in the deps array. |
There was a problem hiding this comment.
We decided against this pub/sub mechanism in favor of leveraging Context, please review the finalized ADR 👍
- Fix estonia buttonTag: 'estoniabank-button' -> 'estonia-button' - Fix thailand: component + buttonTag corrected with proper hyphenation - Update SDKWebComponents to match corrected thailand button tag - Add SDK_LPM_BUTTON_TAGS runtime set for independent test validation - Replace fragile 'button tag derives' test with SDK_LPM_BUTTON_TAGS check - Remove 'has exactly 50 LPM entries' test - Replace pub/sub listener set with LPMSessionContext per ADR decision; field components now consume useContext(LPMSessionContext); createEnhancedLPMHook returns LPMSessionProvider for wrapping fields - Export LPMSessionContext from lpmExports Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Summary
@paypal/react-paypal-js/sdk-v6/local-payment-methodssubpath so the default@paypal/react-paypal-jsexport is unaffected.BancontactOneTimePaymentButton), a split hook + standalone button (useBancontactOneTimePaymentSession+BancontactPaymentButton), and a generic dynamic-selector button (LPMOneTimePaymentButton).src/v6/config/lpmRegistry.ts(registry),src/v6/hooks/useLPMOneTimePaymentSession.ts,src/v6/components/{LPMOneTimePaymentButton,LPMPaymentProvider}.tsx,src/v6/lpmExports.ts(subpath entry), plus a new Rollup build target andexportssubpath.Context
This is PR 2 of 3 split out from #926 per review feedback requesting the original monolithic PR be broken up:
paypal-jsv6 LPM type declarationsreact-paypal-jscore LPM wrapperThis PR depends on #992 merging first. The LPM types (
LPMComponents,LPMSessionMethodName,LPMOneTimePaymentSession, etc.) are re-exported from@paypal/paypal-js/sdk-v6and consumed here viasrc/v6/types/index.ts'sexport type * from "@paypal/paypal-js/sdk-v6". Until #992 merges,npm run typecheckin this package will fail againstmain— this is expected and resolves once #992 lands (verified locally by overlaying #992's type declarations, which produces a cleantsc --noEmit).Known pre-existing issue
src/v6/hooks/useLPMOneTimePaymentSession.test.tshangs underjestin this environment. This is not introduced by this PR — verified by reproducing the identical hang on the original, unmodifiedfeature/lpm-react-wrapperbranch running the same test file in isolation. Flagging for visibility; happy to dig into it further if it reproduces in CI.Test plan
npx tsc --noEmitpasses once feat(paypal-js): add v6 Local Payment Methods (LPM) types #992's types are presentnpx eslintcleannpx jest— blocked by the pre-existing hang noted above (other new LPM test files, e.g.lpmRegistry.test.ts, pass individually).changeset/lpm-react-wrapper.md)