Copy this into your coding assistant and add your request.
Read https://openiap.dev/docs/apis/request-purchase and https://openiap.dev/llms.txt. Follow the reading instructions, detailed reference, and linked guides relevant to my task before making changes.
Inspect my existing project and reuse its framework and conventions. Ask me for missing product decisions. Implement the requested behavior and run the applicable checks.
Show the working result, the commands and actual test results, and any remaining limitations. Keep your explanation brief.
My request: [describe what customers should be able to do]
Initiate a purchase flow. The result is delivered through purchaseUpdatedListener, not the return value.
iOS: Calls Product.purchase(options:) and emits the result on the Transaction.updates listener — the return value is just the dispatch ack. Apple docs. Android: Calls BillingClient.launchBillingFlow and emits the result on PurchasesUpdatedListener. Subscription offers require an offerToken. Google docs.
type(required, 'in-app' | 'subs') — Selects the request shape. Use 'in-app' for one-time products and 'subs' for subscriptions.
request.apple.sku(iOS only, string) — iOS. Single SKU for the iOS purchase.
request.apple.appAccountToken(optional, string) — iOS. UUID-format account token forwarded to Apple. Non-UUID values land as null on the resulting Purchase.
request.apple.quantity(optional, number) — iOS. Quantity for consumable bulk purchases.
request.apple.billingPlanType(subscriptions only, optional, 'monthly' | 'up-front') — iOS 26.4+. Selects the StoreKit subscription billing plan, such as monthly billing with a 12-month commitment. See iOS commitment billing plans.
request.google.skus(Android only, string[]) — Android. Product SKUs to launch the Play purchase flow for.
request.google.subscriptionOffers(optional, recommended for 'subs', { sku: string; offerToken: string }[]) — Android. Pair each SKU with an offerToken from fetchProducts. When omitted, Play uses the first offer returned for the SKU, which may not be the base plan you intend.
request.google.obfuscatedAccountId(optional, string) — Android. Optional account identifier passed to Play.
request.google.obfuscatedProfileId(optional, string) — Android. Optional profile identifier passed to Play.
Promise<Purchase | Purchase[] | null> — dispatched purchase payload. Do not rely on this for the actual outcome — listen via purchaseUpdatedListener / purchaseErrorListener instead.
Invalid arguments or failures that prevent dispatch can reject the promise. Store outcomes are event-based in React Native; Android not-prepared arrives through purchaseErrorListener or the hook's onPurchaseError callback.