> ## Documentation Index
> Fetch the complete documentation index at: https://funnelfox.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Stripe methods

> Take card and Apple Pay or Google Pay payments through Stripe directly with the Billing.stripe methods

The `Billing.stripe` methods process payments through Stripe directly. They
render a card form with the Stripe Payment Element and open Apple Pay or
Google Pay through the browser's payment sheet.

These methods don't use Primer. Your FunnelFox Payments organization must be
set up to process payments with Stripe directly. Ask your Solution Manager if
you're not sure which setup your organization uses.

| Method | What it does |
| - | - |
| `Billing.stripe.createCardForm()` | Renders a card form and returns a `submit()` handle. |
| `Billing.stripe.getAvailableWallet()` | Checks whether Apple Pay or Google Pay is available and prepares the payment sheet. |
| `Billing.stripe.purchaseWallet()` | Opens the Apple Pay or Google Pay payment sheet. |
| `Billing.stripe.getAvailablePaymentMethods()` | Lists the card and any available wallet. |

## Common options

Every `Billing.stripe` method takes these options.

**priceId** `string` *required*

The price point identifier.

**externalId** `string` *required*

Your identifier for the customer.

**email** `string`

The customer's email address.

**orgId** `string`

Your organization ID, if you didn't set it with
[configure()](/docs/develop/configure.md).

**countryCode** `string`

ISO country code of the customer.

**clientMetadata** `object`

Custom metadata attached to the order.

**apiConfig** `object`

Per-call API settings: `baseUrl` and `region`. These override the values from
`configure()`.

> [!NOTE]
>
> Calls with the same `priceId`, `externalId`, `email`, and `countryCode` share
> one order. Pass the same values to every call for one purchase. After a
> successful payment, the next call creates a new order.

## Create card form

`Billing.stripe.createCardForm(element, options)` renders a card form into
`element` and returns a `Promise<{ submit(): Promise<void> }>`.

**appearance** `object`

Stripe Elements appearance options, such as `{ theme: 'stripe' }`.

**showWallets** `boolean` (default: false)

Show Apple Pay and Google Pay inside the card form when the browser supports
them.

**onRenderSuccess** `() =\> void`

Called when the form is ready.

**onLoaderChange** `(isLoading: boolean) =\> void`

Called with `true` while `submit()` runs and `false` when it ends.

**onPaymentSuccess** `(paymentMethod, orderId: string) =\> void`

Called when the payment completes. Receives the Stripe payment method and the
order ID.

**onPaymentFail** `(error: PaymentFailure) =\> void`

