@flopay/react 1.3.2 → 1.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -187,6 +187,17 @@ the entire integration change — no SDK redeploy or consumer code update is
187
187
  required. Wallets only render on supported devices regardless of dashboard
188
188
  state (Apple Pay on Safari/macOS/iOS, Google Pay on Chrome).
189
189
 
190
+ In `layout="buttons"`, the **Credit / Debit Card** button always opens the
191
+ inline card form. External wallets and PayPal keep their own lifecycle:
192
+ buyer cancellation silently returns to the payment-method chooser with all
193
+ eligible options available, while post-click technical failures, popup
194
+ blocking, or a provider surface returning focus without a terminal callback
195
+ restore the chooser, focus a visible retry control for the failed method, show safe method-specific copy such as
196
+ `We couldn't open Google Pay. Try again or choose another payment method.`, and
197
+ call `onError` with a structured `FloPayError`. Passive pre-click load or
198
+ eligibility failures still collapse only the unavailable method and do not show
199
+ a checkout error.
200
+
190
201
  Toggle the whole Stripe region or the PayPal region independently with the
191
202
  two gateway-level props:
192
203
 
@@ -329,6 +340,33 @@ Skip the backend API route — create the session directly in the component:
329
340
 
330
341
  The component POSTs to the billing API, gets the full session back, and renders the form — zero backend code needed.
331
342
 
343
+ That create POST sends a stable `Idempotency-Key` header automatically whenever a
344
+ secure RNG is available, so a timeout or lost response never mints a second
345
+ session. `FloPayCheckout` already coalesces concurrent mounts (StrictMode
346
+ double-mount, Suspense remount, navigation flicker) into a single create, and
347
+ rerenders during an in-flight create do **not** replace the key. You normally
348
+ don't need to think about it.
349
+
350
+ To control the key yourself — for example to keep it stable across your own
351
+ server retries — pass `idempotencyKey` on `createSession`:
352
+
353
+ ```tsx
354
+ <FloPayCheckout
355
+ createSession={{
356
+ /* … */
357
+ idempotencyKey: `checkout:${orderId}`, // one logical checkout; never reuse for a new purchase
358
+ }}
359
+ />
360
+ ```
361
+
362
+ The key must be non-empty and at most 255 characters; an invalid value throws a
363
+ `FloPayError('validation_error')` before any request. Omit it and the SDK
364
+ generates a fresh cryptographically random key per logical create when a secure
365
+ RNG is available; without one it omits the header, and a merchant-supplied
366
+ `idempotencyKey` stays the way to remain idempotent. See the
367
+ [`@flopay/js` idempotency docs](../js/README.md#idempotent-checkout-creation)
368
+ for the full contract.
369
+
332
370
  Session-level `currency` is now **required**. The backend (#760) enforces `@IsNotEmpty` on the field; the SDK pre-validates and throws `FloPayError({ type: 'validation_error', code: 'CurrencyRequired' })` before issuing the request when neither the session nor any item/subscription/product carries a currency. Pass `currency` at the top of `createSession` (preferred), or rely on the legacy fallback to the first item/subscription/product `currency`.
333
371
 
334
372
  When you use `onBeforeButtonClick` with `createSession`, any returned `InlineSessionPatch` is merged into the draft session params before the selected buttons-layout flow continues. That lets you add tracking data or update account fields just in time without pre-creating a separate backend session.