@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
Plain Text
# @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
[](https://badge.fury.io/js/%40rnw-community%2Freact-native-payments)
[](https://app.codecov.io/gh/rnw-community/rnw-community)
[](https://www.npmjs.com/package/%40rnw-community%2Freact-native-payments)
[](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