Called when the payment fails. Learn more about
[decline codes](/docs/develop/error-handling.md#decline-codes).

**onTaxChange** `(info: TaxInfo) =\> void`

Called with the total and tax. Learn more about
[taxes in the Web SDK](/docs/develop/web-sdk-taxes.md).

**onTaxError** `(error: Error) =\> void`

Called when a tax recalculation fails.

How the card form behaves:

* **No pay button**: Add your own button and call `submit()` when the buyer
  clicks it.
* **Validation**: `submit()` validates the fields first. Stripe shows the
  errors in the form.
* **3DS**: The SDK runs the 3DS challenge when the bank asks for one.
* **Failure**: `submit()` calls `onPaymentFail` and also rejects, so wrap it
  in `try`/`catch`.
* **Address fields**: The form shows only a country and a postal code field,
  and only when your organization collects them in
  [Checkout page fields](/docs/billing/settings.md#checkout-page-fields). The country
  defaults to the one detected from the buyer's IP.
* **Stripe Link**: The form offers Link when `stripe_link_enabled` is on in
  [Settings](/docs/billing/settings.md#dashboard-and-organization).
* **Mount again**: Calling `createCardForm()` on the same element replaces
  the existing form.

If the form fails to load, the returned promise rejects.

```javascript theme={null}
import { Billing } from '@funnelfox/billing';

const cardForm = await Billing.stripe.createCardForm(
  document.getElementById('card-form'),
  {
    orgId: 'your-org-id',
    priceId: 'price_123',
    externalId: 'user_456',
    email: 'user@example.com',
    appearance: { theme: 'stripe' },
    onRenderSuccess: () => {
      document.getElementById('pay-button').disabled = false;
    },
    onLoaderChange: isLoading => {
      document.getElementById('pay-button').disabled = isLoading;
    },
    onPaymentSuccess: (paymentMethod, orderId) => {
      window.location.href = '/success?order=' + orderId;
    },
  }
);

document.getElementById('pay-button').addEventListener('click', async () => {
  try {
    await cardForm.submit();
  } catch (error) {
    document.getElementById('payment-error').textContent = error.message;
  }
});
```

## Check wallet availability

`Billing.stripe.getAvailableWallet(options)` returns
`Promise<'APPLE_PAY' | 'GOOGLE_PAY' | null>`. It returns `'APPLE_PAY'` when
both wallets are available, and `null` when neither is.

It also prepares the payment sheet so `purchaseWallet()` can open it
immediately. Call it while the page renders, before the buyer clicks, and use
it to decide whether to show your wallet button.

> [!WARNING]
>
> Safari cancels an Apple Pay sheet that opens after long async work in the
> click handler. Call `getAvailableWallet()` before the click with the same
> options you pass to `purchaseWallet()`.

## Purchase with wallet

`Billing.stripe.purchaseWallet(options)` opens the Apple Pay or Google Pay
payment sheet. Call it inside your wallet button's click handler.

**totalLabel** `string` (default: Total)

The label next to the amount in the payment sheet.

**onPaymentSuccess** `(paymentMethod, orderId: string) =\> void`

Called when the payment completes.

**onPaymentFail** `(error: PaymentFailure) =\> void`

Called when the payment fails.

**onPaymentCancel** `() =\> void`

Called when the buyer closes the payment sheet without paying.

**onLoaderChange** `(isLoading: boolean) =\> void`

Called with `true` while the payment processes and `false` when it ends.

**onTaxChange** `(info: TaxInfo) =\> void`

Called with the total and tax shown in the payment sheet.

The returned promise resolves when the payment succeeds or the buyer cancels.
It rejects when the payment fails or no wallet is available.

The payment sheet shows **Subtotal** and **Tax** lines when tax is added on
top of the price. For subscriptions, Apple Pay shows the recurring-billing
disclosure when it's on in [Apple Pay settings](/docs/billing/settings.md#apple-pay).

```javascript theme={null}
import { Billing } from '@funnelfox/billing';

const options = {
  orgId: 'your-org-id',
  priceId: 'price_123',
  externalId: 'user_456',
  email: 'user@example.com',
};

const wallet = await Billing.stripe.getAvailableWallet(options);

if (wallet) {
  const button = document.getElementById('wallet-button');
  button.textContent =
    wallet === 'APPLE_PAY' ? 'Pay with Apple Pay' : 'Pay with Google Pay';
  button.hidden = false;

  button.addEventListener('click', () => {
    Billing.stripe
      .purchaseWallet({
        ...options,
        totalLabel: 'Premium plan',
        onPaymentSuccess: (paymentMethod, orderId) => {
          window.location.href = '/success?order=' + orderId;
        },
        onPaymentCancel: () => console.log('Payment sheet closed'),
      })
      .catch(error => console.error('Wallet payment failed:', error.message));
  });
}
```

## Get available payment methods

`Billing.stripe.getAvailablePaymentMethods(options)` returns
`Promise<PaymentMethod[]>`. The list always contains `PAYMENT_CARD` and adds
`APPLE_PAY` or `GOOGLE_PAY` when one is available.

```javascript theme={null}
const methods = await Billing.stripe.getAvailablePaymentMethods({
  priceId: 'price_123',
  externalId: 'user_456',
});
// ['PAYMENT_CARD', 'APPLE_PAY'] or ['PAYMENT_CARD']
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.