Skip to content

Add StripeClient per-instance publishable key to EmbeddedPaymentElement 🪿✨#13303

Draft
tjclawson-stripe wants to merge 2 commits into
masterfrom
tjclawson/stripeclient-publishablekey-embeddedpaymentelement-configure
Draft

Add StripeClient per-instance publishable key to EmbeddedPaymentElement 🪿✨#13303
tjclawson-stripe wants to merge 2 commits into
masterfrom
tjclawson/stripeclient-publishablekey-embeddedpaymentelement-configure

Conversation

@tjclawson-stripe

Copy link
Copy Markdown
Collaborator

Minion run

Summary

Adds an optional stripeClient: StripeClient? parameter to both EmbeddedPaymentElement.configure() overloads, allowing each instance to supply its own publishable key instead of always reading from the global PaymentConfiguration singleton. When stripeClient is null, behavior is unchanged.

New classes introduced:

  • StripeClient — a @Parcelize @Poko value type holding a publishableKey and optional stripeAccountId, validated on construction.
  • StripeClientHolder — a @Singleton Dagger-injected holder whose stripeClient field is written by configure() and read by the key-providing lambdas on every network request.
  • StripeClientModule — a @Module that replaces PaymentConfigurationModule in the Embedded Dagger component only, sourcing PaymentConfiguration, @Named(PUBLISHABLE_KEY), and @Named(STRIPE_ACCOUNT_ID) from the holder with a PaymentConfiguration.getInstance() fallback. PaymentConfigurationModule is left intact for PaymentSheet, CustomerSheet, and all other integrations.

A TODO comment was added in EmbeddedConfigurationHandler noting that the Arguments cache key does not yet incorporate stripeClient, so calling configure() twice with the same intent/configuration but a different stripeClient will return the cached result from the first call.

Motivation

EmbeddedPaymentElement currently reads its publishable key from the global PaymentConfiguration singleton, which prevents apps from using different keys for different EmbeddedPaymentElement instances (e.g. multi-merchant or connect scenarios). This change makes the key a per-configure() call concern while preserving full backwards compatibility for callers that don't pass a StripeClient.

Because the Dagger component is constructed before configure() is ever called, @BindsInstance is not a viable approach. The StripeClientHolder singleton pattern allows the @Named(PUBLISHABLE_KEY) lambda — which StripeApiRepository captures as () -> String rather than String — to read the current value fresh on every request.

Testing

  • Added tests
  • Modified tests
  • Manually verified

StripeClientTest covers:

  • A valid pk_test_ key is accepted
  • A key starting with sk_ throws IllegalArgumentException
  • A blank key throws
  • stripeAccountId is null by default
  • stripeAccountId is set correctly when provided

Screenshots

N/A — no UI changes.

Changelog

[Added] StripeClient — pass an optional stripeClient to EmbeddedPaymentElement.configure() to supply a per-instance publishable key instead of relying on the global PaymentConfiguration singleton.

…nt.configure()

- Add StripeClient class (publishableKey + optional stripeAccountId, Parcelable)
- Add StripeClientHolder @singleton to carry per-configure() StripeClient
- Add StripeClientModule replacing PaymentConfigurationModule in
  EmbeddedCommonModule; falls back to PaymentConfiguration singleton when
  no StripeClient is set
- Add optional stripeClient param to both EmbeddedPaymentElement.configure()
  overloads; writes to holder before delegating to coordinator
- Add TODO comment in EmbeddedConfigurationHandler noting that the cache key
  does not yet incorporate stripeClient
- Add StripeClientTest covering key validation and field defaults

Committed-By-Agent: goose
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant