UNPKG

@rnw-community/react-native-payments

Version:

Accept Payments with Apple Pay and Android Pay using the Payment Request API.

1,066 lines (771 loc) 143 kB
# @rnw-community/react-native-payments — full documentation Full concatenation of every doc in this package, in doc-map order, per https://llmstxt.org/. Every relative link below is rebased to be relative to this package root (e.g. docs/api/foo.md), regardless of which file it originally appeared in, since that's this bundle's own frame of reference. Use llms.txt for the linked index instead if you can fetch files individually. --- # FILE: readme.md # ReactNative Payments [![npm version](https://badge.fury.io/js/%40rnw-community%2Freact-native-payments.svg)](https://badge.fury.io/js/%40rnw-community%2Freact-native-payments) [![coverage](https://img.shields.io/codecov/c/github/rnw-community/rnw-community?flag=react-native-payments&label=coverage)](https://app.codecov.io/gh/rnw-community/rnw-community) [![npm downloads](https://img.shields.io/npm/dm/%40rnw-community%2Freact-native-payments.svg)](https://www.npmjs.com/package/%40rnw-community%2Freact-native-payments) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com) > Accept Payments with Apple Pay and Android Pay using the Payment Request API. TurboModule-based implementation of the [W3C Payment Request API](https://www.w3.org/TR/payment-request/) (08 September 2022) for React Native — full TypeScript, a unified iOS/Android API, and an Expo config plugin. A rewrite of [naoufal/react-native-payments](https://github.com/naoufal/react-native-payments); see [Migrating from upstream](docs/guides/migrate-from-upstream.md) if you are porting an existing integration. ## For AI agents Start with [llms.txt](llms.txt) for a curated, agent-oriented index of this package's docs and [AGENTS.md](AGENTS.md) for architecture and contributor conventions. ## Install ```bash yarn add @rnw-community/react-native-payments ``` Autolinking picks up the TurboModule on both architectures — no manual `react-native link` step. Complete the one-time platform setup before writing any code: [iOS](docs/getting-started/quickstart-ios.md) · [Android](docs/getting-started/quickstart-android.md) · [Expo](docs/getting-started/quickstart-expo.md). ## Quickstart ```ts import { PaymentComplete, PaymentMethodNameEnum, PaymentRequest, SupportedNetworkEnum, } from '@rnw-community/react-native-payments'; const methodData = [ { supportedMethods: PaymentMethodNameEnum.ApplePay, data: { merchantIdentifier: 'merchant.com.your-app.namespace', supportedNetworks: [SupportedNetworkEnum.Visa, SupportedNetworkEnum.Mastercard], countryCode: 'US', currencyCode: 'USD', }, }, // Add a matching AndroidPay entry to the same array to support both platforms. ]; const paymentDetails = { total: { label: 'Total', amount: { currency: 'USD', value: '10.00' } } }; const paymentRequest = new PaymentRequest(methodData, paymentDetails); if (await paymentRequest.canMakePayment()) { const paymentResponse = await paymentRequest.show(); const isConfirmed = await sendToYourBackend(paymentResponse.details); // your own gateway call await paymentResponse.complete(isConfirmed ? PaymentComplete.SUCCESS : PaymentComplete.FAIL); } ``` Only call `complete(PaymentComplete.SUCCESS)` once your backend has actually confirmed the charge. A `PaymentRequest` is single-use — build a new one per payment attempt rather than reusing a settled request; see [docs/architecture.md](docs/architecture.md). For the full two-platform `methodData` shape, shipping/coupon change events, and payment details modifiers, see the [doc map](#doc-map) below. ### Screenshots Recording is deferred, not dropped — capture needs the on-device Maestro fleet, tracked in [docs/roadmap.md](docs/roadmap.md#docs). Once captured, an Apple Pay and a Google Pay sheet GIF replace this placeholder. ## Doc map - **Getting started** — [Install](docs/getting-started/install.md) · [iOS](docs/getting-started/quickstart-ios.md) · [Android](docs/getting-started/quickstart-android.md) · [Expo](docs/getting-started/quickstart-expo.md) - **Platforms** — [iOS](docs/platforms/ios.md) · [Android](docs/platforms/android.md) · [Web](docs/platforms/web.md) · [Expo](docs/platforms/expo.md) - **API reference** — [index](docs/api/index.md) (`PaymentRequest`, `PaymentResponse`, every exported type/enum) - **Guides** — [Payment change events](docs/guides/change-events.md) · [Payment details modifiers](docs/guides/modifiers.md) · [Error handling](docs/guides/errors.md) · [Retrying a payment](docs/guides/retry.md) · [Unit testing](docs/guides/testing.md) · [Troubleshooting](docs/guides/troubleshooting.md) - **Architecture** — [The JS↔native contract, single-use requests, event lifecycle](docs/architecture.md) - **Roadmap** — [Open work and the W3C compliance checklist](docs/roadmap.md) ## Migrating - [From `v2` to `v3`](docs/guides/migrate-from-v2.md) — the native module interface change and the single-use request behavior change. - [From upstream `react-native-payments`](docs/guides/migrate-from-upstream.md) — the full API mapping and a worked before/after example. ## W3C compliance This package implements the [W3C Payment Request API](https://www.w3.org/TR/payment-request/) — change events, `PaymentDetailsModifier`, `hasEnrolledInstrument()`, `retry()`, `toJSON()` and the event-handler attributes are all implemented, with a small set of documented platform deviations (Android has no in-sheet change events, iOS ignores `shippingOption.selected`, `PaymentRequest` is single-use). See the full [W3C compliance checklist](docs/roadmap.md#w3c-compliance-checklist) and each platform's known deviations in [docs/platforms/](docs/platforms/). ## Architecture & contributing See [AGENTS.md](AGENTS.md) for the source layout, TurboModule/Expo-plugin architecture, and coverage. For end-to-end verification, see [react-native-payments-example/e2e/readme.md](../react-native-payments-example/e2e/readme.md). ## License This library is licensed under The [MIT License](LICENSE.md). --- # FILE: docs/getting-started/install.md # Install Install the package with your package manager, e.g.: ```bash yarn add @rnw-community/react-native-payments ``` Autolinking picks up the TurboModule on both architectures — no manual `react-native link` step. Before writing any code, complete the one-time platform setup for every platform you target: - [iOS quickstart](docs/getting-started/quickstart-ios.md) — Apple developer account, merchant ID, `PassKit` import in `AppDelegate`. - [Android quickstart](docs/getting-started/quickstart-android.md) — Google developer account, `play-services-wallet` dependency, test-card allowlist. - [Expo quickstart](docs/getting-started/quickstart-expo.md) — the `app.plugin` entry plus `expo prebuild --clean`. Then ship a payment sheet by following the [readme quickstart](readme.md#quickstart) or the full [`PaymentRequest` API reference](docs/api/payment-request.md). --- # FILE: docs/getting-started/quickstart-ios.md # iOS quickstart The fastest path to an Apple Pay sheet. See [Platforms — iOS](docs/platforms/ios.md) for the full setup story (capabilities, deviations, native code snippets). 1. Create an [Apple developer account](https://developer.apple.com/programs/enroll/) and a merchant ID. 2. Follow Apple's [Apple Pay configuration guide](https://developer.apple.com/library/archive/ApplePay_Guide/Configuration.html) to enable the capability and register the merchant ID. 3. Import `PassKit` in your `AppDelegate` — see [Platforms — iOS](docs/platforms/ios.md#native-setup) for the Objective-C and Swift snippets. 4. Construct a `PaymentRequest` with `PaymentMethodNameEnum.ApplePay` method data (`merchantIdentifier`, `supportedNetworks`, `countryCode`, `currencyCode`) and call `show()` — see the [readme quickstart](readme.md#quickstart) for the full snippet. `merchantIdentifier` passed to `methodData.data` must exactly match the merchant ID declared in the app's `com.apple.developer.in-app-payments` entitlement, or the sheet fails with a merchant/entitlement error — see [Troubleshooting](docs/guides/troubleshooting.md). --- # FILE: docs/getting-started/quickstart-android.md # Android quickstart The fastest path to a Google Pay sheet. See [Platforms — Android](docs/platforms/android.md) for the full setup story (capabilities, deviations, dependency version). 1. Create a [Google developer account](https://support.google.com/googleplay/android-developer/answer/6112435?hl=en). 2. Follow Google's [Google Pay API for Android setup guide](https://developers.google.com/pay/api/android/guides/setup). 3. Depend on `com.google.android.gms:play-services-wallet:18.0.0` or newer — see [Platforms — Android](docs/platforms/android.md#native-setup) for the Gradle snippet. 4. Add your test Google account to the [Google Pay API Test Cards Allowlist](https://groups.google.com/g/googlepay-test-mode-stub-data?pli=1). 5. Construct a `PaymentRequest` with `PaymentMethodNameEnum.AndroidPay` method data (`supportedNetworks`, `environment`, `countryCode`, `currencyCode`, `gatewayConfig`) and call `show()` — see the [readme quickstart](readme.md#quickstart) for the full snippet. `canMakePayment()` on Android always checks against `EnvironmentEnum.TEST` regardless of the `environment` set on `methodData.data` — set the real `environment` for `show()` regardless of what `canMakePayment()` reported. See [Platforms — Android](docs/platforms/android.md#known-deviations). --- # FILE: docs/getting-started/quickstart-expo.md # Expo quickstart This package links native code (PassKit on iOS, the Google Pay API on Android), so it cannot run inside **Expo Go**. It requires an Expo [custom build](https://docs.expo.dev/custom-builds/get-started/) (a.k.a. development build / `expo-dev-client`). See [Platforms — Expo](docs/platforms/expo.md) for the full plugin options reference. 1. Add the `@rnw-community/react-native-payments` plugin to your `app.config.js`: ```js export default { plugins: [ ... [ "@rnw-community/react-native-payments/app.plugin", { "merchantIdentifier": "merchant.react-native-payments" } ], ], }; ``` 2. Prebuild your project: ```bash npx expo prebuild --clean ``` Building the package before prebuild is required for local/monorepo consumers: `expo prebuild` resolves `@rnw-community/react-native-payments/app.plugin` through the package's `exports` map, which only points at `dist` — run `yarn build` (or your workspace's build step) for this package before `expo prebuild` if you are linking it locally rather than installing it from npm. See [Platforms — Expo](docs/platforms/expo.md#plugin-options-reference) for every plugin option (`merchantIdentifier`, `supportedNetworks`, `googlePayEnvironment`). --- # FILE: docs/platforms/ios.md # iOS (Apple Pay) Setup, capabilities, and how this package's `PaymentRequest` maps onto PassKit. ## Setup - Apple Pay [overview](https://developer.apple.com/apple-pay/planning/). - Create an [Apple developer account](https://developer.apple.com/programs/enroll/). - Follow [this guide](https://developer.apple.com/library/archive/ApplePay_Guide/Configuration.html) to set up Apple Pay in your application. - [Payment token reference](https://developer.apple.com/documentation/passkit/apple_pay/payment_token_format_reference?language=objc). ### Native setup Add the following code to your `AppDelegate.h` (Objective-C): ```objc #import <RCTAppDelegate.h> #import <UIKit/UIKit.h> #import <PassKit/PassKit.h> // Add this import @interface AppDelegate : RCTAppDelegate ``` Add the following code to your `AppDelegate.swift` (Swift): ```swift import UIKit import React import React_RCTAppDelegate import ReactAppDependencyProvider import PassKit // Add this import ``` ## Capabilities - `merchantCapabilities` (`IosPKMerchantCapability`, see [api/ios-payment-method-data.md](docs/api/ios-payment-method-data.md)) defaults to 3-D Secure, debit and credit when omitted. - `supportedNetworks` accepts every `SupportedNetworkEnum` member, but Apple Pay introduced some of them after the oldest supported iOS version: `girocard` needs iOS 14, `mir` needs iOS 14.5, `dankort` needs iOS 15.1 and `bancontact` needs iOS 16 — each is rejected as an invalid supported network below its minimum iOS version. See [api/supported-network-enum.md](docs/api/supported-network-enum.md). - `shippingType` (`Shipping` / `Delivery` / `Pickup`) forwards to `PKShippingType` — `Pickup` maps to `PKShippingTypeStorePickup`. See [Known deviations](#known-deviations). - `couponCode` prefills the coupon code field of the sheet, but the field itself is only rendered when a `couponcodechange` listener is registered before `show()`, and only on iOS 15+. See [guides/change-events.md](docs/guides/change-events.md). - `canMakePayment()` maps to PassKit's `canMakePaymentsUsingNetworks:`, restricting the check to the request's `supportedNetworks`. - `retry()` reuses the same `PKPaymentErrorDomain` field-error constructors as [Sheet errors](docs/guides/change-events.md#sheet-errors) to fail the pending authorization and let the user correct and resubmit. See [guides/retry.md](docs/guides/retry.md). ## Known deviations - **`PaymentShippingOption.selected` is ignored.** PassKit has no preselection support and always shows its shipping-method picker with the first option of the array highlighted. Put the option you want preselected first in `shippingOptions` instead of relying on `selected`. - **`shippingType: 'pickup'` maps to `PKShippingTypeStorePickup`.** PassKit also has `PKShippingTypeServicePickup`, which has no W3C equivalent and is not exposed by this library. - **`retry()` supports at most one in-sheet correction pass.** This package's `PaymentRequest` is single-use (see [architecture.md](docs/architecture.md)) and its native bridge resolves the `show()` promise exactly once per authorization, so there is no channel left to deliver a second submission to JavaScript. If the user corrects the fields and resubmits, this package fails and dismisses the sheet automatically instead of silently hanging — see [guides/retry.md](docs/guides/retry.md). - **`hasEnrolledInstrument()`** maps to PassKit's `canMakePaymentsUsingNetworks:`, the same capability check as `canMakePayment()` restricted to `supportedNetworks`. --- # FILE: docs/platforms/android.md # Android (Google Pay) Setup, capabilities, and how this package's `PaymentRequest` maps onto the Google Pay API. ## Setup - Create a [Google developer account](https://support.google.com/googleplay/android-developer/answer/6112435?hl=en). - Follow [this guide](https://developers.google.com/pay/api/android/guides/setup) to set up the Google Pay API in your application. - [Google payments tutorial](https://developers.google.com/pay/api/android/guides/tutorial). - [Google brand guidelines](https://developers.google.com/pay/api/android/guides/brand-guidelines). - Your Google account used for testing must be added to the [Google Pay API Test Cards Allowlist](https://groups.google.com/g/googlepay-test-mode-stub-data?pli=1). ### Native setup This package's own `android/build.gradle` depends on `com.google.android.gms:play-services-wallet:18.0.0` — match or exceed that in your application if you pin the wallet dependency yourself: ```groovy dependencies { // The version of react-native is set by the React Native Gradle Plugin implementation("com.facebook.react:react-android") implementation 'com.google.android.gms:play-services-wallet:18.0.0' } ``` ## Capabilities - `environment` (`EnvironmentEnum`) selects the Google Pay environment for the payment; see [api/environment-enum.md](docs/api/environment-enum.md). - `totalPriceStatus` describes how the total price will change: `'FINAL'` (default), `'ESTIMATED'` or `'NOT_CURRENTLY_KNOWN'`. A zero total amount (`'0.00'`) is valid per the W3C spec and can be combined with a non-final status when the price is not known upfront. See [TransactionInfo](https://developers.google.com/pay/api/android/reference/request-objects#TransactionInfo). - `checkoutOption` selects the payment sheet submit behavior: `'DEFAULT'` or `'COMPLETE_IMMEDIATE_PURCHASE'`. Google Pay only allows `'COMPLETE_IMMEDIATE_PURCHASE'` together with the `'FINAL'` `totalPriceStatus`, so the constructor throws on any other combination. - `transactionId` correlates the payment attempt in Google Pay transaction events. - `allowedAuthMethods` (`AndroidAllowedAuthMethodsEnum`) defaults to both `PAN_ONLY` and `CRYPTOGRAM_3DS` when omitted. See [api/android-payment-method-data.md](docs/api/android-payment-method-data.md). - `canMakePayment()` calls Google Pay's `isReadyToPay` and always checks against `EnvironmentEnum.TEST` regardless of the `environment` set in `methodData.data`, mirroring the W3C surface (`canMakePayment` only answers "is a payment handler available", not "is this specific environment reachable"). See [#259](https://github.com/rnw-community/rnw-community/issues/259). - `hasEnrolledInstrument()` calls Google Pay's `isReadyToPay` with `existingPaymentMethodRequired: true`. See [Known deviations](#known-deviations). ## Known deviations - **Change events are a no-op.** Google Pay renders its sheet in its own activity and never asks the app for an in-sheet update, so `addEventListener` can be called but a registered listener never fires on Android. See [guides/change-events.md](docs/guides/change-events.md). - **`complete()` and `abort()` have no effect** — an artifact of the Google Pay activity-result flow, which has no in-sheet dismiss/complete call to make. - **`retry()` is a documented no-op.** It resolves without any visual effect, consistent with the `complete()`/ `abort()` no-op boundary above — Google Pay's sheet is a separate activity with no in-sheet update mechanism at all. See [guides/retry.md](docs/guides/retry.md). - **`methodData.data.shippingType` is a no-op.** Google Pay has no `PKShippingType`-equivalent concept; the value is validated but not forwarded to native. - **`hasEnrolledInstrument()` is an optimistic signal, not a guarantee.** `isReadyToPay` with `existingPaymentMethodRequired: true` is the closest reachable equivalent of "an instrument is enrolled" the API exposes; Google documents this as best-effort and it can still resolve `true` without a fully usable card in some configurations. - **Shipping options and coupon support are not yet implemented** — tracked in [#438](https://github.com/rnw-community/rnw-community/issues/438), spike notes in [roadmap.md](docs/roadmap.md#android-shipping-options-and-coupon-support--438). --- # FILE: docs/platforms/web.md # Web (react-native-web) `payment-request.web.ts` / `payment-response.web.ts` are one-line passthroughs — `PaymentRequest` and `PaymentResponse` resolve to `window.PaymentRequest` / `window.PaymentResponse` (or `null` when `window` is not defined, e.g. during SSR), typed as `WebPaymentRequestConstructor` / `WebPaymentResponseConstructor` — aliases for the browser's own `typeof window.PaymentRequest` / `typeof window.PaymentResponse` from `lib.dom`. On web there is no TurboModule, no native class and none of this package's own logic in the loop: you get the browser's implementation of the W3C Payment Request API, unmodified. > **Type visibility caveat:** a bundler that platform-resolves `.web.ts` files (Metro building for the web > target, `react-native-web` webpack configs) swaps in this passthrough at *runtime* regardless of what > TypeScript shows you. `src/index.ts` re-exports the platform-agnostic `PaymentRequest` / `PaymentResponse` > specifiers without a build-time branch, so a plain `tsc`/IDE setup resolves > `import { PaymentRequest } from '@rnw-community/react-native-payments'` to the native class documented in > [api/payment-request.md](docs/api/payment-request.md) on every platform, web included. Add > `"moduleSuffixes": [".web", ".native", ""]` (or an order matching your own bundler's platform resolution) to > your app's `tsconfig.json` if you need the IDE/`tsc` to show the true DOM types for a web build. Apple Pay through this browser passthrough is **not** the native iOS integration documented in [platforms/ios.md](docs/platforms/ios.md) — calling `show()` in Safari drives Safari's own Apple Pay JS flow, which fires a `merchantvalidation` event that your own server must answer by completing Apple's merchant validation session round-trip (TLS, your merchant certificate, Apple's validation URL) before the sheet can display line items. There is no `merchantIdentifier` Expo plugin config, no PassKit entitlement and no `merchantCapabilities` on this path — see [Apple Pay on the Web](https://developer.apple.com/documentation/apple_pay_on_the_web). Browser support is inconsistent: Chrome, Edge and Safari (with the merchant-validation caveat above) implement the Payment Request API; Firefox removed its implementation. Check [caniuse](https://caniuse.com/payment-request) before shipping a web checkout on top of it, and always guard for `PaymentRequest`/`PaymentResponse` being **nullish** (a truthiness or `== null` check, never `=== null`) — the passthrough returns `null` outside a `window` (SSR), while an unsupported browser has no `window.PaymentRequest` at all, so the export resolves to `undefined` there. ## Known deviations from the native classes None of the native-only behavior documented for the `PaymentRequest`/`PaymentResponse` classes applies to the browser's own implementation: - **`couponCode`** — populated only by the iOS 15+ PassKit `couponcodechange` flow; the browser's `PaymentRequest` has no `couponCode` property. - **Normalized `AbortError`** — dismissing the sheet on web throws the browser's own native `DOMException`, not this package's [`PaymentsErrorEnum`](docs/api/payments-error-enum.md)-driven `DOMException`; `isNativeUserCancellation` never runs on web. - **Single-use request semantics** — the native class tracks `state: 'created' | 'interactive' | 'closed'` itself and rejects a reused, settled request with its own `InvalidStateError`. The browser enforces single-use per the W3C spec independently, through its own internal slots, not this package's state machine. See [architecture.md](docs/architecture.md). - **Listener auto-cleanup** — the request-scoped subscription bookkeeping and automatic teardown on `show()`/`abort()` described in [guides/change-events.md](docs/guides/change-events.md) is this package's `NativeEventEmitter` plumbing over the TurboModule. The browser's `PaymentRequest` follows plain DOM `addEventListener`/`removeEventListener` semantics with no auto-cleanup — remove your own listeners when you are done with them. ## Usage Detailed guide can be found at: - [developer.mozilla.org](https://developer.mozilla.org/en-US/docs/Web/API/Payment_Request_API/Using_the_Payment_Request_API) as the API is fully compliant. - [Google Web Payments guide](https://web.dev/payments/). --- # FILE: docs/platforms/expo.md # Expo This package links native code (PassKit on iOS, the Google Pay API on Android), so it cannot run inside **Expo Go**. It requires an Expo [custom build](https://docs.expo.dev/custom-builds/get-started/) (a.k.a. development build / `expo-dev-client`) — add the `@rnw-community/react-native-payments` plugin into your `app.config.js`. See [getting-started/quickstart-expo.md](docs/getting-started/quickstart-expo.md) for the minimal setup steps. `merchantIdentifier` accepts either a single identifier or an array of identifiers. Pass an array when your app resolves the Apple Pay merchant per country/environment at runtime — every identifier is then declared in the `com.apple.developer.in-app-payments` entitlement. Empty identifiers are ignored; if no non-empty identifier remains, prebuild fails with an error: ```js { "merchantIdentifier": ["merchant.react-native-payments.fr", "merchant.react-native-payments.mg"] } ``` ## Plugin options reference | Option | Type | Default | What it mutates | | --- | --- | --- | --- | | `merchantIdentifier` | `string \| string[]` | *(required)* | iOS entitlements plist: appends every non-empty identifier to `com.apple.developer.in-app-payments`, de-duplicated. Throws at prebuild time if no non-empty identifier is provided. | | `supportedNetworks` | `SupportedNetworkEnum[]` | every `SupportedNetworkEnum` value | Android `AndroidManifest.xml`: writes the comma-joined list as the `com.rnw-community.react-native-payments.supported-networks` meta-data value on the main application. Throws if given an empty array or a value outside `SupportedNetworkEnum`. | | `googlePayEnvironment` | `EnvironmentEnum` | `EnvironmentEnum.PRODUCTION` | Android `AndroidManifest.xml`: writes the `com.google.android.gms.wallet.api.environment` meta-data value on the main application. Throws if given a value outside `EnvironmentEnum`. | `withGooglePay` also always writes `com.google.android.gms.wallet.api.enabled=true` (no option needed) so the Google Pay API is enabled for the app. `SupportedNetworkEnum` and `EnvironmentEnum` are both exported from the package root — see [api/supported-network-enum.md](docs/api/supported-network-enum.md) and [api/environment-enum.md](docs/api/environment-enum.md). Building the package before prebuild is required for local/monorepo consumers: `expo prebuild` resolves `@rnw-community/react-native-payments/app.plugin` through the package's `exports` map, which only points at `dist` — run `yarn build` (or your workspace's build step) for this package before `expo prebuild` if you are linking it locally rather than installing it from npm. ## Example You can find a working example in the `App` component of the [react-native-payments-example](../react-native-payments-example/readme.md) package, running through its `apps/expo` target. --- # FILE: docs/api/index.md # API reference One entry per group of public exports from [`src/index.ts`](src/index.ts). Grouped files follow the same pairing the package already uses for tightly-coupled siblings (a data shape and its platform-specific `*DataInterface`, an event and its payload/listener types). ## Core classes - [payment-request.md](docs/api/payment-request.md) — `PaymentRequest` - [payment-response.md](docs/api/payment-response.md) — `PaymentResponse` - [ios-payment-response.md](docs/api/ios-payment-response.md) — `IosPaymentResponse` - [ios-pk-token.md](docs/api/ios-pk-token.md) — `IosPKToken` - [android-payment-response.md](docs/api/android-payment-response.md) — `AndroidPaymentResponse` - [android-payment-method-token.md](docs/api/android-payment-method-token.md) — `AndroidPaymentMethodToken` ## Change events - [payment-request-update-event.md](docs/api/payment-request-update-event.md) — `PaymentRequestUpdateEvent`, `PaymentMethodChangeEvent` - [events-types.md](docs/api/events-types.md) — `PaymentRequestEventType`, `PaymentRequestEventListener`, `PaymentMethodChangeEventListener`, `PaymentRequestEventPayloadInterface` ## Enums - [payment-method-name-enum.md](docs/api/payment-method-name-enum.md) — `PaymentMethodNameEnum` - [environment-enum.md](docs/api/environment-enum.md) — `EnvironmentEnum` - [payment-complete-enum.md](docs/api/payment-complete-enum.md) — `PaymentComplete` - [supported-network-enum.md](docs/api/supported-network-enum.md) — `SupportedNetworkEnum` - [payments-error-enum.md](docs/api/payments-error-enum.md) — `PaymentsErrorEnum` - [payment-address-contact-field-enums.md](docs/api/payment-address-contact-field-enums.md) — `PaymentAddressFieldEnum`, `PaymentContactFieldEnum` - [payment-update-error-type-enum.md](docs/api/payment-update-error-type-enum.md) — `PaymentUpdateErrorTypeEnum` - [payment-shipping-type-enum.md](docs/api/payment-shipping-type-enum.md) — `PaymentShippingTypeEnum` ## Errors - [constructor-error.md](docs/api/constructor-error.md) — `ConstructorError` - [dom-exception.md](docs/api/dom-exception.md) — `DOMException` - [payments-error.md](docs/api/payments-error.md) — `PaymentsError` ## Payment details shapes - [payment-details-init.md](docs/api/payment-details-init.md) — `PaymentDetailsInit` - [payment-details-update.md](docs/api/payment-details-update.md) — `PaymentDetailsUpdate`, `PaymentDetailsUpdateError` - [payment-details-modifier.md](docs/api/payment-details-modifier.md) — `PaymentDetailsModifier` - [payment-item-shipping-option.md](docs/api/payment-item-shipping-option.md) — `PaymentItem`, `PaymentShippingOption` - [payment-validation-errors.md](docs/api/payment-validation-errors.md) — `PaymentValidationErrors` - [payment-response-json.md](docs/api/payment-response-json.md) — `PaymentResponseJsonInterface` - [payment-response-address.md](docs/api/payment-response-address.md) — `PaymentResponseAddressInterface` - [payment-method-data.md](docs/api/payment-method-data.md) — `PaymentMethodData` ## Platform method data - [android-payment-method-data.md](docs/api/android-payment-method-data.md) — `AndroidPaymentMethodDataInterface`, `AndroidPaymentMethodDataDataInterface` - [android-allowed-auth-methods-enum.md](docs/api/android-allowed-auth-methods-enum.md) — `AndroidAllowedAuthMethodsEnum` - [ios-payment-method-data.md](docs/api/ios-payment-method-data.md) — `IosPaymentMethodDataInterface`, `IosPaymentMethodDataDataInterface` - [ios-pk-merchant-capability.md](docs/api/ios-pk-merchant-capability.md) — `IosPKMerchantCapability` --- # FILE: docs/api/android-allowed-auth-methods-enum.md # `AndroidAllowedAuthMethodsEnum` ## What & why Restricts `methodData.data.allowedAuthMethods` on the Android entry to the auth methods Google Pay should accept. Reach for it only when you need to narrow acceptance below the default. ## How | Member | Meaning | | --- | --- | | `PAN_ONLY` | Accept cards without requiring 3-D Secure cryptogram data. | | `CRYPTOGRAM_3DS` | Accept cards tokenized with a 3-D Secure cryptogram. | Both members are the default when `allowedAuthMethods` is omitted from [`AndroidPaymentMethodDataDataInterface`](docs/api/android-payment-method-data.md). ## Example ```ts import { AndroidAllowedAuthMethodsEnum } from '@rnw-community/react-native-payments'; const allowedAuthMethods = [AndroidAllowedAuthMethodsEnum.PAN_ONLY]; ``` ## Pitfalls None — narrowing this list only restricts which cards Google Pay offers; it does not change any other validation. ## References - [Google Pay API for Android — CardParameters](https://developers.google.com/pay/api/android/reference/request-objects#CardParameters) - [api/android-payment-method-data.md](docs/api/android-payment-method-data.md) --- # FILE: docs/api/android-payment-method-data.md # `AndroidPaymentMethodDataInterface` / `AndroidPaymentMethodDataDataInterface` ## What & why The typed shape of the Android entry of `methodData`. Reach for these when building the `AndroidPay` entry of your `methodData` array. ## How | Type | Notes | | --- | --- | | `AndroidPaymentMethodDataInterface` | `supportedMethods: PaymentMethodNameEnum.AndroidPay` paired with an `AndroidPaymentMethodDataDataInterface` `data`. | | `AndroidPaymentMethodDataDataInterface` | `supportedNetworks`, `environment`, `countryCode?`, `currencyCode`, exactly one of `gatewayConfig` (`{ gateway, gatewayMerchantId }`) or `directConfig` (`{ protocolVersion, publicKey }`) — the type forbids supplying both, `allowedAuthMethods?` ([`AndroidAllowedAuthMethodsEnum`](docs/api/android-allowed-auth-methods-enum.md)), `totalPriceStatus?`, `checkoutOption?`, `transactionId?` — see [platforms/android.md](docs/platforms/android.md) for every field. | `requestBillingAddress`, `requestPayerEmail`, `requestPayerName`, `requestPayerPhone` and `requestShipping` are shared with [`IosPaymentMethodDataDataInterface`](docs/api/ios-payment-method-data.md) (both extend the package's common `GenericPaymentMethodDataDataInterface`): each is an optional boolean that, when `true`, adds the matching field to the resulting `PaymentResponse` — see [api/payment-response.md](docs/api/payment-response.md). ## Example ```ts const androidMethod: AndroidPaymentMethodDataInterface = { supportedMethods: PaymentMethodNameEnum.AndroidPay, data: { supportedNetworks: [SupportedNetworkEnum.Visa], environment: EnvironmentEnum.TEST, countryCode: 'DE', currencyCode: 'EUR', gatewayConfig: { gateway: 'example', gatewayMerchantId: 'exampleGatewayMerchantId' }, }, }; ``` ## Pitfalls - `checkoutOption: 'COMPLETE_IMMEDIATE_PURCHASE'` is only allowed together with `totalPriceStatus: 'FINAL'` — the constructor throws on any other combination. See [platforms/android.md](docs/platforms/android.md). - `countryCode` is optional on this interface (unlike the required `countryCode` on the iOS side) — omitting it is valid TypeScript, but Google Pay's own requirements for your merchant configuration may still need it set. - `gatewayConfig` and `directConfig` are mutually exclusive at the type level (`{ directConfig; gatewayConfig?: never } | { directConfig?: never; gatewayConfig }`) — providing both, or neither, is a type error. ## References - [platforms/android.md](docs/platforms/android.md) - [api/payment-method-name-enum.md](docs/api/payment-method-name-enum.md) - [api/android-allowed-auth-methods-enum.md](docs/api/android-allowed-auth-methods-enum.md) --- # FILE: docs/api/android-payment-method-token.md # `AndroidPaymentMethodToken` ## What & why The Google Pay payment token exposed as `paymentResponse.details.androidPayToken` on an [`AndroidPaymentResponse`](docs/api/android-payment-response.md). Reach for it to read the tokenized card data to send to your payment gateway. ## How | Member | Type | Notes | | --- | --- | --- | | `cardInfo.cardNetwork` | `string` | The card network of the tokenized card. | | `cardInfo.cardDetails` | `string` | The last four digits or similar display detail, as returned by Google Pay. | | `intermediateSigningKey` | `{ signatures: string; signedKey: AndroidSignedKey }` | The intermediate signing key used to verify the token signature — see Pitfalls for a known type/runtime mismatch on `signatures`. | | `protocolVersion` | `string` | The protocol version of the signed message (e.g. `ECv2`). | | `signature` | `string` | The signature over `signedMessage`. | | `signedMessage` | `{ encryptedMessage: string; ephemeralPublicKey: string; tag: string }` | The encrypted message envelope — see [Google Pay payment data cryptography](https://developers.google.com/pay/api/android/guides/resources/payment-data-cryptography#signed-message). | | `rawToken` | `string` | The raw tokenization payload as returned by Google Pay, before this package's parsing. | ## Example ```ts import { AndroidPaymentResponse } from '@rnw-community/react-native-payments'; const response = await paymentRequest.show(); if (response instanceof AndroidPaymentResponse) { const token = response.details.androidPayToken; token.cardInfo.cardNetwork; } ``` ## Pitfalls - `AndroidPaymentMethodToken` is a plain TypeScript interface with no runtime validation of its own — constructing an object that merely matches its shape never throws. `PaymentsError` is thrown by [`AndroidPaymentResponse`](docs/api/android-payment-response.md) when it parses a malformed or incomplete native JSON payload (including direct construction of `AndroidPaymentResponse` with malformed tokenization data), not by this token type — see [guides/errors.md](docs/guides/errors.md). - **`intermediateSigningKey.signatures` is declared `string` in this package's shipped type (`AndroidIntermediateSigningKey`/`AndroidRawIntermediateSigningKey`), but the real Google Pay payload sends an array of signatures** — this package's own test fixtures construct the raw native payload with `signatures: ['testSignature']`, and Google's own Payment Data Cryptography reference documents `IntermediateSigningKey.signatures` as `string[]`. The value is passed through unparsed (nothing in this package reads `.signatures`), so treat the declared `string` type as unreliable until the type is corrected — check the actual runtime value's shape before assuming either type. ## References - [Google Pay API for Android — response objects](https://developers.google.com/pay/api/android/reference/response-objects) - [api/android-payment-response.md](docs/api/android-payment-response.md) --- # FILE: docs/api/android-payment-response.md # `AndroidPaymentResponse` ## What & why The `PaymentResponse` subclass `show()` resolves with on Android. Reach for it when you need to branch on the platform response type or read the Google Pay token via `details.androidPayToken` — see [api/android-payment-method-token.md](docs/api/android-payment-method-token.md). ## How | Member | Signature | Notes | | --- | --- | --- | | `AndroidPaymentResponse` | `class extends PaymentResponse` | Parsed from the Google Pay JSON payload. Consumers do not construct it directly — it comes back from `show()`. | | `AndroidPaymentResponse.details.androidPayToken` | `AndroidPaymentMethodToken` | The Google Pay token exposed on the response — see [api/android-payment-method-token.md](docs/api/android-payment-method-token.md). | ## Example ```ts import { AndroidPaymentResponse } from '@rnw-community/react-native-payments'; const response = await paymentRequest.show(); if (response instanceof AndroidPaymentResponse) { response.details.androidPayToken.cardInfo.cardNetwork; } ``` ## Pitfalls - A native payment response payload that fails to parse (malformed or incomplete JSON from Google Pay, including direct construction of `AndroidPaymentResponse` with malformed tokenization data) throws `PaymentsError` — see [guides/errors.md](docs/guides/errors.md). ## References - [api/payment-response.md](docs/api/payment-response.md) - [api/android-payment-method-token.md](docs/api/android-payment-method-token.md) - [Google Pay API for Android — response objects](https://developers.google.com/pay/api/android/reference/response-objects) --- # FILE: docs/api/constructor-error.md # `ConstructorError` ## What & why A native `TypeError` thrown from `new PaymentRequest(...)` when the input dictionaries fail W3C validation. Reach for `instanceof TypeError` to catch it, matching the spec's WebIDL / `check and canonicalize (total) amount` algorithm, which itself throws `TypeError`. ## How | Check | Trigger | | --- | --- | | `instanceof TypeError` | Always true — `ConstructorError` is a `TypeError` subclass. | | `name` | `'TypeError'` | | Thrown from | Missing/invalid payment methods, total, display items or shipping options. | ## Example ```ts try { new PaymentRequest([], paymentDetails); } catch (error) { if (error instanceof TypeError) { // invalid constructor input } } ``` ## Pitfalls Distinct from `DOMException NotSupportedError`, which is also thrown at construction time but only when the input is otherwise valid and no platform-matching payment method exists — see [architecture.md](docs/architecture.md). ## References - [guides/errors.md](docs/guides/errors.md) --- # FILE: docs/api/dom-exception.md # `DOMException` ## What & why The spec-mandated runtime error for `created`/`interactive`/`closed` state violations and abort/not-supported conditions. Reach for `instanceof DOMException` plus `error.name` to branch on the W3C error name. ## How | Check | Trigger | | --- | --- | | `instanceof DOMException` | Always true for spec-mandated runtime states. | | `error.name` | One of `AbortError`, `InvalidStateError`, `NotAllowedError`, `NotSupportedError`, `SecurityError` — see [api/payments-error-enum.md](docs/api/payments-error-enum.md). | See [guides/errors.md](docs/guides/errors.md) for the full table of which public API failure produces which `DOMException` name. ## Example ```ts import { DOMException } from '@rnw-community/react-native-payments'; try { await paymentRequest.show(); } catch (error) { if (error instanceof DOMException && error.name === 'AbortError') { // user cancelled } } ``` ## Pitfalls `SecurityError` is defined but not currently reachable from this implementation — no permission-policy check exists in React Native. ## References - [guides/errors.md](docs/guides/errors.md) --- # FILE: docs/api/environment-enum.md # `EnvironmentEnum` ## What & why Selects the Google Pay environment for a payment, and the `googlePayEnvironment` Expo plugin option. Reach for it when setting `methodData.data.environment` on the Android entry, or when configuring the Expo plugin. ## How | Member | Runtime value | Meaning | | --- | --- | --- | | `TEST` | `'TEST'` | Google Pay's test environment — used internally by `canMakePayment()` regardless of the configured value. | | `PRODUCTION` | `'PRODUCTION'` | Google Pay's production environment — the default for the Expo plugin's `googlePayEnvironment` option. | ## Example ```ts import { EnvironmentEnum, PaymentMethodNameEnum } from '@rnw-community/react-native-payments'; const methodData = [ { supportedMethods: PaymentMethodNameEnum.AndroidPay, data: { environment: EnvironmentEnum.TEST, supportedNetworks: [], countryCode: 'DE', currencyCode: 'EUR' }, }, ]; ``` ## Pitfalls `canMakePayment()` on Android always checks against `EnvironmentEnum.TEST` regardless of the `environment` set on `methodData.data` — set the real `environment` for `show()` regardless of what `canMakePayment()` reported. See [platforms/android.md](docs/platforms/android.md). ## References - [platforms/android.md](docs/platforms/android.md) - [platforms/expo.md](docs/platforms/expo.md) --- # FILE: docs/api/events-types.md # Event support types ## What & why The small supporting types for the change-event system: the event-name union, the listener signatures, and the raw native payload. Reach for these when typing a standalone listener function or when inspecting the payload before it reaches a listener. ## How | Type | Shape | Notes | | --- | --- | --- | | `PaymentRequestEventType` | `'shippingaddresschange' \| 'shippingoptionchange' \| 'paymentmethodchange' \| 'couponcodechange'` | Accepted by `addEventListener`/`removeEventListener`. | | `PaymentRequestEventListener` | `(event: PaymentRequestUpdateEvent) => Promise<void> \| void` | For `shippingaddresschange`, `shippingoptionchange` and `couponcodechange`. Both sync and async listeners are accepted — see [guides/change-events.md](docs/guides/change-events.md). | | `PaymentMethodChangeEventListener` | `(event: PaymentMethodChangeEvent) => Promise<void> \| void` | For `paymentmethodchange`. | | `PaymentRequestEventPayloadInterface` | `{ requestId: string; eventId?: number; … }` | The raw native payload carried by a change event, before it is applied to the request and dispatched to listeners. `requestId` always identifies the request; `eventId` identifies the native completion handler and is optional — the rest is event-type specific. | ## Example ```ts const eventType: PaymentRequestEventType = 'shippingoptionchange'; paymentRequest.addEventListener(eventType, event => event.updateWith({})); const onShippingOptionChange: PaymentRequestEventListener = event => { event.updateWith({}); }; const onPaymentMethodChange: PaymentMethodChangeEventListener = event => { event.updateWith({}); }; const payload: PaymentRequestEventPayloadInterface = { requestId: paymentRequest.id, eventId: 1, shippingOption: 'express', }; ``` ## Pitfalls - `eventId` on `PaymentRequestEventPayloadInterface` is optional — guard with `isDefined`/`?.` before forwarding it to a native completion call instead of assuming it is always a `number`. - A listener may return either synchronously or a `Promise` — `updateWith` does not have to be called before the listener function returns. See [guides/change-events.md](docs/guides/change-events.md). ## References - [guides/change-events.md](docs/guides/change-events.md) - [api/payment-request-update-event.md](docs/api/payment-request-update-event.md) --- # FILE: docs/api/ios-payment-method-data.md # `IosPaymentMethodDataInterface` / `IosPaymentMethodDataDataInterface` ## What & why The typed shape of the Apple Pay entry of `methodData`. Reach for these when building the `ApplePay` entry of your `methodData` array. ## How | Type | Notes | | --- | --- | | `IosPaymentMethodDataInterface` | `supportedMethods: PaymentMethodNameEnum.ApplePay` paired with an `IosPaymentMethodDataDataInterface` `data`. | | `IosPaymentMethodDataDataInterface` | `merchantIdentifier`, `supportedNetworks`, `countryCode`, `currencyCode`, plus the iOS-only options in [platforms/ios.md](docs/platforms/ios.md) (`merchantCapabilities?` — [`IosPKMerchantCapability`](docs/api/ios-pk-merchant-capability.md), `shippingType`, `couponCode`, `applicationData`) and the cross-platform request flags below. | `requestBillingAddress`, `requestPayerEmail`, `requestPayerName`, `requestPayerPhone` and `requestShipping` are shared with [`AndroidPaymentMethodDataDataInterface`](docs/api/android-payment-method-data.md) (both extend the package's common `GenericPaymentMethodDataDataInterface`): each is an optional boolean that, when `true`, adds the matching field to the resulting `PaymentResponse` — see [api/payment-response.md](docs/api/payment-response.md). ## Example ```ts const iosMethod: IosPaymentMethodDataInterface = { supportedMethods: PaymentMethodNameEnum.ApplePay, data: { merchantIdentifier: 'merchant.com.your-app.namespace', countryCode: 'US', currencyCode: 'USD', supportedNetworks: [SupportedNetworkEnum.Visa], merchantCapabilities: [ IosPKMerchantCapability.PKMerchantCapability3DS, IosPKMerchantCapability.PKMerchantCapabilityDebit, ], }, }; ``` ## Pitfalls `applicationData` is not transmitted to Apple but is included in the decrypted payment token payload as a SHA-256 hash, under the token's own `applicationData` key (per Apple's [Payment Token Format Reference](https://developer.apple.com/documentation/passkit/payment-token-format-reference)) — use it to prevent replay attacks by associating a payment with a specific transaction, not to pass data your backend needs verbatim. ## References - [platforms/ios.md](docs/platforms/ios.md) - [api/payment-method-name-enum.md](docs/api/payment-method-name-enum.md) - [api/ios-pk-merchant-capability.md](docs/api/ios-pk-merchant-capability.md) --- # FILE: docs/api/ios-payment-response.md # `IosPaymentResponse` ## What & why The `PaymentResponse` subclass `show()` resolves with on iOS. Reach for it when you need to branch on the platform response type or read the Apple Pay token via `details.applePayToken` — see [api/ios-pk-token.md](docs/api/ios-pk-token.md). ## How | Member | Signature | Notes | | --- | --- | --- | | `IosPaymentResponse` | `class extends PaymentResponse` | Parsed from the PassKit payment token. Consumers do not construct it directly — it comes back from `show()`. | | `IosPaymentResponse.details.applePayToken` | `IosPKToken` | The Apple Pay token exposed on the response, carrying the PassKit payment data — see [api/ios-pk-token.md](docs/api/ios-pk-token.md). | ## Example ```ts import { IosPaymentResponse } from '@rnw-community/react-native-payments'; const response = await paymentRequest.show(); if (response instanceof IosPaymentResponse) { const token = response.details.applePayToken; token.transactionIdentifier; } ``` ## Pitfalls - A native payment response payload that fails to parse (malformed or incomplete JSON from PassKit, including direct construction of `IosPaymentResponse` with malformed tokenization data) throws `PaymentsError` — see [guides/errors.md](docs/guides/errors.md). ## References - [api/payment-response.md](docs/api/payment-response.md) - [api/ios-pk-token.md](docs/api/ios-pk-token.md) - [Apple Pay payment token reference](https://developer.apple.com/documentation/passkit/apple_pay/payment_token_format_reference?language=objc) --- # FILE: docs/api/ios-pk-merchant-capability.md # `IosPKMerchantCapability` ## What & why Populates the optional `merchantCapabilities` of the Apple Pay `methodData.data`, declaring which payment processing capabilities the merchant supports. Reach for it only when the default set does not match your merchant configuration. ## How | Member | Meaning | Accepted by this package's native bridge? | | --- | --- | --- | | `PKMerchantCapability3DS` | Supports 3-D Secure. | Yes | | `PKMerchantCapabilityCredit` | Supports credit cards. | Yes | | `PKMerchantCapabilityDebit` | Supports debit cards. | Yes | | `PKMerchantCapabilityEMV` | Supports the EMV payment protocol — per Apple's guidance, only relevant for China UnionPay transactions; use `PKMerchantCapability3DS` for other networks. | Yes | | `PKMerchantCapabilityInstantFundsOut` | Supports Instant Funds Out **disbursements** (`PKDisbursementRequest`), not ordinary purchase payments. | **No — see Pitfalls.** | `merchantCapabilities` defaults to `PKMerchantCapability3DS`, `PKMerchantCapabilityDebit` and `PKMerchantCapabilityCredit` when omitted from [`IosPaymentMethodDataDataInterface`](docs/api/ios-payment-method-data.md). ## Example ```ts import { IosPKMerchantCapability } from '@rnw-community/react-native-payments'; const data = { merchantIdentifier: 'merchant.com.your-app.namespace', merchantCapabilities: [ IosPKMerchantCapability.PKMerchantCapability3DS, IosPKMerchantCapability.PKMerchantCapabilityDebit, ], }; ``` ## Pitfalls - **`PKMerchantCapabilityInstantFundsOut` is rejected by this package's native iOS bridge.** `merch