@rnw-community/react-native-payments
Version:
Accept Payments with Apple Pay and Android Pay using the Payment Request API.
110 lines (92 loc) • 8.6 kB
Markdown
# Roadmap
Open work for this package, as tracked GitHub issues, plus the W3C compliance checklist. The [landing
readme](../readme.md) links here instead of carrying its own TODO ledger.
## Open work
- [ ] Payment sheet GIFs for iOS and Android — [#469](https://github.com/rnw-community/rnw-community/issues/469),
capture procedure below.
- [ ] Shipping options and coupon support on Android — [#438](https://github.com/rnw-community/rnw-community/issues/438).
- Rewrite iOS to Swift — **deferred indefinitely**, decision recorded on
[#442](https://github.com/rnw-community/rnw-community/issues/442).
- [ ] Rewrite Android to Kotlin — decided, low effort, tracked in
[#442](https://github.com/rnw-community/rnw-community/issues/442).
- [ ] Drop the `AppDelegate.h` PassKit import requirement — looks droppable, needs a build-verify pass, tracked in
[#442](https://github.com/rnw-community/rnw-community/issues/442).
## Docs
### Payment sheet GIFs — [#469](https://github.com/rnw-community/rnw-community/issues/469)
Capture procedure once the on-device Maestro fleet has capacity:
1. Add `startRecording: "sheet"` / `stopRecording` around the sheet-presenting step of the `sheet_opens_on_show.yaml`
flow documented in [e2e/readme.md](../../react-native-payments-example/e2e/readme.md#flows).
2. Run `maestro test --test-output-dir "$MAESTRO_DEBUG_OUTPUT_DIRECTORY" -e APP_ID=... e2e/flows` from
`packages/react-native-payments-example` (the `e2e:ios:bare` / `e2e:android:bare` / `:expo` scripts in
`package.json` don't pass `--test-output-dir` today — add it for the capture run), with
`MAESTRO_DEBUG_OUTPUT_DIRECTORY` set to an **absolute** path the same way `ios-maestro.yml` / `android-maestro.yml`
do for their post-run screenshot/artifact upload (`${{ github.workspace }}/packages/react-native-payments-example/artifacts/maestro-<platform>-<target>`
in CI; locally, `$(git rev-parse --show-toplevel)/packages/react-native-payments-example/artifacts/maestro-<platform>-<target>`) —
a relative value resolves under the current directory, which is already `packages/react-native-payments-example`,
and would nest a duplicate `packages/react-native-payments-example/` segment. This makes the `.mp4` land there
instead of Maestro's default `~/.maestro/tests/<datetime>/`.
3. Convert with `ffmpeg -i sheet.mp4 -vf "fps=12,scale=320:-1" sheet.gif`.
4. Embed the result under [Screenshots](../readme.md#screenshots), replacing the placeholder.
## Native
### Android shipping options and coupon support — [#438](https://github.com/rnw-community/rnw-community/issues/438)
Google Pay's `loadPaymentData` supports dynamic price updates via `callbackIntents`
(`SHIPPING_ADDRESS`, `SHIPPING_OPTION`) and `PaymentDataCallbacks`, meaning `shippingaddresschange` /
`shippingoptionchange` could fire on Android and feed the same `updateWith` contract iOS already uses — but this is
new infrastructure, not a small tweak to the existing no-op: `AndroidManifest.xml` currently declares no services at
all, and `PaymentsModule.java`'s `setActiveEvents`/`updatePaymentDetails` resolve immediately without touching Google
Pay. Shipping on Android would require registering a `Service` extending `BasePaymentDataCallbacks` in the manifest
(with the `com.google.android.gms.permission.BIND_PAYMENTS_CALLBACK_SERVICE` permission and a
`com.google.android.gms.wallet.callback.PAYMENT_DATA_CALLBACKS` intent filter) that overrides
`onPaymentDataChanged(IntermediatePaymentData, OnCompleteListener<PaymentDataRequestUpdate>)` for the declared
`SHIPPING_ADDRESS`/`SHIPPING_OPTION` callback intents, adapting the `PaymentDataRequestUpdate` handed to that
listener into the existing `updatePaymentDetails` call so JS `updateWith` observes it the same way it does on iOS.
`onPaymentAuthorized` is a second override on that same `BasePaymentDataCallbacks` service — not a separate
mechanism — required only when `PAYMENT_AUTHORIZATION` is also declared in `callbackIntents` for in-sheet
authorization review, which is out of scope for the shipping/coupon work here. Coupons are a separate spike:
investigate the Google Pay offer/promo surface, documenting the outcome either way (`couponcodechange` would stay
iOS-only if unsupported).
### Native modernization — [#442](https://github.com/rnw-community/rnw-community/issues/442)
Spike findings (decision recorded on the issue):
- **iOS → Swift: deferred indefinitely.** `Payments.mm`/`Payments.h` (1079 + 24 lines, ObjC++) implement a hardened
PassKit delegate lifecycle — per-event pending-completion tracking with superseded-event detection, a teardown
state machine invoked from five call sites, iOS 15+ conditional coupon-code support, and ~30 delegate
callbacks/helpers. Codegen (React Native 0.86.2, the version this monorepo is pinned to) has no Swift TurboModule
support — it only emits Objective-C++ glue — so a Swift rewrite would still sit behind an Objective-C++ spec surface,
adding a bridging layer without removing the interop this module already has, while asking to re-verify ~1100 lines
of delegate state whose regressions are silent runtime sheet hangs, not compile errors. Effort: L. Risk: high.
Revisit only as part of an Expo Modules API spike (see #445), not as a standalone plain-Swift TurboModule rewrite.
- **Android → Kotlin: do.** `PaymentsModule.java` (284 lines) is a single activity-result round trip, not a delegate
protocol — `abort`/`complete`/`setActiveEvents`/`updatePaymentDetails` are no-ops that resolve immediately, no
coupon codes, no in-sheet change events, no teardown state machine. The oldarch/newarch split already isolates the
codegen boundary in one abstract spec file, so Kotlin interops with the generated `NativePaymentsSpec` without a
bridging shim. Effort: S. Risk: low.
- **`AppDelegate.h` PassKit import: document + verify.** The regenerated bare example's `AppDelegate.swift` (RN
0.86 community template) contains no `import PassKit`, and `react-native-payments.podspec` already declares
`s.frameworks = "PassKit", "Contacts"`, linking the framework at the Pod target level — the readme's "add this
import" instructions look like they predate that framework-level linking. Not yet build-verified; needs a
`pod install` + build against both the ObjC and Swift `AppDelegate` templates before the readme instruction is
dropped. Effort: XS.
## W3C compliance checklist
- [x] [PaymentRequestUpdateEvent](https://www.w3.org/TR/payment-request/#dom-paymentrequestupdateevent) — JavaScript
layer and iOS PassKit delivery implemented (see [guides/change-events.md](./guides/change-events.md)); on-device
verification is tracked in [#393](https://github.com/rnw-community/rnw-community/issues/393)
- [x] [PaymentMethodChangeEvent](https://www.w3.org/TR/payment-request/#dom-paymentmethodchangeevent) — same
implementation and verification status as `PaymentRequestUpdateEvent`
- [x] Implement [PaymentDetailsModifier](https://www.w3.org/TR/payment-request/#dom-paymentdetailsmodifier) — see
[guides/modifiers.md](./guides/modifiers.md)
- [x] Improve and unify errors according to the spec — see [guides/errors.md](./guides/errors.md)
- [x] Implement [`hasEnrolledInstrument()`](https://www.w3.org/TR/payment-request/#hasenrolledinstrument-method) — see
[api/payment-request.md](./api/payment-request.md); Android answers via Google Pay's
`existingPaymentMethodRequired`, see [platforms/android.md](./platforms/android.md)
- [x] Implement the event-handler attributes (`onshippingaddresschange`, `onshippingoptionchange`,
`onpaymentmethodchange`, `oncouponcodechange`) — see
[guides/change-events.md](./guides/change-events.md#event-handler-attributes)
- [x] Implement [`PaymentOptions.shippingType`](https://www.w3.org/TR/payment-request/#dom-paymentoptions-shippingtype) as
`methodData.data.shippingType` — see [platforms/ios.md](./platforms/ios.md); no-op on Android, see
[platforms/android.md](./platforms/android.md)
- [x] Implement `PaymentResponse` `retry()` method — best-effort subset on iOS, documented no-op on Android; see
[guides/retry.md](./guides/retry.md)
- [x] Implement `PaymentResponse` `toJSON()` method — see [api/payment-response.md](./api/payment-response.md)
## Related
- Epic: [#372](https://github.com/rnw-community/rnw-community/issues/372) — react-native-payments revival
- Docs Oasis: [#467](https://github.com/rnw-community/rnw-community/issues/467) — documentation platform umbrella