Skip to content

paymentIntent.paymentMethod is always null after collectPaymentMethod() for Affirm payments #1107

@mtch99

Description

@mtch99

Describe the bug
After collectPaymentMethod() resolves, paymentIntent.paymentMethod is null — even though the customer has already selected a payment method (e.g. Affirm) on the reader. This prevents the terminal application from knowing which payment method was collected.

We tested at every stage of the flow:

Step paymentIntent.paymentMethod
After createPaymentIntent null
After collectPaymentMethod null
After confirmPaymentIntent null

The field is never populated by the SDK for Affirm payments. We have also observed it occasionally missing for card payments.

Per Stripe's own documentation, paymentIntent.paymentMethod should be accessible after collectPaymentMethod() resolves:

You can examine the payment method details of the presented card and perform your own business logic prior to authorization.

const pm = result.paymentIntent.payment_method;
const card = pm?.card_present ?? pm?.interac_present;

The docs note that paymentMethod is absent when "the SDK is operating offline" — but our reader is online, and the field is still null for Affirm payments.

To Reproduce

  1. Create a payment intent with payment_method_types: ["card_present", "affirm"]
  2. Call collectPaymentMethod() — the reader displays payment options
  3. Customer selects "Pay with Affirm" on the reader and the Affirm QR code is displayed
  4. Customer presses "X" (cancel) on the reader, or the SDK otherwise returns control to the app
  5. Inspect paymentIntent.paymentMethod — it is null

Time (in UTC) when the bug was most recently observed: 2026-03-13

Expected behaviour
After collectPaymentMethod() resolves (whether successfully or via cancellation), paymentIntent.paymentMethod should be populated with the payment method the customer selected on the reader — including for Affirm and other non-card payment methods.

This is important for applications that need to branch their UI based on the collected payment method (e.g. showing an "Affirm payment pending" screen instead of a generic failure screen when the reader is dismissed).

Stripe Terminal React Native SDK version
0.0.1-beta.29

Point of sale device
not on a POS

Reader device

  • Reader type: S700 devkit
  • Serial number: N/A (reproducible across all units)

Additional context
In stripe dashboard, we noticed that the POST request logs on paymentIntent route returned the complete payment method, whereas, this was not the case in the react native sdk.
Workaround: We currently work around this by fetching the payment intent directly from the Stripe REST API with expand[]=payment_method after the SDK returns control:

// After collectPaymentMethod resolves with cancellation:
const url = `https://api.stripe.com/v1/payment_intents/${paymentIntent.id}?client_secret=${paymentIntent.clientSecret}&expand[]=payment_method`;
const response = await fetch(url, {
  headers: { Authorization: `Bearer ${publishableKey}` },
});
const fetched = await response.json();
const paymentMethodType = fetched.payment_method?.type; // "affirm" ✅

This confirms the payment method is recorded server-side — the SDK simply doesn't surface it in the returned paymentIntent object.

Impact: Without the payment method, we cannot detect that the customer initiated an Affirm checkout, and free up the terminal when Affirm payments continue processing on the customer's phone after the reader is dismissed.

Additional note: App code does not run between SDK steps. Once collectPaymentMethod is called, the SDK controls the reader UI and the JS thread is blocked awaiting the promise. There is no intermediate callback or event to detect the payment method selection while the terminal UI is active — detection can only happen after the SDK returns control.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions