From d3683918568c0977641babfcdcc4494358321346 Mon Sep 17 00:00:00 2001
From: hyochan
Date: Sun, 26 Apr 2026 12:03:43 +0900
Subject: [PATCH 01/26] docs: cross-link wrapper SDKs + doc pages to
openiap.dev API references
Comprehensive doc-comment + doc-page enrichment so every public OpenIAP
API surfaces a link to its canonical reference, with iOS/Android-specific
behaviour notes.
Wrapper SDKs (Apple, Google, react-native-iap, expo-iap, flutter, kmp,
godot): added KDoc/JSDoc/Dartdoc/Swiftdoc/GDdoc on every public API
function with a one-line summary and a `@see` link to
www.openiap.dev/docs/apis/. The 5 most-used cross-platform calls
(initConnection, fetchProducts, requestPurchase, finishTransaction,
getAvailablePurchases) get full @param/@returns/@throws/@example blocks.
Original rich docs (Apple StoreKit references, @platform tags, examples)
were preserved during the merge.
GraphQL schema (api.graphql, api-ios.graphql, api-android.graphql):
descriptions now include the canonical doc URL, propagated to every
generated Types file via codegen.
Docs site (packages/docs):
- API + Type pages (~70) get a one-paragraph iOS/Android behaviour
blurb with links to the corresponding Apple StoreKit / Google Play
Billing reference.
- Mobile/tablet UI fixes:
- CodeBlock language badge + Copy button rendered as a tab-bar
attached to the top of the code block (no more floating overlap
over horizontally scrolling code).
- Mobile sidebar drawer starts below the sticky top nav (top: 56px)
so taps on the drawer no longer collide with the nav's hamburger
menu; z-indexes raised to 9000/9001/8999 to remove ambiguity.
- Sidebar margin-left clamped to non-positive so the desktop
centering offset stops shoving the sidebar to the right of the
viewport in the 768-1400px tablet range.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
libraries/expo-iap/src/index.ts | 152 +++++--
libraries/expo-iap/src/modules/android.ts | 16 +
libraries/expo-iap/src/modules/ios.ts | 53 +++
libraries/expo-iap/src/types.ts | 253 +++++++----
libraries/expo-iap/src/useIAP.ts | 127 +++++-
.../lib/flutter_inapp_purchase.dart | 406 ++++++++++--------
.../flutter_inapp_purchase/lib/types.dart | 191 ++++----
.../godot-iap/addons/godot-iap/godot_iap.gd | 191 +++++++-
libraries/godot-iap/addons/godot-iap/types.gd | 188 ++++----
.../hyochan/kmpiap/InAppPurchaseAndroid.kt | 287 ++++++++++++-
.../io/github/hyochan/kmpiap/openiap/Types.kt | 191 ++++----
.../github/hyochan/kmpiap/InAppPurchaseIOS.kt | 271 ++++++++++++
.../react-native-iap/src/hooks/useIAP.ts | 147 ++++++-
libraries/react-native-iap/src/index.ts | 389 +++++++++++------
libraries/react-native-iap/src/types.ts | 253 +++++++----
packages/apple/Sources/Models/Types.swift | 191 ++++----
packages/apple/Sources/OpenIapModule.swift | 117 +++++
.../android/acknowledge-purchase-android.tsx | 13 +
...ternative-billing-availability-android.tsx | 13 +
.../apis/android/consume-purchase-android.tsx | 13 +
...eate-alternative-billing-token-android.tsx | 16 +
...ling-program-reporting-details-android.tsx | 16 +
.../enable-billing-program-android.tsx | 14 +
.../is-billing-program-available-android.tsx | 13 +
.../android/launch-external-link-android.tsx | 14 +
...how-alternative-billing-dialog-android.tsx | 17 +
.../docs/apis/deep-link-to-subscriptions.tsx | 26 ++
.../src/pages/docs/apis/end-connection.tsx | 22 +
.../src/pages/docs/apis/fetch-products.tsx | 24 ++
.../pages/docs/apis/finish-transaction.tsx | 24 ++
.../docs/apis/get-active-subscriptions.tsx | 24 ++
.../docs/apis/get-available-purchases.tsx | 24 ++
.../src/pages/docs/apis/get-storefront.tsx | 23 +
.../docs/apis/has-active-subscriptions.tsx | 23 +
.../src/pages/docs/apis/init-connection.tsx | 22 +
.../apis/ios/begin-refund-request-ios.tsx | 12 +
...n-present-external-purchase-notice-ios.tsx | 12 +
.../docs/apis/ios/clear-transaction-ios.tsx | 13 +
.../docs/apis/ios/current-entitlement-ios.tsx | 12 +
.../apis/ios/get-all-transactions-ios.tsx | 13 +
.../docs/apis/ios/get-app-transaction-ios.tsx | 12 +
...xternal-purchase-custom-link-token-ios.tsx | 13 +
.../apis/ios/get-pending-transactions-ios.tsx | 12 +
.../apis/ios/get-promoted-product-ios.tsx | 13 +
.../docs/apis/ios/get-receipt-data-ios.tsx | 13 +
.../docs/apis/ios/get-storefront-ios.tsx | 12 +
.../docs/apis/ios/get-transaction-jws-ios.tsx | 12 +
...-for-external-purchase-custom-link-ios.tsx | 12 +
.../ios/is-eligible-for-intro-offer-ios.tsx | 12 +
.../apis/ios/is-transaction-verified-ios.tsx | 13 +
.../docs/apis/ios/latest-transaction-ios.tsx | 12 +
.../ios/present-code-redemption-sheet-ios.tsx | 13 +
.../present-external-purchase-link-ios.tsx | 12 +
...ent-external-purchase-notice-sheet-ios.tsx | 12 +
...quest-purchase-on-promoted-product-ios.tsx | 13 +
...ternal-purchase-custom-link-notice-ios.tsx | 12 +
.../ios/show-manage-subscriptions-ios.tsx | 12 +
.../docs/apis/ios/subscription-status-ios.tsx | 13 +
.../docs/src/pages/docs/apis/ios/sync-ios.tsx | 13 +
.../docs/apis/ios/validate-receipt-ios.tsx | 13 +
.../src/pages/docs/apis/request-purchase.tsx | 24 ++
.../src/pages/docs/apis/restore-purchases.tsx | 23 +
.../pages/docs/types/active-subscription.tsx | 23 +
.../docs/types/alternative-billing-types.tsx | 14 +
...one-time-purchase-offer-detail-android.tsx | 12 +
.../types/android/pricing-phase-android.tsx | 13 +
.../android/subscription-offer-android.tsx | 14 +
.../src/pages/docs/types/billing-programs.tsx | 12 +
.../src/pages/docs/types/discount-offer.tsx | 21 +
.../docs/types/external-purchase-link.tsx | 13 +
.../docs/types/ios/app-transaction-ios.tsx | 12 +
.../src/pages/docs/types/ios/discount-ios.tsx | 13 +
.../docs/types/ios/discount-offer-ios.tsx | 12 +
.../pages/docs/types/ios/payment-mode-ios.tsx | 14 +
.../pages/docs/types/ios/renewal-info-ios.tsx | 13 +
.../types/ios/subscription-period-ios.tsx | 13 +
.../types/ios/subscription-status-ios.tsx | 14 +
.../src/pages/docs/types/product-request.tsx | 21 +
.../docs/src/pages/docs/types/product.tsx | 22 +
.../docs/src/pages/docs/types/purchase.tsx | 20 +
.../docs/types/request-purchase-props.tsx | 23 +
.../docs/src/pages/docs/types/storefront.tsx | 20 +
.../pages/docs/types/subscription-offer.tsx | 21 +
.../pages/docs/types/subscription-product.tsx | 22 +
.../verify-purchase-with-provider-props.tsx | 12 +
.../verify-purchase-with-provider-result.tsx | 12 +
.../src/pages/docs/types/verify-purchase.tsx | 22 +
packages/docs/src/styles/code.css | 32 +-
packages/docs/src/styles/documentation.css | 31 +-
packages/docs/src/styles/responsive.css | 12 +-
.../src/main/java/dev/hyo/openiap/Types.kt | 191 ++++----
.../dev/hyo/openiap/store/OpenIapStore.kt | 133 ++++--
packages/gql/src/api-android.graphql | 67 +--
packages/gql/src/api-ios.graphql | 82 ++--
packages/gql/src/api.graphql | 42 +-
packages/gql/src/generated/Types.kt | 191 ++++----
packages/gql/src/generated/Types.swift | 191 ++++----
packages/gql/src/generated/types.dart | 191 ++++----
packages/gql/src/generated/types.gd | 188 ++++----
packages/gql/src/generated/types.ts | 253 +++++++----
100 files changed, 4694 insertions(+), 1440 deletions(-)
diff --git a/libraries/expo-iap/src/index.ts b/libraries/expo-iap/src/index.ts
index efc040c7..d1642cb6 100644
--- a/libraries/expo-iap/src/index.ts
+++ b/libraries/expo-iap/src/index.ts
@@ -331,18 +331,57 @@ export const subscriptionBillingIssueListener = (
);
};
+/**
+ * Initialize the store connection. Must be called before any other IAP API.
+ *
+ * @param config Optional connection config. Use `enableBillingProgramAndroid` (Android,
+ * Play Billing 8.2.0+) to opt into External Payments etc. iOS ignores Android-specific fields.
+ * @returns Promise resolving to `true` when the platform billing client is connected.
+ * @throws When the platform billing client fails to initialize.
+ *
+ * @example
+ * ```ts
+ * await initConnection();
+ * await initConnection({ enableBillingProgramAndroid: 'external-offer' });
+ * ```
+ *
+ * @remarks When using `useIAP()`, connection is auto-managed on mount/unmount —
+ * pass options to the hook instead of calling this directly.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/init-connection}
+ */
export const initConnection: MutationField<'initConnection'> = async (config) =>
ExpoIapModule.initConnection(config ?? null);
+/**
+ * Close the store connection and release resources.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/end-connection}
+ */
export const endConnection: MutationField<'endConnection'> = async () =>
ExpoIapModule.endConnection();
/**
- * Fetch products with unified API (v2.7.0+)
+ * Retrieve products or subscriptions from the store by SKU.
+ *
+ * @param params `ProductRequest` — `skus` (string[]) and optional `type`
+ * (`'in-app' | 'subs' | 'all'`, defaults to `'in-app'`).
+ * @returns Promise resolving to a `FetchProductsResult` union — `Product[]` for `'in-app'`,
+ * `ProductSubscription[]` for `'subs'`, or a mixed array for `'all'`.
+ * @throws When the store rejects the request (unknown SKU, network, not connected).
+ *
+ * @example
+ * ```ts
+ * const products = await fetchProducts({
+ * skus: ['com.app.coins_100', 'com.app.premium'],
+ * type: 'in-app',
+ * });
+ * ```
*
- * @param request - Product fetch configuration
- * @param request.skus - Array of product SKUs to fetch
- * @param request.type - Product query type: 'in-app', 'subs', or 'all'
+ * @remarks This is a regular promise-based call. Don't confuse with `request*` APIs
+ * (`requestPurchase`), which are event-based.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/fetch-products}
*/
export const fetchProducts: QueryField<'fetchProducts'> = async (request) => {
ExpoIapConsole.debug('fetchProducts called with:', request);
@@ -413,6 +452,25 @@ export const fetchProducts: QueryField<'fetchProducts'> = async (request) => {
throw new Error('Unsupported platform');
};
+/**
+ * List the user's unfinished purchases — non-consumables, active subscriptions, and any
+ * pending transactions not yet finished.
+ *
+ * @param options Optional `PurchaseOptions`. iOS-only flags:
+ * `alsoPublishToEventListenerIOS`, `onlyIncludeActiveItemsIOS`.
+ * @returns Promise resolving to an array of `Purchase` currently held by the store.
+ * @throws When the platform query fails.
+ *
+ * @example
+ * ```ts
+ * const purchases = await getAvailablePurchases();
+ * for (const p of purchases) {
+ * if (await verifyOnServer(p)) await finishTransaction({ purchase: p, isConsumable: false });
+ * }
+ * ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/get-available-purchases}
+ */
export const getAvailablePurchases: QueryField<
'getAvailablePurchases'
> = async (options) => {
@@ -467,6 +525,8 @@ export const getAvailablePurchases: QueryField<
* }
* });
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/get-active-subscriptions}
*/
export const getActiveSubscriptions: QueryField<
'getActiveSubscriptions'
@@ -491,6 +551,8 @@ export const getActiveSubscriptions: QueryField<
* // Check specific subscriptions
* const hasPremium = await hasActiveSubscriptions(['premium', 'premium_year']);
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/has-active-subscriptions}
*/
export const hasActiveSubscriptions: QueryField<
'hasActiveSubscriptions'
@@ -500,6 +562,11 @@ export const hasActiveSubscriptions: QueryField<
));
};
+/**
+ * Return the user's storefront country code.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/get-storefront}
+ */
export const getStorefront: QueryField<'getStorefront'> = async () => {
if (Platform.OS !== 'ios' && Platform.OS !== 'android') {
return '';
@@ -541,44 +608,30 @@ function normalizeRequestProps(
}
/**
- * Request a purchase for products or subscriptions.
+ * Initiate a purchase or subscription flow. The result is delivered through
+ * `purchaseUpdatedListener` — NOT the return value.
*
- * @param requestObj - Purchase request configuration
- * @param requestObj.request - Store-specific purchase parameters
- * @param requestObj.type - Type of purchase: 'in-app' for products (default) or 'subs' for subscriptions
+ * @param props `RequestPurchaseProps`, discriminated by `type`:
+ * - `type: 'in-app'` — pass `request.apple.sku` (iOS) and/or `request.google.skus` (Android).
+ * - `type: 'subs'` — same shape, plus `request.google.subscriptionOffers: [{ sku, offerToken }]`.
+ * @returns The dispatched purchase payload. **Do not rely on it** for the actual outcome.
+ * @throws Synchronous rejection from the store (e.g. `E_NOT_PREPARED`, validation failure).
*
* @example
- * ```typescript
- * // Product purchase (recommended: use apple/google)
+ * ```ts
* await requestPurchase({
* request: {
- * apple: { sku: productId },
- * google: { skus: [productId] }
+ * apple: { sku: 'com.app.premium' },
+ * google: { skus: ['com.app.premium'] },
* },
- * type: 'in-app'
+ * type: 'in-app',
* });
+ * ```
*
- * // Subscription purchase
- * await requestPurchase({
- * request: {
- * apple: { sku: subscriptionId },
- * google: {
- * skus: [subscriptionId],
- * subscriptionOffers: [{ sku: subscriptionId, offerToken: 'token' }]
- * }
- * },
- * type: 'subs'
- * });
+ * @remarks Event-based. Listen for the result via {@link purchaseUpdatedListener} /
+ * {@link purchaseErrorListener}, or use `useIAP({ onPurchaseSuccess, onPurchaseError })`.
*
- * // Legacy format (deprecated, but still supported)
- * await requestPurchase({
- * request: {
- * ios: { sku: productId },
- * android: { skus: [productId] }
- * },
- * type: 'in-app'
- * });
- * ```
+ * @see {@link https://www.openiap.dev/docs/apis/request-purchase}
*/
export const requestPurchase: MutationField<'requestPurchase'> = async (
args,
@@ -739,6 +792,29 @@ export const requestPurchase: MutationField<'requestPurchase'> = async (
throw new Error('Platform not supported');
};
+/**
+ * Complete a purchase transaction. Call after server-side verification to remove it
+ * from the queue.
+ *
+ * @param args.purchase The `Purchase` to finalize.
+ * @param args.isConsumable `true` for consumables (consumes the token so the SKU can be
+ * re-bought, e.g. coins); `false` (default) for non-consumables and subscriptions.
+ * @returns Promise that resolves once the platform finalizes the transaction.
+ * @throws When the platform finalize call fails.
+ *
+ * @example
+ * ```ts
+ * // Inside purchaseUpdatedListener:
+ * if (await verifyOnServer(purchase)) {
+ * await finishTransaction({ purchase, isConsumable: false });
+ * }
+ * ```
+ *
+ * @remarks **Critical:** Android purchases must be finalized within 3 days or Google
+ * auto-refunds. iOS unfinished transactions replay on every app launch.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/finish-transaction}
+ */
export const finishTransaction: MutationField<'finishTransaction'> = async ({
purchase,
isConsumable = false,
@@ -781,6 +857,8 @@ export const finishTransaction: MutationField<'finishTransaction'> = async ({
*
* This helper triggers the refresh flows but does not return the purchases; consumers should
* call `getAvailablePurchases` or rely on hook state to inspect the latest items.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/restore-purchases}
*/
export const restorePurchases: MutationField<'restorePurchases'> = async () => {
if (Platform.OS === 'ios') {
@@ -810,6 +888,8 @@ export const restorePurchases: MutationField<'restorePurchases'> = async () => {
* skuAndroid: 'your_subscription_sku',
* packageNameAndroid: 'com.example.app'
* });
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/deep-link-to-subscriptions}
*/
export const deepLinkToSubscriptions: MutationField<
'deepLinkToSubscriptions'
@@ -836,6 +916,8 @@ export const deepLinkToSubscriptions: MutationField<
* - Android: Use Google Play Developer API with service account credentials
*
* @deprecated Use verifyPurchase instead
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/validate-receipt}
*/
export const validateReceipt: MutationField<'validateReceipt'> = async (
options,
@@ -881,6 +963,8 @@ export const validateReceipt: MutationField<'validateReceipt'> = async (
*
* @param options - Receipt validation options containing the SKU
* @returns Promise resolving to receipt validation result
+ *
+ * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase}
*/
export const verifyPurchase: MutationField<'verifyPurchase'> = async (
options,
@@ -916,6 +1000,8 @@ export const verifyPurchase: MutationField<'verifyPurchase'> = async (
* }
* });
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider}
*/
export const verifyPurchaseWithProvider: MutationField<
'verifyPurchaseWithProvider'
diff --git a/libraries/expo-iap/src/modules/android.ts b/libraries/expo-iap/src/modules/android.ts
index 2b2035b5..2bcda814 100644
--- a/libraries/expo-iap/src/modules/android.ts
+++ b/libraries/expo-iap/src/modules/android.ts
@@ -131,6 +131,8 @@ export const validateReceiptAndroid = async ({
* Consume a purchase token so the user can purchase the same product again
* (Android consumable products). Prefer using `finishTransaction` with
* `isConsumable: true`, which dispatches to this under the hood.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/consume-purchase-android}
*/
export const consumePurchaseAndroid: MutationField<
'consumePurchaseAndroid'
@@ -163,6 +165,8 @@ export const consumePurchaseAndroid: MutationField<
* @param {Object} params - The parameters object
* @param {string} params.token - The product's token (on Android)
* @returns {Promise}
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android}
*/
export const acknowledgePurchaseAndroid: MutationField<
'acknowledgePurchaseAndroid'
@@ -213,6 +217,8 @@ export const openRedeemOfferCodeAndroid = async (): Promise => {
* // Proceed with alternative billing flow
* }
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android}
*/
export const checkAlternativeBillingAvailabilityAndroid: MutationField<
'checkAlternativeBillingAvailabilityAndroid'
@@ -243,6 +249,8 @@ export const checkAlternativeBillingAvailabilityAndroid: MutationField<
* }
* }
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android}
*/
export const showAlternativeBillingDialogAndroid: MutationField<
'showAlternativeBillingDialogAndroid'
@@ -273,6 +281,8 @@ export const showAlternativeBillingDialogAndroid: MutationField<
* });
* }
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android}
*/
export const createAlternativeBillingTokenAndroid: MutationField<
'createAlternativeBillingTokenAndroid'
@@ -298,6 +308,8 @@ export const createAlternativeBillingTokenAndroid: MutationField<
* // Proceed with billing program flow
* }
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/is-billing-program-available-android}
*/
export const isBillingProgramAvailableAndroid: MutationField<
'isBillingProgramAvailableAndroid'
@@ -321,6 +333,8 @@ export const isBillingProgramAvailableAndroid: MutationField<
* linkUri: 'https://your-payment-site.com',
* });
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/launch-external-link-android}
*/
export const launchExternalLinkAndroid: MutationField<
'launchExternalLinkAndroid'
@@ -344,6 +358,8 @@ export const launchExternalLinkAndroid: MutationField<
* // Report details.externalTransactionToken to Google Play within 24 hours
* await reportToGooglePlay(details.externalTransactionToken);
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android}
*/
export const createBillingProgramReportingDetailsAndroid: MutationField<
'createBillingProgramReportingDetailsAndroid'
diff --git a/libraries/expo-iap/src/modules/ios.ts b/libraries/expo-iap/src/modules/ios.ts
index 1e8ea80e..e610a563 100644
--- a/libraries/expo-iap/src/modules/ios.ts
+++ b/libraries/expo-iap/src/modules/ios.ts
@@ -53,6 +53,8 @@ export function isProductIOS(
* @throws Error if called on non-iOS platform
*
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/sync-ios}
*/
export const syncIOS: MutationField<'syncIOS'> = async () => {
return !!(await ExpoIapModule.syncIOS());
@@ -66,6 +68,8 @@ export const syncIOS: MutationField<'syncIOS'> = async () => {
* @throws Error if called on non-iOS platform
*
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios}
*/
export const isEligibleForIntroOfferIOS: QueryField<
'isEligibleForIntroOfferIOS'
@@ -84,6 +88,8 @@ export const isEligibleForIntroOfferIOS: QueryField<
* @throws Error if called on non-iOS platform
*
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/subscription-status-ios}
*/
export const subscriptionStatusIOS: QueryField<
'subscriptionStatusIOS'
@@ -103,6 +109,8 @@ export const subscriptionStatusIOS: QueryField<
* @throws Error if called on non-iOS platform
*
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/current-entitlement-ios}
*/
export const currentEntitlementIOS: QueryField<
'currentEntitlementIOS'
@@ -122,6 +130,8 @@ export const currentEntitlementIOS: QueryField<
* @throws Error if called on non-iOS platform
*
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/latest-transaction-ios}
*/
export const latestTransactionIOS: QueryField<'latestTransactionIOS'> = async (
sku,
@@ -141,6 +151,8 @@ export const latestTransactionIOS: QueryField<'latestTransactionIOS'> = async (
* @throws Error if called on non-iOS platform
*
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios}
*/
export const beginRefundRequestIOS: MutationField<
'beginRefundRequestIOS'
@@ -160,6 +172,8 @@ export const beginRefundRequestIOS: MutationField<
* @throws Error if called on non-iOS platform
*
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios}
*/
export const showManageSubscriptionsIOS: MutationField<
'showManageSubscriptionsIOS'
@@ -177,6 +191,8 @@ export const showManageSubscriptionsIOS: MutationField<
* Apple's verifyReceipt endpoint, not directly from the app.
*
* @returns {Promise} Base64 encoded receipt data
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios}
*/
export const getReceiptDataIOS: QueryField<'getReceiptDataIOS'> = async () => {
return ExpoIapModule.getReceiptDataIOS();
@@ -195,6 +211,8 @@ export const getReceiptIOS = getReceiptDataIOS;
* @returns {Promise} ISO 3166-1 alpha-2 country code (e.g. "US")
*
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-storefront-ios}
*/
export const getStorefrontIOS: QueryField<'getStorefrontIOS'> = async () => {
return ExpoIapModule.getStorefront();
@@ -224,6 +242,8 @@ export const requestReceiptRefreshIOS = async (): Promise => {
* @throws Error if called on non-iOS platform
*
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios}
*/
export const isTransactionVerifiedIOS: QueryField<
'isTransactionVerifiedIOS'
@@ -243,6 +263,8 @@ export const isTransactionVerifiedIOS: QueryField<
* @throws Error if called on non-iOS platform
*
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios}
*/
export const getTransactionJwsIOS: QueryField<'getTransactionJwsIOS'> = async (
sku,
@@ -269,6 +291,8 @@ export const getTransactionJwsIOS: QueryField<'getTransactionJwsIOS'> = async (
* jwsRepresentation: string;
* latestTransaction?: Purchase;
* }>}
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/validate-receipt-ios}
*/
const validateReceiptIOSImpl = async (props: VerifyPurchaseProps | string) => {
const sku =
@@ -298,6 +322,8 @@ export const validateReceiptIOS =
* @throws Error if called on non-iOS platform or tvOS
*
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios}
*/
export const presentCodeRedemptionSheetIOS: MutationField<
'presentCodeRedemptionSheetIOS'
@@ -318,6 +344,8 @@ export const presentCodeRedemptionSheetIOS: MutationField<
*
* @platform iOS
* @since iOS 16.0
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios}
*/
export const getAppTransactionIOS: QueryField<
'getAppTransactionIOS'
@@ -334,6 +362,8 @@ export const getAppTransactionIOS: QueryField<
* @throws Error if called on non-iOS platform
*
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios}
*/
export const getPromotedProductIOS: QueryField<
'getPromotedProductIOS'
@@ -353,6 +383,8 @@ export const getPromotedProductIOS: QueryField<
* @throws Error if called on non-iOS platform or no promoted product is available
*
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios}
*/
export const requestPurchaseOnPromotedProductIOS =
async (): Promise => {
@@ -365,6 +397,8 @@ export const requestPurchaseOnPromotedProductIOS =
*
* @returns Promise resolving to array of pending transactions
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios}
*/
export const getPendingTransactionsIOS: QueryField<
'getPendingTransactionsIOS'
@@ -373,6 +407,11 @@ export const getPendingTransactionsIOS: QueryField<
return (transactions ?? []) as PurchaseIOS[];
};
+/**
+ * List every StoreKit transaction (finished + unfinished) for the current user.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios}
+ */
export const getAllTransactionsIOS: QueryField<
'getAllTransactionsIOS'
> = async () => {
@@ -385,6 +424,8 @@ export const getAllTransactionsIOS: QueryField<
*
* @returns Promise resolving when transaction is cleared
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/clear-transaction-ios}
*/
export const clearTransactionIOS: MutationField<
'clearTransactionIOS'
@@ -406,6 +447,8 @@ export const deepLinkToSubscriptionsIOS = (): Promise =>
*
* @returns Promise resolving to true if the notice sheet can be presented
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios}
*/
export const canPresentExternalPurchaseNoticeIOS: QueryField<
'canPresentExternalPurchaseNoticeIOS'
@@ -420,6 +463,8 @@ export const canPresentExternalPurchaseNoticeIOS: QueryField<
*
* @returns Promise resolving to the result with action, token, and error if any
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios}
*/
export const presentExternalPurchaseNoticeSheetIOS =
async (): Promise => {
@@ -433,6 +478,8 @@ export const presentExternalPurchaseNoticeSheetIOS =
* @param url - The external purchase URL to open
* @returns Promise resolving to the result with success status and error if any
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios}
*/
export const presentExternalPurchaseLinkIOS: MutationField<
'presentExternalPurchaseLinkIOS'
@@ -448,6 +495,8 @@ export const presentExternalPurchaseLinkIOS: MutationField<
* @returns Promise resolving to true if eligible
* @platform iOS
* @see https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/iseligible
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios}
*/
export const isEligibleForExternalPurchaseCustomLinkIOS =
async (): Promise => {
@@ -462,6 +511,8 @@ export const isEligibleForExternalPurchaseCustomLinkIOS =
* @returns Promise resolving to the token result with token string or error
* @platform iOS
* @see https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/token(for:)
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios}
*/
export const getExternalPurchaseCustomLinkTokenIOS = async (
tokenType: ExternalPurchaseCustomLinkTokenTypeIOS,
@@ -486,6 +537,8 @@ export const getExternalPurchaseCustomLinkTokenIOS = async (
* @returns Promise resolving to the result with continued status and error if any
* @platform iOS
* @see https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/shownotice(type:)
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios}
*/
export const showExternalPurchaseCustomLinkNoticeIOS = async (
noticeType: ExternalPurchaseCustomLinkNoticeTypeIOS,
diff --git a/libraries/expo-iap/src/types.ts b/libraries/expo-iap/src/types.ts
index 4afb30b7..f7d95686 100644
--- a/libraries/expo-iap/src/types.ts
+++ b/libraries/expo-iap/src/types.ts
@@ -585,118 +585,170 @@ export interface LimitedQuantityInfoAndroid {
}
export interface Mutation {
- /** Acknowledge a non-consumable purchase or subscription */
+ /**
+ * Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
+ * See: https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android
+ */
acknowledgePurchaseAndroid: Promise;
- /** Initiate a refund request for a product (iOS 15+) */
+ /**
+ * Present the refund request sheet (iOS 15+). See also Features → Refund.
+ * See: https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios
+ */
beginRefundRequestIOS?: Promise<(string | null)>;
/**
- * Check if alternative billing is available for this user/device
- * Step 1 of alternative billing flow
+ * Check whether alternative billing is available for the user. Step 1 of the alternative billing flow.
*
- * Returns true if available, false otherwise
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns true if available, false otherwise.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android
*/
checkAlternativeBillingAvailabilityAndroid: Promise;
- /** Clear pending transactions from the StoreKit payment queue */
+ /**
+ * Clear pending transactions in the queue (sandbox helper).
+ * See: https://www.openiap.dev/docs/apis/ios/clear-transaction-ios
+ */
clearTransactionIOS: Promise;
- /** Consume a purchase token so it can be repurchased */
+ /**
+ * Consume a consumable purchase so it can be re-bought.
+ * See: https://www.openiap.dev/docs/apis/android/consume-purchase-android
+ */
consumePurchaseAndroid: Promise;
/**
- * Create external transaction token for Google Play reporting
- * Step 3 of alternative billing flow
- * Must be called AFTER successful payment in your payment system
- * Token must be reported to Google Play backend within 24 hours
+ * Create a reporting token for an alternative billing flow. Step 3 of the alternative billing flow.
+ * Must be called AFTER successful payment in your payment system.
+ * Token must be reported to Google Play backend within 24 hours.
*
- * Returns token string, or null if creation failed
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns token string, or null if creation failed.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android
*/
createAlternativeBillingTokenAndroid?: Promise<(string | null)>;
/**
- * Create reporting details for a billing program
- * Replaces the deprecated createExternalOfferReportingDetailsAsync API
+ * Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+).
+ * Replaces the deprecated createExternalOfferReportingDetailsAsync API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Returns external transaction token needed for reporting external transactions
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns external transaction token needed for reporting external transactions.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android
*/
createBillingProgramReportingDetailsAndroid: Promise;
- /** Open the native subscription management surface */
+ /**
+ * Open the platform's subscription management UI.
+ * See: https://www.openiap.dev/docs/apis/deep-link-to-subscriptions
+ */
deepLinkToSubscriptions: Promise;
- /** Close the platform billing connection */
+ /**
+ * Close the store connection and release resources.
+ * See: https://www.openiap.dev/docs/apis/end-connection
+ */
endConnection: Promise;
- /** Finish a transaction after validating receipts */
+ /**
+ * Complete a transaction after server-side verification. Required on Android within 3 days.
+ * See: https://www.openiap.dev/docs/apis/finish-transaction
+ */
finishTransaction: Promise;
- /** Establish the platform billing connection */
+ /**
+ * Initialize the store connection. Call before any IAP API.
+ * See: https://www.openiap.dev/docs/apis/init-connection
+ */
initConnection: Promise;
/**
- * Check if a billing program is available for the current user
- * Replaces the deprecated isExternalOfferAvailableAsync API
+ * Check whether a billing program (e.g., External Payments) is available for the current user.
+ * Replaces the deprecated isExternalOfferAvailableAsync API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Returns availability result with isAvailable flag
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Available in Google Play Billing Library 8.2.0+.
+ * Returns availability result with isAvailable flag.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/is-billing-program-available-android
*/
isBillingProgramAvailableAndroid: Promise;
/**
- * Launch external link flow for external billing programs
- * Replaces the deprecated showExternalOfferInformationDialog API
+ * Launch an external content/offer link from inside the Billing Programs flow (Play Billing 8.2.0+).
+ * Replaces the deprecated showExternalOfferInformationDialog API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Shows Play Store dialog and optionally launches external URL
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Shows Play Store dialog and optionally launches external URL.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/launch-external-link-android
*/
launchExternalLinkAndroid: Promise;
- /** Present the App Store code redemption sheet */
+ /**
+ * Show the App Store offer code redemption sheet.
+ * See: https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios
+ */
presentCodeRedemptionSheetIOS: Promise;
- /** Present external purchase custom link with StoreKit UI */
+ /**
+ * Present an external purchase link, StoreKit External (iOS 16+).
+ * See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios
+ */
presentExternalPurchaseLinkIOS: Promise;
/**
- * Present external purchase notice sheet (iOS 17.4+).
- * Uses ExternalPurchase.presentNoticeSheet() which returns a token when user continues.
+ * Present the external purchase notice sheet (iOS 17.4+).
+ * Uses ExternalPurchase.presentNoticeSheet() which returns a token when the user continues.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchase/presentnoticesheet()
+ * See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios
*/
presentExternalPurchaseNoticeSheetIOS: Promise;
- /** Initiate a purchase flow; rely on events for final state */
+ /**
+ * Initiate a purchase or subscription flow; rely on events for final state.
+ * See: https://www.openiap.dev/docs/apis/request-purchase
+ */
requestPurchase?: Promise<(Purchase | Purchase[] | null)>;
/**
- * Purchase the promoted product surfaced by the App Store.
+ * Buy the currently promoted product.
*
* @deprecated Use promotedProductListenerIOS to receive the productId,
* then call requestPurchase with that SKU instead. In StoreKit 2,
* promoted products can be purchased directly via the standard purchase flow.
+ * See: https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios
* @deprecated Use promotedProductListenerIOS + requestPurchase instead
*/
requestPurchaseOnPromotedProductIOS: Promise;
- /** Restore completed purchases across platforms */
+ /**
+ * Restore non-consumable and active subscription purchases.
+ * See: https://www.openiap.dev/docs/apis/restore-purchases
+ */
restorePurchases: Promise;
/**
- * Show alternative billing information dialog to user
- * Step 2 of alternative billing flow
- * Must be called BEFORE processing payment in your payment system
+ * Display Google's alternative billing information dialog. Step 2 of the alternative billing flow.
+ * Must be called BEFORE processing payment in your payment system.
*
- * Returns true if user accepted, false if user canceled
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns true if user accepted, false if user canceled.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android
*/
showAlternativeBillingDialogAndroid: Promise;
/**
- * Show ExternalPurchaseCustomLink notice sheet (iOS 18.1+).
- * Displays the system disclosure notice sheet for custom external purchase links.
+ * Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
* Call this after a deliberate customer interaction before linking out to external purchases.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/shownotice(type:)
+ * See: https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios
*/
showExternalPurchaseCustomLinkNoticeIOS: Promise;
- /** Open subscription management UI and return changed purchases (iOS 15+) */
+ /**
+ * Present the manage-subscriptions sheet and return changed purchases (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios
+ */
showManageSubscriptionsIOS: Promise;
- /** Force a StoreKit sync for transactions (iOS 15+) */
+ /**
+ * Force sync transactions with the App Store (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/sync-ios
+ */
syncIOS: Promise;
/**
- * Validate purchase receipts with the configured providers
+ * Deprecated. Validate purchase receipts with the configured providers — use verifyPurchase instead.
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase
* @deprecated Use verifyPurchase
*/
validateReceipt: Promise;
- /** Verify purchases with the configured providers */
+ /**
+ * Verify a purchase against your own backend (returns isValid + raw store metadata).
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase
+ */
verifyPurchase: Promise;
- /** Verify purchases with a specific provider (e.g., IAPKit) */
+ /**
+ * Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
+ */
verifyPurchaseWithProvider: Promise;
}
@@ -1234,66 +1286,117 @@ export type PurchaseVerificationProvider = 'iapkit';
export interface Query {
/**
- * Check if external purchase notice sheet can be presented (iOS 17.4+)
- * Uses ExternalPurchase.canPresent
+ * Check eligibility for the external purchase notice sheet (iOS 17.4+).
+ * Uses ExternalPurchase.canPresent.
+ * See: https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios
*/
canPresentExternalPurchaseNoticeIOS: Promise;
- /** Get current StoreKit 2 entitlements (iOS 15+) */
+ /**
+ * Get the user's current entitlement for a product, using StoreKit 2 (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/current-entitlement-ios
+ */
currentEntitlementIOS?: Promise<(PurchaseIOS | null)>;
- /** Retrieve products or subscriptions from the store */
+ /**
+ * Fetch products or subscriptions from the store.
+ * See: https://www.openiap.dev/docs/apis/fetch-products
+ */
fetchProducts: Promise<(ProductOrSubscription[] | Product[] | ProductSubscription[] | null)>;
- /** Get active subscriptions (filters by subscriptionIds when provided) */
+ /**
+ * Get details of all currently active subscriptions (filters by subscriptionIds when provided).
+ * See: https://www.openiap.dev/docs/apis/get-active-subscriptions
+ */
getActiveSubscriptions: Promise;
/**
- * Get the full StoreKit 2 transaction history as PurchaseIOS values.
+ * List every StoreKit transaction (finished + unfinished) for the current user.
* Requires the SK2ConsumableTransactionHistory Info.plist key in the host app
* for finished consumables to be included (iOS 18+).
* Unlike getAvailablePurchases, always returns the iOS-specific PurchaseIOS shape.
+ * See: https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios
*/
getAllTransactionsIOS: Promise;
- /** Fetch the current app transaction (iOS 16+) */
+ /**
+ * Fetch the app transaction (iOS 16+).
+ * See: https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios
+ */
getAppTransactionIOS?: Promise<(AppTransaction | null)>;
- /** Get all available purchases for the current user */
+ /**
+ * List active purchases for the current user.
+ * See: https://www.openiap.dev/docs/apis/get-available-purchases
+ */
getAvailablePurchases: Promise;
/**
- * Get external purchase token for reporting to Apple (iOS 18.1+).
- * Use this token with Apple's External Purchase Server API to report transactions.
+ * Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
+ * Use this token to report transactions made through ExternalPurchaseCustomLink.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/token(for:)
+ * See: https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios
*/
getExternalPurchaseCustomLinkTokenIOS: Promise;
- /** Retrieve all pending transactions in the StoreKit queue */
+ /**
+ * List unfinished StoreKit transactions in the queue.
+ * See: https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios
+ */
getPendingTransactionsIOS: Promise;
- /** Get the currently promoted product (iOS 11+) */
+ /**
+ * Read the App Store-promoted product, if any (iOS 11+).
+ * See: https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios
+ */
getPromotedProductIOS?: Promise<(ProductIOS | null)>;
- /** Get base64-encoded receipt data for validation */
+ /**
+ * Get base64-encoded receipt data (legacy validation).
+ * See: https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios
+ */
getReceiptDataIOS?: Promise<(string | null)>;
- /** Get the current storefront country code */
+ /**
+ * Return the user's storefront country code.
+ * See: https://www.openiap.dev/docs/apis/get-storefront
+ */
getStorefront: Promise;
/**
- * Get the current App Store storefront country code
+ * Deprecated. Get the current App Store storefront country code — use cross-platform getStorefront instead.
+ * See: https://www.openiap.dev/docs/apis/ios/get-storefront-ios
* @deprecated Use getStorefront
*/
getStorefrontIOS: Promise;
- /** Get the transaction JWS (StoreKit 2) */
+ /**
+ * Return the JWS string for a transaction (StoreKit 2).
+ * See: https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios
+ */
getTransactionJwsIOS?: Promise<(string | null)>;
- /** Check whether the user has active subscriptions */
+ /**
+ * Check whether the user has any active subscription.
+ * See: https://www.openiap.dev/docs/apis/has-active-subscriptions
+ */
hasActiveSubscriptions: Promise;
/**
- * Check if app is eligible for ExternalPurchaseCustomLink API (iOS 18.1+).
+ * Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
* Returns true if the app can use custom external purchase links.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/iseligible
+ * See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios
*/
isEligibleForExternalPurchaseCustomLinkIOS: Promise;
- /** Check introductory offer eligibility for a subscription group */
+ /**
+ * Check intro-offer eligibility for a subscription group.
+ * See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios
+ */
isEligibleForIntroOfferIOS: Promise;
- /** Verify a StoreKit 2 transaction signature */
+ /**
+ * Check whether a transaction's JWS verification passed (StoreKit 2).
+ * See: https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios
+ */
isTransactionVerifiedIOS: Promise;
- /** Get the latest transaction for a product using StoreKit 2 */
+ /**
+ * Get the latest verified transaction for a product, using StoreKit 2.
+ * See: https://www.openiap.dev/docs/apis/ios/latest-transaction-ios
+ */
latestTransactionIOS?: Promise<(PurchaseIOS | null)>;
- /** Get StoreKit 2 subscription status details (iOS 15+) */
+ /**
+ * Get subscription status objects from StoreKit 2 (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/subscription-status-ios
+ */
subscriptionStatusIOS: Promise;
/**
- * Validate a receipt for a specific product
+ * Deprecated. Legacy App Store receipt validation — use verifyPurchase instead.
+ * See: https://www.openiap.dev/docs/apis/ios/validate-receipt-ios
* @deprecated Use verifyPurchase
*/
validateReceiptIOS: Promise;
diff --git a/libraries/expo-iap/src/useIAP.ts b/libraries/expo-iap/src/useIAP.ts
index 6921b818..e56299d6 100644
--- a/libraries/expo-iap/src/useIAP.ts
+++ b/libraries/expo-iap/src/useIAP.ts
@@ -252,6 +252,29 @@ export function useIAP(options?: UseIAPOptions): UseIap {
}
}, []);
+ /**
+ * Retrieve products or subscriptions from the store by SKU.
+ *
+ * @param params `ProductRequest` — `skus` (string[]) and optional `type`
+ * (`'in-app' | 'subs' | 'all'`, defaults to `'in-app'`).
+ * @returns Promise that resolves when the request is dispatched; results land in the
+ * hook's reactive `products` / `subscriptions` state.
+ * @throws When the store rejects the request (unknown SKU, network, not connected).
+ *
+ * @example
+ * ```ts
+ * const { fetchProducts, products } = useIAP();
+ * await fetchProducts({
+ * skus: ['com.app.coins_100', 'com.app.premium'],
+ * type: 'in-app',
+ * });
+ * ```
+ *
+ * @remarks This is a regular promise-based call. Don't confuse with `request*` APIs
+ * (`requestPurchase`), which are event-based.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/fetch-products}
+ */
const fetchProductsInternal = useCallback(
async (params: {
skus: string[];
@@ -349,6 +372,27 @@ export function useIAP(options?: UseIAPOptions): UseIap {
],
);
+ /**
+ * List the user's unfinished purchases — non-consumables, active subscriptions, and any
+ * pending transactions not yet finished.
+ *
+ * @param options Optional `PurchaseOptions`. iOS-only flags:
+ * `alsoPublishToEventListenerIOS`, `onlyIncludeActiveItemsIOS`.
+ * @returns Promise that resolves when the request is dispatched; results land in the
+ * hook's reactive `availablePurchases` state.
+ * @throws When the platform query fails.
+ *
+ * @example
+ * ```ts
+ * const { getAvailablePurchases, availablePurchases } = useIAP();
+ * await getAvailablePurchases();
+ * for (const p of availablePurchases) {
+ * if (await verifyOnServer(p)) await finishTransaction({ purchase: p, isConsumable: false });
+ * }
+ * ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/get-available-purchases}
+ */
const getAvailablePurchasesInternal = useCallback(
async (options?: PurchaseOptions): Promise => {
try {
@@ -368,6 +412,11 @@ export function useIAP(options?: UseIAPOptions): UseIap {
[invokeOnError],
);
+ /**
+ * Get details of all currently active subscriptions.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/get-active-subscriptions}
+ */
const getActiveSubscriptionsInternal = useCallback(
async (subscriptionIds?: string[]): Promise => {
try {
@@ -382,6 +431,11 @@ export function useIAP(options?: UseIAPOptions): UseIap {
[invokeOnError],
);
+ /**
+ * Check whether the user has any active subscription.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/has-active-subscriptions}
+ */
const hasActiveSubscriptionsInternal = useCallback(
async (subscriptionIds?: string[]): Promise => {
try {
@@ -394,6 +448,29 @@ export function useIAP(options?: UseIAPOptions): UseIap {
[],
);
+ /**
+ * Complete a purchase transaction. Call after server-side verification to remove it
+ * from the queue.
+ *
+ * @param args.purchase The `Purchase` to finalize.
+ * @param args.isConsumable `true` for consumables (consumes the token so the SKU can be
+ * re-bought, e.g. coins); `false` (default) for non-consumables and subscriptions.
+ * @returns Promise that resolves once the platform finalizes the transaction.
+ * @throws When the platform finalize call fails.
+ *
+ * @example
+ * ```ts
+ * // Inside purchaseUpdatedListener:
+ * if (await verifyOnServer(purchase)) {
+ * await finishTransaction({ purchase, isConsumable: false });
+ * }
+ * ```
+ *
+ * @remarks **Critical:** Android purchases must be finalized within 3 days or Google
+ * auto-refunds. iOS unfinished transactions replay on every app launch.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/finish-transaction}
+ */
const finishTransaction = useCallback(
async ({
purchase,
@@ -410,6 +487,33 @@ export function useIAP(options?: UseIAPOptions): UseIap {
[toPurchaseInput],
);
+ /**
+ * Initiate a purchase or subscription flow. The result is delivered through
+ * `purchaseUpdatedListener` — NOT the return value.
+ *
+ * @param props `RequestPurchaseProps`, discriminated by `type`:
+ * - `type: 'in-app'` — pass `request.apple.sku` (iOS) and/or `request.google.skus` (Android).
+ * - `type: 'subs'` — same shape, plus `request.google.subscriptionOffers: [{ sku, offerToken }]`.
+ * @returns Promise that resolves when the request is dispatched; the actual purchase
+ * outcome lands in the hook's `onPurchaseSuccess` / `onPurchaseError` callbacks.
+ * @throws Synchronous rejection from the store (e.g. `E_NOT_PREPARED`, validation failure).
+ *
+ * @example
+ * ```ts
+ * await requestPurchase({
+ * request: {
+ * apple: { sku: 'com.app.premium' },
+ * google: { skus: ['com.app.premium'] },
+ * },
+ * type: 'in-app',
+ * });
+ * ```
+ *
+ * @remarks Event-based. Listen for the result via {@link purchaseUpdatedListener} /
+ * {@link purchaseErrorListener}, or use `useIAP({ onPurchaseSuccess, onPurchaseError })`.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/request-purchase}
+ */
const requestPurchaseWithReset = useCallback(
(requestObj: MutationRequestPurchaseArgs) => {
return requestPurchaseInternal(requestObj);
@@ -436,9 +540,11 @@ export function useIAP(options?: UseIAPOptions): UseIap {
],
);
- // Restore completed transactions with cross-platform behavior.
- // iOS: best-effort sync (ignore sync errors) then fetch available purchases.
- // Android: fetch available purchases directly.
+ /**
+ * Restore non-consumable and active subscription purchases.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/restore-purchases}
+ */
const restorePurchasesInternal = useCallback(
async (options?: PurchaseOptions): Promise => {
try {
@@ -463,14 +569,29 @@ export function useIAP(options?: UseIAPOptions): UseIap {
[invokeOnError],
);
+ /**
+ * Deprecated. Use verifyPurchase instead — same input/output shape.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/validate-receipt}
+ */
const validateReceipt = useCallback(async (props: VerifyPurchaseProps) => {
return validateReceiptInternal(props);
}, []);
+ /**
+ * Verify a purchase against your own backend (returns isValid + raw store metadata).
+ *
+ * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase}
+ */
const verifyPurchase = useCallback(async (props: VerifyPurchaseProps) => {
return verifyPurchaseInternal(props);
}, []);
+ /**
+ * Verify via a managed provider (IAPKit, Apple, Google, Horizon).
+ *
+ * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider}
+ */
const verifyPurchaseWithProvider = useCallback(
async (props: VerifyPurchaseWithProviderProps) => {
return verifyPurchaseWithProviderInternal(props);
diff --git a/libraries/flutter_inapp_purchase/lib/flutter_inapp_purchase.dart b/libraries/flutter_inapp_purchase/lib/flutter_inapp_purchase.dart
index b37801be..79693890 100644
--- a/libraries/flutter_inapp_purchase/lib/flutter_inapp_purchase.dart
+++ b/libraries/flutter_inapp_purchase/lib/flutter_inapp_purchase.dart
@@ -246,7 +246,22 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
});
}
- /// Initialize connection (flutter IAP compatible)
+ /// Initialize the store connection. Must be called before any other IAP API.
+ ///
+ /// Parameters:
+ /// - `alternativeBillingModeAndroid`: Android-only — opt into Google's alternative
+ /// billing flow (deprecated; prefer `enableBillingProgramAndroid`).
+ /// - `enableBillingProgramAndroid`: Android-only — Play Billing 8.2.0+ billing program
+ /// (e.g. External Payments). iOS ignores both fields.
+ ///
+ /// Returns `true` once the platform billing client is connected.
+ /// Throws when the billing client fails to initialize.
+ ///
+ /// ```dart
+ /// await FlutterInappPurchase.instance.initConnection();
+ /// ```
+ ///
+ /// See: https://www.openiap.dev/docs/apis/init-connection
gentype.MutationInitConnectionHandler get initConnection => ({
gentype.AlternativeBillingModeAndroid? alternativeBillingModeAndroid,
gentype.BillingProgramAndroid? enableBillingProgramAndroid,
@@ -289,7 +304,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// End connection (flutter IAP compatible)
+ /// Close the store connection and release resources.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/end-connection
gentype.MutationEndConnectionHandler get endConnection => () async {
if (!_isInitialized) {
return false;
@@ -314,7 +331,32 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// Request purchase (flutter IAP compatible)
+ /// Initiate a purchase or subscription flow. The result is delivered via the
+ /// `purchaseUpdated` stream — NOT the return value.
+ ///
+ /// Parameters:
+ /// - `params`: `RequestPurchaseProps`, discriminated by `type`. Pass platform fields
+ /// via `request.apple` (iOS sku) and `request.google` (skus, subscriptionOffers).
+ ///
+ /// Returns the dispatched purchase payload. **Do not rely on it** for the outcome.
+ /// Throws on synchronous rejection (e.g. billing not ready, missing offerToken on subs).
+ ///
+ /// ```dart
+ /// await FlutterInappPurchase.instance.requestPurchase(
+ /// RequestPurchaseProps(
+ /// request: RequestPurchasePropsByPlatforms(
+ /// apple: RequestPurchaseIosProps(sku: 'com.app.premium'),
+ /// google: RequestPurchaseAndroidProps(skus: ['com.app.premium']),
+ /// ),
+ /// type: ProductQueryType.InApp,
+ /// ),
+ /// );
+ /// ```
+ ///
+ /// **Warning:** Event-based. Subscribe to `purchaseUpdated` / `purchaseError` for
+ /// the actual outcome.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/request-purchase
@override
gentype.MutationRequestPurchaseHandler get requestPurchase => (params) async {
if (!_isInitialized) {
@@ -536,14 +578,33 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
/// DSL-like request subscription method with builder pattern
// requestSubscriptionWithBuilder removed in 6.6.0 (use requestPurchaseWithBuilder)
- /// Get all available purchases (OpenIAP standard)
- /// Returns non-consumed purchases that are still pending acknowledgment or consumption
+ /// List the user's unfinished purchases — non-consumables, active subscriptions, and
+ /// any pending transactions not yet finished.
+ ///
+ /// Parameters:
+ /// - `alsoPublishToEventListenerIOS`: iOS-only — also emit results to the
+ /// `purchaseUpdated` event listener.
+ /// - `includeSuspendedAndroid`: Android-only — include suspended subscriptions in the
+ /// result.
+ /// - `onlyIncludeActiveItemsIOS`: iOS-only — when `true` (default), excludes expired
+ /// subscriptions from the result.
///
- /// [options] - Optional configuration for the method behavior
- /// - onlyIncludeActiveItemsIOS: Whether to only include active items (default: true)
- /// Set to false to include expired subscriptions
- /// - includeSuspendedAndroid: Include suspended subscriptions (Android 8.1+, default: false)
- /// Suspended subscriptions have isSuspendedAndroid=true and should NOT be granted entitlements.
+ /// Returns a list of `Purchase` currently held by the store.
+ /// Throws when the platform query fails.
+ ///
+ /// ```dart
+ /// final purchases = await FlutterInappPurchase.instance.getAvailablePurchases();
+ /// for (final p in purchases) {
+ /// if (await verifyOnServer(p)) {
+ /// await FlutterInappPurchase.instance.finishTransaction(
+ /// purchase: p,
+ /// isConsumable: false,
+ /// );
+ /// }
+ /// }
+ /// ```
+ ///
+ /// See: https://www.openiap.dev/docs/apis/get-available-purchases
gentype.QueryGetAvailablePurchasesHandler get getAvailablePurchases => ({
bool? alsoPublishToEventListenerIOS,
bool? includeSuspendedAndroid,
@@ -638,7 +699,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// Get the current storefront country code (unified method)
+ /// Return the user's storefront country code.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/get-storefront
gentype.QueryGetStorefrontHandler get getStorefront => () async {
if (!isIOS && !_platform.isAndroid) {
return '';
@@ -662,7 +725,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// iOS specific: Get storefront
+ /// Deprecated. Use cross-platform `getStorefront` instead.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/get-storefront-ios
gentype.QueryGetStorefrontIOSHandler get getStorefrontIOS => () async {
if (!_platform.isIOS || _platform.isMacOS) {
throw PurchaseError(
@@ -696,6 +761,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
+ /// Force sync transactions with the App Store.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/sync-ios
gentype.MutationSyncIOSHandler get syncIOS => () async {
if (!_platform.isIOS || _platform.isMacOS) {
debugPrint('syncIOS is only supported on iOS');
@@ -717,6 +785,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
+ /// Check intro-offer eligibility for a subscription group.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios
gentype.QueryIsEligibleForIntroOfferIOSHandler
get isEligibleForIntroOfferIOS => (groupId) async {
if (!_platform.isIOS || _platform.isMacOS) {
@@ -735,6 +806,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
+ /// Get subscription status objects from StoreKit 2.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/subscription-status-ios
gentype.QuerySubscriptionStatusIOSHandler get subscriptionStatusIOS =>
(sku) async {
if (!_platform.isIOS || _platform.isMacOS) {
@@ -778,6 +852,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
+ /// Clear pending transactions in the queue (sandbox helper).
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/clear-transaction-ios
gentype.MutationClearTransactionIOSHandler get clearTransactionIOS =>
() async {
if (!_platform.isIOS || _platform.isMacOS) {
@@ -793,6 +870,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
+ /// Read the App Store-promoted product, if any.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios
gentype.QueryGetPromotedProductIOSHandler get getPromotedProductIOS =>
() async {
if (!_platform.isIOS || _platform.isMacOS) {
@@ -826,26 +906,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// Request purchase on promoted product (iOS only)
- ///
- /// @deprecated Use `purchasePromoted` stream to receive the product ID when a
- /// user taps a promoted product in the App Store, then call `requestPurchase()`
- /// with the received SKU directly. In StoreKit 2, promoted products can be
- /// purchased via the standard `requestPurchase()` flow.
+ /// Buy the currently promoted product.
///
- /// Example:
- /// ```dart
- /// iap.purchasePromoted.listen((productId) async {
- /// if (productId != null) {
- /// await iap.requestPurchaseWithBuilder(
- /// build: (builder) {
- /// builder.ios.sku = productId;
- /// builder.type = ProductQueryType.InApp;
- /// },
- /// );
- /// }
- /// });
- /// ```
+ /// See: https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios
@Deprecated(
'Use purchasePromoted stream + requestPurchase() instead. '
'In StoreKit 2, promoted products are purchased via standard flow.',
@@ -866,6 +929,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
+ /// Fetch the app transaction (iOS 16+).
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios
gentype.QueryGetAppTransactionIOSHandler get getAppTransactionIOS =>
() async {
if (!_platform.isIOS || _platform.isMacOS) {
@@ -890,7 +956,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// iOS specific: Present code redemption sheet
+ /// Show the App Store offer code redemption sheet.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios
gentype.MutationPresentCodeRedemptionSheetIOSHandler
get presentCodeRedemptionSheetIOS => () async {
if (!_platform.isIOS || _platform.isMacOS) {
@@ -919,11 +987,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// iOS specific: Begin a refund request for a purchase
+ /// Present the refund request sheet (iOS 15+).
///
- /// Opens the StoreKit 2 refund sheet for the given SKU and returns the
- /// resulting status string (`"success"` or `"userCancelled"`). Returns
- /// `null` when StoreKit reports an unknown status. Requires iOS 15.0+.
+ /// See: https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios
gentype.MutationBeginRefundRequestIOSHandler get beginRefundRequestIOS =>
(String sku) async {
if (!_platform.isIOS || _platform.isMacOS) {
@@ -953,7 +1019,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// iOS specific: Show manage subscriptions
+ /// Present the manage-subscriptions sheet.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios
gentype.MutationShowManageSubscriptionsIOSHandler
get showManageSubscriptionsIOS => () async {
if (!_platform.isIOS || _platform.isMacOS) {
@@ -983,6 +1051,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
// Original API methods (with deprecation annotations where needed)
+ /// List unfinished StoreKit transactions.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios
gentype.QueryGetPendingTransactionsIOSHandler get getPendingTransactionsIOS =>
() async {
if (_platform.isIOS || _platform.isMacOS) {
@@ -1003,6 +1074,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
return const [];
};
+ /// List every StoreKit transaction (finished + unfinished) for the current user.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios
gentype.QueryGetAllTransactionsIOSHandler get getAllTransactionsIOS =>
() async {
if (_platform.isIOS || _platform.isMacOS) {
@@ -1023,7 +1097,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
return const [];
};
- /// iOS specific: Return the current active entitlement for a SKU, if any.
+ /// Get the user's current entitlement for a product.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/current-entitlement-ios
gentype.QueryCurrentEntitlementIOSHandler get currentEntitlementIOS =>
(String sku) async {
if (!_platform.isIOS || _platform.isMacOS) {
@@ -1057,8 +1133,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// iOS specific: Return the most recent transaction for a SKU, including
- /// expired or revoked ones.
+ /// Get the latest verified transaction for a product.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/latest-transaction-ios
gentype.QueryLatestTransactionIOSHandler get latestTransactionIOS =>
(String sku) async {
if (!_platform.isIOS || _platform.isMacOS) {
@@ -1092,8 +1169,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// iOS specific: Whether the latest transaction for a SKU passes StoreKit 2
- /// verification.
+ /// Check whether a transaction's JWS verification passed.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios
gentype.QueryIsTransactionVerifiedIOSHandler get isTransactionVerifiedIOS =>
(String sku) async {
if (!_platform.isIOS || _platform.isMacOS) {
@@ -1119,8 +1197,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// iOS specific: Return the signed JWS representation of the latest
- /// transaction for a SKU, suitable for server-side verification.
+ /// Return the JWS string for a transaction.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios
gentype.QueryGetTransactionJwsIOSHandler get getTransactionJwsIOS =>
(String sku) async {
if (!_platform.isIOS || _platform.isMacOS) {
@@ -1145,8 +1224,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// iOS specific: Return the base64-encoded App Store receipt data (legacy
- /// StoreKit 1 API). Use JWS-based verification for StoreKit 2.
+ /// Get base64 receipt data (legacy validation).
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios
gentype.QueryGetReceiptDataIOSHandler get getReceiptDataIOS => () async {
if (!_platform.isIOS || _platform.isMacOS) {
return null;
@@ -1167,10 +1247,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// iOS 17.4+: Whether the current device/region can present the external
- /// purchase notice sheet. The underlying StoreKit call
- /// `ExternalPurchase.canPresent` is available from iOS 17.4 / macOS 14.4 /
- /// tvOS 17.4 / visionOS 1.1 — older runtimes return false.
+ /// Check eligibility for the external purchase notice sheet (iOS 17.4+).
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios
gentype.QueryCanPresentExternalPurchaseNoticeIOSHandler
get canPresentExternalPurchaseNoticeIOS => () async {
if (!_platform.isIOS || _platform.isMacOS) {
@@ -1196,6 +1275,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
+ /// Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android
gentype.MutationAcknowledgePurchaseAndroidHandler
get acknowledgePurchaseAndroid => (purchaseToken) async {
if (!_platform.isAndroid) {
@@ -1247,6 +1329,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
+ /// Consume a consumable purchase so it can be re-bought.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/android/consume-purchase-android
gentype.MutationConsumePurchaseAndroidHandler get consumePurchaseAndroid =>
(purchaseToken) async {
if (!_platform.isAndroid) {
@@ -1280,6 +1365,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
+ /// Open the platform's subscription management UI.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/deep-link-to-subscriptions
gentype.MutationDeepLinkToSubscriptionsHandler get deepLinkToSubscriptions =>
({String? packageNameAndroid, String? skuAndroid}) async {
if (!_platform.isAndroid) {
@@ -1303,7 +1391,27 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
await _channel.invokeMethod('deepLinkToSubscriptionsAndroid', args);
};
- /// Finish a transaction using OpenIAP generated handler signature
+ /// Complete a purchase transaction. Call after server-side verification to remove
+ /// it from the queue.
+ ///
+ /// Parameters:
+ /// - `purchase` (required): the `Purchase` to finalize.
+ /// - `isConsumable`: `true` for consumables (re-buyable like coins); `false` (default)
+ /// for non-consumables and subscriptions.
+ ///
+ /// Throws when the platform finalize call fails.
+ ///
+ /// ```dart
+ /// await FlutterInappPurchase.instance.finishTransaction(
+ /// purchase: purchase,
+ /// isConsumable: false,
+ /// );
+ /// ```
+ ///
+ /// **Critical:** Android purchases must be finalized within 3 days or Google
+ /// auto-refunds. iOS unfinished transactions replay on every app launch.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/finish-transaction
gentype.MutationFinishTransactionHandler get finishTransaction =>
({required gentype.Purchase purchase, bool? isConsumable}) async {
final bool consumable = isConsumable ?? false;
@@ -1453,44 +1561,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
);
};
- /// Validate receipt using StoreKit 2 (iOS only) - LOCAL TESTING ONLY
- ///
- /// ⚠️ WARNING: This performs LOCAL validation for TESTING purposes.
- /// For production, send the JWS representation to your server for validation.
- ///
- /// What this method does:
- /// 1. Performs local on-device validation (for testing)
- /// 2. Returns JWS representation (send this to your server)
- /// 3. Provides transaction details for debugging
- ///
- /// Server-side validation guide:
- /// 1. Send `result.jwsRepresentation` to your server
- /// 2. Verify the JWS using Apple's public keys
- /// 3. Decode and validate the transaction on your server
- /// 4. Grant entitlements based on server validation
- ///
- /// Example for LOCAL TESTING:
- /// ```dart
- /// // Step 1: Local validation (testing only)
- /// final result = await FlutterInappPurchase.instance.validateReceiptIOS(
- /// apple: VerifyPurchaseAppleOptions(sku: 'com.example.premium'),
- /// );
- ///
- /// if (result.isValid) {
- /// print('Local validation passed (TEST ONLY)');
+ /// Deprecated. Legacy App Store receipt validation. Use `verifyPurchase` instead.
///
- /// // Step 2: Send to your server for PRODUCTION validation
- /// final serverPayload = {
- /// 'purchaseToken': result.purchaseToken, // Unified field (JWS for iOS)
- /// 'productId': 'com.example.premium',
- /// };
- ///
- /// // await yourApi.validateOnServer(serverPayload);
- /// print('Send purchaseToken to your server for production validation');
- /// }
- /// ```
- ///
- /// Note: This method requires iOS 15.0+ for StoreKit 2 support.
+ /// See: https://www.openiap.dev/docs/apis/ios/validate-receipt-ios
gentype.QueryValidateReceiptIOSHandler get validateReceiptIOS => ({
gentype.VerifyPurchaseAppleOptions? apple,
gentype.VerifyPurchaseGoogleOptions? google,
@@ -1572,6 +1645,10 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
);
}
};
+
+ /// Deprecated. Use verifyPurchase instead — same input/output shape.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/validate-receipt
gentype.MutationValidateReceiptHandler get validateReceipt => ({
gentype.VerifyPurchaseAppleOptions? apple,
gentype.VerifyPurchaseGoogleOptions? google,
@@ -1599,26 +1676,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
);
};
- /// Verify purchase with an external provider (IAPKit)
- ///
- /// This method allows you to verify purchases using external verification
- /// providers like IAPKit. It sends the purchase receipt to the provider
- /// for server-side verification.
+ /// Verify via a managed provider (IAPKit, Apple, Google, Horizon).
///
- /// Example:
- /// ```dart
- /// final result = await FlutterInappPurchase.instance.verifyPurchaseWithProvider(
- /// provider: PurchaseVerificationProvider.Iapkit,
- /// iapkit: RequestVerifyPurchaseWithIapkitProps(
- /// apiKey: 'your-iapkit-api-key',
- /// apple: RequestVerifyPurchaseWithIapkitAppleProps(jws: purchase.jws),
- /// // or for Android:
- /// // google: RequestVerifyPurchaseWithIapkitGoogleProps(
- /// // purchaseToken: purchase.purchaseToken,
- /// // ),
- /// ),
- /// );
- /// ```
+ /// See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
gentype.MutationVerifyPurchaseWithProviderHandler
get verifyPurchaseWithProvider => ({
required gentype.PurchaseVerificationProvider provider,
@@ -1726,33 +1786,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// Verifies a purchase using the native platform's local verification.
- ///
- /// On iOS, this verifies the transaction using StoreKit 2's built-in
- /// verification. On Android, this requires providing Google Play Developer
- /// API credentials via [google].
- ///
- /// Example (iOS):
- /// ```dart
- /// final result = await iap.verifyPurchase(
- /// apple: VerifyPurchaseAppleOptions(sku: 'premium_upgrade'),
- /// );
- /// if (result is VerifyPurchaseResultIOS && result.isValid) {
- /// // Purchase verified locally
- /// }
- /// ```
+ /// Verify a purchase against your own backend (returns isValid + raw store metadata).
///
- /// Example (Android):
- /// ```dart
- /// final result = await iap.verifyPurchase(
- /// google: VerifyPurchaseGoogleOptions(
- /// sku: 'premium_upgrade',
- /// accessToken: 'your-google-access-token', // From your backend
- /// packageName: 'com.your.app',
- /// purchaseToken: purchase.purchaseToken,
- /// ),
- /// );
- /// ```
+ /// See: https://www.openiap.dev/docs/features/validation#verify-purchase
gentype.MutationVerifyPurchaseHandler get verifyPurchase => ({
gentype.VerifyPurchaseAppleOptions? apple,
gentype.VerifyPurchaseGoogleOptions? google,
@@ -1944,24 +1980,31 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
}
- /// Fetch products from the store
+ /// Retrieve products or subscriptions from the store by SKU.
+ ///
+ /// Parameters:
+ /// - `skus` (required): list of product identifiers to fetch.
+ /// - `type`: `ProductQueryType.InApp`, `Subs`, or `All`. Defaults to `InApp`.
///
- /// When type is InApp, returns List
- /// When type is Subs, returns List
- /// When type is All, returns List
+ /// Returns a `List` cast to the generic type — pass `` for one-time
+ /// items, `` for subs, or `` for mixed `All`
+ /// queries.
+ /// Throws when the store rejects the request.
///
- /// Example:
/// ```dart
- /// final products = await iap.fetchProducts(
- /// skus: ['product_id'],
+ /// final products = await FlutterInappPurchase.instance.fetchProducts(
+ /// skus: ['com.app.premium'],
/// type: ProductQueryType.InApp,
- /// ); // Type: List
- ///
- /// final subs = await iap.fetchProducts(
- /// skus: ['sub_id'],
- /// type: ProductQueryType.Subs,
- /// ); // Type: List
+ /// );
+ /// for (final product in products) {
+ /// print('${product.title}: ${product.displayPrice}');
+ /// }
/// ```
+ ///
+ /// **Note:** This is a regular promise-based call. Don't confuse with `request*`
+ /// APIs (e.g. `requestPurchase`), which are event-based.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/fetch-products
Future> fetchProducts({
required List skus,
gentype.ProductQueryType type = gentype.ProductQueryType.InApp,
@@ -1972,6 +2015,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
// MARK: - StoreKit 2 specific methods
+ /// Restore non-consumable and active subscription purchases.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/restore-purchases
gentype.MutationRestorePurchasesHandler get restorePurchases => () async {
try {
if (_platform.isIOS || _platform.isMacOS) {
@@ -2071,15 +2117,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
return subscriptions;
}
- /// Get all active subscriptions with detailed information (OpenIAP compliant)
- /// Returns an array of active subscriptions. If subscriptionIds is not provided,
- /// returns all active subscriptions. Platform-specific fields are populated based
- /// on the current platform.
+ /// Get details of all currently active subscriptions.
///
- /// This uses the native getActiveSubscriptions method on both platforms:
- /// - iOS: includes renewalInfoIOS with subscription renewal status, pending
- /// upgrades/downgrades, cancellation status, and auto-renewal preferences
- /// - Android: includes autoRenewingAndroid and other subscription details
+ /// See: https://www.openiap.dev/docs/apis/get-active-subscriptions
gentype.QueryGetActiveSubscriptionsHandler get getActiveSubscriptions =>
([subscriptionIds]) async {
if (!_isInitialized) {
@@ -2119,9 +2159,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// Check if the user has any active subscriptions (OpenIAP compliant)
- /// Returns true if the user has at least one active subscription, false otherwise.
- /// If subscriptionIds is provided, only checks for those specific subscriptions.
+ /// Check whether the user has any active subscription.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/has-active-subscriptions
gentype.QueryHasActiveSubscriptionsHandler get hasActiveSubscriptions =>
([subscriptionIds]) async {
try {
@@ -2149,7 +2189,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
// MARK: - Alternative Billing APIs
- /// Check if alternative billing is available on Android
+ /// Check whether alternative billing is available for the user.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android
gentype.MutationCheckAlternativeBillingAvailabilityAndroidHandler
get checkAlternativeBillingAvailabilityAndroid => () async {
if (!_platform.isAndroid) {
@@ -2167,7 +2209,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// Show alternative billing information dialog on Android
+ /// Display Google's alternative billing information dialog.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android
gentype.MutationShowAlternativeBillingDialogAndroidHandler
get showAlternativeBillingDialogAndroid => () async {
if (!_platform.isAndroid) {
@@ -2184,7 +2228,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// Create alternative billing reporting token on Android
+ /// Create a reporting token for an alternative billing flow.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android
gentype.MutationCreateAlternativeBillingTokenAndroidHandler
get createAlternativeBillingTokenAndroid => () async {
if (!_platform.isAndroid) {
@@ -2203,7 +2249,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
// MARK: - Billing Programs API (Android 8.2.0+)
- /// Check if a billing program is available on Android (8.2.0+)
+ /// Check whether a billing program (e.g., External Payments) is available.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/android/is-billing-program-available-android
Future
isBillingProgramAvailableAndroid(
gentype.BillingProgramAndroid program,
@@ -2236,7 +2284,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
}
- /// Create billing program reporting details on Android (8.2.0+)
+ /// Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+).
+ ///
+ /// See: https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android
Future
createBillingProgramReportingDetailsAndroid(
gentype.BillingProgramAndroid program,
@@ -2267,7 +2317,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
}
- /// Launch external link on Android (8.2.0+)
+ /// Launch an external content/offer link from inside the Billing Programs flow (Play Billing 8.2.0+).
+ ///
+ /// See: https://www.openiap.dev/docs/apis/android/launch-external-link-android
Future launchExternalLinkAndroid(
gentype.LaunchExternalLinkParamsAndroid params,
) async {
@@ -2292,7 +2344,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
}
- /// Present external purchase notice sheet on iOS (iOS 18.2+)
+ /// Present the external purchase notice sheet (iOS 17.4+).
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios
gentype.MutationPresentExternalPurchaseNoticeSheetIOSHandler
get presentExternalPurchaseNoticeSheetIOS => () async {
if (!_platform.isIOS || _platform.isMacOS) {
@@ -2321,7 +2375,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// Present external purchase link on iOS (iOS 16.0+)
+ /// Present an external purchase link, StoreKit External (iOS 16+).
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios
gentype.MutationPresentExternalPurchaseLinkIOSHandler
get presentExternalPurchaseLinkIOS => (String url) async {
if (!_platform.isIOS || _platform.isMacOS) {
@@ -2351,10 +2407,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
// MARK: - ExternalPurchaseCustomLink (iOS 18.1+)
- /// Check if app is eligible for ExternalPurchaseCustomLink API (iOS 18.1+).
- /// Returns true if the app can use custom external purchase links.
+ /// Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
///
- /// Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/iseligible
+ /// See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios
gentype.QueryIsEligibleForExternalPurchaseCustomLinkIOSHandler
get isEligibleForExternalPurchaseCustomLinkIOS => () async {
if (!_platform.isIOS && !_platform.isMacOS) {
@@ -2380,12 +2435,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// Get external purchase token for reporting to Apple (iOS 18.1+).
- /// Use this token with Apple's External Purchase Server API to report transactions.
- ///
- /// [tokenType] - Token type: 'acquisition' (new customers) or 'services' (existing customers)
+ /// Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
///
- /// Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/token(for:)
+ /// See: https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios
gentype.QueryGetExternalPurchaseCustomLinkTokenIOSHandler
get getExternalPurchaseCustomLinkTokenIOS =>
(gentype.ExternalPurchaseCustomLinkTokenTypeIOS tokenType) async {
@@ -2417,13 +2469,9 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi {
}
};
- /// Show ExternalPurchaseCustomLink notice sheet (iOS 18.1+).
- /// Displays the system disclosure notice sheet for custom external purchase links.
- /// Call this after a deliberate customer interaction before linking out to external purchases.
- ///
- /// [noticeType] - Notice type: 'browser' (external purchases displayed in browser)
+ /// Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
///
- /// Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/shownotice(type:)
+ /// See: https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios
gentype.MutationShowExternalPurchaseCustomLinkNoticeIOSHandler
get showExternalPurchaseCustomLinkNoticeIOS =>
(gentype.ExternalPurchaseCustomLinkNoticeTypeIOS noticeType) async {
diff --git a/libraries/flutter_inapp_purchase/lib/types.dart b/libraries/flutter_inapp_purchase/lib/types.dart
index ea75b5b3..696a9148 100644
--- a/libraries/flutter_inapp_purchase/lib/types.dart
+++ b/libraries/flutter_inapp_purchase/lib/types.dart
@@ -4846,118 +4846,138 @@ sealed class VerifyPurchaseResult {
/// GraphQL root mutation operations.
abstract class MutationResolver {
- /// Acknowledge a non-consumable purchase or subscription
+ /// Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
+ /// See: https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android
Future acknowledgePurchaseAndroid(String purchaseToken);
- /// Initiate a refund request for a product (iOS 15+)
+ /// Present the refund request sheet (iOS 15+). See also Features → Refund.
+ /// See: https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios
Future beginRefundRequestIOS(String sku);
- /// Check if alternative billing is available for this user/device
- /// Step 1 of alternative billing flow
+ /// Check whether alternative billing is available for the user. Step 1 of the alternative billing flow.
///
- /// Returns true if available, false otherwise
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Returns true if available, false otherwise.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android
Future checkAlternativeBillingAvailabilityAndroid();
- /// Clear pending transactions from the StoreKit payment queue
+ /// Clear pending transactions in the queue (sandbox helper).
+ /// See: https://www.openiap.dev/docs/apis/ios/clear-transaction-ios
Future clearTransactionIOS();
- /// Consume a purchase token so it can be repurchased
+ /// Consume a consumable purchase so it can be re-bought.
+ /// See: https://www.openiap.dev/docs/apis/android/consume-purchase-android
Future consumePurchaseAndroid(String purchaseToken);
- /// Create external transaction token for Google Play reporting
- /// Step 3 of alternative billing flow
- /// Must be called AFTER successful payment in your payment system
- /// Token must be reported to Google Play backend within 24 hours
+ /// Create a reporting token for an alternative billing flow. Step 3 of the alternative billing flow.
+ /// Must be called AFTER successful payment in your payment system.
+ /// Token must be reported to Google Play backend within 24 hours.
///
- /// Returns token string, or null if creation failed
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Returns token string, or null if creation failed.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android
Future createAlternativeBillingTokenAndroid();
- /// Create reporting details for a billing program
- /// Replaces the deprecated createExternalOfferReportingDetailsAsync API
+ /// Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+).
+ /// Replaces the deprecated createExternalOfferReportingDetailsAsync API.
///
- /// Available in Google Play Billing Library 8.2.0+
- /// Returns external transaction token needed for reporting external transactions
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Returns external transaction token needed for reporting external transactions.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android
Future createBillingProgramReportingDetailsAndroid(BillingProgramAndroid program);
- /// Open the native subscription management surface
+ /// Open the platform's subscription management UI.
+ /// See: https://www.openiap.dev/docs/apis/deep-link-to-subscriptions
Future deepLinkToSubscriptions({
String? packageNameAndroid,
String? skuAndroid,
});
- /// Close the platform billing connection
+ /// Close the store connection and release resources.
+ /// See: https://www.openiap.dev/docs/apis/end-connection
Future endConnection();
- /// Finish a transaction after validating receipts
+ /// Complete a transaction after server-side verification. Required on Android within 3 days.
+ /// See: https://www.openiap.dev/docs/apis/finish-transaction
Future finishTransaction({
required PurchaseInput purchase,
bool? isConsumable,
});
- /// Establish the platform billing connection
+ /// Initialize the store connection. Call before any IAP API.
+ /// See: https://www.openiap.dev/docs/apis/init-connection
Future initConnection({
AlternativeBillingModeAndroid? alternativeBillingModeAndroid,
BillingProgramAndroid? enableBillingProgramAndroid,
});
- /// Check if a billing program is available for the current user
- /// Replaces the deprecated isExternalOfferAvailableAsync API
+ /// Check whether a billing program (e.g., External Payments) is available for the current user.
+ /// Replaces the deprecated isExternalOfferAvailableAsync API.
///
- /// Available in Google Play Billing Library 8.2.0+
- /// Returns availability result with isAvailable flag
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Available in Google Play Billing Library 8.2.0+.
+ /// Returns availability result with isAvailable flag.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/is-billing-program-available-android
Future isBillingProgramAvailableAndroid(BillingProgramAndroid program);
- /// Launch external link flow for external billing programs
- /// Replaces the deprecated showExternalOfferInformationDialog API
+ /// Launch an external content/offer link from inside the Billing Programs flow (Play Billing 8.2.0+).
+ /// Replaces the deprecated showExternalOfferInformationDialog API.
///
- /// Available in Google Play Billing Library 8.2.0+
- /// Shows Play Store dialog and optionally launches external URL
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Shows Play Store dialog and optionally launches external URL.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/launch-external-link-android
Future launchExternalLinkAndroid({
required BillingProgramAndroid billingProgram,
required ExternalLinkLaunchModeAndroid launchMode,
required ExternalLinkTypeAndroid linkType,
required String linkUri,
});
- /// Present the App Store code redemption sheet
+ /// Show the App Store offer code redemption sheet.
+ /// See: https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios
Future presentCodeRedemptionSheetIOS();
- /// Present external purchase custom link with StoreKit UI
+ /// Present an external purchase link, StoreKit External (iOS 16+).
+ /// See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios
Future presentExternalPurchaseLinkIOS(String url);
- /// Present external purchase notice sheet (iOS 17.4+).
- /// Uses ExternalPurchase.presentNoticeSheet() which returns a token when user continues.
+ /// Present the external purchase notice sheet (iOS 17.4+).
+ /// Uses ExternalPurchase.presentNoticeSheet() which returns a token when the user continues.
/// Reference: https://developer.apple.com/documentation/storekit/externalpurchase/presentnoticesheet()
+ /// See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios
Future presentExternalPurchaseNoticeSheetIOS();
- /// Initiate a purchase flow; rely on events for final state
+ /// Initiate a purchase or subscription flow; rely on events for final state.
+ /// See: https://www.openiap.dev/docs/apis/request-purchase
Future requestPurchase(RequestPurchaseProps params);
- /// Purchase the promoted product surfaced by the App Store.
+ /// Buy the currently promoted product.
///
/// @deprecated Use promotedProductListenerIOS to receive the productId,
/// then call requestPurchase with that SKU instead. In StoreKit 2,
/// promoted products can be purchased directly via the standard purchase flow.
+ /// See: https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios
Future requestPurchaseOnPromotedProductIOS();
- /// Restore completed purchases across platforms
+ /// Restore non-consumable and active subscription purchases.
+ /// See: https://www.openiap.dev/docs/apis/restore-purchases
Future restorePurchases();
- /// Show alternative billing information dialog to user
- /// Step 2 of alternative billing flow
- /// Must be called BEFORE processing payment in your payment system
+ /// Display Google's alternative billing information dialog. Step 2 of the alternative billing flow.
+ /// Must be called BEFORE processing payment in your payment system.
///
- /// Returns true if user accepted, false if user canceled
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Returns true if user accepted, false if user canceled.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android
Future showAlternativeBillingDialogAndroid();
- /// Show ExternalPurchaseCustomLink notice sheet (iOS 18.1+).
- /// Displays the system disclosure notice sheet for custom external purchase links.
+ /// Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
/// Call this after a deliberate customer interaction before linking out to external purchases.
/// Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/shownotice(type:)
+ /// See: https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios
Future showExternalPurchaseCustomLinkNoticeIOS(ExternalPurchaseCustomLinkNoticeTypeIOS noticeType);
- /// Open subscription management UI and return changed purchases (iOS 15+)
+ /// Present the manage-subscriptions sheet and return changed purchases (iOS 15+).
+ /// See: https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios
Future> showManageSubscriptionsIOS();
- /// Force a StoreKit sync for transactions (iOS 15+)
+ /// Force sync transactions with the App Store (iOS 15+).
+ /// See: https://www.openiap.dev/docs/apis/ios/sync-ios
Future syncIOS();
- /// Validate purchase receipts with the configured providers
+ /// Deprecated. Validate purchase receipts with the configured providers — use verifyPurchase instead.
+ /// See: https://www.openiap.dev/docs/features/validation#verify-purchase
Future validateReceipt({
VerifyPurchaseAppleOptions? apple,
VerifyPurchaseGoogleOptions? google,
VerifyPurchaseHorizonOptions? horizon,
});
- /// Verify purchases with the configured providers
+ /// Verify a purchase against your own backend (returns isValid + raw store metadata).
+ /// See: https://www.openiap.dev/docs/features/validation#verify-purchase
Future verifyPurchase({
VerifyPurchaseAppleOptions? apple,
VerifyPurchaseGoogleOptions? google,
VerifyPurchaseHorizonOptions? horizon,
});
- /// Verify purchases with a specific provider (e.g., IAPKit)
+ /// Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+ /// See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
Future verifyPurchaseWithProvider({
RequestVerifyPurchaseWithIapkitProps? iapkit,
required PurchaseVerificationProvider provider,
@@ -4966,62 +4986,83 @@ abstract class MutationResolver {
/// GraphQL root query operations.
abstract class QueryResolver {
- /// Check if external purchase notice sheet can be presented (iOS 17.4+)
- /// Uses ExternalPurchase.canPresent
+ /// Check eligibility for the external purchase notice sheet (iOS 17.4+).
+ /// Uses ExternalPurchase.canPresent.
+ /// See: https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios
Future canPresentExternalPurchaseNoticeIOS();
- /// Get current StoreKit 2 entitlements (iOS 15+)
+ /// Get the user's current entitlement for a product, using StoreKit 2 (iOS 15+).
+ /// See: https://www.openiap.dev/docs/apis/ios/current-entitlement-ios
Future currentEntitlementIOS(String sku);
- /// Retrieve products or subscriptions from the store
+ /// Fetch products or subscriptions from the store.
+ /// See: https://www.openiap.dev/docs/apis/fetch-products
Future fetchProducts({
required List skus,
ProductQueryType? type,
});
- /// Get active subscriptions (filters by subscriptionIds when provided)
+ /// Get details of all currently active subscriptions (filters by subscriptionIds when provided).
+ /// See: https://www.openiap.dev/docs/apis/get-active-subscriptions
Future> getActiveSubscriptions([List? subscriptionIds]);
- /// Get the full StoreKit 2 transaction history as PurchaseIOS values.
+ /// List every StoreKit transaction (finished + unfinished) for the current user.
/// Requires the SK2ConsumableTransactionHistory Info.plist key in the host app
/// for finished consumables to be included (iOS 18+).
/// Unlike getAvailablePurchases, always returns the iOS-specific PurchaseIOS shape.
+ /// See: https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios
Future> getAllTransactionsIOS();
- /// Fetch the current app transaction (iOS 16+)
+ /// Fetch the app transaction (iOS 16+).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios
Future getAppTransactionIOS();
- /// Get all available purchases for the current user
+ /// List active purchases for the current user.
+ /// See: https://www.openiap.dev/docs/apis/get-available-purchases
Future> getAvailablePurchases({
bool? alsoPublishToEventListenerIOS,
bool? includeSuspendedAndroid,
bool? onlyIncludeActiveItemsIOS,
});
- /// Get external purchase token for reporting to Apple (iOS 18.1+).
- /// Use this token with Apple's External Purchase Server API to report transactions.
+ /// Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
+ /// Use this token to report transactions made through ExternalPurchaseCustomLink.
/// Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/token(for:)
+ /// See: https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios
Future getExternalPurchaseCustomLinkTokenIOS(ExternalPurchaseCustomLinkTokenTypeIOS tokenType);
- /// Retrieve all pending transactions in the StoreKit queue
+ /// List unfinished StoreKit transactions in the queue.
+ /// See: https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios
Future> getPendingTransactionsIOS();
- /// Get the currently promoted product (iOS 11+)
+ /// Read the App Store-promoted product, if any (iOS 11+).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios
Future getPromotedProductIOS();
- /// Get base64-encoded receipt data for validation
+ /// Get base64-encoded receipt data (legacy validation).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios
Future getReceiptDataIOS();
- /// Get the current storefront country code
+ /// Return the user's storefront country code.
+ /// See: https://www.openiap.dev/docs/apis/get-storefront
Future getStorefront();
- /// Get the current App Store storefront country code
+ /// Deprecated. Get the current App Store storefront country code — use cross-platform getStorefront instead.
+ /// See: https://www.openiap.dev/docs/apis/ios/get-storefront-ios
Future getStorefrontIOS();
- /// Get the transaction JWS (StoreKit 2)
+ /// Return the JWS string for a transaction (StoreKit 2).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios
Future getTransactionJwsIOS(String sku);
- /// Check whether the user has active subscriptions
+ /// Check whether the user has any active subscription.
+ /// See: https://www.openiap.dev/docs/apis/has-active-subscriptions
Future hasActiveSubscriptions([List? subscriptionIds]);
- /// Check if app is eligible for ExternalPurchaseCustomLink API (iOS 18.1+).
+ /// Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
/// Returns true if the app can use custom external purchase links.
/// Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/iseligible
+ /// See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios
Future isEligibleForExternalPurchaseCustomLinkIOS();
- /// Check introductory offer eligibility for a subscription group
+ /// Check intro-offer eligibility for a subscription group.
+ /// See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios
Future isEligibleForIntroOfferIOS(String groupID);
- /// Verify a StoreKit 2 transaction signature
+ /// Check whether a transaction's JWS verification passed (StoreKit 2).
+ /// See: https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios
Future isTransactionVerifiedIOS(String sku);
- /// Get the latest transaction for a product using StoreKit 2
+ /// Get the latest verified transaction for a product, using StoreKit 2.
+ /// See: https://www.openiap.dev/docs/apis/ios/latest-transaction-ios
Future latestTransactionIOS(String sku);
- /// Get StoreKit 2 subscription status details (iOS 15+)
+ /// Get subscription status objects from StoreKit 2 (iOS 15+).
+ /// See: https://www.openiap.dev/docs/apis/ios/subscription-status-ios
Future> subscriptionStatusIOS(String sku);
- /// Validate a receipt for a specific product
+ /// Deprecated. Legacy App Store receipt validation — use verifyPurchase instead.
+ /// See: https://www.openiap.dev/docs/apis/ios/validate-receipt-ios
Future validateReceiptIOS({
VerifyPurchaseAppleOptions? apple,
VerifyPurchaseGoogleOptions? google,
diff --git a/libraries/godot-iap/addons/godot-iap/godot_iap.gd b/libraries/godot-iap/addons/godot-iap/godot_iap.gd
index 579b1675..83c4bb74 100644
--- a/libraries/godot-iap/addons/godot-iap/godot_iap.gd
+++ b/libraries/godot-iap/addons/godot-iap/godot_iap.gd
@@ -200,8 +200,24 @@ func _on_android_subscription_billing_issue(purchase_json: String) -> void:
# Connection (OpenIAP Mutation)
# ==========================================
-## Initialize the IAP connection.
-## @return bool - true if connection was successful
+## Initialize the store connection. Must be called before any other IAP API.
+##
+## [param config] (optional): [InitConnectionConfig]. Use [code]enable_billing_program_android[/code]
+## (Android, Play Billing 8.2.0+) to opt into External Payments etc. iOS ignores Android fields.
+##
+## Returns [code]true[/code] once the platform billing client is connected.
+##
+## [codeblock]
+## # Standard
+## var ok = await iap.init_connection()
+##
+## # With Android billing program
+## var config = InitConnectionConfig.new()
+## config.enable_billing_program_android = BillingProgramAndroid.EXTERNAL_OFFER
+## var ok = await iap.init_connection(config)
+## [/codeblock]
+##
+## See: https://www.openiap.dev/docs/apis/init-connection
func init_connection() -> bool:
print("[GodotIap] init_connection called")
if _native_plugin:
@@ -229,6 +245,8 @@ func init_connection() -> bool:
## End the IAP connection.
## @return bool - true if disconnection was successful
+##
+## See: https://www.openiap.dev/docs/apis/end-connection
func end_connection() -> bool:
print("[GodotIap] end_connection called")
if _native_plugin:
@@ -248,11 +266,26 @@ func is_store_connected() -> bool:
# Products (OpenIAP Query)
# ==========================================
-## Fetch products from the store.
-## Note: This function is asynchronous and must be called with 'await'.
-## On iOS, it awaits the 'products_fetched' signal internally.
-## @param request: Types.ProductRequest - product request with SKUs and type
-## @return Array[Types.ProductAndroid] or Array[Types.ProductIOS] depending on platform
+## Retrieve products or subscriptions from the store by SKU.
+##
+## [param request]: [ProductRequest] with [code]skus[/code] (Array[String]) and optional
+## [code]type[/code] ([code]ProductQueryType.IN_APP[/code], [code]SUBS[/code], or [code]ALL[/code]).
+##
+## Returns an Array — typed as [Array] because GDScript can't express heterogeneous element
+## types. The runtime variant is [Array][[Product]] for IN_APP, [Array][[ProductSubscription]]
+## for SUBS, or a mixed Array for ALL.
+##
+## [codeblock]
+## var request = ProductRequest.new()
+## request.skus = ["com.app.coins_100", "com.app.premium"]
+## request.type = ProductQueryType.IN_APP
+## var products = await iap.fetch_products(request)
+## [/codeblock]
+##
+## [b]Note:[/b] This is a regular awaitable call. Don't confuse with [code]request_*[/code]
+## APIs (e.g. [method request_purchase]), which are event-based.
+##
+## See: https://www.openiap.dev/docs/apis/fetch-products
func fetch_products(request) -> Array:
print("[GodotIap] fetch_products called")
var result = await _fetch_products_raw(request.to_dict())
@@ -303,9 +336,28 @@ func _fetch_products_raw(request: Dictionary) -> Dictionary:
# Purchases (OpenIAP Mutation)
# ==========================================
-## Request a purchase from the store.
-## @param props: Types.RequestPurchaseProps - purchase request properties
-## @return Types.PurchaseAndroid or Types.PurchaseIOS on success, null on failure
+## Initiate a purchase or subscription flow. The result is delivered via the
+## [signal purchase_updated] / [signal purchase_error] signals — NOT the return value.
+##
+## [param props]: [RequestPurchaseProps]. Set [code]props.request.apple.sku[/code] for iOS
+## and/or [code]props.request.google.skus[/code] for Android. Subscriptions also need
+## [code]subscription_offers[/code] on Android.
+##
+## Returns the dispatched purchase payload — [b]do not rely on it[/b] for the outcome.
+##
+## [codeblock]
+## var props = RequestPurchaseProps.new()
+## props.request = RequestPurchasePropsByPlatforms.new()
+## props.request.apple = RequestPurchaseIosProps.new()
+## props.request.apple.sku = "com.app.premium"
+## props.type = ProductQueryType.IN_APP
+## await iap.request_purchase(props)
+## [/codeblock]
+##
+## [b]Warning:[/b] Event-based. Connect to [signal purchase_updated] /
+## [signal purchase_error] before calling this.
+##
+## See: https://www.openiap.dev/docs/apis/request-purchase
func request_purchase(props) -> Variant:
var result = _request_purchase_raw(props.to_dict())
if result.get("success", false):
@@ -374,10 +426,20 @@ func _request_purchase_raw(args: Dictionary) -> Dictionary:
print("[GodotIap] requestPurchase parse error for: ", result_json)
return { "success": false, "error": "Failed to parse response" }
-## Finish a transaction (acknowledge or consume).
-## @param purchase: Types.PurchaseInput - the purchase to finish
-## @param is_consumable: bool - whether to consume (true) or acknowledge (false)
-## @return Types.VoidResult
+## Complete a purchase transaction. Call after server-side verification.
+##
+## [param purchase]: the [Purchase] to finalize.
+## [param is_consumable]: [code]true[/code] for consumables (re-buyable like coins),
+## [code]false[/code] (default) for non-consumables and subscriptions.
+##
+## [codeblock]
+## await iap.finish_transaction(purchase, false)
+## [/codeblock]
+##
+## [b]Critical:[/b] Android purchases must be finalized within 3 days or Google auto-refunds.
+## iOS unfinished transactions replay on every app launch.
+##
+## See: https://www.openiap.dev/docs/apis/finish-transaction
func finish_transaction(purchase, is_consumable: bool = false) -> Variant:
print("[GodotIap] finish_transaction called, consumable: ", is_consumable)
var result = _finish_transaction_raw(purchase.to_dict(), is_consumable)
@@ -435,6 +497,8 @@ func _finish_transaction_raw(purchase: Dictionary, is_consumable: bool) -> Dicti
## iOS: Performs a lightweight sync then fetches available purchases.
## Android: Simply fetches available purchases.
## @return Types.VoidResult
+##
+## See: https://www.openiap.dev/docs/apis/restore-purchases
func restore_purchases() -> Variant:
print("[GodotIap] restore_purchases called")
@@ -447,9 +511,22 @@ func restore_purchases() -> Variant:
result.success = true
return result
-## Get available (owned) purchases.
-## @param options: Types.PurchaseOptions or null - optional purchase query options
-## @return Array[Types.PurchaseAndroid] or Array[Types.PurchaseIOS] depending on platform
+## List the user's unfinished purchases — non-consumables, active subscriptions, and any
+## pending transactions not finished previously.
+##
+## [param options] (optional): [PurchaseOptions]. iOS-only flags
+## ([code]also_publish_to_event_listener_ios[/code], [code]only_include_active_items_ios[/code]).
+##
+## Returns [Array][[Purchase]] currently held by the store.
+##
+## [codeblock]
+## var purchases = await iap.get_available_purchases()
+## for purchase in purchases:
+## if await verify_on_server(purchase):
+## await iap.finish_transaction(purchase, false)
+## [/codeblock]
+##
+## See: https://www.openiap.dev/docs/apis/get-available-purchases
func get_available_purchases(options = null) -> Array:
print("[GodotIap] get_available_purchases called")
var raw_purchases = _get_available_purchases_raw()
@@ -484,6 +561,8 @@ func _get_available_purchases_raw() -> Array:
## Get active subscriptions.
## @param subscription_ids: Array[String] - optional array of subscription IDs to filter
## @return Array[Types.ActiveSubscription]
+##
+## See: https://www.openiap.dev/docs/apis/get-active-subscriptions
func get_active_subscriptions(subscription_ids: Array[String] = []) -> Array:
print("[GodotIap] get_active_subscriptions called")
var raw_subs = _get_active_subscriptions_raw(subscription_ids)
@@ -512,6 +591,8 @@ func _get_active_subscriptions_raw(subscription_ids: Array = []) -> Array:
## Check if user has any active subscriptions.
## @param subscription_ids: Array[String] - optional array of subscription IDs to check
## @return bool - true if any subscription is active
+##
+## See: https://www.openiap.dev/docs/apis/has-active-subscriptions
func has_active_subscriptions(subscription_ids: Array[String] = []) -> bool:
print("[GodotIap] has_active_subscriptions called")
if _native_plugin and (_platform == "Android" or _platform == "iOS"):
@@ -533,6 +614,8 @@ func has_active_subscriptions(subscription_ids: Array[String] = []) -> bool:
## Get the current storefront country code.
## @return String - country code (e.g., "US")
+##
+## See: https://www.openiap.dev/docs/apis/get-storefront
func get_storefront() -> String:
print("[GodotIap] get_storefront called")
if _native_plugin:
@@ -556,6 +639,8 @@ func get_storefront() -> String:
## Verify a purchase locally.
## @param props: Types.VerifyPurchaseProps - verification properties
## @return Types.VerifyPurchaseResultIOS or Types.VerifyPurchaseResultAndroid, or null on failure
+##
+## See: https://www.openiap.dev/docs/features/validation#verify-purchase
func verify_purchase(props) -> Variant:
print("[GodotIap] verify_purchase called")
var result = _verify_purchase_raw(props.to_dict())
@@ -580,6 +665,8 @@ func _verify_purchase_raw(props: Dictionary) -> Dictionary:
## Verify a purchase using external provider (IAPKit).
## @param props: Types.VerifyPurchaseWithProviderProps - provider verification properties
## @return Types.VerifyPurchaseWithProviderResult
+##
+## See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
func verify_purchase_with_provider(props) -> Variant:
print("[GodotIap] verify_purchase_with_provider called")
var result = _verify_purchase_with_provider_raw(props.to_dict())
@@ -603,6 +690,8 @@ func _verify_purchase_with_provider_raw(props: Dictionary) -> Dictionary:
## Sync with App Store (iOS only).
## @return Types.VoidResult
+##
+## See: https://www.openiap.dev/docs/apis/ios/sync-ios
func sync_ios() -> Variant:
var result = Types.VoidResult.new()
result.success = false
@@ -615,6 +704,8 @@ func sync_ios() -> Variant:
## Clear pending transactions from the StoreKit payment queue (iOS only).
## @return Types.VoidResult
+##
+## See: https://www.openiap.dev/docs/apis/ios/clear-transaction-ios
func clear_transaction_ios() -> Variant:
var result = Types.VoidResult.new()
result.success = false
@@ -627,6 +718,8 @@ func clear_transaction_ios() -> Variant:
## Get pending transactions (iOS only).
## @return Array[Types.PurchaseIOS]
+##
+## See: https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios
func get_pending_transactions_ios() -> Array:
var purchases: Array = []
if _native_plugin and _platform == "iOS":
@@ -644,6 +737,8 @@ func get_pending_transactions_ios() -> Array:
## Get all transactions including finished consumables (iOS only).
## Requires SK2ConsumableTransactionHistory Info.plist key for finished consumables (iOS 18+).
## @return Array of Types.PurchaseIOS
+##
+## See: https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios
func get_all_transactions_ios() -> Array:
var purchases: Array = []
if _native_plugin and _platform == "iOS":
@@ -660,6 +755,8 @@ func get_all_transactions_ios() -> Array:
## Present code redemption sheet (iOS only).
## @return Types.VoidResult
+##
+## See: https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios
func present_code_redemption_sheet_ios() -> Variant:
var result = Types.VoidResult.new()
result.success = false
@@ -672,6 +769,8 @@ func present_code_redemption_sheet_ios() -> Variant:
## Show manage subscriptions UI (iOS only).
## @return Array[Types.PurchaseIOS] - changed purchases
+##
+## See: https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios
func show_manage_subscriptions_ios() -> Array:
var purchases: Array = []
if _native_plugin and _platform == "iOS":
@@ -689,6 +788,8 @@ func show_manage_subscriptions_ios() -> Array:
## Begin refund request (iOS only).
## @param product_id: String - the product ID to request refund for
## @return Types.RefundResultIOS
+##
+## See: https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios
func begin_refund_request_ios(product_id: String) -> Variant:
if _native_plugin and _platform == "iOS":
var result_json = _native_plugin.call("beginRefundRequestIOS", product_id)
@@ -701,6 +802,8 @@ func begin_refund_request_ios(product_id: String) -> Variant:
## Get current entitlement for a product (iOS only).
## @param sku: String - product SKU
## @return Types.PurchaseIOS or null
+##
+## See: https://www.openiap.dev/docs/apis/ios/current-entitlement-ios
func current_entitlement_ios(sku: String) -> Variant:
if _native_plugin and _platform == "iOS":
var result_json = _native_plugin.call("currentEntitlementIOS", sku)
@@ -716,6 +819,8 @@ func current_entitlement_ios(sku: String) -> Variant:
## Get the latest transaction for a product (iOS only).
## @param sku: String - product SKU
## @return Types.PurchaseIOS or null
+##
+## See: https://www.openiap.dev/docs/apis/ios/latest-transaction-ios
func latest_transaction_ios(sku: String) -> Variant:
if _native_plugin and _platform == "iOS":
var result_json = _native_plugin.call("latestTransactionIOS", sku)
@@ -730,6 +835,8 @@ func latest_transaction_ios(sku: String) -> Variant:
## Get app transaction (iOS 16+).
## @return Types.AppTransaction or null
+##
+## See: https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios
func get_app_transaction_ios() -> Variant:
if _native_plugin and _platform == "iOS":
var result_json = _native_plugin.call("getAppTransactionIOS")
@@ -744,6 +851,8 @@ func get_app_transaction_ios() -> Variant:
## Get subscription status (iOS only).
## @param sku: String - product SKU
## @return Array[Types.SubscriptionStatusIOS]
+##
+## See: https://www.openiap.dev/docs/apis/ios/subscription-status-ios
func subscription_status_ios(sku: String) -> Array:
var statuses: Array = []
if _native_plugin and _platform == "iOS":
@@ -761,6 +870,8 @@ func subscription_status_ios(sku: String) -> Array:
## Check if eligible for intro offer (iOS only).
## @param group_id: String - subscription group ID
## @return bool - true if eligible for introductory offer
+##
+## See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios
func is_eligible_for_intro_offer_ios(group_id: String) -> bool:
if _native_plugin and _platform == "iOS":
var result_json = _native_plugin.call("isEligibleForIntroOfferIOS", group_id)
@@ -771,6 +882,8 @@ func is_eligible_for_intro_offer_ios(group_id: String) -> bool:
## Get promoted product (iOS only).
## @return Types.ProductIOS or null
+##
+## See: https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios
func get_promoted_product_ios() -> Variant:
if _native_plugin and _platform == "iOS":
var result_json = _native_plugin.call("getPromotedProductIOS")
@@ -785,6 +898,8 @@ func get_promoted_product_ios() -> Variant:
## Request purchase on promoted product (iOS only).
## @return Types.VoidResult
+##
+## See: https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios
func request_purchase_on_promoted_product_ios() -> Variant:
var result = Types.VoidResult.new()
result.success = false
@@ -797,6 +912,8 @@ func request_purchase_on_promoted_product_ios() -> Variant:
## Check if can present external purchase notice (iOS 18.2+).
## @return bool - true if external purchase notice can be presented
+##
+## See: https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios
func can_present_external_purchase_notice_ios() -> bool:
if _native_plugin and _platform == "iOS":
var result_json = _native_plugin.call("canPresentExternalPurchaseNoticeIOS")
@@ -807,6 +924,8 @@ func can_present_external_purchase_notice_ios() -> bool:
## Present external purchase notice sheet (iOS 18.2+).
## @return Types.ExternalPurchaseNoticeResultIOS
+##
+## See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios
func present_external_purchase_notice_sheet_ios() -> Variant:
if _native_plugin and _platform == "iOS":
var result_json = _native_plugin.call("presentExternalPurchaseNoticeSheetIOS")
@@ -819,6 +938,8 @@ func present_external_purchase_notice_sheet_ios() -> Variant:
## Present external purchase link (iOS 18.2+).
## @param url: String - external purchase URL
## @return Types.ExternalPurchaseLinkResultIOS
+##
+## See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios
func present_external_purchase_link_ios(url: String) -> Variant:
if _native_plugin and _platform == "iOS":
var result_json = _native_plugin.call("presentExternalPurchaseLinkIOS", url)
@@ -830,6 +951,8 @@ func present_external_purchase_link_ios(url: String) -> Variant:
## Get receipt data (iOS only).
## @return String - receipt data as base64
+##
+## See: https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios
func get_receipt_data_ios() -> String:
if _native_plugin and _platform == "iOS":
var result_json = _native_plugin.call("getReceiptDataIOS")
@@ -841,6 +964,8 @@ func get_receipt_data_ios() -> String:
## Check if transaction is verified (iOS only).
## @param sku: String - product SKU
## @return bool - true if transaction is verified
+##
+## See: https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios
func is_transaction_verified_ios(sku: String) -> bool:
if _native_plugin and _platform == "iOS":
var result_json = _native_plugin.call("isTransactionVerifiedIOS", sku)
@@ -852,6 +977,8 @@ func is_transaction_verified_ios(sku: String) -> bool:
## Get transaction JWS (iOS only).
## @param sku: String - product SKU
## @return String - JWS representation of the transaction
+##
+## See: https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios
func get_transaction_jws_ios(sku: String) -> String:
if _native_plugin and _platform == "iOS":
var result_json = _native_plugin.call("getTransactionJwsIOS", sku)
@@ -887,6 +1014,8 @@ func _parse_request_id(pending_json) -> String:
## code, so callers can use it like a synchronous getter.
## @deprecated Prefer cross-platform get_storefront() which also works on iOS.
## @return String ISO 3166-1 alpha-2 country code, or empty string on failure
+##
+## See: https://www.openiap.dev/docs/apis/ios/get-storefront-ios
func get_storefront_ios() -> String:
if not (_native_plugin and _platform == "iOS"):
return ""
@@ -903,6 +1032,8 @@ func get_storefront_ios() -> String:
## @deprecated Use verify_purchase or verify_purchase_with_provider instead.
## @param props: Types.VerifyPurchaseProps with `apple: {sku: String}` set
## @return Variant Types.VerifyPurchaseResultIOS on success, null otherwise
+##
+## See: https://www.openiap.dev/docs/apis/ios/validate-receipt-ios
func validate_receipt_ios(props) -> Variant:
if not (_native_plugin and _platform == "iOS"):
return null
@@ -922,6 +1053,8 @@ func validate_receipt_ios(props) -> Variant:
## @deprecated Use verify_purchase instead.
## @param props: Types.VerifyPurchaseProps with platform-specific fields
## @return Variant Types.VerifyPurchaseResultIOS | Types.VerifyPurchaseResultAndroid | null
+##
+## See: https://www.openiap.dev/docs/apis/validate-receipt
func validate_receipt(props) -> Variant:
if _platform == "iOS":
return await validate_receipt_ios(props)
@@ -938,6 +1071,8 @@ func validate_receipt(props) -> Variant:
## emit tagged with method == "isEligibleForExternalPurchaseCustomLinkIOS";
## returns false on any error.
## @return bool true if the current context can show external purchase custom link
+##
+## See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios
func is_eligible_for_external_purchase_custom_link_ios() -> bool:
if not (_native_plugin and _platform == "iOS"):
return false
@@ -954,6 +1089,8 @@ func is_eligible_for_external_purchase_custom_link_ios() -> bool:
## Returns null on error or on unsupported platforms (i.e. iOS < 18.1).
## @param token_type: String "acquisition" | "services"
## @return Variant Types.ExternalPurchaseCustomLinkTokenResultIOS or null
+##
+## See: https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios
func get_external_purchase_custom_link_token_ios(token_type: String) -> Variant:
if not (_native_plugin and _platform == "iOS"):
return null
@@ -973,6 +1110,8 @@ func get_external_purchase_custom_link_token_ios(token_type: String) -> Variant:
## null on error.
## @param notice_type: String "browser"
## @return Variant Types.ExternalPurchaseCustomLinkNoticeResultIOS or null
+##
+## See: https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios
func show_external_purchase_custom_link_notice_ios(notice_type: String) -> Variant:
if not (_native_plugin and _platform == "iOS"):
return null
@@ -993,6 +1132,8 @@ func show_external_purchase_custom_link_notice_ios(notice_type: String) -> Varia
## Acknowledge a purchase (Android only, for non-consumables).
## @param purchase_token: String - the purchase token to acknowledge
## @return Types.VoidResult
+##
+## See: https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android
func acknowledge_purchase_android(purchase_token: String) -> Variant:
var result = _acknowledge_purchase_android_raw(purchase_token)
return Types.VoidResult.from_dict(result)
@@ -1012,6 +1153,8 @@ func _acknowledge_purchase_android_raw(purchase_token: String) -> Dictionary:
## Consume a purchase (Android only, for consumables).
## @param purchase_token: String - the purchase token to consume
## @return Types.VoidResult
+##
+## See: https://www.openiap.dev/docs/apis/android/consume-purchase-android
func consume_purchase_android(purchase_token: String) -> Variant:
var result = _consume_purchase_android_raw(purchase_token)
return Types.VoidResult.from_dict(result)
@@ -1030,6 +1173,8 @@ func _consume_purchase_android_raw(purchase_token: String) -> Dictionary:
## Check alternative billing availability (Android).
## @return Types.BillingProgramAvailabilityResultAndroid
+##
+## See: https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android
func check_alternative_billing_availability_android() -> Variant:
if _native_plugin and _platform == "Android":
var result_json = _native_plugin.call("checkAlternativeBillingAvailabilityAndroid")
@@ -1042,6 +1187,8 @@ func check_alternative_billing_availability_android() -> Variant:
## Show alternative billing dialog (Android).
## @return Types.UserChoiceBillingDetails
+##
+## See: https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android
func show_alternative_billing_dialog_android() -> Variant:
if _native_plugin and _platform == "Android":
var result_json = _native_plugin.call("showAlternativeBillingDialogAndroid")
@@ -1053,6 +1200,8 @@ func show_alternative_billing_dialog_android() -> Variant:
## Create alternative billing token (Android).
## @return Types.BillingProgramReportingDetailsAndroid
+##
+## See: https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android
func create_alternative_billing_token_android() -> Variant:
if _native_plugin and _platform == "Android":
var result_json = _native_plugin.call("createAlternativeBillingTokenAndroid")
@@ -1065,6 +1214,8 @@ func create_alternative_billing_token_android() -> Variant:
## Check if a billing program is available (Android 8.2.0+).
## @param billing_program: Types.BillingProgramAndroid - billing program enum value
## @return Types.BillingProgramAvailabilityResultAndroid
+##
+## See: https://www.openiap.dev/docs/apis/android/is-billing-program-available-android
func is_billing_program_available_android(billing_program) -> Variant:
if _native_plugin and _platform == "Android":
var result_json = _native_plugin.call("isBillingProgramAvailableAndroid", billing_program)
@@ -1079,6 +1230,8 @@ func is_billing_program_available_android(billing_program) -> Variant:
## Launch external link (Android 8.2.0+).
## @param params: Types.LaunchExternalLinkParamsAndroid - external link parameters
## @return Types.VoidResult
+##
+## See: https://www.openiap.dev/docs/apis/android/launch-external-link-android
func launch_external_link_android(params) -> Variant:
if _native_plugin and _platform == "Android":
var params_json = JSON.stringify(params.to_dict())
@@ -1093,6 +1246,8 @@ func launch_external_link_android(params) -> Variant:
## Create billing program reporting details (Android 8.2.0+).
## @param billing_program: Types.BillingProgramAndroid - billing program enum value
## @return Types.BillingProgramReportingDetailsAndroid
+##
+## See: https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android
func create_billing_program_reporting_details_android(billing_program) -> Variant:
if _native_plugin and _platform == "Android":
var result_json = _native_plugin.call("createBillingProgramReportingDetailsAndroid", billing_program)
@@ -1117,6 +1272,8 @@ func get_package_name_android() -> String:
## Open subscription management deep link.
## @param options: Types.DeepLinkOptions or null - optional deep link configuration
## @return void
+##
+## See: https://www.openiap.dev/docs/apis/deep-link-to-subscriptions
func deep_link_to_subscriptions(options = null) -> void:
var opts = options if options != null else Types.DeepLinkOptions.new()
if _native_plugin and (_platform == "Android" or _platform == "iOS"):
diff --git a/libraries/godot-iap/addons/godot-iap/types.gd b/libraries/godot-iap/addons/godot-iap/types.gd
index f1b51f5a..a475be19 100644
--- a/libraries/godot-iap/addons/godot-iap/types.gd
+++ b/libraries/godot-iap/addons/godot-iap/types.gd
@@ -4800,7 +4800,7 @@ class Query:
const return_type = "Boolean"
const is_array = false
- ## Retrieve products or subscriptions from the store
+ ## Fetch products or subscriptions from the store.
class fetchProductsField:
const name = "fetchProducts"
const snake_name = "fetch_products"
@@ -4820,7 +4820,7 @@ class Query:
const return_type = "FetchProductsResult"
const is_array = false
- ## Get all available purchases for the current user
+ ## List active purchases for the current user.
class getAvailablePurchasesField:
const name = "getAvailablePurchases"
const snake_name = "get_available_purchases"
@@ -4840,7 +4840,7 @@ class Query:
const return_type = "Purchase"
const is_array = true
- ## Get active subscriptions (filters by subscriptionIds when provided)
+ ## Get details of all currently active subscriptions (filters by subscriptionIds when provided).
class getActiveSubscriptionsField:
const name = "getActiveSubscriptions"
const snake_name = "get_active_subscriptions"
@@ -4860,7 +4860,7 @@ class Query:
const return_type = "ActiveSubscription"
const is_array = true
- ## Check whether the user has active subscriptions
+ ## Check whether the user has any active subscription.
class hasActiveSubscriptionsField:
const name = "hasActiveSubscriptions"
const snake_name = "has_active_subscriptions"
@@ -4880,7 +4880,7 @@ class Query:
const return_type = "Boolean"
const is_array = false
- ## Get the current storefront country code
+ ## Return the user's storefront country code.
class getStorefrontField:
const name = "getStorefront"
const snake_name = "get_storefront"
@@ -4889,7 +4889,7 @@ class Query:
const return_type = "String"
const is_array = false
- ## Get the current App Store storefront country code
+ ## Deprecated. Get the current App Store storefront country code — use cross-platform getStorefront instead.
class getStorefrontIOSField:
const name = "getStorefrontIOS"
const snake_name = "get_storefront_ios"
@@ -4898,7 +4898,7 @@ class Query:
const return_type = "String"
const is_array = false
- ## Get the currently promoted product (iOS 11+)
+ ## Read the App Store-promoted product, if any (iOS 11+).
class getPromotedProductIOSField:
const name = "getPromotedProductIOS"
const snake_name = "get_promoted_product_ios"
@@ -4907,7 +4907,7 @@ class Query:
const return_type = "ProductIOS"
const is_array = false
- ## Check if external purchase notice sheet can be presented (iOS 17.4+)
+ ## Check eligibility for the external purchase notice sheet (iOS 17.4+).
class canPresentExternalPurchaseNoticeIOSField:
const name = "canPresentExternalPurchaseNoticeIOS"
const snake_name = "can_present_external_purchase_notice_ios"
@@ -4916,7 +4916,7 @@ class Query:
const return_type = "Boolean"
const is_array = false
- ## Check if app is eligible for ExternalPurchaseCustomLink API (iOS 18.1+).
+ ## Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
class isEligibleForExternalPurchaseCustomLinkIOSField:
const name = "isEligibleForExternalPurchaseCustomLinkIOS"
const snake_name = "is_eligible_for_external_purchase_custom_link_ios"
@@ -4925,7 +4925,7 @@ class Query:
const return_type = "Boolean"
const is_array = false
- ## Get external purchase token for reporting to Apple (iOS 18.1+).
+ ## Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
class getExternalPurchaseCustomLinkTokenIOSField:
const name = "getExternalPurchaseCustomLinkTokenIOS"
const snake_name = "get_external_purchase_custom_link_token_ios"
@@ -4953,7 +4953,7 @@ class Query:
const return_type = "ExternalPurchaseCustomLinkTokenResultIOS"
const is_array = false
- ## Retrieve all pending transactions in the StoreKit queue
+ ## List unfinished StoreKit transactions in the queue.
class getPendingTransactionsIOSField:
const name = "getPendingTransactionsIOS"
const snake_name = "get_pending_transactions_ios"
@@ -4962,7 +4962,7 @@ class Query:
const return_type = "PurchaseIOS"
const is_array = true
- ## Check introductory offer eligibility for a subscription group
+ ## Check intro-offer eligibility for a subscription group.
class isEligibleForIntroOfferIOSField:
const name = "isEligibleForIntroOfferIOS"
const snake_name = "is_eligible_for_intro_offer_ios"
@@ -4982,7 +4982,7 @@ class Query:
const return_type = "Boolean"
const is_array = false
- ## Get StoreKit 2 subscription status details (iOS 15+)
+ ## Get subscription status objects from StoreKit 2 (iOS 15+).
class subscriptionStatusIOSField:
const name = "subscriptionStatusIOS"
const snake_name = "subscription_status_ios"
@@ -5002,7 +5002,7 @@ class Query:
const return_type = "SubscriptionStatusIOS"
const is_array = true
- ## Get current StoreKit 2 entitlements (iOS 15+)
+ ## Get the user's current entitlement for a product, using StoreKit 2 (iOS 15+).
class currentEntitlementIOSField:
const name = "currentEntitlementIOS"
const snake_name = "current_entitlement_ios"
@@ -5022,7 +5022,7 @@ class Query:
const return_type = "PurchaseIOS"
const is_array = false
- ## Get the latest transaction for a product using StoreKit 2
+ ## Get the latest verified transaction for a product, using StoreKit 2.
class latestTransactionIOSField:
const name = "latestTransactionIOS"
const snake_name = "latest_transaction_ios"
@@ -5042,7 +5042,7 @@ class Query:
const return_type = "PurchaseIOS"
const is_array = false
- ## Verify a StoreKit 2 transaction signature
+ ## Check whether a transaction's JWS verification passed (StoreKit 2).
class isTransactionVerifiedIOSField:
const name = "isTransactionVerifiedIOS"
const snake_name = "is_transaction_verified_ios"
@@ -5062,7 +5062,7 @@ class Query:
const return_type = "Boolean"
const is_array = false
- ## Get the transaction JWS (StoreKit 2)
+ ## Return the JWS string for a transaction (StoreKit 2).
class getTransactionJwsIOSField:
const name = "getTransactionJwsIOS"
const snake_name = "get_transaction_jws_ios"
@@ -5082,7 +5082,7 @@ class Query:
const return_type = "String"
const is_array = false
- ## Get base64-encoded receipt data for validation
+ ## Get base64-encoded receipt data (legacy validation).
class getReceiptDataIOSField:
const name = "getReceiptDataIOS"
const snake_name = "get_receipt_data_ios"
@@ -5091,7 +5091,7 @@ class Query:
const return_type = "String"
const is_array = false
- ## Fetch the current app transaction (iOS 16+)
+ ## Fetch the app transaction (iOS 16+).
class getAppTransactionIOSField:
const name = "getAppTransactionIOS"
const snake_name = "get_app_transaction_ios"
@@ -5100,7 +5100,7 @@ class Query:
const return_type = "AppTransaction"
const is_array = false
- ## Get the full StoreKit 2 transaction history as PurchaseIOS values.
+ ## List every StoreKit transaction (finished + unfinished) for the current user.
class getAllTransactionsIOSField:
const name = "getAllTransactionsIOS"
const snake_name = "get_all_transactions_ios"
@@ -5109,7 +5109,7 @@ class Query:
const return_type = "PurchaseIOS"
const is_array = true
- ## Validate a receipt for a specific product
+ ## Deprecated. Legacy App Store receipt validation — use verifyPurchase instead.
class validateReceiptIOSField:
const name = "validateReceiptIOS"
const snake_name = "validate_receipt_ios"
@@ -5143,7 +5143,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Establish the platform billing connection
+ ## Initialize the store connection. Call before any IAP API.
class initConnectionField:
const name = "initConnection"
const snake_name = "init_connection"
@@ -5163,7 +5163,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Close the platform billing connection
+ ## Close the store connection and release resources.
class endConnectionField:
const name = "endConnection"
const snake_name = "end_connection"
@@ -5172,7 +5172,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Initiate a purchase flow; rely on events for final state
+ ## Initiate a purchase or subscription flow; rely on events for final state.
class requestPurchaseField:
const name = "requestPurchase"
const snake_name = "request_purchase"
@@ -5192,7 +5192,7 @@ class Mutation:
const return_type = "RequestPurchaseResult"
const is_array = false
- ## Finish a transaction after validating receipts
+ ## Complete a transaction after server-side verification. Required on Android within 3 days.
class finishTransactionField:
const name = "finishTransaction"
const snake_name = "finish_transaction"
@@ -5216,7 +5216,7 @@ class Mutation:
const return_type = "VoidResult"
const is_array = false
- ## Restore completed purchases across platforms
+ ## Restore non-consumable and active subscription purchases.
class restorePurchasesField:
const name = "restorePurchases"
const snake_name = "restore_purchases"
@@ -5225,7 +5225,7 @@ class Mutation:
const return_type = "VoidResult"
const is_array = false
- ## Open the native subscription management surface
+ ## Open the platform's subscription management UI.
class deepLinkToSubscriptionsField:
const name = "deepLinkToSubscriptions"
const snake_name = "deep_link_to_subscriptions"
@@ -5245,7 +5245,7 @@ class Mutation:
const return_type = "VoidResult"
const is_array = false
- ## Validate purchase receipts with the configured providers
+ ## Deprecated. Validate purchase receipts with the configured providers — use verifyPurchase instead.
class validateReceiptField:
const name = "validateReceipt"
const snake_name = "validate_receipt"
@@ -5265,7 +5265,7 @@ class Mutation:
const return_type = "VerifyPurchaseResult"
const is_array = false
- ## Verify purchases with the configured providers
+ ## Verify a purchase against your own backend (returns isValid + raw store metadata).
class verifyPurchaseField:
const name = "verifyPurchase"
const snake_name = "verify_purchase"
@@ -5285,7 +5285,7 @@ class Mutation:
const return_type = "VerifyPurchaseResult"
const is_array = false
- ## Verify purchases with a specific provider (e.g., IAPKit)
+ ## Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
class verifyPurchaseWithProviderField:
const name = "verifyPurchaseWithProvider"
const snake_name = "verify_purchase_with_provider"
@@ -5305,7 +5305,7 @@ class Mutation:
const return_type = "VerifyPurchaseWithProviderResult"
const is_array = false
- ## Clear pending transactions from the StoreKit payment queue
+ ## Clear pending transactions in the queue (sandbox helper).
class clearTransactionIOSField:
const name = "clearTransactionIOS"
const snake_name = "clear_transaction_ios"
@@ -5314,7 +5314,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Purchase the promoted product surfaced by the App Store.
+ ## Buy the currently promoted product.
class requestPurchaseOnPromotedProductIOSField:
const name = "requestPurchaseOnPromotedProductIOS"
const snake_name = "request_purchase_on_promoted_product_ios"
@@ -5323,7 +5323,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Open subscription management UI and return changed purchases (iOS 15+)
+ ## Present the manage-subscriptions sheet and return changed purchases (iOS 15+).
class showManageSubscriptionsIOSField:
const name = "showManageSubscriptionsIOS"
const snake_name = "show_manage_subscriptions_ios"
@@ -5332,7 +5332,7 @@ class Mutation:
const return_type = "PurchaseIOS"
const is_array = true
- ## Initiate a refund request for a product (iOS 15+)
+ ## Present the refund request sheet (iOS 15+). See also Features → Refund.
class beginRefundRequestIOSField:
const name = "beginRefundRequestIOS"
const snake_name = "begin_refund_request_ios"
@@ -5352,7 +5352,7 @@ class Mutation:
const return_type = "String"
const is_array = false
- ## Force a StoreKit sync for transactions (iOS 15+)
+ ## Force sync transactions with the App Store (iOS 15+).
class syncIOSField:
const name = "syncIOS"
const snake_name = "sync_ios"
@@ -5361,7 +5361,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Present the App Store code redemption sheet
+ ## Show the App Store offer code redemption sheet.
class presentCodeRedemptionSheetIOSField:
const name = "presentCodeRedemptionSheetIOS"
const snake_name = "present_code_redemption_sheet_ios"
@@ -5370,7 +5370,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Present external purchase notice sheet (iOS 17.4+).
+ ## Present the external purchase notice sheet (iOS 17.4+).
class presentExternalPurchaseNoticeSheetIOSField:
const name = "presentExternalPurchaseNoticeSheetIOS"
const snake_name = "present_external_purchase_notice_sheet_ios"
@@ -5379,7 +5379,7 @@ class Mutation:
const return_type = "ExternalPurchaseNoticeResultIOS"
const is_array = false
- ## Present external purchase custom link with StoreKit UI
+ ## Present an external purchase link, StoreKit External (iOS 16+).
class presentExternalPurchaseLinkIOSField:
const name = "presentExternalPurchaseLinkIOS"
const snake_name = "present_external_purchase_link_ios"
@@ -5399,7 +5399,7 @@ class Mutation:
const return_type = "ExternalPurchaseLinkResultIOS"
const is_array = false
- ## Show ExternalPurchaseCustomLink notice sheet (iOS 18.1+).
+ ## Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
class showExternalPurchaseCustomLinkNoticeIOSField:
const name = "showExternalPurchaseCustomLinkNoticeIOS"
const snake_name = "show_external_purchase_custom_link_notice_ios"
@@ -5427,7 +5427,7 @@ class Mutation:
const return_type = "ExternalPurchaseCustomLinkNoticeResultIOS"
const is_array = false
- ## Acknowledge a non-consumable purchase or subscription
+ ## Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
class acknowledgePurchaseAndroidField:
const name = "acknowledgePurchaseAndroid"
const snake_name = "acknowledge_purchase_android"
@@ -5447,7 +5447,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Consume a purchase token so it can be repurchased
+ ## Consume a consumable purchase so it can be re-bought.
class consumePurchaseAndroidField:
const name = "consumePurchaseAndroid"
const snake_name = "consume_purchase_android"
@@ -5467,7 +5467,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Check if alternative billing is available for this user/device
+ ## Check whether alternative billing is available for the user. Step 1 of the alternative billing flow.
class checkAlternativeBillingAvailabilityAndroidField:
const name = "checkAlternativeBillingAvailabilityAndroid"
const snake_name = "check_alternative_billing_availability_android"
@@ -5476,7 +5476,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Show alternative billing information dialog to user
+ ## Display Google's alternative billing information dialog. Step 2 of the alternative billing flow.
class showAlternativeBillingDialogAndroidField:
const name = "showAlternativeBillingDialogAndroid"
const snake_name = "show_alternative_billing_dialog_android"
@@ -5485,7 +5485,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Create external transaction token for Google Play reporting
+ ## Create a reporting token for an alternative billing flow. Step 3 of the alternative billing flow.
class createAlternativeBillingTokenAndroidField:
const name = "createAlternativeBillingTokenAndroid"
const snake_name = "create_alternative_billing_token_android"
@@ -5494,7 +5494,7 @@ class Mutation:
const return_type = "String"
const is_array = false
- ## Check if a billing program is available for the current user
+ ## Check whether a billing program (e.g., External Payments) is available for the current user.
class isBillingProgramAvailableAndroidField:
const name = "isBillingProgramAvailableAndroid"
const snake_name = "is_billing_program_available_android"
@@ -5521,7 +5521,7 @@ class Mutation:
const return_type = "BillingProgramAvailabilityResultAndroid"
const is_array = false
- ## Create reporting details for a billing program
+ ## Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+).
class createBillingProgramReportingDetailsAndroidField:
const name = "createBillingProgramReportingDetailsAndroid"
const snake_name = "create_billing_program_reporting_details_android"
@@ -5548,7 +5548,7 @@ class Mutation:
const return_type = "BillingProgramReportingDetailsAndroid"
const is_array = false
- ## Launch external link flow for external billing programs
+ ## Launch an external content/offer link from inside the Billing Programs flow (Play Billing 8.2.0+).
class launchExternalLinkAndroidField:
const name = "launchExternalLinkAndroid"
const snake_name = "launch_external_link_android"
@@ -5576,7 +5576,7 @@ class Mutation:
# Query API helpers
-## Retrieve products or subscriptions from the store
+## Fetch products or subscriptions from the store.
static func fetch_products_args(params: ProductRequest) -> Dictionary:
var args = {}
if params != null:
@@ -5586,7 +5586,7 @@ static func fetch_products_args(params: ProductRequest) -> Dictionary:
args["params"] = params
return args
-## Get all available purchases for the current user
+## List active purchases for the current user.
static func get_available_purchases_args(options: PurchaseOptions) -> Dictionary:
var args = {}
if options != null:
@@ -5596,97 +5596,97 @@ static func get_available_purchases_args(options: PurchaseOptions) -> Dictionary
args["options"] = options
return args
-## Get active subscriptions (filters by subscriptionIds when provided)
+## Get details of all currently active subscriptions (filters by subscriptionIds when provided).
static func get_active_subscriptions_args(subscription_ids: Array[String]) -> Dictionary:
var args = {}
args["subscriptionIds"] = subscription_ids
return args
-## Check whether the user has active subscriptions
+## Check whether the user has any active subscription.
static func has_active_subscriptions_args(subscription_ids: Array[String]) -> Dictionary:
var args = {}
args["subscriptionIds"] = subscription_ids
return args
-## Get the current storefront country code
+## Return the user's storefront country code.
static func get_storefront_args() -> Dictionary:
return {}
-## Get the current App Store storefront country code
+## Deprecated. Get the current App Store storefront country code — use cross-platform getStorefront instead.
static func get_storefront_ios_args() -> Dictionary:
return {}
-## Get the currently promoted product (iOS 11+)
+## Read the App Store-promoted product, if any (iOS 11+).
static func get_promoted_product_ios_args() -> Dictionary:
return {}
-## Check if external purchase notice sheet can be presented (iOS 17.4+)
+## Check eligibility for the external purchase notice sheet (iOS 17.4+).
static func can_present_external_purchase_notice_ios_args() -> Dictionary:
return {}
-## Check if app is eligible for ExternalPurchaseCustomLink API (iOS 18.1+).
+## Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
static func is_eligible_for_external_purchase_custom_link_ios_args() -> Dictionary:
return {}
-## Get external purchase token for reporting to Apple (iOS 18.1+).
+## Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
static func get_external_purchase_custom_link_token_ios_args(token_type: ExternalPurchaseCustomLinkTokenTypeIOS) -> Dictionary:
var args = {}
args["tokenType"] = token_type
return args
-## Retrieve all pending transactions in the StoreKit queue
+## List unfinished StoreKit transactions in the queue.
static func get_pending_transactions_ios_args() -> Dictionary:
return {}
-## Check introductory offer eligibility for a subscription group
+## Check intro-offer eligibility for a subscription group.
static func is_eligible_for_intro_offer_ios_args(group_id: String) -> Dictionary:
var args = {}
args["groupID"] = group_id
return args
-## Get StoreKit 2 subscription status details (iOS 15+)
+## Get subscription status objects from StoreKit 2 (iOS 15+).
static func subscription_status_ios_args(sku: String) -> Dictionary:
var args = {}
args["sku"] = sku
return args
-## Get current StoreKit 2 entitlements (iOS 15+)
+## Get the user's current entitlement for a product, using StoreKit 2 (iOS 15+).
static func current_entitlement_ios_args(sku: String) -> Dictionary:
var args = {}
args["sku"] = sku
return args
-## Get the latest transaction for a product using StoreKit 2
+## Get the latest verified transaction for a product, using StoreKit 2.
static func latest_transaction_ios_args(sku: String) -> Dictionary:
var args = {}
args["sku"] = sku
return args
-## Verify a StoreKit 2 transaction signature
+## Check whether a transaction's JWS verification passed (StoreKit 2).
static func is_transaction_verified_ios_args(sku: String) -> Dictionary:
var args = {}
args["sku"] = sku
return args
-## Get the transaction JWS (StoreKit 2)
+## Return the JWS string for a transaction (StoreKit 2).
static func get_transaction_jws_ios_args(sku: String) -> Dictionary:
var args = {}
args["sku"] = sku
return args
-## Get base64-encoded receipt data for validation
+## Get base64-encoded receipt data (legacy validation).
static func get_receipt_data_ios_args() -> Dictionary:
return {}
-## Fetch the current app transaction (iOS 16+)
+## Fetch the app transaction (iOS 16+).
static func get_app_transaction_ios_args() -> Dictionary:
return {}
-## Get the full StoreKit 2 transaction history as PurchaseIOS values.
+## List every StoreKit transaction (finished + unfinished) for the current user.
static func get_all_transactions_ios_args() -> Dictionary:
return {}
-## Validate a receipt for a specific product
+## Deprecated. Legacy App Store receipt validation — use verifyPurchase instead.
static func validate_receipt_ios_args(options: VerifyPurchaseProps) -> Dictionary:
var args = {}
if options != null:
@@ -5698,7 +5698,7 @@ static func validate_receipt_ios_args(options: VerifyPurchaseProps) -> Dictionar
# Mutation API helpers
-## Establish the platform billing connection
+## Initialize the store connection. Call before any IAP API.
static func init_connection_args(config: InitConnectionConfig) -> Dictionary:
var args = {}
if config != null:
@@ -5708,11 +5708,11 @@ static func init_connection_args(config: InitConnectionConfig) -> Dictionary:
args["config"] = config
return args
-## Close the platform billing connection
+## Close the store connection and release resources.
static func end_connection_args() -> Dictionary:
return {}
-## Initiate a purchase flow; rely on events for final state
+## Initiate a purchase or subscription flow; rely on events for final state.
static func request_purchase_args(params: RequestPurchaseProps) -> Dictionary:
var args = {}
if params != null:
@@ -5722,7 +5722,7 @@ static func request_purchase_args(params: RequestPurchaseProps) -> Dictionary:
args["params"] = params
return args
-## Finish a transaction after validating receipts
+## Complete a transaction after server-side verification. Required on Android within 3 days.
static func finish_transaction_args(purchase: PurchaseInput, is_consumable: bool) -> Dictionary:
var args = {}
if purchase != null:
@@ -5733,11 +5733,11 @@ static func finish_transaction_args(purchase: PurchaseInput, is_consumable: bool
args["isConsumable"] = is_consumable
return args
-## Restore completed purchases across platforms
+## Restore non-consumable and active subscription purchases.
static func restore_purchases_args() -> Dictionary:
return {}
-## Open the native subscription management surface
+## Open the platform's subscription management UI.
static func deep_link_to_subscriptions_args(options: DeepLinkOptions) -> Dictionary:
var args = {}
if options != null:
@@ -5747,7 +5747,7 @@ static func deep_link_to_subscriptions_args(options: DeepLinkOptions) -> Diction
args["options"] = options
return args
-## Validate purchase receipts with the configured providers
+## Deprecated. Validate purchase receipts with the configured providers — use verifyPurchase instead.
static func validate_receipt_args(options: VerifyPurchaseProps) -> Dictionary:
var args = {}
if options != null:
@@ -5757,7 +5757,7 @@ static func validate_receipt_args(options: VerifyPurchaseProps) -> Dictionary:
args["options"] = options
return args
-## Verify purchases with the configured providers
+## Verify a purchase against your own backend (returns isValid + raw store metadata).
static func verify_purchase_args(options: VerifyPurchaseProps) -> Dictionary:
var args = {}
if options != null:
@@ -5767,7 +5767,7 @@ static func verify_purchase_args(options: VerifyPurchaseProps) -> Dictionary:
args["options"] = options
return args
-## Verify purchases with a specific provider (e.g., IAPKit)
+## Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
static func verify_purchase_with_provider_args(options: VerifyPurchaseWithProviderProps) -> Dictionary:
var args = {}
if options != null:
@@ -5777,85 +5777,85 @@ static func verify_purchase_with_provider_args(options: VerifyPurchaseWithProvid
args["options"] = options
return args
-## Clear pending transactions from the StoreKit payment queue
+## Clear pending transactions in the queue (sandbox helper).
static func clear_transaction_ios_args() -> Dictionary:
return {}
-## Purchase the promoted product surfaced by the App Store.
+## Buy the currently promoted product.
static func request_purchase_on_promoted_product_ios_args() -> Dictionary:
return {}
-## Open subscription management UI and return changed purchases (iOS 15+)
+## Present the manage-subscriptions sheet and return changed purchases (iOS 15+).
static func show_manage_subscriptions_ios_args() -> Dictionary:
return {}
-## Initiate a refund request for a product (iOS 15+)
+## Present the refund request sheet (iOS 15+). See also Features → Refund.
static func begin_refund_request_ios_args(sku: String) -> Dictionary:
var args = {}
args["sku"] = sku
return args
-## Force a StoreKit sync for transactions (iOS 15+)
+## Force sync transactions with the App Store (iOS 15+).
static func sync_ios_args() -> Dictionary:
return {}
-## Present the App Store code redemption sheet
+## Show the App Store offer code redemption sheet.
static func present_code_redemption_sheet_ios_args() -> Dictionary:
return {}
-## Present external purchase notice sheet (iOS 17.4+).
+## Present the external purchase notice sheet (iOS 17.4+).
static func present_external_purchase_notice_sheet_ios_args() -> Dictionary:
return {}
-## Present external purchase custom link with StoreKit UI
+## Present an external purchase link, StoreKit External (iOS 16+).
static func present_external_purchase_link_ios_args(url: String) -> Dictionary:
var args = {}
args["url"] = url
return args
-## Show ExternalPurchaseCustomLink notice sheet (iOS 18.1+).
+## Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
static func show_external_purchase_custom_link_notice_ios_args(notice_type: ExternalPurchaseCustomLinkNoticeTypeIOS) -> Dictionary:
var args = {}
args["noticeType"] = notice_type
return args
-## Acknowledge a non-consumable purchase or subscription
+## Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
static func acknowledge_purchase_android_args(purchase_token: String) -> Dictionary:
var args = {}
args["purchaseToken"] = purchase_token
return args
-## Consume a purchase token so it can be repurchased
+## Consume a consumable purchase so it can be re-bought.
static func consume_purchase_android_args(purchase_token: String) -> Dictionary:
var args = {}
args["purchaseToken"] = purchase_token
return args
-## Check if alternative billing is available for this user/device
+## Check whether alternative billing is available for the user. Step 1 of the alternative billing flow.
static func check_alternative_billing_availability_android_args() -> Dictionary:
return {}
-## Show alternative billing information dialog to user
+## Display Google's alternative billing information dialog. Step 2 of the alternative billing flow.
static func show_alternative_billing_dialog_android_args() -> Dictionary:
return {}
-## Create external transaction token for Google Play reporting
+## Create a reporting token for an alternative billing flow. Step 3 of the alternative billing flow.
static func create_alternative_billing_token_android_args() -> Dictionary:
return {}
-## Check if a billing program is available for the current user
+## Check whether a billing program (e.g., External Payments) is available for the current user.
static func is_billing_program_available_android_args(program: BillingProgramAndroid) -> Dictionary:
var args = {}
args["program"] = program
return args
-## Create reporting details for a billing program
+## Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+).
static func create_billing_program_reporting_details_android_args(program: BillingProgramAndroid) -> Dictionary:
var args = {}
args["program"] = program
return args
-## Launch external link flow for external billing programs
+## Launch an external content/offer link from inside the Billing Programs flow (Play Billing 8.2.0+).
static func launch_external_link_android_args(params: LaunchExternalLinkParamsAndroid) -> Dictionary:
var args = {}
if params != null:
diff --git a/libraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseAndroid.kt b/libraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseAndroid.kt
index 23ffe1f8..690d43eb 100644
--- a/libraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseAndroid.kt
+++ b/libraries/kmp-iap/library/src/androidMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseAndroid.kt
@@ -484,47 +484,160 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife
// ---------------------------------------------------------------------
// Interface implementation
// ---------------------------------------------------------------------
+ /**
+ * Initialize the store connection. Must be called before any other IAP API.
+ *
+ * @param config Optional [InitConnectionConfig]. Use `enableBillingProgramAndroid`
+ * (Android, Play Billing 8.2.0+) to opt into External Payments etc.; iOS ignores
+ * Android-specific fields.
+ * @return `true` once the platform billing client is connected.
+ * @throws PurchaseException when the billing client fails to initialize.
+ *
+ * @see init-connection
+ */
override suspend fun initConnection(config: InitConnectionConfig?): Boolean = initConnectionHandler(config)
+ /**
+ * Close the store connection and release resources.
+ *
+ * @see https://www.openiap.dev/docs/apis/end-connection
+ */
override suspend fun endConnection(): Boolean = endConnectionHandler()
+ /**
+ * Retrieve products or subscriptions from the store by SKU.
+ *
+ * @param params [ProductRequest] with `skus` and optional `type`
+ * ([ProductQueryType.InApp], [ProductQueryType.Subs], or [ProductQueryType.All];
+ * defaults to InApp).
+ * @return [FetchProductsResult] sealed variant — Products for InApp, Subscriptions
+ * for Subs, mixed for All.
+ * @throws PurchaseException on store rejection (unknown SKU, network, not connected).
+ *
+ * @see fetch-products
+ */
override suspend fun fetchProducts(params: ProductRequest): FetchProductsResult =
fetchProductsHandler(params)
+ /**
+ * Initiate a purchase or subscription flow. Result is delivered via the
+ * purchaseUpdated event flow — NOT the return value.
+ *
+ * @param props [RequestPurchaseProps]. Pass `request.apple.sku` (iOS) and/or
+ * `request.google.skus` (Android); subscriptions need `subscriptionOffers`.
+ * @return The dispatched purchase payload (do not rely on this for the outcome).
+ * @throws PurchaseException on synchronous rejection (billing not ready, missing offerToken).
+ *
+ * Warning: Event-based. Collect from `purchaseUpdatedListener` / `purchaseErrorListener`
+ * (or the equivalent flows on `KmpIAP`) for the final state.
+ *
+ * @see request-purchase
+ */
override suspend fun requestPurchase(request: RequestPurchaseProps): RequestPurchaseResult? =
requestPurchaseHandler(request)
+ /**
+ * List the user's unfinished purchases — non-consumables, active subscriptions, and
+ * any pending transactions not finished previously.
+ *
+ * @param options Optional [PurchaseOptions]. iOS-only fields
+ * (`alsoPublishToEventListenerIOS`, `onlyIncludeActiveItemsIOS`) are ignored on Android.
+ * @return List of [Purchase] currently held by the platform store.
+ * @throws PurchaseException when the platform query fails.
+ *
+ * @see get-available-purchases
+ */
override suspend fun getAvailablePurchases(options: PurchaseOptions?): List =
getAvailablePurchasesHandler(options)
suspend fun getPurchaseHistories(options: PurchaseOptions?): List = emptyList()
+ /**
+ * Get details of all currently active subscriptions.
+ *
+ * @see https://www.openiap.dev/docs/apis/get-active-subscriptions
+ */
override suspend fun getActiveSubscriptions(subscriptionIds: List?): List =
getActiveSubscriptionsHandler(subscriptionIds)
+ /**
+ * Check whether the user has any active subscription.
+ *
+ * @see https://www.openiap.dev/docs/apis/has-active-subscriptions
+ */
override suspend fun hasActiveSubscriptions(subscriptionIds: List?): Boolean =
hasActiveSubscriptionsHandler(subscriptionIds)
+ /**
+ * Restore non-consumable and active subscription purchases.
+ *
+ * @see https://www.openiap.dev/docs/apis/restore-purchases
+ */
override suspend fun restorePurchases() {
getAvailablePurchasesHandler.invoke(null)
}
+ /**
+ * Get the user's current entitlement for a product.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/current-entitlement-ios
+ */
override suspend fun currentEntitlementIOS(sku: String): PurchaseIOS? = null
+ /**
+ * Fetch the app transaction (iOS 16+).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios
+ */
override suspend fun getAppTransactionIOS(): AppTransaction? = null
+ /**
+ * List unfinished StoreKit transactions.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios
+ */
override suspend fun getPendingTransactionsIOS(): List = emptyList()
+ /**
+ * List every StoreKit transaction (finished + unfinished).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios
+ */
override suspend fun getAllTransactionsIOS(): List = emptyList()
+ /**
+ * Get base64 receipt data (legacy validation).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios
+ */
override suspend fun getReceiptDataIOS(): String? = null
+ /**
+ * Return the JWS string for a transaction.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios
+ */
override suspend fun getTransactionJwsIOS(sku: String): String? = null
+ /**
+ * Check intro-offer eligibility for a subscription group.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios
+ */
override suspend fun isEligibleForIntroOfferIOS(groupID: String): Boolean = false
+ /**
+ * Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios
+ */
override suspend fun isEligibleForExternalPurchaseCustomLinkIOS(): Boolean = false
+ /**
+ * Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios
+ */
override suspend fun showExternalPurchaseCustomLinkNoticeIOS(
noticeType: ExternalPurchaseCustomLinkNoticeTypeIOS
): ExternalPurchaseCustomLinkNoticeResultIOS {
@@ -536,6 +649,11 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife
)
}
+ /**
+ * Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios
+ */
override suspend fun getExternalPurchaseCustomLinkTokenIOS(
tokenType: ExternalPurchaseCustomLinkTokenTypeIOS
): ExternalPurchaseCustomLinkTokenResultIOS {
@@ -547,12 +665,32 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife
)
}
+ /**
+ * Check whether a transaction's JWS verification passed.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios
+ */
override suspend fun isTransactionVerifiedIOS(sku: String): Boolean = false
+ /**
+ * Get the latest verified transaction for a product.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/latest-transaction-ios
+ */
override suspend fun latestTransactionIOS(sku: String): PurchaseIOS? = null
+ /**
+ * Get subscription status objects from StoreKit 2.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/subscription-status-ios
+ */
override suspend fun subscriptionStatusIOS(sku: String): List = emptyList()
+ /**
+ * Deprecated. Legacy App Store receipt validation.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/validate-receipt-ios
+ */
override suspend fun validateReceiptIOS(options: VerifyPurchaseProps): VerifyPurchaseResultIOS {
failWith(
PurchaseError(
@@ -572,10 +710,28 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife
override suspend fun subscriptionBillingIssue(): Purchase = subscriptionBillingIssueListener.first()
+ /**
+ * Complete a purchase transaction. Call after server-side verification.
+ *
+ * @param purchase The [Purchase] to finalize.
+ * @param isConsumable `true` for consumables (Android consume — token can be re-bought),
+ * `false` for non-consumables and subscriptions (acknowledge only). Default `false`.
+ * @throws PurchaseException when the platform finalize call fails.
+ *
+ * Important: Android auto-refunds purchases NOT acknowledged/consumed within 3 days.
+ * iOS unfinished transactions replay on every app launch.
+ *
+ * @see finish-transaction
+ */
override suspend fun finishTransaction(purchase: PurchaseInput, isConsumable: Boolean?) {
finishTransactionHandler(purchase, isConsumable)
}
+ /**
+ * Open the platform's subscription management UI.
+ *
+ * @see https://www.openiap.dev/docs/apis/deep-link-to-subscriptions
+ */
override suspend fun deepLinkToSubscriptions(options: DeepLinkOptions?) {
deepLinkToSubscriptionsHandler(options)
}
@@ -805,6 +961,11 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife
// ---------------------------------------------------------------------
// Android specific overrides
// ---------------------------------------------------------------------
+ /**
+ * Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
+ *
+ * @see https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android
+ */
override suspend fun acknowledgePurchaseAndroid(purchaseToken: String): Boolean {
ensureConnectedOrFail(isConnected, ::failWith)
val params = AcknowledgePurchaseParams.newBuilder()
@@ -829,6 +990,11 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife
}
}
+ /**
+ * Consume a consumable purchase so it can be re-bought.
+ *
+ * @see https://www.openiap.dev/docs/apis/android/consume-purchase-android
+ */
override suspend fun consumePurchaseAndroid(purchaseToken: String): Boolean {
ensureConnectedOrFail(isConnected, ::failWith)
val params = ConsumeParams.newBuilder()
@@ -851,18 +1017,78 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife
}
}
+ /**
+ * Deprecated. Use cross-platform getStorefront instead.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/get-storefront-ios
+ */
override suspend fun getStorefrontIOS(): String = ""
+
+ /**
+ * Show the App Store offer code redemption sheet.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios
+ */
override suspend fun presentCodeRedemptionSheetIOS(): Boolean = false
+
suspend fun finishTransactionIOS(transactionId: String) {}
+
+ /**
+ * Clear pending transactions in the queue (sandbox helper).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/clear-transaction-ios
+ */
override suspend fun clearTransactionIOS(): Boolean = false
+
suspend fun clearProductsIOS() {}
+
+ /**
+ * Read the App Store-promoted product, if any.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios
+ */
override suspend fun getPromotedProductIOS(): ProductIOS? = null
+
+ /**
+ * Buy the currently promoted product.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios
+ */
override suspend fun requestPurchaseOnPromotedProductIOS(): Boolean = false
+
+ /**
+ * Present the refund request sheet (iOS 15+).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios
+ */
override suspend fun beginRefundRequestIOS(sku: String): String? = null
+
+ /**
+ * Present the manage-subscriptions sheet.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios
+ */
override suspend fun showManageSubscriptionsIOS(): List = emptyList()
+
+ /**
+ * Force sync transactions with the App Store.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/sync-ios
+ */
override suspend fun syncIOS(): Boolean = false
+
+ /**
+ * Deprecated. Use verifyPurchase instead.
+ *
+ * @see https://www.openiap.dev/docs/apis/validate-receipt
+ */
override suspend fun validateReceipt(options: ValidationOptions): ValidationResult = validateReceiptHandler(options)
+ /**
+ * Verify a purchase against your own backend.
+ *
+ * @see https://www.openiap.dev/docs/features/validation#verify-purchase
+ */
override suspend fun verifyPurchase(options: VerifyPurchaseProps): VerifyPurchaseResult {
// Android doesn't support native receipt verification like iOS
// Use verifyPurchaseWithProvider for server-side verification via IAPKit
@@ -874,6 +1100,11 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife
)
}
+ /**
+ * Verify via a managed provider (IAPKit, Apple, Google, Horizon).
+ *
+ * @see https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
+ */
override suspend fun verifyPurchaseWithProvider(options: VerifyPurchaseWithProviderProps): VerifyPurchaseWithProviderResult {
if (options.provider != PurchaseVerificationProvider.Iapkit) {
failWith(
@@ -961,6 +1192,11 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife
activity.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
}
+ /**
+ * Return the user's storefront country code.
+ *
+ * @see https://www.openiap.dev/docs/apis/get-storefront
+ */
override suspend fun getStorefront(): String {
// Android doesn't have a storefront concept like iOS
// Return a default value or country code based on locale
@@ -971,14 +1207,29 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife
// iOS External Purchase Methods (stubs for Android)
// ---------------------------------------------------------------------
+ /**
+ * Present an external purchase link (iOS 16+).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios
+ */
override suspend fun presentExternalPurchaseLinkIOS(url: String): ExternalPurchaseLinkResultIOS {
failWith(PurchaseError(code = ErrorCode.FeatureNotSupported, message = "External purchase links are iOS only"))
}
+ /**
+ * Present the external purchase notice sheet (iOS 17.4+).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios
+ */
override suspend fun presentExternalPurchaseNoticeSheetIOS(): ExternalPurchaseNoticeResultIOS {
failWith(PurchaseError(code = ErrorCode.FeatureNotSupported, message = "External purchase notice sheet is iOS only"))
}
+ /**
+ * Check eligibility for the external purchase notice sheet (iOS 17.4+).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios
+ */
override suspend fun canPresentExternalPurchaseNoticeIOS(): Boolean {
return false // Not supported on Android
}
@@ -1000,11 +1251,9 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife
// ---------------------------------------------------------------------
/**
- * Check if alternative billing is available for this user/device (Android only).
- * Step 1 of alternative billing flow.
+ * Check whether alternative billing is available for the user.
*
- * For AlternativeOnly mode: Uses isAlternativeBillingOnlyAvailableAsync
- * For UserChoice mode: Uses isFeatureSupported with ALTERNATIVE_BILLING feature
+ * @see https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android
*/
override suspend fun checkAlternativeBillingAvailabilityAndroid(): Boolean {
return withContext(Dispatchers.IO) {
@@ -1032,12 +1281,9 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife
}
/**
- * Show alternative billing information dialog to user (Android only).
- * Step 2 of alternative billing flow.
- * Must be called BEFORE processing payment in your payment system.
+ * Display Google's alternative billing information dialog.
*
- * Note: This is only applicable for AlternativeOnly mode.
- * For UserChoice mode, Google automatically shows selection dialog.
+ * @see https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android
*/
override suspend fun showAlternativeBillingDialogAndroid(): Boolean {
// Only applicable for AlternativeOnly mode
@@ -1063,13 +1309,9 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife
}
/**
- * Create external transaction token for Google Play reporting (Android only).
- * Step 3 of alternative billing flow.
- * Must be called AFTER successful payment in your payment system.
- * Token must be reported to Google Play backend within 24 hours.
+ * Create a reporting token for an alternative billing flow.
*
- * Note: This is only applicable for AlternativeOnly mode.
- * For UserChoice mode, the token is provided in UserChoiceBillingDetails.
+ * @see https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android
*/
override suspend fun createAlternativeBillingTokenAndroid(): String? {
// Only applicable for AlternativeOnly mode
@@ -1100,6 +1342,11 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife
// Full implementation uses Google Play Billing Library 8.2.1
// ---------------------------------------------------------------------
+ /**
+ * Check whether a billing program is available.
+ *
+ * @see https://www.openiap.dev/docs/apis/android/is-billing-program-available-android
+ */
override suspend fun isBillingProgramAvailableAndroid(
program: BillingProgramAndroid
): BillingProgramAvailabilityResultAndroid {
@@ -1173,6 +1420,11 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife
}
}
+ /**
+ * Create the reporting payload Google requires (Play Billing 8.3.0+).
+ *
+ * @see https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android
+ */
override suspend fun createBillingProgramReportingDetailsAndroid(
program: BillingProgramAndroid
): BillingProgramReportingDetailsAndroid {
@@ -1275,6 +1527,11 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife
}
}
+ /**
+ * Launch an external content/offer link (Play Billing 8.2.0+).
+ *
+ * @see https://www.openiap.dev/docs/apis/android/launch-external-link-android
+ */
override suspend fun launchExternalLinkAndroid(params: LaunchExternalLinkParamsAndroid): Boolean {
val client = billingClient ?: throw PurchaseException(
PurchaseError(
diff --git a/libraries/kmp-iap/library/src/commonMain/kotlin/io/github/hyochan/kmpiap/openiap/Types.kt b/libraries/kmp-iap/library/src/commonMain/kotlin/io/github/hyochan/kmpiap/openiap/Types.kt
index becd8523..521b22cb 100644
--- a/libraries/kmp-iap/library/src/commonMain/kotlin/io/github/hyochan/kmpiap/openiap/Types.kt
+++ b/libraries/kmp-iap/library/src/commonMain/kotlin/io/github/hyochan/kmpiap/openiap/Types.kt
@@ -4835,146 +4835,166 @@ public sealed interface VerifyPurchaseResult {
*/
public interface MutationResolver {
/**
- * Acknowledge a non-consumable purchase or subscription
+ * Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
+ * See: https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android
*/
suspend fun acknowledgePurchaseAndroid(purchaseToken: String): Boolean
/**
- * Initiate a refund request for a product (iOS 15+)
+ * Present the refund request sheet (iOS 15+). See also Features → Refund.
+ * See: https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios
*/
suspend fun beginRefundRequestIOS(sku: String): String?
/**
- * Check if alternative billing is available for this user/device
- * Step 1 of alternative billing flow
+ * Check whether alternative billing is available for the user. Step 1 of the alternative billing flow.
*
- * Returns true if available, false otherwise
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns true if available, false otherwise.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android
*/
suspend fun checkAlternativeBillingAvailabilityAndroid(): Boolean
/**
- * Clear pending transactions from the StoreKit payment queue
+ * Clear pending transactions in the queue (sandbox helper).
+ * See: https://www.openiap.dev/docs/apis/ios/clear-transaction-ios
*/
suspend fun clearTransactionIOS(): Boolean
/**
- * Consume a purchase token so it can be repurchased
+ * Consume a consumable purchase so it can be re-bought.
+ * See: https://www.openiap.dev/docs/apis/android/consume-purchase-android
*/
suspend fun consumePurchaseAndroid(purchaseToken: String): Boolean
/**
- * Create external transaction token for Google Play reporting
- * Step 3 of alternative billing flow
- * Must be called AFTER successful payment in your payment system
- * Token must be reported to Google Play backend within 24 hours
+ * Create a reporting token for an alternative billing flow. Step 3 of the alternative billing flow.
+ * Must be called AFTER successful payment in your payment system.
+ * Token must be reported to Google Play backend within 24 hours.
*
- * Returns token string, or null if creation failed
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns token string, or null if creation failed.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android
*/
suspend fun createAlternativeBillingTokenAndroid(): String?
/**
- * Create reporting details for a billing program
- * Replaces the deprecated createExternalOfferReportingDetailsAsync API
+ * Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+).
+ * Replaces the deprecated createExternalOfferReportingDetailsAsync API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Returns external transaction token needed for reporting external transactions
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns external transaction token needed for reporting external transactions.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android
*/
suspend fun createBillingProgramReportingDetailsAndroid(program: BillingProgramAndroid): BillingProgramReportingDetailsAndroid
/**
- * Open the native subscription management surface
+ * Open the platform's subscription management UI.
+ * See: https://www.openiap.dev/docs/apis/deep-link-to-subscriptions
*/
suspend fun deepLinkToSubscriptions(options: DeepLinkOptions? = null): Unit
/**
- * Close the platform billing connection
+ * Close the store connection and release resources.
+ * See: https://www.openiap.dev/docs/apis/end-connection
*/
suspend fun endConnection(): Boolean
/**
- * Finish a transaction after validating receipts
+ * Complete a transaction after server-side verification. Required on Android within 3 days.
+ * See: https://www.openiap.dev/docs/apis/finish-transaction
*/
suspend fun finishTransaction(purchase: PurchaseInput, isConsumable: Boolean? = null): Unit
/**
- * Establish the platform billing connection
+ * Initialize the store connection. Call before any IAP API.
+ * See: https://www.openiap.dev/docs/apis/init-connection
*/
suspend fun initConnection(config: InitConnectionConfig? = null): Boolean
/**
- * Check if a billing program is available for the current user
- * Replaces the deprecated isExternalOfferAvailableAsync API
+ * Check whether a billing program (e.g., External Payments) is available for the current user.
+ * Replaces the deprecated isExternalOfferAvailableAsync API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Returns availability result with isAvailable flag
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Available in Google Play Billing Library 8.2.0+.
+ * Returns availability result with isAvailable flag.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/is-billing-program-available-android
*/
suspend fun isBillingProgramAvailableAndroid(program: BillingProgramAndroid): BillingProgramAvailabilityResultAndroid
/**
- * Launch external link flow for external billing programs
- * Replaces the deprecated showExternalOfferInformationDialog API
+ * Launch an external content/offer link from inside the Billing Programs flow (Play Billing 8.2.0+).
+ * Replaces the deprecated showExternalOfferInformationDialog API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Shows Play Store dialog and optionally launches external URL
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Shows Play Store dialog and optionally launches external URL.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/launch-external-link-android
*/
suspend fun launchExternalLinkAndroid(params: LaunchExternalLinkParamsAndroid): Boolean
/**
- * Present the App Store code redemption sheet
+ * Show the App Store offer code redemption sheet.
+ * See: https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios
*/
suspend fun presentCodeRedemptionSheetIOS(): Boolean
/**
- * Present external purchase custom link with StoreKit UI
+ * Present an external purchase link, StoreKit External (iOS 16+).
+ * See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios
*/
suspend fun presentExternalPurchaseLinkIOS(url: String): ExternalPurchaseLinkResultIOS
/**
- * Present external purchase notice sheet (iOS 17.4+).
- * Uses ExternalPurchase.presentNoticeSheet() which returns a token when user continues.
+ * Present the external purchase notice sheet (iOS 17.4+).
+ * Uses ExternalPurchase.presentNoticeSheet() which returns a token when the user continues.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchase/presentnoticesheet()
+ * See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios
*/
suspend fun presentExternalPurchaseNoticeSheetIOS(): ExternalPurchaseNoticeResultIOS
/**
- * Initiate a purchase flow; rely on events for final state
+ * Initiate a purchase or subscription flow; rely on events for final state.
+ * See: https://www.openiap.dev/docs/apis/request-purchase
*/
suspend fun requestPurchase(params: RequestPurchaseProps): RequestPurchaseResult?
/**
- * Purchase the promoted product surfaced by the App Store.
+ * Buy the currently promoted product.
*
* @deprecated Use promotedProductListenerIOS to receive the productId,
* then call requestPurchase with that SKU instead. In StoreKit 2,
* promoted products can be purchased directly via the standard purchase flow.
+ * See: https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios
*/
suspend fun requestPurchaseOnPromotedProductIOS(): Boolean
/**
- * Restore completed purchases across platforms
+ * Restore non-consumable and active subscription purchases.
+ * See: https://www.openiap.dev/docs/apis/restore-purchases
*/
suspend fun restorePurchases(): Unit
/**
- * Show alternative billing information dialog to user
- * Step 2 of alternative billing flow
- * Must be called BEFORE processing payment in your payment system
+ * Display Google's alternative billing information dialog. Step 2 of the alternative billing flow.
+ * Must be called BEFORE processing payment in your payment system.
*
- * Returns true if user accepted, false if user canceled
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns true if user accepted, false if user canceled.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android
*/
suspend fun showAlternativeBillingDialogAndroid(): Boolean
/**
- * Show ExternalPurchaseCustomLink notice sheet (iOS 18.1+).
- * Displays the system disclosure notice sheet for custom external purchase links.
+ * Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
* Call this after a deliberate customer interaction before linking out to external purchases.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/shownotice(type:)
+ * See: https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios
*/
suspend fun showExternalPurchaseCustomLinkNoticeIOS(noticeType: ExternalPurchaseCustomLinkNoticeTypeIOS): ExternalPurchaseCustomLinkNoticeResultIOS
/**
- * Open subscription management UI and return changed purchases (iOS 15+)
+ * Present the manage-subscriptions sheet and return changed purchases (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios
*/
suspend fun showManageSubscriptionsIOS(): List
/**
- * Force a StoreKit sync for transactions (iOS 15+)
+ * Force sync transactions with the App Store (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/sync-ios
*/
suspend fun syncIOS(): Boolean
/**
- * Validate purchase receipts with the configured providers
+ * Deprecated. Validate purchase receipts with the configured providers — use verifyPurchase instead.
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase
*/
suspend fun validateReceipt(options: VerifyPurchaseProps): VerifyPurchaseResult
/**
- * Verify purchases with the configured providers
+ * Verify a purchase against your own backend (returns isValid + raw store metadata).
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase
*/
suspend fun verifyPurchase(options: VerifyPurchaseProps): VerifyPurchaseResult
/**
- * Verify purchases with a specific provider (e.g., IAPKit)
+ * Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
*/
suspend fun verifyPurchaseWithProvider(options: VerifyPurchaseWithProviderProps): VerifyPurchaseWithProviderResult
}
@@ -4984,95 +5004,116 @@ public interface MutationResolver {
*/
public interface QueryResolver {
/**
- * Check if external purchase notice sheet can be presented (iOS 17.4+)
- * Uses ExternalPurchase.canPresent
+ * Check eligibility for the external purchase notice sheet (iOS 17.4+).
+ * Uses ExternalPurchase.canPresent.
+ * See: https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios
*/
suspend fun canPresentExternalPurchaseNoticeIOS(): Boolean
/**
- * Get current StoreKit 2 entitlements (iOS 15+)
+ * Get the user's current entitlement for a product, using StoreKit 2 (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/current-entitlement-ios
*/
suspend fun currentEntitlementIOS(sku: String): PurchaseIOS?
/**
- * Retrieve products or subscriptions from the store
+ * Fetch products or subscriptions from the store.
+ * See: https://www.openiap.dev/docs/apis/fetch-products
*/
suspend fun fetchProducts(params: ProductRequest): FetchProductsResult
/**
- * Get active subscriptions (filters by subscriptionIds when provided)
+ * Get details of all currently active subscriptions (filters by subscriptionIds when provided).
+ * See: https://www.openiap.dev/docs/apis/get-active-subscriptions
*/
suspend fun getActiveSubscriptions(subscriptionIds: List? = null): List
/**
- * Get the full StoreKit 2 transaction history as PurchaseIOS values.
+ * List every StoreKit transaction (finished + unfinished) for the current user.
* Requires the SK2ConsumableTransactionHistory Info.plist key in the host app
* for finished consumables to be included (iOS 18+).
* Unlike getAvailablePurchases, always returns the iOS-specific PurchaseIOS shape.
+ * See: https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios
*/
suspend fun getAllTransactionsIOS(): List
/**
- * Fetch the current app transaction (iOS 16+)
+ * Fetch the app transaction (iOS 16+).
+ * See: https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios
*/
suspend fun getAppTransactionIOS(): AppTransaction?
/**
- * Get all available purchases for the current user
+ * List active purchases for the current user.
+ * See: https://www.openiap.dev/docs/apis/get-available-purchases
*/
suspend fun getAvailablePurchases(options: PurchaseOptions? = null): List
/**
- * Get external purchase token for reporting to Apple (iOS 18.1+).
- * Use this token with Apple's External Purchase Server API to report transactions.
+ * Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
+ * Use this token to report transactions made through ExternalPurchaseCustomLink.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/token(for:)
+ * See: https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios
*/
suspend fun getExternalPurchaseCustomLinkTokenIOS(tokenType: ExternalPurchaseCustomLinkTokenTypeIOS): ExternalPurchaseCustomLinkTokenResultIOS
/**
- * Retrieve all pending transactions in the StoreKit queue
+ * List unfinished StoreKit transactions in the queue.
+ * See: https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios
*/
suspend fun getPendingTransactionsIOS(): List
/**
- * Get the currently promoted product (iOS 11+)
+ * Read the App Store-promoted product, if any (iOS 11+).
+ * See: https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios
*/
suspend fun getPromotedProductIOS(): ProductIOS?
/**
- * Get base64-encoded receipt data for validation
+ * Get base64-encoded receipt data (legacy validation).
+ * See: https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios
*/
suspend fun getReceiptDataIOS(): String?
/**
- * Get the current storefront country code
+ * Return the user's storefront country code.
+ * See: https://www.openiap.dev/docs/apis/get-storefront
*/
suspend fun getStorefront(): String
/**
- * Get the current App Store storefront country code
+ * Deprecated. Get the current App Store storefront country code — use cross-platform getStorefront instead.
+ * See: https://www.openiap.dev/docs/apis/ios/get-storefront-ios
*/
suspend fun getStorefrontIOS(): String
/**
- * Get the transaction JWS (StoreKit 2)
+ * Return the JWS string for a transaction (StoreKit 2).
+ * See: https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios
*/
suspend fun getTransactionJwsIOS(sku: String): String?
/**
- * Check whether the user has active subscriptions
+ * Check whether the user has any active subscription.
+ * See: https://www.openiap.dev/docs/apis/has-active-subscriptions
*/
suspend fun hasActiveSubscriptions(subscriptionIds: List? = null): Boolean
/**
- * Check if app is eligible for ExternalPurchaseCustomLink API (iOS 18.1+).
+ * Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
* Returns true if the app can use custom external purchase links.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/iseligible
+ * See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios
*/
suspend fun isEligibleForExternalPurchaseCustomLinkIOS(): Boolean
/**
- * Check introductory offer eligibility for a subscription group
+ * Check intro-offer eligibility for a subscription group.
+ * See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios
*/
suspend fun isEligibleForIntroOfferIOS(groupID: String): Boolean
/**
- * Verify a StoreKit 2 transaction signature
+ * Check whether a transaction's JWS verification passed (StoreKit 2).
+ * See: https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios
*/
suspend fun isTransactionVerifiedIOS(sku: String): Boolean
/**
- * Get the latest transaction for a product using StoreKit 2
+ * Get the latest verified transaction for a product, using StoreKit 2.
+ * See: https://www.openiap.dev/docs/apis/ios/latest-transaction-ios
*/
suspend fun latestTransactionIOS(sku: String): PurchaseIOS?
/**
- * Get StoreKit 2 subscription status details (iOS 15+)
+ * Get subscription status objects from StoreKit 2 (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/subscription-status-ios
*/
suspend fun subscriptionStatusIOS(sku: String): List
/**
- * Validate a receipt for a specific product
+ * Deprecated. Legacy App Store receipt validation — use verifyPurchase instead.
+ * See: https://www.openiap.dev/docs/apis/ios/validate-receipt-ios
*/
suspend fun validateReceiptIOS(options: VerifyPurchaseProps): VerifyPurchaseResultIOS
}
diff --git a/libraries/kmp-iap/library/src/iosMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseIOS.kt b/libraries/kmp-iap/library/src/iosMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseIOS.kt
index f9a592d7..55cfb5c6 100644
--- a/libraries/kmp-iap/library/src/iosMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseIOS.kt
+++ b/libraries/kmp-iap/library/src/iosMain/kotlin/io/github/hyochan/kmpiap/InAppPurchaseIOS.kt
@@ -133,6 +133,17 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
// MutationResolver Implementation
// -------------------------------------------------------------------------
+ /**
+ * Initialize the store connection. Must be called before any other IAP API.
+ *
+ * @param config Optional [InitConnectionConfig]. Use `enableBillingProgramAndroid`
+ * (Android, Play Billing 8.2.0+) to opt into External Payments etc.; iOS ignores
+ * Android-specific fields.
+ * @return `true` once the platform billing client is connected.
+ * @throws PurchaseException when the billing client fails to initialize.
+ *
+ * @see init-connection
+ */
override suspend fun initConnection(config: InitConnectionConfig?): Boolean = suspendCoroutine { continuation ->
// iOS doesn't use alternative billing config, it's Android only
openIapModule.initConnectionWithCompletion { success, error ->
@@ -151,6 +162,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Close the store connection and release resources.
+ *
+ * @see https://www.openiap.dev/docs/apis/end-connection
+ */
override suspend fun endConnection(): Boolean = suspendCoroutine { continuation ->
// Remove all listeners and null the subscription tokens so initConnection()
// can freshly re-register without orphaning the previous subscriptions.
@@ -173,6 +189,20 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Initiate a purchase or subscription flow. Result is delivered via the
+ * purchaseUpdated event flow — NOT the return value.
+ *
+ * @param props [RequestPurchaseProps]. Pass `request.apple.sku` (iOS) and/or
+ * `request.google.skus` (Android); subscriptions need `subscriptionOffers`.
+ * @return The dispatched purchase payload (do not rely on this for the outcome).
+ * @throws PurchaseException on synchronous rejection (billing not ready, missing offerToken).
+ *
+ * Warning: Event-based. Collect from `purchaseUpdatedListener` / `purchaseErrorListener`
+ * (or the equivalent flows on `KmpIAP`) for the final state.
+ *
+ * @see request-purchase
+ */
override suspend fun requestPurchase(params: RequestPurchaseProps): RequestPurchaseResult? =
suspendCoroutine { continuation ->
when (val request = params.request) {
@@ -243,6 +273,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Buy the currently promoted product.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios
+ */
override suspend fun requestPurchaseOnPromotedProductIOS(): Boolean =
suspendCoroutine { continuation ->
openIapModule.requestPurchaseOnPromotedProductIOSWithCompletion { success, error ->
@@ -254,6 +289,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Restore non-consumable and active subscription purchases.
+ *
+ * @see https://www.openiap.dev/docs/apis/restore-purchases
+ */
override suspend fun restorePurchases(): Unit = suspendCoroutine { continuation ->
openIapModule.restorePurchasesWithCompletion { error ->
if (error != null) {
@@ -264,6 +304,19 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Complete a purchase transaction. Call after server-side verification.
+ *
+ * @param purchase The [Purchase] to finalize.
+ * @param isConsumable `true` for consumables (Android consume — token can be re-bought),
+ * `false` for non-consumables and subscriptions (acknowledge only). Default `false`.
+ * @throws PurchaseException when the platform finalize call fails.
+ *
+ * Important: Android auto-refunds purchases NOT acknowledged/consumed within 3 days.
+ * iOS unfinished transactions replay on every app launch.
+ *
+ * @see finish-transaction
+ */
override suspend fun finishTransaction(purchase: PurchaseInput, isConsumable: Boolean?): Unit =
suspendCoroutine { continuation ->
val transactionId = purchase.id
@@ -282,6 +335,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Open the platform's subscription management UI.
+ *
+ * @see https://www.openiap.dev/docs/apis/deep-link-to-subscriptions
+ */
override suspend fun deepLinkToSubscriptions(options: DeepLinkOptions?): Unit =
suspendCoroutine { continuation ->
openIapModule.deepLinkToSubscriptionsWithCompletion { error ->
@@ -293,6 +351,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Show the App Store offer code redemption sheet.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios
+ */
override suspend fun presentCodeRedemptionSheetIOS(): Boolean =
suspendCoroutine { continuation ->
openIapModule.presentCodeRedemptionSheetIOSWithCompletion { success, error ->
@@ -304,6 +367,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Present the refund request sheet (iOS 15+).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios
+ */
override suspend fun beginRefundRequestIOS(sku: String): String? =
suspendCoroutine { continuation ->
openIapModule.beginRefundRequestIOSWithSku(sku) { status, error ->
@@ -315,6 +383,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Clear pending transactions in the queue (sandbox helper).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/clear-transaction-ios
+ */
override suspend fun clearTransactionIOS(): Boolean = suspendCoroutine { continuation ->
openIapModule.clearTransactionIOSWithCompletion { success, error ->
if (error != null) {
@@ -325,6 +398,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Present the manage-subscriptions sheet.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios
+ */
override suspend fun showManageSubscriptionsIOS(): List =
suspendCoroutine { continuation ->
openIapModule.showManageSubscriptionsIOSWithCompletion { result, error ->
@@ -339,6 +417,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Force sync transactions with the App Store.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/sync-ios
+ */
override suspend fun syncIOS(): Boolean = suspendCoroutine { continuation ->
openIapModule.syncIOSWithCompletion { success, error ->
if (error != null) {
@@ -349,6 +432,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Deprecated. Use verifyPurchase instead.
+ *
+ * @see https://www.openiap.dev/docs/apis/validate-receipt
+ */
override suspend fun validateReceipt(options: VerifyPurchaseProps): VerifyPurchaseResult {
// Call the iOS-specific version and return the result directly
return validateReceiptIOS(options)
@@ -358,6 +446,18 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
// QueryResolver Implementation
// -------------------------------------------------------------------------
+ /**
+ * Retrieve products or subscriptions from the store by SKU.
+ *
+ * @param params [ProductRequest] with `skus` and optional `type`
+ * ([ProductQueryType.InApp], [ProductQueryType.Subs], or [ProductQueryType.All];
+ * defaults to InApp).
+ * @return [FetchProductsResult] sealed variant — Products for InApp, Subscriptions
+ * for Subs, mixed for All.
+ * @throws PurchaseException on store rejection (unknown SKU, network, not connected).
+ *
+ * @see fetch-products
+ */
override suspend fun fetchProducts(params: ProductRequest): FetchProductsResult =
suspendCoroutine { continuation ->
val skus = params.skus
@@ -396,6 +496,17 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * List the user's unfinished purchases — non-consumables, active subscriptions, and
+ * any pending transactions not finished previously.
+ *
+ * @param options Optional [PurchaseOptions]. iOS-only fields
+ * (`alsoPublishToEventListenerIOS`, `onlyIncludeActiveItemsIOS`) are ignored on Android.
+ * @return List of [Purchase] currently held by the platform store.
+ * @throws PurchaseException when the platform query fails.
+ *
+ * @see get-available-purchases
+ */
override suspend fun getAvailablePurchases(options: PurchaseOptions?): List =
suspendCoroutine { continuation ->
openIapModule.getAvailablePurchasesWithCompletion { result, error ->
@@ -410,10 +521,20 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Return the user's storefront country code.
+ *
+ * @see https://www.openiap.dev/docs/apis/get-storefront
+ */
override suspend fun getStorefront(): String {
return getStorefrontIOS()
}
+ /**
+ * Deprecated. Use cross-platform getStorefront instead.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/get-storefront-ios
+ */
override suspend fun getStorefrontIOS(): String = suspendCoroutine { continuation ->
openIapModule.getStorefrontIOSWithCompletion { result, error ->
if (error != null) {
@@ -424,6 +545,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * List unfinished StoreKit transactions.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios
+ */
override suspend fun getPendingTransactionsIOS(): List =
suspendCoroutine { continuation ->
openIapModule.getPendingTransactionsIOSWithCompletion { result, error ->
@@ -438,6 +564,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * List every StoreKit transaction (finished + unfinished).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios
+ */
override suspend fun getAllTransactionsIOS(): List =
suspendCoroutine { continuation ->
openIapModule.getAllTransactionsIOSWithCompletion { result, error ->
@@ -452,6 +583,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Get base64 receipt data (legacy validation).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios
+ */
override suspend fun getReceiptDataIOS(): String? = suspendCoroutine { continuation ->
openIapModule.getReceiptDataIOSWithCompletion { result, error ->
if (error != null) {
@@ -462,6 +598,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Read the App Store-promoted product, if any.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios
+ */
override suspend fun getPromotedProductIOS(): ProductIOS? = suspendCoroutine { continuation ->
openIapModule.getPromotedProductIOSWithCompletion { result, error ->
if (error != null) {
@@ -475,6 +616,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Get details of all currently active subscriptions.
+ *
+ * @see https://www.openiap.dev/docs/apis/get-active-subscriptions
+ */
override suspend fun getActiveSubscriptions(subscriptionIds: List?): List =
suspendCoroutine { continuation ->
openIapModule.getActiveSubscriptionsWithCompletion { result, error ->
@@ -497,6 +643,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Fetch the app transaction (iOS 16+).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios
+ */
override suspend fun getAppTransactionIOS(): AppTransaction? =
suspendCoroutine { continuation ->
// Note: getAppTransactionIOS requires iOS 16.0+
@@ -521,6 +672,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Get the user's current entitlement for a product.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/current-entitlement-ios
+ */
override suspend fun currentEntitlementIOS(sku: String): PurchaseIOS? =
suspendCoroutine { continuation ->
openIapModule.currentEntitlementIOSWithSku(sku) { result, error ->
@@ -534,6 +690,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Return the JWS string for a transaction.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios
+ */
override suspend fun getTransactionJwsIOS(sku: String): String? =
suspendCoroutine { continuation ->
openIapModule.getTransactionJwsIOSWithSku(sku) { result, error ->
@@ -546,6 +707,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Check whether the user has any active subscription.
+ *
+ * @see https://www.openiap.dev/docs/apis/has-active-subscriptions
+ */
override suspend fun hasActiveSubscriptions(subscriptionIds: List?): Boolean =
suspendCoroutine { continuation ->
openIapModule.hasActiveSubscriptionsWithCompletion { hasActive, error ->
@@ -558,6 +724,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Check intro-offer eligibility for a subscription group.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios
+ */
override suspend fun isEligibleForIntroOfferIOS(groupID: String): Boolean =
suspendCoroutine { continuation ->
openIapModule.isEligibleForIntroOfferIOSWithGroupID(groupID) { isEligible, error ->
@@ -570,6 +741,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios
+ */
override suspend fun isEligibleForExternalPurchaseCustomLinkIOS(): Boolean =
suspendCoroutine { continuation ->
openIapModule.isEligibleForExternalPurchaseCustomLinkIOSWithCompletion { isEligible, error ->
@@ -582,6 +758,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios
+ */
override suspend fun showExternalPurchaseCustomLinkNoticeIOS(
noticeType: ExternalPurchaseCustomLinkNoticeTypeIOS
): ExternalPurchaseCustomLinkNoticeResultIOS =
@@ -612,6 +793,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios
+ */
override suspend fun getExternalPurchaseCustomLinkTokenIOS(
tokenType: ExternalPurchaseCustomLinkTokenTypeIOS
): ExternalPurchaseCustomLinkTokenResultIOS =
@@ -642,6 +828,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Check whether a transaction's JWS verification passed.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios
+ */
override suspend fun isTransactionVerifiedIOS(sku: String): Boolean =
suspendCoroutine { continuation ->
openIapModule.isTransactionVerifiedIOSWithSku(sku) { isVerified, error ->
@@ -654,6 +845,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Get the latest verified transaction for a product.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/latest-transaction-ios
+ */
override suspend fun latestTransactionIOS(sku: String): PurchaseIOS? =
suspendCoroutine { continuation ->
openIapModule.latestTransactionIOSWithSku(sku) { result, error ->
@@ -667,6 +863,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Get subscription status objects from StoreKit 2.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/subscription-status-ios
+ */
override suspend fun subscriptionStatusIOS(sku: String): List =
suspendCoroutine { continuation ->
openIapModule.subscriptionStatusIOSWithSku(sku) { result, error ->
@@ -689,6 +890,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Deprecated. Legacy App Store receipt validation.
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/validate-receipt-ios
+ */
override suspend fun validateReceiptIOS(options: VerifyPurchaseProps): VerifyPurchaseResultIOS {
// Get receipt data
val receiptData = getReceiptDataIOS() ?: ""
@@ -702,11 +908,21 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
)
}
+ /**
+ * Verify a purchase against your own backend.
+ *
+ * @see https://www.openiap.dev/docs/features/validation#verify-purchase
+ */
override suspend fun verifyPurchase(options: VerifyPurchaseProps): VerifyPurchaseResult {
// Call the iOS-specific validation method
return validateReceiptIOS(options)
}
+ /**
+ * Verify via a managed provider (IAPKit, Apple, Google, Horizon).
+ *
+ * @see https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
+ */
override suspend fun verifyPurchaseWithProvider(options: VerifyPurchaseWithProviderProps): VerifyPurchaseWithProviderResult =
suspendCoroutine { continuation ->
val provider = options.provider.rawValue
@@ -1054,10 +1270,20 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
// Android-specific stubs (not implemented on iOS)
// -------------------------------------------------------------------------
+ /**
+ * Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
+ *
+ * @see https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android
+ */
override suspend fun acknowledgePurchaseAndroid(purchaseToken: String): Boolean {
throw UnsupportedOperationException("Android method not available on iOS")
}
+ /**
+ * Consume a consumable purchase so it can be re-bought.
+ *
+ * @see https://www.openiap.dev/docs/apis/android/consume-purchase-android
+ */
override suspend fun consumePurchaseAndroid(purchaseToken: String): Boolean {
throw UnsupportedOperationException("Android method not available on iOS")
}
@@ -1066,14 +1292,29 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
// Android Alternative Billing Methods (stubs for iOS)
// -------------------------------------------------------------------------
+ /**
+ * Check whether alternative billing is available for the user.
+ *
+ * @see https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android
+ */
override suspend fun checkAlternativeBillingAvailabilityAndroid(): Boolean {
return false // Not supported on iOS
}
+ /**
+ * Display Google's alternative billing information dialog.
+ *
+ * @see https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android
+ */
override suspend fun showAlternativeBillingDialogAndroid(): Boolean {
throw UnsupportedOperationException("Android alternative billing not available on iOS")
}
+ /**
+ * Create a reporting token for an alternative billing flow.
+ *
+ * @see https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android
+ */
override suspend fun createAlternativeBillingTokenAndroid(): String? {
return null // Not supported on iOS
}
@@ -1086,6 +1327,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
// iOS External Purchase Methods
// -------------------------------------------------------------------------
+ /**
+ * Present an external purchase link (iOS 16+).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios
+ */
override suspend fun presentExternalPurchaseLinkIOS(url: String): ExternalPurchaseLinkResultIOS =
suspendCoroutine { continuation ->
openIapModule.presentExternalPurchaseLinkIOSWithUrl(url) { result, error ->
@@ -1109,6 +1355,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Present the external purchase notice sheet (iOS 17.4+).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios
+ */
override suspend fun presentExternalPurchaseNoticeSheetIOS(): ExternalPurchaseNoticeResultIOS =
suspendCoroutine { continuation ->
openIapModule.presentExternalPurchaseNoticeSheetIOSWithCompletion { result, error ->
@@ -1137,6 +1388,11 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
}
+ /**
+ * Check eligibility for the external purchase notice sheet (iOS 17.4+).
+ *
+ * @see https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios
+ */
override suspend fun canPresentExternalPurchaseNoticeIOS(): Boolean =
suspendCoroutine { continuation ->
openIapModule.canPresentExternalPurchaseNoticeIOSWithCompletion { canPresent, error ->
@@ -1145,14 +1401,29 @@ internal class InAppPurchaseIOS : KmpInAppPurchase {
}
// Billing Programs API (Android 8.2.0+ only) - iOS stubs
+ /**
+ * Check whether a billing program is available.
+ *
+ * @see https://www.openiap.dev/docs/apis/android/is-billing-program-available-android
+ */
override suspend fun isBillingProgramAvailableAndroid(program: BillingProgramAndroid): BillingProgramAvailabilityResultAndroid {
throw UnsupportedOperationException("isBillingProgramAvailableAndroid is only available on Android")
}
+ /**
+ * Create the reporting payload Google requires (Play Billing 8.3.0+).
+ *
+ * @see https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android
+ */
override suspend fun createBillingProgramReportingDetailsAndroid(program: BillingProgramAndroid): BillingProgramReportingDetailsAndroid {
throw UnsupportedOperationException("createBillingProgramReportingDetailsAndroid is only available on Android")
}
+ /**
+ * Launch an external content/offer link (Play Billing 8.2.0+).
+ *
+ * @see https://www.openiap.dev/docs/apis/android/launch-external-link-android
+ */
override suspend fun launchExternalLinkAndroid(params: LaunchExternalLinkParamsAndroid): Boolean {
throw UnsupportedOperationException("launchExternalLinkAndroid is only available on Android")
}
diff --git a/libraries/react-native-iap/src/hooks/useIAP.ts b/libraries/react-native-iap/src/hooks/useIAP.ts
index c127d918..fbc88e68 100644
--- a/libraries/react-native-iap/src/hooks/useIAP.ts
+++ b/libraries/react-native-iap/src/hooks/useIAP.ts
@@ -64,33 +64,161 @@ type UseIap = {
availablePurchases: Purchase[];
promotedProductIOS?: Product;
activeSubscriptions: ActiveSubscription[];
+ /**
+ * Complete a purchase transaction. Call after server-side verification to remove it
+ * from the queue.
+ *
+ * @param args.purchase The `Purchase` to finalize.
+ * @param args.isConsumable `true` for consumables (consumes the token so the SKU can be
+ * re-bought, e.g. coins); `false` (default) for non-consumables and subscriptions.
+ * @returns Promise that resolves once the platform finalizes the transaction.
+ * @throws When the platform finalize call fails.
+ *
+ * @example
+ * ```ts
+ * purchaseUpdatedListener(async (purchase) => {
+ * if (await verifyOnServer(purchase)) {
+ * await finishTransaction({ purchase, isConsumable: false });
+ * }
+ * });
+ * ```
+ *
+ * @remarks **Critical:** Android purchases must be finalized within 3 days or Google
+ * auto-refunds. iOS unfinished transactions replay on every app launch.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/finish-transaction}
+ */
finishTransaction: (args: MutationFinishTransactionArgs) => Promise;
+ /**
+ * List the user's unfinished purchases — non-consumables, active subscriptions, and any
+ * pending transactions not yet finished.
+ *
+ * @param options Optional `PurchaseOptions`. iOS-only flags:
+ * `alsoPublishToEventListenerIOS`, `onlyIncludeActiveItemsIOS`.
+ * @returns Promise that resolves when the request is dispatched; results land in the
+ * hook's reactive `availablePurchases` state.
+ * @throws When the platform query fails.
+ *
+ * @example
+ * ```ts
+ * const purchases = await getAvailablePurchases();
+ * for (const p of purchases) {
+ * if (await verifyOnServer(p)) await finishTransaction({ purchase: p, isConsumable: false });
+ * }
+ * ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/get-available-purchases}
+ */
getAvailablePurchases: (options?: PurchaseOptions) => Promise;
+ /**
+ * Retrieve products or subscriptions from the store by SKU.
+ *
+ * @param params `ProductRequest` — `skus` (string[]) and optional `type`
+ * (`'in-app' | 'subs' | 'all'`, defaults to `'in-app'`).
+ * @returns Promise that resolves when the request is dispatched; results land in the
+ * hook's reactive `products` / `subscriptions` state.
+ * @throws When the store rejects the request (unknown SKU, network, not connected).
+ *
+ * @example
+ * ```ts
+ * const products = await fetchProducts({
+ * skus: ['com.app.coins_100', 'com.app.premium'],
+ * type: 'in-app',
+ * });
+ * ```
+ *
+ * @remarks This is a regular promise-based call. Don't confuse with `request*` APIs
+ * (`requestPurchase`), which are event-based.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/fetch-products}
+ */
fetchProducts: (params: {
skus: string[];
type?: ProductQueryType | null;
}) => Promise;
+ /**
+ * Initiate a purchase or subscription flow. The result is delivered through
+ * `purchaseUpdatedListener` — NOT the return value.
+ *
+ * @param props `RequestPurchaseProps`, discriminated by `type`:
+ * - `type: 'in-app'` — pass `request.apple.sku` (iOS) and/or `request.google.skus` (Android).
+ * - `type: 'subs'` — same shape, plus `request.google.subscriptionOffers: [{ sku, offerToken }]`.
+ * @returns Promise that resolves when the request is dispatched; results land in the
+ * hook's `onPurchaseSuccess` / `onPurchaseError` callbacks.
+ * @throws Synchronous rejection from the store (e.g. `E_NOT_PREPARED`, validation failure).
+ *
+ * @example
+ * ```ts
+ * await requestPurchase({
+ * request: {
+ * apple: { sku: 'com.app.premium' },
+ * google: { skus: ['com.app.premium'] },
+ * },
+ * type: 'in-app',
+ * });
+ * ```
+ *
+ * @remarks Event-based. Listen for the result via {@link purchaseUpdatedListener} /
+ * {@link purchaseErrorListener}, or use `useIAP({ onPurchaseSuccess, onPurchaseError })`.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/request-purchase}
+ */
requestPurchase: (params: RequestPurchaseProps) => Promise;
/**
* @deprecated Use `verifyPurchase` instead. This function will be removed in a future version.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/validate-receipt}
*/
validateReceipt: (
options: VerifyPurchaseProps,
) => Promise;
- /** Verify purchase with the configured providers */
+ /**
+ * Verify a purchase against your own backend (returns isValid + raw store metadata).
+ *
+ * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase}
+ */
verifyPurchase: (
options: VerifyPurchaseProps,
) => Promise;
- /** Verify purchase with a specific provider (e.g., IAPKit) */
+ /**
+ * Verify via a managed provider (IAPKit, Apple, Google, Horizon).
+ *
+ * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider}
+ */
verifyPurchaseWithProvider: (
options: VerifyPurchaseWithProviderProps,
) => Promise;
+ /**
+ * Restore non-consumable and active subscription purchases.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/restore-purchases}
+ */
restorePurchases: (options?: PurchaseOptions) => Promise;
+ /**
+ * Read the App Store-promoted product, if any.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios}
+ */
getPromotedProductIOS: () => Promise;
+ /**
+ * Buy the currently promoted product.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios}
+ */
requestPurchaseOnPromotedProductIOS: () => Promise;
+ /**
+ * Get details of all currently active subscriptions.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/get-active-subscriptions}
+ */
getActiveSubscriptions: (
subscriptionIds?: string[],
) => Promise;
+ /**
+ * Check whether the user has any active subscription.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/has-active-subscriptions}
+ */
hasActiveSubscriptions: (subscriptionIds?: string[]) => Promise;
/**
* Manually retry the store connection.
@@ -99,8 +227,23 @@ type UseIap = {
*/
reconnect: () => Promise;
// Alternative billing (Android)
+ /**
+ * Check whether alternative billing is available for the user.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android}
+ */
checkAlternativeBillingAvailabilityAndroid?: () => Promise;
+ /**
+ * Display Google's alternative billing information dialog.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android}
+ */
showAlternativeBillingDialogAndroid?: () => Promise;
+ /**
+ * Create a reporting token for an alternative billing flow.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android}
+ */
createAlternativeBillingTokenAndroid?: (
sku?: string,
) => Promise;
diff --git a/libraries/react-native-iap/src/index.ts b/libraries/react-native-iap/src/index.ts
index 70e1f386..d65f71ef 100644
--- a/libraries/react-native-iap/src/index.ts
+++ b/libraries/react-native-iap/src/index.ts
@@ -662,20 +662,26 @@ export const subscriptionBillingIssueListener = (
// ------------------------------
/**
- * Fetch products from the store
- * @param params - Product request configuration
- * @param params.skus - Array of product SKUs to fetch
- * @param params.type - Optional filter: 'in-app' (default) for products, 'subs' for subscriptions, or 'all' for both.
- * @returns Promise - Array of products from the store
+ * Retrieve products or subscriptions from the store by SKU.
*
- * @example
- * ```typescript
- * // Regular products
- * const products = await fetchProducts({ skus: ['product1', 'product2'] });
+ * @param params `ProductRequest` — `skus` (string[]) and optional `type`
+ * (`'in-app' | 'subs' | 'all'`, defaults to `'in-app'`).
+ * @returns Promise resolving to a `FetchProductsResult` union — `Product[]` for `'in-app'`,
+ * `ProductSubscription[]` for `'subs'`, or a mixed array for `'all'`.
+ * @throws When the store rejects the request (unknown SKU, network, not connected).
*
- * // Subscriptions
- * const subscriptions = await fetchProducts({ skus: ['sub1', 'sub2'], type: 'subs' });
+ * @example
+ * ```ts
+ * const products = await fetchProducts({
+ * skus: ['com.app.coins_100', 'com.app.premium'],
+ * type: 'in-app',
+ * });
* ```
+ *
+ * @remarks This is a regular promise-based call. Don't confuse with `request*` APIs
+ * (`requestPurchase`), which are event-based.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/fetch-products}
*/
export const fetchProducts: QueryField<'fetchProducts'> = async (request) => {
const {skus, type} = request;
@@ -789,17 +795,23 @@ export const fetchProducts: QueryField<'fetchProducts'> = async (request) => {
};
/**
- * Get available purchases (purchased items not yet consumed/finished)
- * @param params - Options for getting available purchases
- * @param params.alsoPublishToEventListener - Whether to also publish to event listener
- * @param params.onlyIncludeActiveItems - Whether to only include active items
+ * List the user's unfinished purchases — non-consumables, active subscriptions, and any
+ * pending transactions not yet finished.
+ *
+ * @param options Optional `PurchaseOptions`. iOS-only flags:
+ * `alsoPublishToEventListenerIOS`, `onlyIncludeActiveItemsIOS`.
+ * @returns Promise resolving to an array of `Purchase` currently held by the store.
+ * @throws When the platform query fails.
*
* @example
- * ```typescript
- * const purchases = await getAvailablePurchases({
- * onlyIncludeActiveItemsIOS: true
- * });
+ * ```ts
+ * const purchases = await getAvailablePurchases();
+ * for (const p of purchases) {
+ * if (await verifyOnServer(p)) await finishTransaction({ purchase: p, isConsumable: false });
+ * }
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/get-available-purchases}
*/
export const getAvailablePurchases: QueryField<
'getAvailablePurchases'
@@ -866,6 +878,8 @@ export const getAvailablePurchases: QueryField<
* Request the promoted product from the App Store (iOS only)
* @returns Promise - The promoted product or null if none available
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios}
*/
export const getPromotedProductIOS: QueryField<
'getPromotedProductIOS'
@@ -898,6 +912,19 @@ export const getPromotedProductIOS: QueryField<
export const requestPromotedProductIOS = getPromotedProductIOS;
+/**
+ * Get the storefront identifier for the user's App Store account (iOS only)
+ * @returns Promise - The storefront identifier (e.g., 'USA' for United States)
+ * @platform iOS
+ *
+ * @example
+ * ```typescript
+ * const storefront = await getStorefrontIOS();
+ * console.log('User storefront:', storefront); // e.g., 'USA', 'GBR', 'KOR'
+ * ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-storefront-ios}
+ */
export const getStorefrontIOS: QueryField<'getStorefrontIOS'> = async () => {
if (Platform.OS !== 'ios') {
throw new Error('getStorefrontIOS is only available on iOS');
@@ -912,6 +939,11 @@ export const getStorefrontIOS: QueryField<'getStorefrontIOS'> = async () => {
}
};
+/**
+ * Return the user's storefront country code.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/get-storefront}
+ */
export const getStorefront: QueryField<'getStorefront'> = async () => {
if (Platform.OS !== 'ios' && Platform.OS !== 'android') {
RnIapConsole.warn(
@@ -945,6 +977,27 @@ export const getStorefront: QueryField<'getStorefront'> = async () => {
}
};
+/**
+ * iOS only - Gets the original app transaction ID if the app was purchased from the App Store
+ * @platform iOS
+ * @description
+ * This function retrieves the original app transaction information if the app was purchased
+ * from the App Store. Returns null if the app was not purchased (e.g., free app or TestFlight).
+ *
+ * @returns {Promise} The original app transaction ID or null
+ *
+ * @example
+ * ```typescript
+ * const appTransaction = await getAppTransactionIOS();
+ * if (appTransaction) {
+ * console.log('App was purchased, transaction ID:', appTransaction);
+ * } else {
+ * console.log('App was not purchased from App Store');
+ * }
+ * ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios}
+ */
export const getAppTransactionIOS: QueryField<
'getAppTransactionIOS'
> = async () => {
@@ -977,6 +1030,15 @@ export const getAppTransactionIOS: QueryField<
}
};
+/**
+ * Get subscription status for a product (iOS only)
+ * @param sku - The product SKU
+ * @returns Promise - Array of subscription status objects
+ * @throws Error when called on non-iOS platforms or when IAP is not initialized
+ * @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/subscription-status-ios}
+ */
export const subscriptionStatusIOS: QueryField<
'subscriptionStatusIOS'
> = async (sku) => {
@@ -1002,6 +1064,14 @@ export const subscriptionStatusIOS: QueryField<
}
};
+/**
+ * Get current entitlement for a product (iOS only)
+ * @param sku - The product SKU
+ * @returns Promise - Current entitlement or null
+ * @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/current-entitlement-ios}
+ */
export const currentEntitlementIOS: QueryField<
'currentEntitlementIOS'
> = async (sku) => {
@@ -1028,6 +1098,14 @@ export const currentEntitlementIOS: QueryField<
}
};
+/**
+ * Get latest transaction for a product (iOS only)
+ * @param sku - The product SKU
+ * @returns Promise - Latest transaction or null
+ * @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/latest-transaction-ios}
+ */
export const latestTransactionIOS: QueryField<'latestTransactionIOS'> = async (
sku,
) => {
@@ -1054,6 +1132,13 @@ export const latestTransactionIOS: QueryField<'latestTransactionIOS'> = async (
}
};
+/**
+ * Get pending transactions (iOS only)
+ * @returns Promise - Array of pending transactions
+ * @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios}
+ */
export const getPendingTransactionsIOS: QueryField<
'getPendingTransactionsIOS'
> = async () => {
@@ -1080,6 +1165,11 @@ export const getPendingTransactionsIOS: QueryField<
}
};
+/**
+ * List every StoreKit transaction (finished + unfinished) for the current user.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios}
+ */
export const getAllTransactionsIOS: QueryField<
'getAllTransactionsIOS'
> = async () => {
@@ -1106,6 +1196,13 @@ export const getAllTransactionsIOS: QueryField<
}
};
+/**
+ * Show manage subscriptions screen (iOS only)
+ * @returns Promise - Subscriptions where auto-renewal status changed
+ * @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios}
+ */
export const showManageSubscriptionsIOS: MutationField<
'showManageSubscriptionsIOS'
> = async () => {
@@ -1132,6 +1229,14 @@ export const showManageSubscriptionsIOS: MutationField<
}
};
+/**
+ * Check if user is eligible for intro offer (iOS only)
+ * @param groupID - The subscription group ID
+ * @returns Promise - Eligibility status
+ * @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios}
+ */
export const isEligibleForIntroOfferIOS: QueryField<
'isEligibleForIntroOfferIOS'
> = async (groupID) => {
@@ -1153,6 +1258,13 @@ export const isEligibleForIntroOfferIOS: QueryField<
}
};
+/**
+ * Get receipt data (iOS only)
+ * @returns Promise - Base64 encoded receipt data
+ * @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios}
+ */
export const getReceiptDataIOS: QueryField<'getReceiptDataIOS'> = async () => {
if (Platform.OS !== 'ios') {
throw new Error('getReceiptDataIOS is only available on iOS');
@@ -1234,6 +1346,14 @@ export const requestReceiptRefreshIOS = async (): Promise => {
}
};
+/**
+ * Check if transaction is verified (iOS only)
+ * @param sku - The product SKU
+ * @returns Promise - Verification status
+ * @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios}
+ */
export const isTransactionVerifiedIOS: QueryField<
'isTransactionVerifiedIOS'
> = async (sku) => {
@@ -1255,6 +1375,14 @@ export const isTransactionVerifiedIOS: QueryField<
}
};
+/**
+ * Get transaction JWS representation (iOS only)
+ * @param sku - The product SKU
+ * @returns Promise - JWS representation or null
+ * @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios}
+ */
export const getTransactionJwsIOS: QueryField<'getTransactionJwsIOS'> = async (
sku,
) => {
@@ -1281,25 +1409,23 @@ export const getTransactionJwsIOS: QueryField<'getTransactionJwsIOS'> = async (
// ------------------------------
/**
- * Initialize connection to the store
- * @param config - Optional configuration including alternative billing mode for Android
- * @param config.alternativeBillingModeAndroid - Alternative billing mode: 'none', 'user-choice', or 'alternative-only'
+ * Initialize the store connection. Must be called before any other IAP API.
+ *
+ * @param config Optional connection config. Use `enableBillingProgramAndroid` (Android,
+ * Play Billing 8.2.0+) to opt into External Payments etc. iOS ignores Android-specific fields.
+ * @returns Promise resolving to `true` when the platform billing client is connected.
+ * @throws When the platform billing client fails to initialize.
*
* @example
- * ```typescript
- * // Standard billing (default)
+ * ```ts
* await initConnection();
+ * await initConnection({ enableBillingProgramAndroid: 'external-offer' });
+ * ```
*
- * // User choice billing (Android)
- * await initConnection({
- * alternativeBillingModeAndroid: 'user-choice'
- * });
+ * @remarks When using `useIAP()`, connection is auto-managed on mount/unmount —
+ * pass options to the hook instead of calling this directly.
*
- * // Alternative billing only (Android)
- * await initConnection({
- * alternativeBillingModeAndroid: 'alternative-only'
- * });
- * ```
+ * @see {@link https://www.openiap.dev/docs/apis/init-connection}
*/
export const initConnection: MutationField<'initConnection'> = async (
config,
@@ -1321,7 +1447,9 @@ export const initConnection: MutationField<'initConnection'> = async (
};
/**
- * End connection to the store
+ * Close the store connection and release resources.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/end-connection}
*/
export const endConnection: MutationField<'endConnection'> = async () => {
try {
@@ -1341,6 +1469,11 @@ export const endConnection: MutationField<'endConnection'> = async () => {
}
};
+/**
+ * Restore non-consumable and active subscription purchases.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/restore-purchases}
+ */
export const restorePurchases: MutationField<'restorePurchases'> = async () => {
try {
if (Platform.OS === 'ios') {
@@ -1364,9 +1497,30 @@ export const restorePurchases: MutationField<'restorePurchases'> = async () => {
};
/**
- * Request a purchase for products or subscriptions
- * ⚠️ Important: This is an event-based operation, not promise-based.
- * Listen for events through purchaseUpdatedListener or purchaseErrorListener.
+ * Initiate a purchase or subscription flow. The result is delivered through
+ * `purchaseUpdatedListener` — NOT the return value.
+ *
+ * @param props `RequestPurchaseProps`, discriminated by `type`:
+ * - `type: 'in-app'` — pass `request.apple.sku` (iOS) and/or `request.google.skus` (Android).
+ * - `type: 'subs'` — same shape, plus `request.google.subscriptionOffers: [{ sku, offerToken }]`.
+ * @returns The dispatched purchase payload. **Do not rely on it** for the actual outcome.
+ * @throws Synchronous rejection from the store (e.g. `E_NOT_PREPARED`, validation failure).
+ *
+ * @example
+ * ```ts
+ * await requestPurchase({
+ * request: {
+ * apple: { sku: 'com.app.premium' },
+ * google: { skus: ['com.app.premium'] },
+ * },
+ * type: 'in-app',
+ * });
+ * ```
+ *
+ * @remarks Event-based. Listen for the result via {@link purchaseUpdatedListener} /
+ * {@link purchaseErrorListener}, or use `useIAP({ onPurchaseSuccess, onPurchaseError })`.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/request-purchase}
*/
export const requestPurchase: MutationField<'requestPurchase'> = async (
request,
@@ -1513,19 +1667,28 @@ export const requestPurchase: MutationField<'requestPurchase'> = async (
};
/**
- * Finish a transaction (consume or acknowledge)
- * @param params - Transaction finish parameters
- * @param params.purchase - The purchase to finish
- * @param params.isConsumable - Whether this is a consumable product (Android only)
- * @returns Promise - Resolves when the transaction is successfully finished
+ * Complete a purchase transaction. Call after server-side verification to remove it
+ * from the queue.
+ *
+ * @param args.purchase The `Purchase` to finalize.
+ * @param args.isConsumable `true` for consumables (consumes the token so the SKU can be
+ * re-bought, e.g. coins); `false` (default) for non-consumables and subscriptions.
+ * @returns Promise that resolves once the platform finalizes the transaction.
+ * @throws When the platform finalize call fails.
*
* @example
- * ```typescript
- * await finishTransaction({
- * purchase: myPurchase,
- * isConsumable: true
+ * ```ts
+ * purchaseUpdatedListener(async (purchase) => {
+ * if (await verifyOnServer(purchase)) {
+ * await finishTransaction({ purchase, isConsumable: false });
+ * }
* });
* ```
+ *
+ * @remarks **Critical:** Android purchases must be finalized within 3 days or Google
+ * auto-refunds. iOS unfinished transactions replay on every app launch.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/finish-transaction}
*/
export const finishTransaction: MutationField<'finishTransaction'> = async (
args,
@@ -1593,6 +1756,8 @@ export const finishTransaction: MutationField<'finishTransaction'> = async (
* ```typescript
* await acknowledgePurchaseAndroid('purchase_token_here');
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android}
*/
export const acknowledgePurchaseAndroid: MutationField<
'acknowledgePurchaseAndroid'
@@ -1632,6 +1797,8 @@ export const acknowledgePurchaseAndroid: MutationField<
* ```typescript
* await consumePurchaseAndroid('purchase_token_here');
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/consume-purchase-android}
*/
export const consumePurchaseAndroid: MutationField<
'consumePurchaseAndroid'
@@ -1687,6 +1854,8 @@ export const consumePurchaseAndroid: MutationField<
* }
* });
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/validate-receipt}
*/
export const validateReceipt: MutationField<'validateReceipt'> = async (
options,
@@ -1816,6 +1985,8 @@ export const validateReceipt: MutationField<'validateReceipt'> = async (
*
* @param options - Receipt validation options containing the SKU
* @returns Promise resolving to receipt validation result
+ *
+ * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase}
*/
export const verifyPurchase: MutationField<'verifyPurchase'> = validateReceipt;
@@ -1825,6 +1996,8 @@ export const verifyPurchase: MutationField<'verifyPurchase'> = validateReceipt;
* @deprecated Use `verifyPurchase` (or `validateReceipt`) instead. Kept so
* consumers who imported `validateReceiptIOS` — which is still declared on the
* OpenIAP Query interface — keep working. Throws on non-iOS platforms.
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/validate-receipt-ios}
*/
export const validateReceiptIOS: QueryField<'validateReceiptIOS'> = async (
options,
@@ -1856,6 +2029,8 @@ export const validateReceiptIOS: QueryField<'validateReceiptIOS'> = async (
* },
* });
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider}
*/
export const verifyPurchaseWithProvider: MutationField<
'verifyPurchaseWithProvider'
@@ -1899,6 +2074,8 @@ export const verifyPurchaseWithProvider: MutationField<
* Sync iOS purchases with App Store (iOS only)
* @returns Promise
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/sync-ios}
*/
export const syncIOS: MutationField<'syncIOS'> = async () => {
if (Platform.OS !== 'ios') {
@@ -1924,6 +2101,8 @@ export const syncIOS: MutationField<'syncIOS'> = async () => {
* Present the code redemption sheet for offer codes (iOS only)
* @returns Promise - Indicates whether the redemption sheet was presented
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios}
*/
export const presentCodeRedemptionSheetIOS: MutationField<
'presentCodeRedemptionSheetIOS'
@@ -1966,6 +2145,8 @@ export const presentCodeRedemptionSheetIOS: MutationField<
*
* @returns Promise - true when the request triggers successfully
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios}
*/
export const requestPurchaseOnPromotedProductIOS =
async (): Promise => {
@@ -2008,6 +2189,8 @@ export const requestPurchaseOnPromotedProductIOS =
* Clear unfinished transactions on iOS
* @returns Promise
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/clear-transaction-ios}
*/
export const clearTransactionIOS: MutationField<
'clearTransactionIOS'
@@ -2036,6 +2219,8 @@ export const clearTransactionIOS: MutationField<
* @param sku - The product SKU to refund
* @returns Promise - The refund status or null if not available
* @platform iOS
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios}
*/
export const beginRefundRequestIOS: MutationField<
'beginRefundRequestIOS'
@@ -2059,72 +2244,11 @@ export const beginRefundRequestIOS: MutationField<
}
};
-/**
- * Get subscription status for a product (iOS only)
- * @param sku - The product SKU
- * @returns Promise - Array of subscription status objects
- * @throws Error when called on non-iOS platforms or when IAP is not initialized
- * @platform iOS
- */
-/**
- * Get current entitlement for a product (iOS only)
- * @param sku - The product SKU
- * @returns Promise - Current entitlement or null
- * @platform iOS
- */
-/**
- * Get latest transaction for a product (iOS only)
- * @param sku - The product SKU
- * @returns Promise - Latest transaction or null
- * @platform iOS
- */
-/**
- * Get pending transactions (iOS only)
- * @returns Promise - Array of pending transactions
- * @platform iOS
- */
-/**
- * Show manage subscriptions screen (iOS only)
- * @returns Promise - Subscriptions where auto-renewal status changed
- * @platform iOS
- */
-/**
- * Check if user is eligible for intro offer (iOS only)
- * @param groupID - The subscription group ID
- * @returns Promise - Eligibility status
- * @platform iOS
- */
-/**
- * Get receipt data (iOS only)
- * @returns Promise - Base64 encoded receipt data
- * @platform iOS
- */
-/**
- * Check if transaction is verified (iOS only)
- * @param sku - The product SKU
- * @returns Promise - Verification status
- * @platform iOS
- */
-/**
- * Get transaction JWS representation (iOS only)
- * @param sku - The product SKU
- * @returns Promise - JWS representation or null
- * @platform iOS
- */
-/**
- * Get the storefront identifier for the user's App Store account (iOS only)
- * @returns Promise - The storefront identifier (e.g., 'USA' for United States)
- * @platform iOS
- *
- * @example
- * ```typescript
- * const storefront = await getStorefrontIOS();
- * console.log('User storefront:', storefront); // e.g., 'USA', 'GBR', 'KOR'
- * ```
- */
/**
* Deeplinks to native interface that allows users to manage their subscriptions
* Cross-platform alias aligning with expo-iap
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/deep-link-to-subscriptions}
*/
export const deepLinkToSubscriptions: MutationField<
'deepLinkToSubscriptions'
@@ -2174,25 +2298,6 @@ export const deepLinkToSubscriptionsIOS = async (): Promise => {
}
};
-/**
- * iOS only - Gets the original app transaction ID if the app was purchased from the App Store
- * @platform iOS
- * @description
- * This function retrieves the original app transaction information if the app was purchased
- * from the App Store. Returns null if the app was not purchased (e.g., free app or TestFlight).
- *
- * @returns {Promise} The original app transaction ID or null
- *
- * @example
- * ```typescript
- * const appTransaction = await getAppTransactionIOS();
- * if (appTransaction) {
- * console.log('App was purchased, transaction ID:', appTransaction);
- * } else {
- * console.log('App was not purchased from App Store');
- * }
- * ```
- */
/**
* Get all active subscriptions with detailed information (OpenIAP compliant)
* Returns an array of active subscriptions. If subscriptionIds is not provided,
@@ -2205,6 +2310,8 @@ export const deepLinkToSubscriptionsIOS = async (): Promise => {
*
* @param subscriptionIds - Optional array of subscription IDs to filter by
* @returns Promise - Array of active subscriptions
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/get-active-subscriptions}
*/
export const getActiveSubscriptions: QueryField<
'getActiveSubscriptions'
@@ -2364,6 +2471,8 @@ export const getActiveSubscriptions_OLD: QueryField<
*
* @param subscriptionIds - Optional array of subscription IDs to check
* @returns Promise - True if there are active subscriptions
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/has-active-subscriptions}
*/
export const hasActiveSubscriptions: QueryField<
'hasActiveSubscriptions'
@@ -2491,6 +2600,8 @@ const normalizeProductQueryType = (
* // Proceed with alternative billing flow
* }
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android}
*/
export const checkAlternativeBillingAvailabilityAndroid: MutationField<
'checkAlternativeBillingAvailabilityAndroid'
@@ -2531,6 +2642,8 @@ export const checkAlternativeBillingAvailabilityAndroid: MutationField<
* }
* }
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android}
*/
export const showAlternativeBillingDialogAndroid: MutationField<
'showAlternativeBillingDialogAndroid'
@@ -2568,6 +2681,8 @@ export const showAlternativeBillingDialogAndroid: MutationField<
* });
* }
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android}
*/
export const createAlternativeBillingTokenAndroid: MutationField<
'createAlternativeBillingTokenAndroid'
@@ -2663,6 +2778,8 @@ export const enableBillingProgramAndroid = (
* // External offers are available for this user
* }
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/is-billing-program-available-android}
*/
export const isBillingProgramAvailableAndroid: MutationField<
'isBillingProgramAvailableAndroid'
@@ -2702,6 +2819,8 @@ export const isBillingProgramAvailableAndroid: MutationField<
* body: JSON.stringify({ token: details.externalTransactionToken })
* });
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android}
*/
export const createBillingProgramReportingDetailsAndroid: MutationField<
'createBillingProgramReportingDetailsAndroid'
@@ -2747,6 +2866,8 @@ export const createBillingProgramReportingDetailsAndroid: MutationField<
* console.log('User accepted external link');
* }
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/android/launch-external-link-android}
*/
export const launchExternalLinkAndroid: MutationField<
'launchExternalLinkAndroid'
@@ -2785,6 +2906,8 @@ export const launchExternalLinkAndroid: MutationField<
* const result = await presentExternalPurchaseNoticeSheetIOS();
* }
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios}
*/
export const canPresentExternalPurchaseNoticeIOS: QueryField<
'canPresentExternalPurchaseNoticeIOS'
@@ -2818,6 +2941,8 @@ export const canPresentExternalPurchaseNoticeIOS: QueryField<
* await presentExternalPurchaseLinkIOS('https://your-website.com/purchase');
* }
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios}
*/
export const presentExternalPurchaseNoticeSheetIOS =
async (): Promise => {
@@ -2849,6 +2974,8 @@ export const presentExternalPurchaseNoticeSheetIOS =
* console.log('User completed external purchase');
* }
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios}
*/
export const presentExternalPurchaseLinkIOS: MutationField<
'presentExternalPurchaseLinkIOS'
@@ -2883,6 +3010,8 @@ export const presentExternalPurchaseLinkIOS: MutationField<
* // App can use custom external purchase links
* }
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios}
*/
export const isEligibleForExternalPurchaseCustomLinkIOS =
async (): Promise => {
@@ -2918,6 +3047,8 @@ export const isEligibleForExternalPurchaseCustomLinkIOS =
* await reportToApple(result.token);
* }
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios}
*/
export const getExternalPurchaseCustomLinkTokenIOS = async (
tokenType: ExternalPurchaseCustomLinkTokenTypeIOS,
@@ -2956,6 +3087,8 @@ export const getExternalPurchaseCustomLinkTokenIOS = async (
* await Linking.openURL('https://your-store.com/checkout');
* }
* ```
+ *
+ * @see {@link https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios}
*/
export const showExternalPurchaseCustomLinkNoticeIOS = async (
noticeType: ExternalPurchaseCustomLinkNoticeTypeIOS,
diff --git a/libraries/react-native-iap/src/types.ts b/libraries/react-native-iap/src/types.ts
index 4afb30b7..f7d95686 100644
--- a/libraries/react-native-iap/src/types.ts
+++ b/libraries/react-native-iap/src/types.ts
@@ -585,118 +585,170 @@ export interface LimitedQuantityInfoAndroid {
}
export interface Mutation {
- /** Acknowledge a non-consumable purchase or subscription */
+ /**
+ * Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
+ * See: https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android
+ */
acknowledgePurchaseAndroid: Promise;
- /** Initiate a refund request for a product (iOS 15+) */
+ /**
+ * Present the refund request sheet (iOS 15+). See also Features → Refund.
+ * See: https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios
+ */
beginRefundRequestIOS?: Promise<(string | null)>;
/**
- * Check if alternative billing is available for this user/device
- * Step 1 of alternative billing flow
+ * Check whether alternative billing is available for the user. Step 1 of the alternative billing flow.
*
- * Returns true if available, false otherwise
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns true if available, false otherwise.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android
*/
checkAlternativeBillingAvailabilityAndroid: Promise;
- /** Clear pending transactions from the StoreKit payment queue */
+ /**
+ * Clear pending transactions in the queue (sandbox helper).
+ * See: https://www.openiap.dev/docs/apis/ios/clear-transaction-ios
+ */
clearTransactionIOS: Promise;
- /** Consume a purchase token so it can be repurchased */
+ /**
+ * Consume a consumable purchase so it can be re-bought.
+ * See: https://www.openiap.dev/docs/apis/android/consume-purchase-android
+ */
consumePurchaseAndroid: Promise;
/**
- * Create external transaction token for Google Play reporting
- * Step 3 of alternative billing flow
- * Must be called AFTER successful payment in your payment system
- * Token must be reported to Google Play backend within 24 hours
+ * Create a reporting token for an alternative billing flow. Step 3 of the alternative billing flow.
+ * Must be called AFTER successful payment in your payment system.
+ * Token must be reported to Google Play backend within 24 hours.
*
- * Returns token string, or null if creation failed
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns token string, or null if creation failed.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android
*/
createAlternativeBillingTokenAndroid?: Promise<(string | null)>;
/**
- * Create reporting details for a billing program
- * Replaces the deprecated createExternalOfferReportingDetailsAsync API
+ * Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+).
+ * Replaces the deprecated createExternalOfferReportingDetailsAsync API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Returns external transaction token needed for reporting external transactions
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns external transaction token needed for reporting external transactions.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android
*/
createBillingProgramReportingDetailsAndroid: Promise;
- /** Open the native subscription management surface */
+ /**
+ * Open the platform's subscription management UI.
+ * See: https://www.openiap.dev/docs/apis/deep-link-to-subscriptions
+ */
deepLinkToSubscriptions: Promise;
- /** Close the platform billing connection */
+ /**
+ * Close the store connection and release resources.
+ * See: https://www.openiap.dev/docs/apis/end-connection
+ */
endConnection: Promise;
- /** Finish a transaction after validating receipts */
+ /**
+ * Complete a transaction after server-side verification. Required on Android within 3 days.
+ * See: https://www.openiap.dev/docs/apis/finish-transaction
+ */
finishTransaction: Promise;
- /** Establish the platform billing connection */
+ /**
+ * Initialize the store connection. Call before any IAP API.
+ * See: https://www.openiap.dev/docs/apis/init-connection
+ */
initConnection: Promise;
/**
- * Check if a billing program is available for the current user
- * Replaces the deprecated isExternalOfferAvailableAsync API
+ * Check whether a billing program (e.g., External Payments) is available for the current user.
+ * Replaces the deprecated isExternalOfferAvailableAsync API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Returns availability result with isAvailable flag
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Available in Google Play Billing Library 8.2.0+.
+ * Returns availability result with isAvailable flag.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/is-billing-program-available-android
*/
isBillingProgramAvailableAndroid: Promise;
/**
- * Launch external link flow for external billing programs
- * Replaces the deprecated showExternalOfferInformationDialog API
+ * Launch an external content/offer link from inside the Billing Programs flow (Play Billing 8.2.0+).
+ * Replaces the deprecated showExternalOfferInformationDialog API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Shows Play Store dialog and optionally launches external URL
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Shows Play Store dialog and optionally launches external URL.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/launch-external-link-android
*/
launchExternalLinkAndroid: Promise;
- /** Present the App Store code redemption sheet */
+ /**
+ * Show the App Store offer code redemption sheet.
+ * See: https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios
+ */
presentCodeRedemptionSheetIOS: Promise;
- /** Present external purchase custom link with StoreKit UI */
+ /**
+ * Present an external purchase link, StoreKit External (iOS 16+).
+ * See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios
+ */
presentExternalPurchaseLinkIOS: Promise;
/**
- * Present external purchase notice sheet (iOS 17.4+).
- * Uses ExternalPurchase.presentNoticeSheet() which returns a token when user continues.
+ * Present the external purchase notice sheet (iOS 17.4+).
+ * Uses ExternalPurchase.presentNoticeSheet() which returns a token when the user continues.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchase/presentnoticesheet()
+ * See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios
*/
presentExternalPurchaseNoticeSheetIOS: Promise;
- /** Initiate a purchase flow; rely on events for final state */
+ /**
+ * Initiate a purchase or subscription flow; rely on events for final state.
+ * See: https://www.openiap.dev/docs/apis/request-purchase
+ */
requestPurchase?: Promise<(Purchase | Purchase[] | null)>;
/**
- * Purchase the promoted product surfaced by the App Store.
+ * Buy the currently promoted product.
*
* @deprecated Use promotedProductListenerIOS to receive the productId,
* then call requestPurchase with that SKU instead. In StoreKit 2,
* promoted products can be purchased directly via the standard purchase flow.
+ * See: https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios
* @deprecated Use promotedProductListenerIOS + requestPurchase instead
*/
requestPurchaseOnPromotedProductIOS: Promise;
- /** Restore completed purchases across platforms */
+ /**
+ * Restore non-consumable and active subscription purchases.
+ * See: https://www.openiap.dev/docs/apis/restore-purchases
+ */
restorePurchases: Promise;
/**
- * Show alternative billing information dialog to user
- * Step 2 of alternative billing flow
- * Must be called BEFORE processing payment in your payment system
+ * Display Google's alternative billing information dialog. Step 2 of the alternative billing flow.
+ * Must be called BEFORE processing payment in your payment system.
*
- * Returns true if user accepted, false if user canceled
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns true if user accepted, false if user canceled.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android
*/
showAlternativeBillingDialogAndroid: Promise;
/**
- * Show ExternalPurchaseCustomLink notice sheet (iOS 18.1+).
- * Displays the system disclosure notice sheet for custom external purchase links.
+ * Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
* Call this after a deliberate customer interaction before linking out to external purchases.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/shownotice(type:)
+ * See: https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios
*/
showExternalPurchaseCustomLinkNoticeIOS: Promise;
- /** Open subscription management UI and return changed purchases (iOS 15+) */
+ /**
+ * Present the manage-subscriptions sheet and return changed purchases (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios
+ */
showManageSubscriptionsIOS: Promise;
- /** Force a StoreKit sync for transactions (iOS 15+) */
+ /**
+ * Force sync transactions with the App Store (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/sync-ios
+ */
syncIOS: Promise;
/**
- * Validate purchase receipts with the configured providers
+ * Deprecated. Validate purchase receipts with the configured providers — use verifyPurchase instead.
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase
* @deprecated Use verifyPurchase
*/
validateReceipt: Promise;
- /** Verify purchases with the configured providers */
+ /**
+ * Verify a purchase against your own backend (returns isValid + raw store metadata).
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase
+ */
verifyPurchase: Promise;
- /** Verify purchases with a specific provider (e.g., IAPKit) */
+ /**
+ * Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
+ */
verifyPurchaseWithProvider: Promise;
}
@@ -1234,66 +1286,117 @@ export type PurchaseVerificationProvider = 'iapkit';
export interface Query {
/**
- * Check if external purchase notice sheet can be presented (iOS 17.4+)
- * Uses ExternalPurchase.canPresent
+ * Check eligibility for the external purchase notice sheet (iOS 17.4+).
+ * Uses ExternalPurchase.canPresent.
+ * See: https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios
*/
canPresentExternalPurchaseNoticeIOS: Promise;
- /** Get current StoreKit 2 entitlements (iOS 15+) */
+ /**
+ * Get the user's current entitlement for a product, using StoreKit 2 (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/current-entitlement-ios
+ */
currentEntitlementIOS?: Promise<(PurchaseIOS | null)>;
- /** Retrieve products or subscriptions from the store */
+ /**
+ * Fetch products or subscriptions from the store.
+ * See: https://www.openiap.dev/docs/apis/fetch-products
+ */
fetchProducts: Promise<(ProductOrSubscription[] | Product[] | ProductSubscription[] | null)>;
- /** Get active subscriptions (filters by subscriptionIds when provided) */
+ /**
+ * Get details of all currently active subscriptions (filters by subscriptionIds when provided).
+ * See: https://www.openiap.dev/docs/apis/get-active-subscriptions
+ */
getActiveSubscriptions: Promise;
/**
- * Get the full StoreKit 2 transaction history as PurchaseIOS values.
+ * List every StoreKit transaction (finished + unfinished) for the current user.
* Requires the SK2ConsumableTransactionHistory Info.plist key in the host app
* for finished consumables to be included (iOS 18+).
* Unlike getAvailablePurchases, always returns the iOS-specific PurchaseIOS shape.
+ * See: https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios
*/
getAllTransactionsIOS: Promise;
- /** Fetch the current app transaction (iOS 16+) */
+ /**
+ * Fetch the app transaction (iOS 16+).
+ * See: https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios
+ */
getAppTransactionIOS?: Promise<(AppTransaction | null)>;
- /** Get all available purchases for the current user */
+ /**
+ * List active purchases for the current user.
+ * See: https://www.openiap.dev/docs/apis/get-available-purchases
+ */
getAvailablePurchases: Promise;
/**
- * Get external purchase token for reporting to Apple (iOS 18.1+).
- * Use this token with Apple's External Purchase Server API to report transactions.
+ * Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
+ * Use this token to report transactions made through ExternalPurchaseCustomLink.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/token(for:)
+ * See: https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios
*/
getExternalPurchaseCustomLinkTokenIOS: Promise;
- /** Retrieve all pending transactions in the StoreKit queue */
+ /**
+ * List unfinished StoreKit transactions in the queue.
+ * See: https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios
+ */
getPendingTransactionsIOS: Promise;
- /** Get the currently promoted product (iOS 11+) */
+ /**
+ * Read the App Store-promoted product, if any (iOS 11+).
+ * See: https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios
+ */
getPromotedProductIOS?: Promise<(ProductIOS | null)>;
- /** Get base64-encoded receipt data for validation */
+ /**
+ * Get base64-encoded receipt data (legacy validation).
+ * See: https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios
+ */
getReceiptDataIOS?: Promise<(string | null)>;
- /** Get the current storefront country code */
+ /**
+ * Return the user's storefront country code.
+ * See: https://www.openiap.dev/docs/apis/get-storefront
+ */
getStorefront: Promise;
/**
- * Get the current App Store storefront country code
+ * Deprecated. Get the current App Store storefront country code — use cross-platform getStorefront instead.
+ * See: https://www.openiap.dev/docs/apis/ios/get-storefront-ios
* @deprecated Use getStorefront
*/
getStorefrontIOS: Promise;
- /** Get the transaction JWS (StoreKit 2) */
+ /**
+ * Return the JWS string for a transaction (StoreKit 2).
+ * See: https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios
+ */
getTransactionJwsIOS?: Promise<(string | null)>;
- /** Check whether the user has active subscriptions */
+ /**
+ * Check whether the user has any active subscription.
+ * See: https://www.openiap.dev/docs/apis/has-active-subscriptions
+ */
hasActiveSubscriptions: Promise;
/**
- * Check if app is eligible for ExternalPurchaseCustomLink API (iOS 18.1+).
+ * Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
* Returns true if the app can use custom external purchase links.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/iseligible
+ * See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios
*/
isEligibleForExternalPurchaseCustomLinkIOS: Promise;
- /** Check introductory offer eligibility for a subscription group */
+ /**
+ * Check intro-offer eligibility for a subscription group.
+ * See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios
+ */
isEligibleForIntroOfferIOS: Promise;
- /** Verify a StoreKit 2 transaction signature */
+ /**
+ * Check whether a transaction's JWS verification passed (StoreKit 2).
+ * See: https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios
+ */
isTransactionVerifiedIOS: Promise;
- /** Get the latest transaction for a product using StoreKit 2 */
+ /**
+ * Get the latest verified transaction for a product, using StoreKit 2.
+ * See: https://www.openiap.dev/docs/apis/ios/latest-transaction-ios
+ */
latestTransactionIOS?: Promise<(PurchaseIOS | null)>;
- /** Get StoreKit 2 subscription status details (iOS 15+) */
+ /**
+ * Get subscription status objects from StoreKit 2 (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/subscription-status-ios
+ */
subscriptionStatusIOS: Promise;
/**
- * Validate a receipt for a specific product
+ * Deprecated. Legacy App Store receipt validation — use verifyPurchase instead.
+ * See: https://www.openiap.dev/docs/apis/ios/validate-receipt-ios
* @deprecated Use verifyPurchase
*/
validateReceiptIOS: Promise;
diff --git a/packages/apple/Sources/Models/Types.swift b/packages/apple/Sources/Models/Types.swift
index a3547e12..4d823837 100644
--- a/packages/apple/Sources/Models/Types.swift
+++ b/packages/apple/Sources/Models/Types.swift
@@ -2334,150 +2334,191 @@ public enum VerifyPurchaseResult: Codable {
/// GraphQL root mutation operations.
public protocol MutationResolver {
- /// Acknowledge a non-consumable purchase or subscription
+ /// Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
+ /// See: https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android
func acknowledgePurchaseAndroid(_ purchaseToken: String) async throws -> Bool
- /// Initiate a refund request for a product (iOS 15+)
+ /// Present the refund request sheet (iOS 15+). See also Features → Refund.
+ /// See: https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios
func beginRefundRequestIOS(_ sku: String) async throws -> String?
- /// Check if alternative billing is available for this user/device
- /// Step 1 of alternative billing flow
+ /// Check whether alternative billing is available for the user. Step 1 of the alternative billing flow.
///
- /// Returns true if available, false otherwise
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Returns true if available, false otherwise.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android
func checkAlternativeBillingAvailabilityAndroid() async throws -> Bool
- /// Clear pending transactions from the StoreKit payment queue
+ /// Clear pending transactions in the queue (sandbox helper).
+ /// See: https://www.openiap.dev/docs/apis/ios/clear-transaction-ios
func clearTransactionIOS() async throws -> Bool
- /// Consume a purchase token so it can be repurchased
+ /// Consume a consumable purchase so it can be re-bought.
+ /// See: https://www.openiap.dev/docs/apis/android/consume-purchase-android
func consumePurchaseAndroid(_ purchaseToken: String) async throws -> Bool
- /// Create external transaction token for Google Play reporting
- /// Step 3 of alternative billing flow
- /// Must be called AFTER successful payment in your payment system
- /// Token must be reported to Google Play backend within 24 hours
+ /// Create a reporting token for an alternative billing flow. Step 3 of the alternative billing flow.
+ /// Must be called AFTER successful payment in your payment system.
+ /// Token must be reported to Google Play backend within 24 hours.
///
- /// Returns token string, or null if creation failed
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Returns token string, or null if creation failed.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android
func createAlternativeBillingTokenAndroid() async throws -> String?
- /// Create reporting details for a billing program
- /// Replaces the deprecated createExternalOfferReportingDetailsAsync API
+ /// Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+).
+ /// Replaces the deprecated createExternalOfferReportingDetailsAsync API.
///
- /// Available in Google Play Billing Library 8.2.0+
- /// Returns external transaction token needed for reporting external transactions
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Returns external transaction token needed for reporting external transactions.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android
func createBillingProgramReportingDetailsAndroid(_ program: BillingProgramAndroid) async throws -> BillingProgramReportingDetailsAndroid
- /// Open the native subscription management surface
+ /// Open the platform's subscription management UI.
+ /// See: https://www.openiap.dev/docs/apis/deep-link-to-subscriptions
func deepLinkToSubscriptions(_ options: DeepLinkOptions?) async throws -> Void
- /// Close the platform billing connection
+ /// Close the store connection and release resources.
+ /// See: https://www.openiap.dev/docs/apis/end-connection
func endConnection() async throws -> Bool
- /// Finish a transaction after validating receipts
+ /// Complete a transaction after server-side verification. Required on Android within 3 days.
+ /// See: https://www.openiap.dev/docs/apis/finish-transaction
func finishTransaction(purchase: PurchaseInput, isConsumable: Bool?) async throws -> Void
- /// Establish the platform billing connection
+ /// Initialize the store connection. Call before any IAP API.
+ /// See: https://www.openiap.dev/docs/apis/init-connection
func initConnection(_ config: InitConnectionConfig?) async throws -> Bool
- /// Check if a billing program is available for the current user
- /// Replaces the deprecated isExternalOfferAvailableAsync API
+ /// Check whether a billing program (e.g., External Payments) is available for the current user.
+ /// Replaces the deprecated isExternalOfferAvailableAsync API.
///
- /// Available in Google Play Billing Library 8.2.0+
- /// Returns availability result with isAvailable flag
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Available in Google Play Billing Library 8.2.0+.
+ /// Returns availability result with isAvailable flag.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/is-billing-program-available-android
func isBillingProgramAvailableAndroid(_ program: BillingProgramAndroid) async throws -> BillingProgramAvailabilityResultAndroid
- /// Launch external link flow for external billing programs
- /// Replaces the deprecated showExternalOfferInformationDialog API
+ /// Launch an external content/offer link from inside the Billing Programs flow (Play Billing 8.2.0+).
+ /// Replaces the deprecated showExternalOfferInformationDialog API.
///
- /// Available in Google Play Billing Library 8.2.0+
- /// Shows Play Store dialog and optionally launches external URL
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Shows Play Store dialog and optionally launches external URL.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/launch-external-link-android
func launchExternalLinkAndroid(_ params: LaunchExternalLinkParamsAndroid) async throws -> Bool
- /// Present the App Store code redemption sheet
+ /// Show the App Store offer code redemption sheet.
+ /// See: https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios
func presentCodeRedemptionSheetIOS() async throws -> Bool
- /// Present external purchase custom link with StoreKit UI
+ /// Present an external purchase link, StoreKit External (iOS 16+).
+ /// See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios
func presentExternalPurchaseLinkIOS(_ url: String) async throws -> ExternalPurchaseLinkResultIOS
- /// Present external purchase notice sheet (iOS 17.4+).
- /// Uses ExternalPurchase.presentNoticeSheet() which returns a token when user continues.
+ /// Present the external purchase notice sheet (iOS 17.4+).
+ /// Uses ExternalPurchase.presentNoticeSheet() which returns a token when the user continues.
/// Reference: https://developer.apple.com/documentation/storekit/externalpurchase/presentnoticesheet()
+ /// See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios
func presentExternalPurchaseNoticeSheetIOS() async throws -> ExternalPurchaseNoticeResultIOS
- /// Initiate a purchase flow; rely on events for final state
+ /// Initiate a purchase or subscription flow; rely on events for final state.
+ /// See: https://www.openiap.dev/docs/apis/request-purchase
func requestPurchase(_ params: RequestPurchaseProps) async throws -> RequestPurchaseResult?
- /// Purchase the promoted product surfaced by the App Store.
+ /// Buy the currently promoted product.
///
/// @deprecated Use promotedProductListenerIOS to receive the productId,
/// then call requestPurchase with that SKU instead. In StoreKit 2,
/// promoted products can be purchased directly via the standard purchase flow.
+ /// See: https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios
func requestPurchaseOnPromotedProductIOS() async throws -> Bool
- /// Restore completed purchases across platforms
+ /// Restore non-consumable and active subscription purchases.
+ /// See: https://www.openiap.dev/docs/apis/restore-purchases
func restorePurchases() async throws -> Void
- /// Show alternative billing information dialog to user
- /// Step 2 of alternative billing flow
- /// Must be called BEFORE processing payment in your payment system
+ /// Display Google's alternative billing information dialog. Step 2 of the alternative billing flow.
+ /// Must be called BEFORE processing payment in your payment system.
///
- /// Returns true if user accepted, false if user canceled
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Returns true if user accepted, false if user canceled.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android
func showAlternativeBillingDialogAndroid() async throws -> Bool
- /// Show ExternalPurchaseCustomLink notice sheet (iOS 18.1+).
- /// Displays the system disclosure notice sheet for custom external purchase links.
+ /// Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
/// Call this after a deliberate customer interaction before linking out to external purchases.
/// Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/shownotice(type:)
+ /// See: https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios
func showExternalPurchaseCustomLinkNoticeIOS(_ noticeType: ExternalPurchaseCustomLinkNoticeTypeIOS) async throws -> ExternalPurchaseCustomLinkNoticeResultIOS
- /// Open subscription management UI and return changed purchases (iOS 15+)
+ /// Present the manage-subscriptions sheet and return changed purchases (iOS 15+).
+ /// See: https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios
func showManageSubscriptionsIOS() async throws -> [PurchaseIOS]
- /// Force a StoreKit sync for transactions (iOS 15+)
+ /// Force sync transactions with the App Store (iOS 15+).
+ /// See: https://www.openiap.dev/docs/apis/ios/sync-ios
func syncIOS() async throws -> Bool
- /// Validate purchase receipts with the configured providers
+ /// Deprecated. Validate purchase receipts with the configured providers — use verifyPurchase instead.
+ /// See: https://www.openiap.dev/docs/features/validation#verify-purchase
func validateReceipt(_ options: VerifyPurchaseProps) async throws -> VerifyPurchaseResult
- /// Verify purchases with the configured providers
+ /// Verify a purchase against your own backend (returns isValid + raw store metadata).
+ /// See: https://www.openiap.dev/docs/features/validation#verify-purchase
func verifyPurchase(_ options: VerifyPurchaseProps) async throws -> VerifyPurchaseResult
- /// Verify purchases with a specific provider (e.g., IAPKit)
+ /// Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+ /// See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
func verifyPurchaseWithProvider(_ options: VerifyPurchaseWithProviderProps) async throws -> VerifyPurchaseWithProviderResult
}
/// GraphQL root query operations.
public protocol QueryResolver {
- /// Check if external purchase notice sheet can be presented (iOS 17.4+)
- /// Uses ExternalPurchase.canPresent
+ /// Check eligibility for the external purchase notice sheet (iOS 17.4+).
+ /// Uses ExternalPurchase.canPresent.
+ /// See: https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios
func canPresentExternalPurchaseNoticeIOS() async throws -> Bool
- /// Get current StoreKit 2 entitlements (iOS 15+)
+ /// Get the user's current entitlement for a product, using StoreKit 2 (iOS 15+).
+ /// See: https://www.openiap.dev/docs/apis/ios/current-entitlement-ios
func currentEntitlementIOS(_ sku: String) async throws -> PurchaseIOS?
- /// Retrieve products or subscriptions from the store
+ /// Fetch products or subscriptions from the store.
+ /// See: https://www.openiap.dev/docs/apis/fetch-products
func fetchProducts(_ params: ProductRequest) async throws -> FetchProductsResult
- /// Get active subscriptions (filters by subscriptionIds when provided)
+ /// Get details of all currently active subscriptions (filters by subscriptionIds when provided).
+ /// See: https://www.openiap.dev/docs/apis/get-active-subscriptions
func getActiveSubscriptions(_ subscriptionIds: [String]?) async throws -> [ActiveSubscription]
- /// Get the full StoreKit 2 transaction history as PurchaseIOS values.
+ /// List every StoreKit transaction (finished + unfinished) for the current user.
/// Requires the SK2ConsumableTransactionHistory Info.plist key in the host app
/// for finished consumables to be included (iOS 18+).
/// Unlike getAvailablePurchases, always returns the iOS-specific PurchaseIOS shape.
+ /// See: https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios
func getAllTransactionsIOS() async throws -> [PurchaseIOS]
- /// Fetch the current app transaction (iOS 16+)
+ /// Fetch the app transaction (iOS 16+).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios
func getAppTransactionIOS() async throws -> AppTransaction?
- /// Get all available purchases for the current user
+ /// List active purchases for the current user.
+ /// See: https://www.openiap.dev/docs/apis/get-available-purchases
func getAvailablePurchases(_ options: PurchaseOptions?) async throws -> [Purchase]
- /// Get external purchase token for reporting to Apple (iOS 18.1+).
- /// Use this token with Apple's External Purchase Server API to report transactions.
+ /// Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
+ /// Use this token to report transactions made through ExternalPurchaseCustomLink.
/// Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/token(for:)
+ /// See: https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios
func getExternalPurchaseCustomLinkTokenIOS(_ tokenType: ExternalPurchaseCustomLinkTokenTypeIOS) async throws -> ExternalPurchaseCustomLinkTokenResultIOS
- /// Retrieve all pending transactions in the StoreKit queue
+ /// List unfinished StoreKit transactions in the queue.
+ /// See: https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios
func getPendingTransactionsIOS() async throws -> [PurchaseIOS]
- /// Get the currently promoted product (iOS 11+)
+ /// Read the App Store-promoted product, if any (iOS 11+).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios
func getPromotedProductIOS() async throws -> ProductIOS?
- /// Get base64-encoded receipt data for validation
+ /// Get base64-encoded receipt data (legacy validation).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios
func getReceiptDataIOS() async throws -> String?
- /// Get the current storefront country code
+ /// Return the user's storefront country code.
+ /// See: https://www.openiap.dev/docs/apis/get-storefront
func getStorefront() async throws -> String
- /// Get the current App Store storefront country code
+ /// Deprecated. Get the current App Store storefront country code — use cross-platform getStorefront instead.
+ /// See: https://www.openiap.dev/docs/apis/ios/get-storefront-ios
func getStorefrontIOS() async throws -> String
- /// Get the transaction JWS (StoreKit 2)
+ /// Return the JWS string for a transaction (StoreKit 2).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios
func getTransactionJwsIOS(_ sku: String) async throws -> String?
- /// Check whether the user has active subscriptions
+ /// Check whether the user has any active subscription.
+ /// See: https://www.openiap.dev/docs/apis/has-active-subscriptions
func hasActiveSubscriptions(_ subscriptionIds: [String]?) async throws -> Bool
- /// Check if app is eligible for ExternalPurchaseCustomLink API (iOS 18.1+).
+ /// Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
/// Returns true if the app can use custom external purchase links.
/// Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/iseligible
+ /// See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios
func isEligibleForExternalPurchaseCustomLinkIOS() async throws -> Bool
- /// Check introductory offer eligibility for a subscription group
+ /// Check intro-offer eligibility for a subscription group.
+ /// See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios
func isEligibleForIntroOfferIOS(_ groupID: String) async throws -> Bool
- /// Verify a StoreKit 2 transaction signature
+ /// Check whether a transaction's JWS verification passed (StoreKit 2).
+ /// See: https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios
func isTransactionVerifiedIOS(_ sku: String) async throws -> Bool
- /// Get the latest transaction for a product using StoreKit 2
+ /// Get the latest verified transaction for a product, using StoreKit 2.
+ /// See: https://www.openiap.dev/docs/apis/ios/latest-transaction-ios
func latestTransactionIOS(_ sku: String) async throws -> PurchaseIOS?
- /// Get StoreKit 2 subscription status details (iOS 15+)
+ /// Get subscription status objects from StoreKit 2 (iOS 15+).
+ /// See: https://www.openiap.dev/docs/apis/ios/subscription-status-ios
func subscriptionStatusIOS(_ sku: String) async throws -> [SubscriptionStatusIOS]
- /// Validate a receipt for a specific product
+ /// Deprecated. Legacy App Store receipt validation — use verifyPurchase instead.
+ /// See: https://www.openiap.dev/docs/apis/ios/validate-receipt-ios
func validateReceiptIOS(_ options: VerifyPurchaseProps) async throws -> VerifyPurchaseResultIOS
}
diff --git a/packages/apple/Sources/OpenIapModule.swift b/packages/apple/Sources/OpenIapModule.swift
index 7cd95b39..89d4c679 100644
--- a/packages/apple/Sources/OpenIapModule.swift
+++ b/packages/apple/Sources/OpenIapModule.swift
@@ -36,6 +36,14 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
// MARK: - Connection Management
+ /// Initialize the store connection. Must be called before any other IAP API.
+ ///
+ /// - Returns: `true` once StoreKit is connected.
+ /// - Throws: When StoreKit fails to initialize.
+ /// - Note: This wraps `OpenIapStoreKit2.initialize()`. Safe to call multiple times — the
+ /// second call is a no-op.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/init-connection
public func initConnection() async throws -> Bool {
if let task = initTask {
return try await task.value
@@ -81,6 +89,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
}
}
+ /// Close the store connection and release resources.
+ /// See: https://www.openiap.dev/docs/apis/end-connection
public func endConnection() async throws -> Bool {
initTask?.cancel()
initTask = nil
@@ -90,6 +100,17 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
// MARK: - Product Management
+ /// Retrieve products or subscriptions from the App Store by SKU.
+ ///
+ /// - Parameter params: `ProductRequest` with `skus` (the product identifiers) and an
+ /// optional `type` (`.inApp`, `.subs`, or `.all`; defaults to `.inApp`).
+ /// - Returns: A `FetchProductsResult` variant — `Product[]` for `.inApp`,
+ /// `ProductSubscription[]` for `.subs`, or a mixed list for `.all`.
+ /// - Throws: When the store rejects the request (unknown SKU, network failure, not connected).
+ /// - Note: This is a regular promise-based call. Do not confuse with `request*` APIs,
+ /// which are event-based.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/fetch-products
public func fetchProducts(_ params: ProductRequest) async throws -> FetchProductsResult {
guard !params.skus.isEmpty else {
let error = makePurchaseError(code: .emptySkuList)
@@ -188,6 +209,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
}
}
+ /// Read the App Store-promoted product, if any.
+ /// See: https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios
public func getPromotedProductIOS() async throws -> ProductIOS? {
// iOS-only: Promoted in-app purchases (App Store promotional purchases) only available on iOS
// Reference: https://developer.apple.com/documentation/storekit/promoting-in-app-purchases
@@ -227,6 +250,16 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
// MARK: - Purchase Management
+ /// Initiate a purchase flow. The result is delivered via the purchase update listener,
+ /// NOT through the return value.
+ ///
+ /// - Parameter params: `RequestPurchaseProps` — discriminated by `type`:
+ /// `.inApp` for one-time products (use `request.apple.sku`), `.subs` for subscriptions.
+ /// - Returns: The dispatched request payload. Do not rely on this for the purchase outcome.
+ /// - Throws: Synchronous rejections from StoreKit (e.g. user cancel before sheet, not prepared).
+ /// - Warning: Event-based. Listen via `purchaseUpdatedListener` / `purchaseErrorListener`.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/request-purchase
public func requestPurchase(_ params: RequestPurchaseProps) async throws -> RequestPurchaseResult? {
try await ensureConnection()
let iosProps = try resolveIOSPurchaseProps(from: params)
@@ -466,15 +499,28 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
}
}
+ /// Buy the currently promoted product.
+ /// See: https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios
@available(*, deprecated, message: "Use promotedProductListenerIOS + requestPurchase instead")
public func requestPurchaseOnPromotedProductIOS() async throws -> Bool {
throw makePurchaseError(code: .featureNotSupported)
}
+ /// Restore non-consumable and active subscription purchases.
+ /// See: https://www.openiap.dev/docs/apis/restore-purchases
public func restorePurchases() async throws -> Void {
_ = try await syncIOS()
}
+ /// List the user's unfinished purchases. Use this to restore non-consumables / active
+ /// subscriptions, or to pick up transactions that weren't finished previously.
+ ///
+ /// - Parameter options: Optional iOS-specific flags
+ /// (`alsoPublishToEventListenerIOS`, `onlyIncludeActiveItemsIOS`).
+ /// - Returns: An array of `Purchase` values currently held by StoreKit.
+ /// - Throws: When the StoreKit query fails.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/get-available-purchases
public func getAvailablePurchases(_ options: PurchaseOptions?) async throws -> [Purchase] {
try await ensureConnection()
let onlyActive = options?.onlyIncludeActiveItemsIOS ?? false
@@ -509,6 +555,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
/// Unlike `getAvailablePurchases(_:)`, this method always reads from
/// `Transaction.all` and returns the iOS-specific `PurchaseIOS` shape rather than
/// the cross-platform `Purchase` type.
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios
public func getAllTransactionsIOS() async throws -> [PurchaseIOS] {
try await ensureConnection()
var transactions: [PurchaseIOS] = []
@@ -533,6 +581,19 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
// MARK: - Transaction Management
+ /// Complete a purchase transaction. Call after server-side verification to remove it
+ /// from the StoreKit queue.
+ ///
+ /// - Parameters:
+ /// - purchase: The `PurchaseInput` to finalize.
+ /// - isConsumable: Pass `true` for consumables (re-buyable like coins), `false` for
+ /// subscriptions and non-consumables. Affects only Android consume vs acknowledge;
+ /// iOS always calls `Transaction.finish()`.
+ /// - Throws: When the platform finalization fails.
+ /// - Important: iOS unfinished transactions replay on every app launch. (Android purchases
+ /// must be acknowledged within 3 days, but that path lives in the Android module.)
+ ///
+ /// See: https://www.openiap.dev/docs/apis/finish-transaction
public func finishTransaction(purchase: PurchaseInput, isConsumable: Bool?) async throws -> Void {
try await ensureConnection()
let identifier = purchase.id
@@ -578,6 +639,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
throw error
}
+ /// List unfinished StoreKit transactions.
+ /// See: https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios
public func getPendingTransactionsIOS() async throws -> [PurchaseIOS] {
try await ensureConnection()
let snapshot = await state.pendingSnapshot()
@@ -588,6 +651,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
return purchases
}
+ /// Clear pending transactions in the queue (sandbox helper).
+ /// See: https://www.openiap.dev/docs/apis/ios/clear-transaction-ios
public func clearTransactionIOS() async throws -> Bool {
try await ensureConnection()
for await result in Transaction.unfinished {
@@ -602,6 +667,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
return true
}
+ /// Check whether a transaction's JWS verification passed.
+ /// See: https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios
public func isTransactionVerifiedIOS(sku: String) async throws -> Bool {
try await ensureConnection()
let product = try await storeProduct(for: sku)
@@ -614,6 +681,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
}
}
+ /// Return the JWS string for a transaction.
+ /// See: https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios
public func getTransactionJwsIOS(sku: String) async throws -> String? {
try await ensureConnection()
let product = try await storeProduct(for: sku)
@@ -627,6 +696,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
// MARK: - Validation
+ /// Get base64 receipt data (legacy validation).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios
public func getReceiptDataIOS() async throws -> String? {
guard let receiptURL = Bundle.main.appStoreReceiptURL,
FileManager.default.fileExists(atPath: receiptURL.path) else {
@@ -636,6 +707,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
return data.base64EncodedString()
}
+ /// Deprecated. Legacy App Store receipt validation. Use `verifyPurchase` instead.
+ /// See: https://www.openiap.dev/docs/apis/ios/validate-receipt-ios
@available(*, deprecated, message: "Use verifyPurchase")
public func validateReceiptIOS(_ props: VerifyPurchaseProps) async throws -> VerifyPurchaseResultIOS {
try await performVerifyPurchaseIOS(props)
@@ -675,17 +748,23 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
)
}
+ /// Deprecated. Use verifyPurchase instead — same input/output shape.
+ /// See: https://www.openiap.dev/docs/apis/validate-receipt
@available(*, deprecated, message: "Use verifyPurchase")
public func validateReceipt(_ props: VerifyPurchaseProps) async throws -> VerifyPurchaseResult {
try await verifyPurchase(props)
}
+ /// Verify a purchase against your own backend (returns isValid + raw store metadata).
+ /// See: https://www.openiap.dev/docs/features/validation#verify-purchase
public func verifyPurchase(_ props: VerifyPurchaseProps) async throws -> VerifyPurchaseResult {
try await ensureConnection()
let iosResult = try await performVerifyPurchaseIOS(props)
return .verifyPurchaseResultIos(iosResult)
}
+ /// Verify via a managed provider (IAPKit, Apple, Google, Horizon).
+ /// See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
public func verifyPurchaseWithProvider(_ props: VerifyPurchaseWithProviderProps) async throws -> VerifyPurchaseWithProviderResult {
try await ensureConnection()
guard props.provider == .iapkit else {
@@ -853,6 +932,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
// MARK: - Store Information
+ /// Deprecated. Use cross-platform `getStorefront` instead.
+ /// See: https://www.openiap.dev/docs/apis/ios/get-storefront-ios
public func getStorefrontIOS() async throws -> String {
try await ensureConnection()
guard let storefront = await Storefront.current else {
@@ -866,6 +947,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
/// Get the app transaction that represents the user's purchase of the app
/// - Note: Available on iOS 16.0+, macOS 14.0+, tvOS 16.0+, watchOS 9.0+
/// - SeeAlso: https://developer.apple.com/documentation/storekit/apptransaction
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios
@available(iOS 16.0, macOS 14.0, tvOS 16.0, watchOS 9.0, *)
public func getAppTransactionIOS() async throws -> AppTransaction? {
try await ensureConnection()
@@ -880,6 +963,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
// MARK: - Subscription Management
+ /// Get details of all currently active subscriptions.
+ /// See: https://www.openiap.dev/docs/apis/get-active-subscriptions
public func getActiveSubscriptions(_ subscriptionIds: [String]?) async throws -> [ActiveSubscription] {
try await ensureConnection()
var allSubscriptions: [ActiveSubscription] = []
@@ -940,6 +1025,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
return allSubscriptions
}
+ /// Check whether the user has any active subscription.
+ /// See: https://www.openiap.dev/docs/apis/has-active-subscriptions
public func hasActiveSubscriptions(_ subscriptionIds: [String]?) async throws -> Bool {
let subscriptions = try await getActiveSubscriptions(subscriptionIds)
return subscriptions.contains { $0.isActive }
@@ -948,6 +1035,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
/// Show the subscription management interface
/// - Note: Available on iOS 15.0+, iPadOS 15.0+, Mac Catalyst 15.0+, macOS 14.0+, visionOS 1.0+. Not available on tvOS (subscriptions are managed in Settings > Accounts) or watchOS.
/// - SeeAlso: https://developer.apple.com/documentation/storekit/appstore/showmanagesubscriptions(in:)
+ ///
+ /// See: https://www.openiap.dev/docs/apis/deep-link-to-subscriptions
public func deepLinkToSubscriptions(_ options: DeepLinkOptions?) async throws -> Void {
try await ensureConnection()
// tvOS: AppStore.showManageSubscriptions not available on tvOS (subscriptions managed in Settings > Accounts)
@@ -971,6 +1060,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
#endif // !os(tvOS) && !os(watchOS)
}
+ /// Get subscription status objects from StoreKit 2.
+ /// See: https://www.openiap.dev/docs/apis/ios/subscription-status-ios
public func subscriptionStatusIOS(sku: String) async throws -> [SubscriptionStatusIOS] {
try await ensureConnection()
let product = try await storeProduct(for: sku)
@@ -1007,6 +1098,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
}
}
+ /// Get the user's current entitlement for a product.
+ /// See: https://www.openiap.dev/docs/apis/ios/current-entitlement-ios
public func currentEntitlementIOS(sku: String) async throws -> PurchaseIOS? {
try await ensureConnection()
let product = try await storeProduct(for: sku)
@@ -1021,6 +1114,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
}
}
+ /// Get the latest verified transaction for a product.
+ /// See: https://www.openiap.dev/docs/apis/ios/latest-transaction-ios
public func latestTransactionIOS(sku: String) async throws -> PurchaseIOS? {
try await ensureConnection()
let product = try await storeProduct(for: sku)
@@ -1040,6 +1135,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
/// Begin a refund request for a transaction
/// - Note: Available on iOS 15.0+, iPadOS 15.0+, Mac Catalyst 15.0+, macOS 12.0+, visionOS 1.0+. Not available on tvOS or watchOS.
/// - SeeAlso: https://developer.apple.com/documentation/storekit/transaction/3803220-beginrefundrequest
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios
public func beginRefundRequestIOS(sku: String) async throws -> String? {
try await ensureConnection()
// tvOS: Transaction.beginRefundRequest not available on tvOS
@@ -1086,6 +1183,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
/// Check if the user is eligible for an introductory offer for a subscription group
/// - SeeAlso: https://developer.apple.com/documentation/storekit/product/subscriptioninfo/iseligibleforintrooffer(for:)
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios
public func isEligibleForIntroOfferIOS(groupID: String) async throws -> Bool {
try await ensureConnection()
return await StoreKit.Product.SubscriptionInfo.isEligibleForIntroOffer(for: groupID)
@@ -1093,6 +1192,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
/// Sync the user's in-app purchases with the App Store
/// - SeeAlso: https://developer.apple.com/documentation/storekit/appstore/sync()
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/sync-ios
public func syncIOS() async throws -> Bool {
try await ensureConnection()
do {
@@ -1106,6 +1207,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
/// Present a sheet for redeeming subscription offer codes
/// - Note: Only available on iOS 14.0+ and Mac Catalyst. Not available on tvOS, macOS, or watchOS
/// - SeeAlso: https://developer.apple.com/documentation/storekit/skpaymentqueue/3566726-presentcoderedemptionsheet
+ ///
+ /// See: https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios
public func presentCodeRedemptionSheetIOS() async throws -> Bool {
try await ensureConnection()
// presentCodeRedemptionSheet is only available on iOS, not tvOS/watchOS/macOS
@@ -1119,6 +1222,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
#endif // os(iOS)
}
+ /// Present the manage-subscriptions sheet.
+ /// See: https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios
public func showManageSubscriptionsIOS() async throws -> [PurchaseIOS] {
try await deepLinkToSubscriptions(nil)
return []
@@ -1126,6 +1231,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
// MARK: - External Purchase (iOS 17.4+, macOS 14.4+, tvOS 17.4+, visionOS 1.1+)
+ /// Check eligibility for the external purchase notice sheet (iOS 17.4+).
+ /// See: https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios
public func canPresentExternalPurchaseNoticeIOS() async throws -> Bool {
try await ensureConnection()
// iOS 17.4+, macOS 14.4+, tvOS 17.4+, watchOS 10.4+, visionOS 1.1+: ExternalPurchase.canPresent
@@ -1137,6 +1244,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
}
}
+ /// Present the external purchase notice sheet (iOS 17.4+).
+ /// See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios
public func presentExternalPurchaseNoticeSheetIOS() async throws -> ExternalPurchaseNoticeResultIOS {
try await ensureConnection()
// iOS 17.4+, macOS 14.4+, tvOS 17.4+, watchOS 10.4+, visionOS 1.1+: ExternalPurchase.presentNoticeSheet
@@ -1199,6 +1308,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
}
}
+ /// Present an external purchase link, StoreKit External (iOS 16+).
+ /// See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios
public func presentExternalPurchaseLinkIOS(_ url: String) async throws -> ExternalPurchaseLinkResultIOS {
try await ensureConnection()
// UIApplication.open is available on iOS/tvOS/visionOS but not watchOS/macOS
@@ -1231,6 +1342,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
// MARK: - ExternalPurchaseCustomLink (iOS 18.1+)
+ /// Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
+ /// See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios
public func isEligibleForExternalPurchaseCustomLinkIOS() async throws -> Bool {
try await ensureConnection()
// iOS 18.1+: ExternalPurchaseCustomLink.isEligible
@@ -1242,6 +1355,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
}
}
+ /// Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios
public func getExternalPurchaseCustomLinkTokenIOS(
_ tokenType: ExternalPurchaseCustomLinkTokenTypeIOS
) async throws -> ExternalPurchaseCustomLinkTokenResultIOS {
@@ -1282,6 +1397,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol {
}
}
+ /// Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
+ /// See: https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios
public func showExternalPurchaseCustomLinkNoticeIOS(
_ noticeType: ExternalPurchaseCustomLinkNoticeTypeIOS
) async throws -> ExternalPurchaseCustomLinkNoticeResultIOS {
diff --git a/packages/docs/src/pages/docs/apis/android/acknowledge-purchase-android.tsx b/packages/docs/src/pages/docs/apis/android/acknowledge-purchase-android.tsx
index 9c047fcd..a86bca13 100644
--- a/packages/docs/src/pages/docs/apis/android/acknowledge-purchase-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/acknowledge-purchase-android.tsx
@@ -23,6 +23,19 @@ function AcknowledgePurchaseAndroid() {
Acknowledge a non-consumable purchase or subscription. Required within 3
days or the purchase will be refunded.
+
+ Wraps BillingClient.acknowledgePurchase(AcknowledgePurchaseParams){' '}
+ — required for non-consumables and subscriptions within 3 days, otherwise
+ Google auto-refunds. See the{' '}
+
+ Google Play Billing reference
+
+ .
+
diff --git a/packages/docs/src/pages/docs/apis/android/check-alternative-billing-availability-android.tsx b/packages/docs/src/pages/docs/apis/android/check-alternative-billing-availability-android.tsx
index 96138d87..b3bb4589 100644
--- a/packages/docs/src/pages/docs/apis/android/check-alternative-billing-availability-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/check-alternative-billing-availability-android.tsx
@@ -22,6 +22,19 @@ function CheckAlternativeBillingAvailabilityAndroid() {
Step 1 of alternative billing flow. Check if alternative billing is
available for this user/device.
+
+ Wraps BillingClient.isAlternativeBillingOnlyAvailableAsync(){' '}
+ — step 1 of the alternative billing flow. Returns whether the user/device
+ is eligible. See the{' '}
+
+ Google Play Billing reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/android/consume-purchase-android.tsx b/packages/docs/src/pages/docs/apis/android/consume-purchase-android.tsx
index 4f3fa0a2..5bf77ec2 100644
--- a/packages/docs/src/pages/docs/apis/android/consume-purchase-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/consume-purchase-android.tsx
@@ -23,6 +23,19 @@ function ConsumePurchaseAndroid() {
Consume a consumable purchase, allowing repurchase. Automatically
acknowledges the purchase.
+
+ Wraps BillingClient.consumeAsync(ConsumeParams) — for
+ consumables (re-buyable like coins). Same 3-day deadline as acknowledge.
+ See the{' '}
+
+ Google Play Billing reference
+
+ .
+
diff --git a/packages/docs/src/pages/docs/apis/android/create-alternative-billing-token-android.tsx b/packages/docs/src/pages/docs/apis/android/create-alternative-billing-token-android.tsx
index 1160020a..08f9c031 100644
--- a/packages/docs/src/pages/docs/apis/android/create-alternative-billing-token-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/create-alternative-billing-token-android.tsx
@@ -22,6 +22,22 @@ function CreateAlternativeBillingTokenAndroid() {
Step 3 of alternative billing flow. Create external transaction token
for Google Play reporting.
+
+ Wraps{' '}
+
+ BillingClient.createAlternativeBillingOnlyReportingDetailsAsync()
+ {' '}
+ — step 3. Token must be reported to Google within 24h of payment. See
+ the{' '}
+
+ Google Play Billing reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/android/create-billing-program-reporting-details-android.tsx b/packages/docs/src/pages/docs/apis/android/create-billing-program-reporting-details-android.tsx
index 7cf943d8..59759773 100644
--- a/packages/docs/src/pages/docs/apis/android/create-billing-program-reporting-details-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/create-billing-program-reporting-details-android.tsx
@@ -22,6 +22,22 @@ function CreateBillingProgramReportingDetailsAndroid() {
Step 3 of Billing Programs API. Create reporting details with external
transaction token after successful payment.
+
+ Wraps{' '}
+
+ BillingClient.createBillingProgramReportingDetailsAsync(BillingProgram)
+ {' '}
+ — returns the external transaction token to report a Developer-Provided
+ Billing transaction. Play Billing 8.3.0+. See the{' '}
+
+ Google Play Billing reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/android/enable-billing-program-android.tsx b/packages/docs/src/pages/docs/apis/android/enable-billing-program-android.tsx
index 39452d6c..c8d720ee 100644
--- a/packages/docs/src/pages/docs/apis/android/enable-billing-program-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/enable-billing-program-android.tsx
@@ -32,6 +32,20 @@ function EnableBillingProgramAndroid() {
when calling initConnection() — there is no separate
top-level call.
+
+ Sets enableBillingProgramAndroid on{' '}
+ InitConnectionConfig; under the hood it configures{' '}
+ BillingClient.Builder.enableBillingPrograms(...) (Play
+ Billing 8.2.0+). See the{' '}
+
+ Google Play Billing reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/android/is-billing-program-available-android.tsx b/packages/docs/src/pages/docs/apis/android/is-billing-program-available-android.tsx
index caee40b3..990b57a2 100644
--- a/packages/docs/src/pages/docs/apis/android/is-billing-program-available-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/is-billing-program-available-android.tsx
@@ -22,6 +22,19 @@ function IsBillingProgramAvailableAndroid() {
Step 1 of Billing Programs API. Check if a billing program is available
for the current user.
+
+ Wraps BillingClient.isBillingProgramAvailableAsync(BillingProgram){' '}
+ — replaces isExternalOfferAvailableAsync. Play Billing
+ 8.2.0+. See the{' '}
+
+ Google Play Billing reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/android/launch-external-link-android.tsx b/packages/docs/src/pages/docs/apis/android/launch-external-link-android.tsx
index 135c448b..f3709281 100644
--- a/packages/docs/src/pages/docs/apis/android/launch-external-link-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/launch-external-link-android.tsx
@@ -22,6 +22,20 @@ function LaunchExternalLinkAndroid() {
Step 2 of Billing Programs API. Launch external link flow — shows Play
Store dialog and optionally launches external URL.
+
+ Wraps BillingClient.launchExternalLinkFlow(activity, params){' '}
+ — replaces showExternalOfferInformationDialog. Shows the
+ Play disclosure dialog and (optionally) launches the URL. Play Billing
+ 8.2.0+. See the{' '}
+
+ Google Play Billing reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/android/show-alternative-billing-dialog-android.tsx b/packages/docs/src/pages/docs/apis/android/show-alternative-billing-dialog-android.tsx
index 143c5ba8..b1f8cb25 100644
--- a/packages/docs/src/pages/docs/apis/android/show-alternative-billing-dialog-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/show-alternative-billing-dialog-android.tsx
@@ -22,6 +22,23 @@ function ShowAlternativeBillingDialogAndroid() {
Step 2 of alternative billing flow. Show alternative billing information
dialog before processing payment.
+
+ Wraps{' '}
+
+ BillingClient.showAlternativeBillingOnlyInformationDialog(activity,
+ listener)
+ {' '}
+ — step 2. Required disclosure sheet before charging via your own payment
+ system. See the{' '}
+
+ Google Play Billing reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/deep-link-to-subscriptions.tsx b/packages/docs/src/pages/docs/apis/deep-link-to-subscriptions.tsx
index 91666e9d..23a5abd7 100644
--- a/packages/docs/src/pages/docs/apis/deep-link-to-subscriptions.tsx
+++ b/packages/docs/src/pages/docs/apis/deep-link-to-subscriptions.tsx
@@ -20,6 +20,32 @@ function DeepLinkToSubscriptions() {
Open the native subscription management interface where users can view
and manage their subscriptions.
+
+ iOS: Opens{' '}
+ https://apps.apple.com/account/subscriptions (universal
+ link) so the user can manage subscriptions in the App Store.{' '}
+
+ Apple docs
+
+ . Android: Opens the Play Store subscription
+ management deep link{' '}
+
+ https://play.google.com/store/account/subscriptions?package=<pkg>&sku=<sku>
+
+ .{' '}
+
+ Google docs
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/end-connection.tsx b/packages/docs/src/pages/docs/apis/end-connection.tsx
index 5e38b300..1ccccd69 100644
--- a/packages/docs/src/pages/docs/apis/end-connection.tsx
+++ b/packages/docs/src/pages/docs/apis/end-connection.tsx
@@ -19,6 +19,28 @@ function EndConnection() {
End connection to the store service. Call this when your app closes or
the IAP component unmounts to clean up resources.
+
+ iOS: Cancels the StoreKit{' '}
+ Transaction.updates task and clears in-memory caches.{' '}
+
+ Apple docs
+
+ . Android: Calls{' '}
+ BillingClient.endConnection(); the client cannot be reused
+ after this — call initConnection again to reconnect.{' '}
+
+ Google docs
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/fetch-products.tsx b/packages/docs/src/pages/docs/apis/fetch-products.tsx
index 4245acaf..5799f62c 100644
--- a/packages/docs/src/pages/docs/apis/fetch-products.tsx
+++ b/packages/docs/src/pages/docs/apis/fetch-products.tsx
@@ -18,6 +18,30 @@ function FetchProducts() {
/>
fetchProducts
Retrieve products or subscriptions from the store by SKU.
+
+ iOS: Wraps Product.products(for:){' '}
+ (StoreKit 2). Fetches the localized price/title for each SKU; throws if
+ any SKU is invalid.{' '}
+
+ Apple docs
+
+ . Android: Calls{' '}
+ BillingClient.queryProductDetailsAsync with the right{' '}
+ ProductType (INAPP/SUBS) per request. Unknown SKUs return
+ an empty list, not an error.{' '}
+
+ Google docs
+
+ .
+
Note about request* APIs
diff --git a/packages/docs/src/pages/docs/apis/finish-transaction.tsx b/packages/docs/src/pages/docs/apis/finish-transaction.tsx
index fe1cb88e..230ce424 100644
--- a/packages/docs/src/pages/docs/apis/finish-transaction.tsx
+++ b/packages/docs/src/pages/docs/apis/finish-transaction.tsx
@@ -19,6 +19,30 @@ function FinishTransaction() {
Complete a purchase transaction. Must be called after verifying the
purchase to remove it from the queue.
+
+ iOS: Calls Transaction.finish(). Until
+ you do, the same transaction replays through{' '}
+ Transaction.updates on every app launch.{' '}
+
+ Apple docs
+
+ . Android: Acknowledges (
+ acknowledgePurchase) for non-consumables/subscriptions or
+ consumes (consumeAsync) for consumables. Google
+ auto-refunds within 3 days if neither runs.{' '}
+
+ Google docs
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/get-active-subscriptions.tsx b/packages/docs/src/pages/docs/apis/get-active-subscriptions.tsx
index b168f3bc..e17684ed 100644
--- a/packages/docs/src/pages/docs/apis/get-active-subscriptions.tsx
+++ b/packages/docs/src/pages/docs/apis/get-active-subscriptions.tsx
@@ -19,6 +19,30 @@ function GetActiveSubscriptions() {
Get all active subscriptions with detailed renewal status information.
+
+ iOS: Iterates{' '}
+ Transaction.currentEntitlements and filters to subscription
+ product types; checks expirationDate and{' '}
+ revocationDate.{' '}
+
+ Apple docs
+
+ . Android: Calls queryPurchasesAsync(SUBS){' '}
+ and treats purchaseState == PURCHASED && autoRenewing{' '}
+ as active.{' '}
+
+ Google docs
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/get-available-purchases.tsx b/packages/docs/src/pages/docs/apis/get-available-purchases.tsx
index ab35df4a..d4b89ba1 100644
--- a/packages/docs/src/pages/docs/apis/get-available-purchases.tsx
+++ b/packages/docs/src/pages/docs/apis/get-available-purchases.tsx
@@ -20,6 +20,30 @@ function GetAvailablePurchases() {
Get all available (unfinished) purchases for the current user. Use this
to restore purchases or check for pending transactions.
+
+ iOS: Iterates{' '}
+ Transaction.currentEntitlements (StoreKit 2). Excludes
+ revoked / refunded transactions by default.{' '}
+
+ Apple docs
+
+ . Android: Calls{' '}
+ BillingClient.queryPurchasesAsync for both{' '}
+ INAPP and SUBS and merges. Only returns
+ purchases still owned by the user.{' '}
+
+ Google docs
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/get-storefront.tsx b/packages/docs/src/pages/docs/apis/get-storefront.tsx
index 92df9add..c0e1b46a 100644
--- a/packages/docs/src/pages/docs/apis/get-storefront.tsx
+++ b/packages/docs/src/pages/docs/apis/get-storefront.tsx
@@ -16,6 +16,29 @@ function GetStorefront() {
/>
getStorefront
Get the storefront country code for the active user.
+
+ iOS: Reads Storefront.current?.countryCode{' '}
+ (StoreKit 2). Returns the user's App Store storefront, not the device
+ locale.{' '}
+
+ Apple docs
+
+ . Android: Reads BillingConfig.countryCode{' '}
+ from BillingClient.getBillingConfigAsync. Reflects the Play
+ Store account region, not the SIM/device locale.{' '}
+
+ Google docs
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/has-active-subscriptions.tsx b/packages/docs/src/pages/docs/apis/has-active-subscriptions.tsx
index e8324509..d8e7d417 100644
--- a/packages/docs/src/pages/docs/apis/has-active-subscriptions.tsx
+++ b/packages/docs/src/pages/docs/apis/has-active-subscriptions.tsx
@@ -16,6 +16,29 @@ function HasActiveSubscriptions() {
/>
hasActiveSubscriptions
Quick check if the user has any active subscriptions.
+
+ iOS: Convenience over{' '}
+ getActiveSubscriptions — returns true if the
+ iterator yields at least one non-expired subscription.{' '}
+
+ Apple docs
+
+ . Android: Convenience over{' '}
+ queryPurchasesAsync(SUBS) — returns true if
+ any subscription is in PURCHASED state.{' '}
+
+ Google docs
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/init-connection.tsx b/packages/docs/src/pages/docs/apis/init-connection.tsx
index 7c17a415..949c7c16 100644
--- a/packages/docs/src/pages/docs/apis/init-connection.tsx
+++ b/packages/docs/src/pages/docs/apis/init-connection.tsx
@@ -20,6 +20,28 @@ function InitConnection() {
Initialize connection to the store service. Must be called before any
other IAP operations.
+
+ iOS: Calls AppStore.sync() lazily and
+ verifies StoreKit 2 is available; safe to call repeatedly.{' '}
+
+ Apple docs
+
+ . Android: Starts BillingClient and waits
+ for onBillingSetupFinished. Required before any other Play
+ Billing call.{' '}
+
+ Google docs
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/begin-refund-request-ios.tsx b/packages/docs/src/pages/docs/apis/ios/begin-refund-request-ios.tsx
index fa812d6f..691a535e 100644
--- a/packages/docs/src/pages/docs/apis/ios/begin-refund-request-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/begin-refund-request-ios.tsx
@@ -23,6 +23,18 @@ function BeginRefundRequestIOS() {
Initiate a refund request for a product (iOS 15+). Presents the StoreKit
refund sheet.
+
+ Wraps Transaction.beginRefundRequest(in:) — presents the
+ refund-request sheet. iOS 15+. See the{' '}
+
+ Apple StoreKit reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/can-present-external-purchase-notice-ios.tsx b/packages/docs/src/pages/docs/apis/ios/can-present-external-purchase-notice-ios.tsx
index 4f62def5..0f5ff22c 100644
--- a/packages/docs/src/pages/docs/apis/ios/can-present-external-purchase-notice-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/can-present-external-purchase-notice-ios.tsx
@@ -21,6 +21,18 @@ function CanPresentExternalPurchaseNoticeIOS() {
Check if external purchase notice sheet can be presented (iOS 17.4+).
+
+ Wraps ExternalPurchase.canPresent — gate before calling{' '}
+ presentExternalPurchaseNoticeSheetIOS. iOS 17.4+. See the{' '}
+
+ Apple StoreKit reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/clear-transaction-ios.tsx b/packages/docs/src/pages/docs/apis/ios/clear-transaction-ios.tsx
index 632179e3..2d705269 100644
--- a/packages/docs/src/pages/docs/apis/ios/clear-transaction-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/clear-transaction-ios.tsx
@@ -19,6 +19,19 @@ function ClearTransactionIOS() {
clearTransactionIOS
Clear pending transactions from the StoreKit payment queue.
+
+ Iterates Transaction.unfinished and calls{' '}
+ .finish() on each — sandbox/dev helper, do NOT ship in
+ production paths. See the{' '}
+
+ Apple StoreKit reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/current-entitlement-ios.tsx b/packages/docs/src/pages/docs/apis/ios/current-entitlement-ios.tsx
index 7d0834a7..b9d01fc3 100644
--- a/packages/docs/src/pages/docs/apis/ios/current-entitlement-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/current-entitlement-ios.tsx
@@ -19,6 +19,18 @@ function CurrentEntitlementIOS() {
currentEntitlementIOS
Get current StoreKit 2 entitlement for a product (iOS 15+).
+
+ Wraps Transaction.currentEntitlement(for:) — single-product
+ convenience over currentEntitlements. See the{' '}
+
+ Apple StoreKit reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/get-all-transactions-ios.tsx b/packages/docs/src/pages/docs/apis/ios/get-all-transactions-ios.tsx
index b236cd20..a779c289 100644
--- a/packages/docs/src/pages/docs/apis/ios/get-all-transactions-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/get-all-transactions-ios.tsx
@@ -23,6 +23,19 @@ function GetAllTransactionsIOS() {
Requires the SK2ConsumableTransactionHistory Info.plist key for finished
consumables to be included (iOS 18+).
+
+ Iterates Transaction.all. iOS 18+ requires{' '}
+ SK2ConsumableTransactionHistory Info.plist key for finished
+ consumables to appear. See the{' '}
+
+ Apple StoreKit reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/get-app-transaction-ios.tsx b/packages/docs/src/pages/docs/apis/ios/get-app-transaction-ios.tsx
index 91d8c97b..25b9041d 100644
--- a/packages/docs/src/pages/docs/apis/ios/get-app-transaction-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/get-app-transaction-ios.tsx
@@ -20,6 +20,18 @@ function GetAppTransactionIOS() {
getAppTransactionIOS
Fetch the current app transaction (iOS 16+).
+
+ Wraps AppTransaction.shared — the JWS-verified record of
+ how the app was acquired. iOS 16+. See the{' '}
+
+ Apple StoreKit reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/get-external-purchase-custom-link-token-ios.tsx b/packages/docs/src/pages/docs/apis/ios/get-external-purchase-custom-link-token-ios.tsx
index 51124119..97bf2a32 100644
--- a/packages/docs/src/pages/docs/apis/ios/get-external-purchase-custom-link-token-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/get-external-purchase-custom-link-token-ios.tsx
@@ -30,6 +30,19 @@ function GetExternalPurchaseCustomLinkTokenIOS() {
API (iOS 18.1+). Pair the returned token with Apple's External Purchase
Server API to report acquisition or services transactions.
+
+ Wraps ExternalPurchaseCustomLink.token(for:) — token to
+ report transactions to Apple's External Purchase Server. iOS 18.1+. See
+ the{' '}
+
+ Apple StoreKit reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/get-pending-transactions-ios.tsx b/packages/docs/src/pages/docs/apis/ios/get-pending-transactions-ios.tsx
index 25cc0898..ac6d9e1b 100644
--- a/packages/docs/src/pages/docs/apis/ios/get-pending-transactions-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/get-pending-transactions-ios.tsx
@@ -19,6 +19,18 @@ function GetPendingTransactionsIOS() {
getPendingTransactionsIOS
Retrieve all pending transactions in the StoreKit queue.
+
+ Iterates Transaction.unfinished to surface transactions
+ still awaiting finish(). See the{' '}
+
+ Apple StoreKit reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/get-promoted-product-ios.tsx b/packages/docs/src/pages/docs/apis/ios/get-promoted-product-ios.tsx
index 38a8070a..5843af06 100644
--- a/packages/docs/src/pages/docs/apis/ios/get-promoted-product-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/get-promoted-product-ios.tsx
@@ -19,6 +19,19 @@ function GetPromotedProductIOS() {
getPromotedProductIOS
Get the currently promoted product from App Store (iOS 11+).
+
+ Reads the product surfaced via App Store promoted IAP campaigns (
+ SKPaymentTransactionObserver.shouldAddStorePayment). iOS
+ 11+. See the{' '}
+
+ Apple StoreKit reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/get-receipt-data-ios.tsx b/packages/docs/src/pages/docs/apis/ios/get-receipt-data-ios.tsx
index 05b39119..cacb57ad 100644
--- a/packages/docs/src/pages/docs/apis/ios/get-receipt-data-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/get-receipt-data-ios.tsx
@@ -20,6 +20,19 @@ function GetReceiptDataIOS() {
getReceiptDataIOS
Get base64-encoded receipt data for legacy validation.
+
+ Reads Bundle.main.appStoreReceiptURL and base64-encodes the
+ file. Legacy StoreKit 1 flow — prefer JWS / verifyPurchase.
+ See the{' '}
+
+ Apple StoreKit reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/get-storefront-ios.tsx b/packages/docs/src/pages/docs/apis/ios/get-storefront-ios.tsx
index 1bd3f26e..6768002e 100644
--- a/packages/docs/src/pages/docs/apis/ios/get-storefront-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/get-storefront-ios.tsx
@@ -20,6 +20,18 @@ function GetStorefrontIOS() {
getStorefrontIOS
Deprecated. Use getStorefront() (cross-platform) instead.
+
+ Wraps Storefront.current — deprecated in OpenIAP. Returns
+ the App Store storefront country code. iOS 13+. See the{' '}
+
+ Apple StoreKit reference
+
+ .
+
diff --git a/packages/docs/src/pages/docs/apis/ios/get-transaction-jws-ios.tsx b/packages/docs/src/pages/docs/apis/ios/get-transaction-jws-ios.tsx
index 520f243a..24ebe16a 100644
--- a/packages/docs/src/pages/docs/apis/ios/get-transaction-jws-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/get-transaction-jws-ios.tsx
@@ -20,6 +20,18 @@ function GetTransactionJwsIOS() {
getTransactionJwsIOS
Get the transaction JWS for server-side validation (iOS 15+).
+
+ Returns Transaction.jsonRepresentation (signed JWS) — pass
+ to your backend for cryptographic validation. See the{' '}
+
+ Apple StoreKit reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios.tsx b/packages/docs/src/pages/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios.tsx
index 3f6d6594..e72a55ab 100644
--- a/packages/docs/src/pages/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios.tsx
@@ -31,6 +31,18 @@ function IsEligibleForExternalPurchaseCustomLinkIOS() {
for the corresponding entitlement and music-streaming-app-style flows
are allowed.
+
+ Wraps ExternalPurchase.presentNoticeSheet() — returns a
+ token if the user accepts. iOS 17.4+. See the{' '}
+
+ Apple StoreKit reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/request-purchase-on-promoted-product-ios.tsx b/packages/docs/src/pages/docs/apis/ios/request-purchase-on-promoted-product-ios.tsx
index 2886ea4f..7c165ec3 100644
--- a/packages/docs/src/pages/docs/apis/ios/request-purchase-on-promoted-product-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/request-purchase-on-promoted-product-ios.tsx
@@ -22,6 +22,19 @@ function RequestPurchaseOnPromotedProductIOS() {
Deprecated. Use promotedProductListenerIOS plus requestPurchase instead.
+
+ Triggers the promoted product's purchase. Deprecated —
+ prefer promotedProductListenerIOS +{' '}
+ requestPurchase for StoreKit 2. See the{' '}
+
+ Apple StoreKit reference
+
+ .
+
diff --git a/packages/docs/src/pages/docs/apis/ios/show-external-purchase-custom-link-notice-ios.tsx b/packages/docs/src/pages/docs/apis/ios/show-external-purchase-custom-link-notice-ios.tsx
index 86858c78..6f927500 100644
--- a/packages/docs/src/pages/docs/apis/ios/show-external-purchase-custom-link-notice-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/show-external-purchase-custom-link-notice-ios.tsx
@@ -31,6 +31,18 @@ function ShowExternalPurchaseCustomLinkNoticeIOS() {
deliberate customer interaction, before you can route the user to an
external purchase URL.
+
+ Wraps ExternalPurchaseCustomLink.showNotice(type:) —
+ required disclosure sheet before linking out. iOS 18.1+. See the{' '}
+
+ Apple StoreKit reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/show-manage-subscriptions-ios.tsx b/packages/docs/src/pages/docs/apis/ios/show-manage-subscriptions-ios.tsx
index eda7db09..1d4b2c4f 100644
--- a/packages/docs/src/pages/docs/apis/ios/show-manage-subscriptions-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/show-manage-subscriptions-ios.tsx
@@ -23,6 +23,18 @@ function ShowManageSubscriptionsIOS() {
15+). Returns purchases for subscriptions whose auto-renewal status
changed.
+
+ Wraps AppStore.showManageSubscriptions(in:) — presents the
+ system manage-subscriptions sheet. iOS 15+. See the{' '}
+
+ Apple StoreKit reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/subscription-status-ios.tsx b/packages/docs/src/pages/docs/apis/ios/subscription-status-ios.tsx
index 5d6fb7f8..f9da5a3e 100644
--- a/packages/docs/src/pages/docs/apis/ios/subscription-status-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/subscription-status-ios.tsx
@@ -19,6 +19,19 @@ function SubscriptionStatusIOS() {
subscriptionStatusIOS
Get detailed subscription status using StoreKit 2 (iOS 15+).
+
+ Wraps Product.SubscriptionInfo.status — returns the array
+ of Status objects with transaction,{' '}
+ renewalInfo, state. iOS 15+. See the{' '}
+
+ Apple StoreKit reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/sync-ios.tsx b/packages/docs/src/pages/docs/apis/ios/sync-ios.tsx
index ff9a0770..e9ee3cac 100644
--- a/packages/docs/src/pages/docs/apis/ios/sync-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/sync-ios.tsx
@@ -18,6 +18,19 @@ function SyncIOS() {
iOS syncIOS
Force a StoreKit sync for transactions (iOS 15+).
+
+ Wraps AppStore.sync() — forces StoreKit to refresh
+ transactions and entitlements, prompts the user to authenticate. iOS
+ 15+. See the{' '}
+
+ Apple StoreKit reference
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/validate-receipt-ios.tsx b/packages/docs/src/pages/docs/apis/ios/validate-receipt-ios.tsx
index 9072429f..196b9c03 100644
--- a/packages/docs/src/pages/docs/apis/ios/validate-receipt-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/validate-receipt-ios.tsx
@@ -20,6 +20,19 @@ function ValidateReceiptIOS() {
validateReceiptIOS
Deprecated. Use verifyPurchase instead.
+
+ Deprecated. Legacy appStoreReceiptURL{' '}
+ validation. Use verifyPurchase with the JWS instead. See
+ the{' '}
+
+ Apple StoreKit reference
+
+ .
+
diff --git a/packages/docs/src/pages/docs/apis/request-purchase.tsx b/packages/docs/src/pages/docs/apis/request-purchase.tsx
index ade42a18..f30ed7bd 100644
--- a/packages/docs/src/pages/docs/apis/request-purchase.tsx
+++ b/packages/docs/src/pages/docs/apis/request-purchase.tsx
@@ -20,6 +20,30 @@ function RequestPurchase() {
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
+
+ .
+
diff --git a/packages/docs/src/pages/docs/apis/restore-purchases.tsx b/packages/docs/src/pages/docs/apis/restore-purchases.tsx
index 92c7d944..988f1f23 100644
--- a/packages/docs/src/pages/docs/apis/restore-purchases.tsx
+++ b/packages/docs/src/pages/docs/apis/restore-purchases.tsx
@@ -19,6 +19,29 @@ function RestorePurchases() {
Restore completed transactions. Use this to implement a "Restore
Purchases" button for users who reinstall the app.
+
+ iOS: Triggers AppStore.sync() and
+ re-emits entitlements on Transaction.currentEntitlements.
+ Asks the user to authenticate.{' '}
+
+ Apple docs
+
+ . Android: Calls queryPurchasesAsync for
+ both INAPP and SUBS. No system-level UI
+ prompt — Play has no concept of an explicit "restore" action.{' '}
+
+ Google docs
+
+ .
+
Signature
diff --git a/packages/docs/src/pages/docs/types/active-subscription.tsx b/packages/docs/src/pages/docs/types/active-subscription.tsx
index 32706103..2acfb880 100644
--- a/packages/docs/src/pages/docs/types/active-subscription.tsx
+++ b/packages/docs/src/pages/docs/types/active-subscription.tsx
@@ -29,6 +29,29 @@ function ActiveSubscription() {
. Provides a unified view of subscription status across platforms.
+
+ Cross-platform shape returned by getActiveSubscriptions.{' '}
+ iOS: derived from{' '}
+ Transaction.currentEntitlements filtered to subscription
+ products (
+
+ Apple docs
+
+ ). Android: derived from{' '}
+ BillingClient.queryPurchasesAsync(SUBS) (
+
+ Google docs
+
+ ).
+
diff --git a/packages/docs/src/pages/docs/types/verify-purchase-with-provider-result.tsx b/packages/docs/src/pages/docs/types/verify-purchase-with-provider-result.tsx
index d1d94d03..79e1dfcf 100644
--- a/packages/docs/src/pages/docs/types/verify-purchase-with-provider-result.tsx
+++ b/packages/docs/src/pages/docs/types/verify-purchase-with-provider-result.tsx
@@ -24,6 +24,18 @@ function VerifyPurchaseWithProviderResult() {
Result type returned by verifyPurchaseWithProvider().
+
+ Result envelope from verifyPurchaseWithProvider. Carries{' '}
+ isValid plus the underlying provider response. See{' '}
+
+ Validation docs
+
+ .
+
diff --git a/packages/docs/src/pages/docs/types/verify-purchase.tsx b/packages/docs/src/pages/docs/types/verify-purchase.tsx
index 36d4b3a1..b9a77d69 100644
--- a/packages/docs/src/pages/docs/types/verify-purchase.tsx
+++ b/packages/docs/src/pages/docs/types/verify-purchase.tsx
@@ -23,6 +23,28 @@ function VerifyPurchase() {
Types used with verifyPurchase() for server-side purchase
verification.
+
+ Input/output shape for verifyPurchase.{' '}
+ iOS: validates the JWS from{' '}
+ Transaction.jsonRepresentation (
+
+ Apple docs
+
+ ). Android: validates the purchaseToken{' '}
+ against Google Play Developer API (
+
+ Google docs
+
+ ).
+
Native references:{' '}
--max-width
+ (calc is negative). Below --max-width the calc flips positive and would
+ visually shove the sidebar to the right of the viewport (the
+ tablet-range bug); clamp to 0 so it stays put. */
+ margin-left: min(0px, calc((var(--max-width) - 100vw) / 2));
box-sizing: content-box;
}
@@ -859,13 +863,15 @@
scrollbar-color: var(--border-color) transparent;
}
-/* Docs Sidebar Toggle - Mobile Only */
+/* Docs Sidebar Toggle - Mobile Only.
+ z-index pushed well above the top nav (which is z-index: 100) so it
+ stays clickable even if the nav's mobile dropdown is mid-transition. */
.docs-sidebar-toggle {
display: none;
position: fixed;
top: 100px;
left: 1.5rem;
- z-index: 1001;
+ z-index: 9001;
background: var(--primary-color);
color: white;
border: none;
@@ -906,16 +912,18 @@
pointer-events: none;
}
-/* Sidebar Overlay (mobile only) */
+/* Sidebar Overlay (mobile only). Starts below the top nav (56px) so the
+ nav stays visible/interactive — but the backdrop swallows every other
+ tap on the page so menu items behind don't fire by accident. */
.sidebar-overlay {
display: none;
position: fixed;
- top: 0;
+ top: 56px;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
- z-index: 999;
+ z-index: 8999;
}
/* Mobile Responsive Styles */
@@ -938,7 +946,10 @@
.docs-sidebar {
position: fixed !important;
- top: 0 !important;
+ /* Start the drawer BELOW the sticky top nav (which is 56px tall) so
+ the two never overlap geometrically — taps at the very top of the
+ drawer can't bleed into the nav's hamburger menu and vice versa. */
+ top: 56px !important;
left: 0;
bottom: 0;
/* Reset desktop centering offset — at viewports below --max-width,
@@ -948,10 +959,10 @@
--sidebar-edge-fill: 0px;
width: 280px;
max-width: 85vw;
- height: 100vh !important;
- max-height: 100vh !important;
+ height: calc(100vh - 56px) !important;
+ max-height: calc(100vh - 56px) !important;
background: var(--bg-secondary);
- z-index: 1000;
+ z-index: 9000;
transition:
opacity 0.2s ease,
visibility 0.2s ease;
diff --git a/packages/docs/src/styles/responsive.css b/packages/docs/src/styles/responsive.css
index bdfd8981..f1fc3d5e 100644
--- a/packages/docs/src/styles/responsive.css
+++ b/packages/docs/src/styles/responsive.css
@@ -48,14 +48,10 @@
flex-direction: column;
}
- .docs-sidebar {
- width: 100%;
- margin-bottom: 2rem;
- }
-
- .docs-nav {
- position: static;
- }
+ /* Sidebar drawer styling lives in documentation.css's mobile block —
+ don't redefine width/position here (the older inline-sidebar layout
+ leaked `width: 100%` and `position: static` rules that would override
+ the drawer and let taps fall through to the top nav). */
.features-container,
.benefit-grid,
diff --git a/packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt b/packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt
index bc6306db..f564ef92 100644
--- a/packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt
+++ b/packages/google/openiap/src/main/java/dev/hyo/openiap/Types.kt
@@ -4744,146 +4744,166 @@ public sealed interface VerifyPurchaseResult {
*/
public interface MutationResolver {
/**
- * Acknowledge a non-consumable purchase or subscription
+ * Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
+ * See: https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android
*/
suspend fun acknowledgePurchaseAndroid(purchaseToken: String): Boolean
/**
- * Initiate a refund request for a product (iOS 15+)
+ * Present the refund request sheet (iOS 15+). See also Features → Refund.
+ * See: https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios
*/
suspend fun beginRefundRequestIOS(sku: String): String?
/**
- * Check if alternative billing is available for this user/device
- * Step 1 of alternative billing flow
+ * Check whether alternative billing is available for the user. Step 1 of the alternative billing flow.
*
- * Returns true if available, false otherwise
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns true if available, false otherwise.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android
*/
suspend fun checkAlternativeBillingAvailabilityAndroid(): Boolean
/**
- * Clear pending transactions from the StoreKit payment queue
+ * Clear pending transactions in the queue (sandbox helper).
+ * See: https://www.openiap.dev/docs/apis/ios/clear-transaction-ios
*/
suspend fun clearTransactionIOS(): Boolean
/**
- * Consume a purchase token so it can be repurchased
+ * Consume a consumable purchase so it can be re-bought.
+ * See: https://www.openiap.dev/docs/apis/android/consume-purchase-android
*/
suspend fun consumePurchaseAndroid(purchaseToken: String): Boolean
/**
- * Create external transaction token for Google Play reporting
- * Step 3 of alternative billing flow
- * Must be called AFTER successful payment in your payment system
- * Token must be reported to Google Play backend within 24 hours
+ * Create a reporting token for an alternative billing flow. Step 3 of the alternative billing flow.
+ * Must be called AFTER successful payment in your payment system.
+ * Token must be reported to Google Play backend within 24 hours.
*
- * Returns token string, or null if creation failed
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns token string, or null if creation failed.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android
*/
suspend fun createAlternativeBillingTokenAndroid(): String?
/**
- * Create reporting details for a billing program
- * Replaces the deprecated createExternalOfferReportingDetailsAsync API
+ * Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+).
+ * Replaces the deprecated createExternalOfferReportingDetailsAsync API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Returns external transaction token needed for reporting external transactions
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns external transaction token needed for reporting external transactions.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android
*/
suspend fun createBillingProgramReportingDetailsAndroid(program: BillingProgramAndroid): BillingProgramReportingDetailsAndroid
/**
- * Open the native subscription management surface
+ * Open the platform's subscription management UI.
+ * See: https://www.openiap.dev/docs/apis/deep-link-to-subscriptions
*/
suspend fun deepLinkToSubscriptions(options: DeepLinkOptions? = null): Unit
/**
- * Close the platform billing connection
+ * Close the store connection and release resources.
+ * See: https://www.openiap.dev/docs/apis/end-connection
*/
suspend fun endConnection(): Boolean
/**
- * Finish a transaction after validating receipts
+ * Complete a transaction after server-side verification. Required on Android within 3 days.
+ * See: https://www.openiap.dev/docs/apis/finish-transaction
*/
suspend fun finishTransaction(purchase: PurchaseInput, isConsumable: Boolean? = null): Unit
/**
- * Establish the platform billing connection
+ * Initialize the store connection. Call before any IAP API.
+ * See: https://www.openiap.dev/docs/apis/init-connection
*/
suspend fun initConnection(config: InitConnectionConfig? = null): Boolean
/**
- * Check if a billing program is available for the current user
- * Replaces the deprecated isExternalOfferAvailableAsync API
+ * Check whether a billing program (e.g., External Payments) is available for the current user.
+ * Replaces the deprecated isExternalOfferAvailableAsync API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Returns availability result with isAvailable flag
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Available in Google Play Billing Library 8.2.0+.
+ * Returns availability result with isAvailable flag.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/is-billing-program-available-android
*/
suspend fun isBillingProgramAvailableAndroid(program: BillingProgramAndroid): BillingProgramAvailabilityResultAndroid
/**
- * Launch external link flow for external billing programs
- * Replaces the deprecated showExternalOfferInformationDialog API
+ * Launch an external content/offer link from inside the Billing Programs flow (Play Billing 8.2.0+).
+ * Replaces the deprecated showExternalOfferInformationDialog API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Shows Play Store dialog and optionally launches external URL
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Shows Play Store dialog and optionally launches external URL.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/launch-external-link-android
*/
suspend fun launchExternalLinkAndroid(params: LaunchExternalLinkParamsAndroid): Boolean
/**
- * Present the App Store code redemption sheet
+ * Show the App Store offer code redemption sheet.
+ * See: https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios
*/
suspend fun presentCodeRedemptionSheetIOS(): Boolean
/**
- * Present external purchase custom link with StoreKit UI
+ * Present an external purchase link, StoreKit External (iOS 16+).
+ * See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios
*/
suspend fun presentExternalPurchaseLinkIOS(url: String): ExternalPurchaseLinkResultIOS
/**
- * Present external purchase notice sheet (iOS 17.4+).
- * Uses ExternalPurchase.presentNoticeSheet() which returns a token when user continues.
+ * Present the external purchase notice sheet (iOS 17.4+).
+ * Uses ExternalPurchase.presentNoticeSheet() which returns a token when the user continues.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchase/presentnoticesheet()
+ * See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios
*/
suspend fun presentExternalPurchaseNoticeSheetIOS(): ExternalPurchaseNoticeResultIOS
/**
- * Initiate a purchase flow; rely on events for final state
+ * Initiate a purchase or subscription flow; rely on events for final state.
+ * See: https://www.openiap.dev/docs/apis/request-purchase
*/
suspend fun requestPurchase(params: RequestPurchaseProps): RequestPurchaseResult?
/**
- * Purchase the promoted product surfaced by the App Store.
+ * Buy the currently promoted product.
*
* @deprecated Use promotedProductListenerIOS to receive the productId,
* then call requestPurchase with that SKU instead. In StoreKit 2,
* promoted products can be purchased directly via the standard purchase flow.
+ * See: https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios
*/
suspend fun requestPurchaseOnPromotedProductIOS(): Boolean
/**
- * Restore completed purchases across platforms
+ * Restore non-consumable and active subscription purchases.
+ * See: https://www.openiap.dev/docs/apis/restore-purchases
*/
suspend fun restorePurchases(): Unit
/**
- * Show alternative billing information dialog to user
- * Step 2 of alternative billing flow
- * Must be called BEFORE processing payment in your payment system
+ * Display Google's alternative billing information dialog. Step 2 of the alternative billing flow.
+ * Must be called BEFORE processing payment in your payment system.
*
- * Returns true if user accepted, false if user canceled
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns true if user accepted, false if user canceled.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android
*/
suspend fun showAlternativeBillingDialogAndroid(): Boolean
/**
- * Show ExternalPurchaseCustomLink notice sheet (iOS 18.1+).
- * Displays the system disclosure notice sheet for custom external purchase links.
+ * Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
* Call this after a deliberate customer interaction before linking out to external purchases.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/shownotice(type:)
+ * See: https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios
*/
suspend fun showExternalPurchaseCustomLinkNoticeIOS(noticeType: ExternalPurchaseCustomLinkNoticeTypeIOS): ExternalPurchaseCustomLinkNoticeResultIOS
/**
- * Open subscription management UI and return changed purchases (iOS 15+)
+ * Present the manage-subscriptions sheet and return changed purchases (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios
*/
suspend fun showManageSubscriptionsIOS(): List
/**
- * Force a StoreKit sync for transactions (iOS 15+)
+ * Force sync transactions with the App Store (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/sync-ios
*/
suspend fun syncIOS(): Boolean
/**
- * Validate purchase receipts with the configured providers
+ * Deprecated. Validate purchase receipts with the configured providers — use verifyPurchase instead.
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase
*/
suspend fun validateReceipt(options: VerifyPurchaseProps): VerifyPurchaseResult
/**
- * Verify purchases with the configured providers
+ * Verify a purchase against your own backend (returns isValid + raw store metadata).
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase
*/
suspend fun verifyPurchase(options: VerifyPurchaseProps): VerifyPurchaseResult
/**
- * Verify purchases with a specific provider (e.g., IAPKit)
+ * Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
*/
suspend fun verifyPurchaseWithProvider(options: VerifyPurchaseWithProviderProps): VerifyPurchaseWithProviderResult
}
@@ -4893,95 +4913,116 @@ public interface MutationResolver {
*/
public interface QueryResolver {
/**
- * Check if external purchase notice sheet can be presented (iOS 17.4+)
- * Uses ExternalPurchase.canPresent
+ * Check eligibility for the external purchase notice sheet (iOS 17.4+).
+ * Uses ExternalPurchase.canPresent.
+ * See: https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios
*/
suspend fun canPresentExternalPurchaseNoticeIOS(): Boolean
/**
- * Get current StoreKit 2 entitlements (iOS 15+)
+ * Get the user's current entitlement for a product, using StoreKit 2 (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/current-entitlement-ios
*/
suspend fun currentEntitlementIOS(sku: String): PurchaseIOS?
/**
- * Retrieve products or subscriptions from the store
+ * Fetch products or subscriptions from the store.
+ * See: https://www.openiap.dev/docs/apis/fetch-products
*/
suspend fun fetchProducts(params: ProductRequest): FetchProductsResult
/**
- * Get active subscriptions (filters by subscriptionIds when provided)
+ * Get details of all currently active subscriptions (filters by subscriptionIds when provided).
+ * See: https://www.openiap.dev/docs/apis/get-active-subscriptions
*/
suspend fun getActiveSubscriptions(subscriptionIds: List? = null): List
/**
- * Get the full StoreKit 2 transaction history as PurchaseIOS values.
+ * List every StoreKit transaction (finished + unfinished) for the current user.
* Requires the SK2ConsumableTransactionHistory Info.plist key in the host app
* for finished consumables to be included (iOS 18+).
* Unlike getAvailablePurchases, always returns the iOS-specific PurchaseIOS shape.
+ * See: https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios
*/
suspend fun getAllTransactionsIOS(): List
/**
- * Fetch the current app transaction (iOS 16+)
+ * Fetch the app transaction (iOS 16+).
+ * See: https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios
*/
suspend fun getAppTransactionIOS(): AppTransaction?
/**
- * Get all available purchases for the current user
+ * List active purchases for the current user.
+ * See: https://www.openiap.dev/docs/apis/get-available-purchases
*/
suspend fun getAvailablePurchases(options: PurchaseOptions? = null): List
/**
- * Get external purchase token for reporting to Apple (iOS 18.1+).
- * Use this token with Apple's External Purchase Server API to report transactions.
+ * Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
+ * Use this token to report transactions made through ExternalPurchaseCustomLink.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/token(for:)
+ * See: https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios
*/
suspend fun getExternalPurchaseCustomLinkTokenIOS(tokenType: ExternalPurchaseCustomLinkTokenTypeIOS): ExternalPurchaseCustomLinkTokenResultIOS
/**
- * Retrieve all pending transactions in the StoreKit queue
+ * List unfinished StoreKit transactions in the queue.
+ * See: https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios
*/
suspend fun getPendingTransactionsIOS(): List
/**
- * Get the currently promoted product (iOS 11+)
+ * Read the App Store-promoted product, if any (iOS 11+).
+ * See: https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios
*/
suspend fun getPromotedProductIOS(): ProductIOS?
/**
- * Get base64-encoded receipt data for validation
+ * Get base64-encoded receipt data (legacy validation).
+ * See: https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios
*/
suspend fun getReceiptDataIOS(): String?
/**
- * Get the current storefront country code
+ * Return the user's storefront country code.
+ * See: https://www.openiap.dev/docs/apis/get-storefront
*/
suspend fun getStorefront(): String
/**
- * Get the current App Store storefront country code
+ * Deprecated. Get the current App Store storefront country code — use cross-platform getStorefront instead.
+ * See: https://www.openiap.dev/docs/apis/ios/get-storefront-ios
*/
suspend fun getStorefrontIOS(): String
/**
- * Get the transaction JWS (StoreKit 2)
+ * Return the JWS string for a transaction (StoreKit 2).
+ * See: https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios
*/
suspend fun getTransactionJwsIOS(sku: String): String?
/**
- * Check whether the user has active subscriptions
+ * Check whether the user has any active subscription.
+ * See: https://www.openiap.dev/docs/apis/has-active-subscriptions
*/
suspend fun hasActiveSubscriptions(subscriptionIds: List? = null): Boolean
/**
- * Check if app is eligible for ExternalPurchaseCustomLink API (iOS 18.1+).
+ * Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
* Returns true if the app can use custom external purchase links.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/iseligible
+ * See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios
*/
suspend fun isEligibleForExternalPurchaseCustomLinkIOS(): Boolean
/**
- * Check introductory offer eligibility for a subscription group
+ * Check intro-offer eligibility for a subscription group.
+ * See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios
*/
suspend fun isEligibleForIntroOfferIOS(groupID: String): Boolean
/**
- * Verify a StoreKit 2 transaction signature
+ * Check whether a transaction's JWS verification passed (StoreKit 2).
+ * See: https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios
*/
suspend fun isTransactionVerifiedIOS(sku: String): Boolean
/**
- * Get the latest transaction for a product using StoreKit 2
+ * Get the latest verified transaction for a product, using StoreKit 2.
+ * See: https://www.openiap.dev/docs/apis/ios/latest-transaction-ios
*/
suspend fun latestTransactionIOS(sku: String): PurchaseIOS?
/**
- * Get StoreKit 2 subscription status details (iOS 15+)
+ * Get subscription status objects from StoreKit 2 (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/subscription-status-ios
*/
suspend fun subscriptionStatusIOS(sku: String): List
/**
- * Validate a receipt for a specific product
+ * Deprecated. Legacy App Store receipt validation — use verifyPurchase instead.
+ * See: https://www.openiap.dev/docs/apis/ios/validate-receipt-ios
*/
suspend fun validateReceiptIOS(options: VerifyPurchaseProps): VerifyPurchaseResultIOS
}
diff --git a/packages/google/openiap/src/main/java/dev/hyo/openiap/store/OpenIapStore.kt b/packages/google/openiap/src/main/java/dev/hyo/openiap/store/OpenIapStore.kt
index 4484cf9f..93cf9c10 100644
--- a/packages/google/openiap/src/main/java/dev/hyo/openiap/store/OpenIapStore.kt
+++ b/packages/google/openiap/src/main/java/dev/hyo/openiap/store/OpenIapStore.kt
@@ -219,6 +219,17 @@ class OpenIapStore(private val module: OpenIapProtocol) {
// Connection Management - Using GraphQL handler pattern
// -------------------------------------------------------------------------
+ /**
+ * Initialize the store connection. Must be called before any other IAP API.
+ *
+ * @param config Optional [InitConnectionConfig]. Use `enableBillingProgramAndroid` to
+ * opt in to External Payments / similar Play Billing programs. Pass `null` for default.
+ * @return `true` once the Play Billing client is connected.
+ * @throws OpenIapError.InitConnection when the billing client fails to initialize
+ * (e.g. Play Store missing, version too old).
+ *
+ * @see init-connection
+ */
val initConnection: MutationInitConnectionHandler = { config ->
setLoading { it.initConnection = true }
try {
@@ -237,13 +248,26 @@ class OpenIapStore(private val module: OpenIapProtocol) {
}
/**
- * Convenience overload that calls initConnection with null config
+ * Initialize the store connection. Must be called before any other IAP API.
+ *
+ * Convenience overload — calls the config-accepting variant with `null`.
+ *
+ * @return `true` once the Play Billing client is connected.
+ * @throws OpenIapError.InitConnection when the billing client fails to initialize
+ * (e.g. Play Store missing, version too old).
+ *
+ * @see init-connection
*/
suspend fun initConnection(): Boolean {
OpenIapLog.i("OpenIapStore.initConnection(): Calling initConnection(null)...", "OpenIapStore")
return initConnection(null)
}
+ /**
+ * Close the store connection and release resources.
+ *
+ * @see https://www.openiap.dev/docs/apis/end-connection
+ */
val endConnection: MutationEndConnectionHandler = {
removePurchaseUpdateListener(purchaseUpdateListener)
removePurchaseErrorListener(purchaseErrorListener)
@@ -262,6 +286,18 @@ class OpenIapStore(private val module: OpenIapProtocol) {
// -------------------------------------------------------------------------
// Product Management - Using GraphQL handler pattern
// -------------------------------------------------------------------------
+ /**
+ * Retrieve products or subscriptions from Google Play by SKU.
+ *
+ * @param params [ProductRequest] with `skus` and an optional `type`
+ * ([ProductQueryType.InApp], [ProductQueryType.Subs], or [ProductQueryType.All];
+ * defaults to InApp).
+ * @return A [FetchProductsResult] sealed variant — `Products` for InApp,
+ * `Subscriptions` for Subs, mixed list for All.
+ * @throws OpenIapError on store rejection (unknown SKU, network failure, not connected).
+ *
+ * @see fetch-products
+ */
val fetchProducts: QueryFetchProductsHandler = { request ->
android.util.Log.i("OpenIapStore", "fetchProducts called with SKUs: ${request.skus}, type: ${request.type}")
setLoading { it.fetchProducts = true }
@@ -341,6 +377,17 @@ class OpenIapStore(private val module: OpenIapProtocol) {
// -------------------------------------------------------------------------
// Purchases / Restore - Using GraphQL handler pattern
// -------------------------------------------------------------------------
+ /**
+ * List the user's unfinished purchases. Use this to restore non-consumables /
+ * active subscriptions, or to pick up purchases that weren't finished previously.
+ *
+ * @param options Optional [PurchaseOptions]. Most fields are iOS-only and ignored
+ * on Android.
+ * @return List of [Purchase] currently held by Play Billing.
+ * @throws OpenIapError when the Play Billing query fails.
+ *
+ * @see get-available-purchases
+ */
val getAvailablePurchases: QueryGetAvailablePurchasesHandler = { options ->
android.util.Log.i("OpenIapStore", "getAvailablePurchases called, module type: ${module.javaClass.simpleName}")
setLoading { it.restorePurchases = true }
@@ -363,6 +410,21 @@ class OpenIapStore(private val module: OpenIapProtocol) {
// -------------------------------------------------------------------------
// Purchase Flow - Using GraphQL handler pattern
// -------------------------------------------------------------------------
+ /**
+ * Initiate a purchase flow. The result is delivered via the purchase update listener,
+ * NOT through the return value.
+ *
+ * @param props [RequestPurchaseProps]. Use `request.google.skus` and pass
+ * `subscriptionOffers = [{sku, offerToken}]` for subscriptions.
+ * @return The dispatched purchase payload (do not rely on this for the actual outcome).
+ * @throws OpenIapError on synchronous rejection (e.g. billing client not ready,
+ * developer error such as missing offerToken on subs).
+ *
+ * Warning: Event-based. Collect from `purchaseUpdatedListener` / `purchaseErrorListener`
+ * (or `OpenIapStore.currentPurchase` / `currentError` flows) for the final state.
+ *
+ * @see request-purchase
+ */
val requestPurchase: MutationRequestPurchaseHandler = { props ->
val skuForStatus = when (val request = props.request) {
is RequestPurchaseProps.Request.Purchase -> request.value.android?.skus?.firstOrNull()
@@ -383,7 +445,18 @@ class OpenIapStore(private val module: OpenIapProtocol) {
}
- // Using GraphQL handler pattern
+ /**
+ * Complete a purchase transaction. Call after server-side verification.
+ *
+ * @param purchase The [PurchaseInput] to finalize.
+ * @param isConsumable Pass `true` for consumables (consumes the token so the SKU can be
+ * bought again), `false` for non-consumables and subscriptions (acknowledges only).
+ * @throws OpenIapError when the Play Billing finalize call fails.
+ *
+ * Important: Google auto-refunds Android purchases NOT acknowledged/consumed within 3 days.
+ *
+ * @see finish-transaction
+ */
val finishTransaction: MutationFinishTransactionHandler = { purchaseInput, isConsumable ->
val token = purchaseInput.purchaseToken
// Check if already processed - but we can't check isAcknowledgedAndroid on PurchaseInput
@@ -402,32 +475,45 @@ class OpenIapStore(private val module: OpenIapProtocol) {
// -------------------------------------------------------------------------
// Subscriptions
// -------------------------------------------------------------------------
+ /**
+ * Get details of all currently active subscriptions.
+ *
+ * @see https://www.openiap.dev/docs/apis/get-active-subscriptions
+ */
suspend fun getActiveSubscriptions(subscriptionIds: List? = null): List =
module.queryHandlers.getActiveSubscriptions?.invoke(subscriptionIds) ?: emptyList()
+ /**
+ * Check whether the user has any active subscription.
+ *
+ * @see https://www.openiap.dev/docs/apis/has-active-subscriptions
+ */
suspend fun hasActiveSubscriptions(subscriptionIds: List? = null): Boolean =
module.queryHandlers.hasActiveSubscriptions?.invoke(subscriptionIds) ?: false
+ /**
+ * Open the platform's subscription management UI.
+ *
+ * @see https://www.openiap.dev/docs/apis/deep-link-to-subscriptions
+ */
suspend fun deepLinkToSubscriptions(options: DeepLinkOptions) = module.mutationHandlers.deepLinkToSubscriptions?.invoke(options)
// -------------------------------------------------------------------------
// Alternative Billing (Step-by-Step API)
// -------------------------------------------------------------------------
/**
- * Step 1: Check if alternative billing is available for this user/device
- * @return true if available, false otherwise
- * @deprecated Use isBillingProgramAvailable with BillingProgramAndroid.ExternalOffer instead
+ * Check whether alternative billing is available for the user.
+ *
+ * @see https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android
*/
@Deprecated("Use isBillingProgramAvailable with BillingProgramAndroid.ExternalOffer instead")
@Suppress("DEPRECATION")
suspend fun checkAlternativeBillingAvailability(): Boolean = module.checkAlternativeBillingAvailability()
/**
- * Step 2: Show alternative billing information dialog to user
- * Must be called BEFORE processing payment
- * @param activity Current activity context
- * @return true if user accepted, false if canceled
- * @deprecated Use launchExternalLink instead
+ * Display Google's alternative billing information dialog.
+ *
+ * @see https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android
*/
@Deprecated("Use launchExternalLink instead")
@Suppress("DEPRECATION")
@@ -435,11 +521,9 @@ class OpenIapStore(private val module: OpenIapProtocol) {
module.showAlternativeBillingInformationDialog(activity)
/**
- * Step 3: Create external transaction token for alternative billing
- * Must be called AFTER successful payment in your payment system
- * Token must be reported to Google Play backend within 24 hours
- * @return External transaction token, or null if failed
- * @deprecated Use createBillingProgramReportingDetails with BillingProgramAndroid.ExternalOffer instead
+ * Create a reporting token for an alternative billing flow.
+ *
+ * @see https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android
*/
@Deprecated("Use createBillingProgramReportingDetails with BillingProgramAndroid.ExternalOffer instead")
@Suppress("DEPRECATION")
@@ -450,32 +534,25 @@ class OpenIapStore(private val module: OpenIapProtocol) {
// Billing Programs (Google Play Billing Library 8.2.0+)
// -------------------------------------------------------------------------
/**
- * Check if a billing program is available for this user/device.
- * This is the new API that replaces checkAlternativeBillingAvailability for external offers.
+ * Check whether a billing program (e.g., External Payments) is available.
*
- * @param program The billing program to check (EXTERNAL_CONTENT_LINK or EXTERNAL_OFFER)
- * @return Result containing availability information
+ * @see https://www.openiap.dev/docs/apis/android/is-billing-program-available-android
*/
suspend fun isBillingProgramAvailable(program: BillingProgramAndroid): BillingProgramAvailabilityResultAndroid =
module.isBillingProgramAvailable(program)
/**
- * Create reporting details for transactions made outside of Google Play Billing.
- * This is the new API that replaces createAlternativeBillingReportingToken for external offers.
+ * Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+).
*
- * @param program The billing program (EXTERNAL_CONTENT_LINK or EXTERNAL_OFFER)
- * @return Reporting details containing the external transaction token
+ * @see https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android
*/
suspend fun createBillingProgramReportingDetails(program: BillingProgramAndroid): BillingProgramReportingDetailsAndroid =
module.createBillingProgramReportingDetails(program)
/**
- * Launch an external link for external offer or app download.
- * This is the new API that replaces showAlternativeBillingInformationDialog for external offers.
+ * Launch an external content/offer link from inside the Billing Programs flow (Play Billing 8.2.0+).
*
- * @param activity Current activity context
- * @param params Parameters for the external link
- * @return true if launch was successful, false otherwise
+ * @see https://www.openiap.dev/docs/apis/android/launch-external-link-android
*/
suspend fun launchExternalLink(activity: Activity, params: LaunchExternalLinkParamsAndroid): Boolean =
module.launchExternalLink(activity, params)
diff --git a/packages/gql/src/api-android.graphql b/packages/gql/src/api-android.graphql
index d6baf87a..2530e2d2 100644
--- a/packages/gql/src/api-android.graphql
+++ b/packages/gql/src/api-android.graphql
@@ -2,78 +2,81 @@
extend type Mutation {
"""
- Acknowledge a non-consumable purchase or subscription
+ Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
+ See: https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android
"""
# Future
acknowledgePurchaseAndroid(purchaseToken: String!): Boolean!
"""
- Consume a purchase token so it can be repurchased
+ Consume a consumable purchase so it can be re-bought.
+ See: https://www.openiap.dev/docs/apis/android/consume-purchase-android
"""
# Future
consumePurchaseAndroid(purchaseToken: String!): Boolean!
# Alternative Billing APIs
"""
- Check if alternative billing is available for this user/device
- Step 1 of alternative billing flow
+ Check whether alternative billing is available for the user. Step 1 of the alternative billing flow.
- Returns true if available, false otherwise
- Throws OpenIapError.NotPrepared if billing client not ready
+ Returns true if available, false otherwise.
+ Throws OpenIapError.NotPrepared if billing client not ready.
+ See: https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android
"""
# Future
checkAlternativeBillingAvailabilityAndroid: Boolean!
"""
- Show alternative billing information dialog to user
- Step 2 of alternative billing flow
- Must be called BEFORE processing payment in your payment system
+ Display Google's alternative billing information dialog. Step 2 of the alternative billing flow.
+ Must be called BEFORE processing payment in your payment system.
- Returns true if user accepted, false if user canceled
- Throws OpenIapError.NotPrepared if billing client not ready
+ Returns true if user accepted, false if user canceled.
+ Throws OpenIapError.NotPrepared if billing client not ready.
+ See: https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android
"""
# Future
showAlternativeBillingDialogAndroid: Boolean!
"""
- Create external transaction token for Google Play reporting
- Step 3 of alternative billing flow
- Must be called AFTER successful payment in your payment system
- Token must be reported to Google Play backend within 24 hours
+ Create a reporting token for an alternative billing flow. Step 3 of the alternative billing flow.
+ Must be called AFTER successful payment in your payment system.
+ Token must be reported to Google Play backend within 24 hours.
- Returns token string, or null if creation failed
- Throws OpenIapError.NotPrepared if billing client not ready
+ Returns token string, or null if creation failed.
+ Throws OpenIapError.NotPrepared if billing client not ready.
+ See: https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android
"""
# Future
createAlternativeBillingTokenAndroid: String
# Billing Programs API (Google Play Billing Library 8.2.0+)
"""
- Check if a billing program is available for the current user
- Replaces the deprecated isExternalOfferAvailableAsync API
+ Check whether a billing program (e.g., External Payments) is available for the current user.
+ Replaces the deprecated isExternalOfferAvailableAsync API.
- Available in Google Play Billing Library 8.2.0+
- Returns availability result with isAvailable flag
- Throws OpenIapError.NotPrepared if billing client not ready
+ Available in Google Play Billing Library 8.2.0+.
+ Returns availability result with isAvailable flag.
+ Throws OpenIapError.NotPrepared if billing client not ready.
+ See: https://www.openiap.dev/docs/apis/android/is-billing-program-available-android
"""
# Future
isBillingProgramAvailableAndroid(program: BillingProgramAndroid!): BillingProgramAvailabilityResultAndroid!
"""
- Create reporting details for a billing program
- Replaces the deprecated createExternalOfferReportingDetailsAsync API
+ Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+).
+ Replaces the deprecated createExternalOfferReportingDetailsAsync API.
- Available in Google Play Billing Library 8.2.0+
- Returns external transaction token needed for reporting external transactions
- Throws OpenIapError.NotPrepared if billing client not ready
+ Returns external transaction token needed for reporting external transactions.
+ Throws OpenIapError.NotPrepared if billing client not ready.
+ See: https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android
"""
# Future
createBillingProgramReportingDetailsAndroid(program: BillingProgramAndroid!): BillingProgramReportingDetailsAndroid!
"""
- Launch external link flow for external billing programs
- Replaces the deprecated showExternalOfferInformationDialog API
+ Launch an external content/offer link from inside the Billing Programs flow (Play Billing 8.2.0+).
+ Replaces the deprecated showExternalOfferInformationDialog API.
- Available in Google Play Billing Library 8.2.0+
- Shows Play Store dialog and optionally launches external URL
- Throws OpenIapError.NotPrepared if billing client not ready
+ Shows Play Store dialog and optionally launches external URL.
+ Throws OpenIapError.NotPrepared if billing client not ready.
+ See: https://www.openiap.dev/docs/apis/android/launch-external-link-android
"""
# Future
launchExternalLinkAndroid(params: LaunchExternalLinkParamsAndroid!): Boolean!
diff --git a/packages/gql/src/api-ios.graphql b/packages/gql/src/api-ios.graphql
index ba7802c0..a9494f2e 100644
--- a/packages/gql/src/api-ios.graphql
+++ b/packages/gql/src/api-ios.graphql
@@ -2,32 +2,37 @@
extend type Query {
"""
- Get the current App Store storefront country code
+ Deprecated. Get the current App Store storefront country code — use cross-platform getStorefront instead.
+ See: https://www.openiap.dev/docs/apis/ios/get-storefront-ios
"""
# Future
getStorefrontIOS: String! @deprecated(reason: "Use getStorefront")
"""
- Get the currently promoted product (iOS 11+)
+ Read the App Store-promoted product, if any (iOS 11+).
+ See: https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios
"""
# Future
getPromotedProductIOS: ProductIOS
"""
- Check if external purchase notice sheet can be presented (iOS 17.4+)
- Uses ExternalPurchase.canPresent
+ Check eligibility for the external purchase notice sheet (iOS 17.4+).
+ Uses ExternalPurchase.canPresent.
+ See: https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios
"""
# Future
canPresentExternalPurchaseNoticeIOS: Boolean!
"""
- Check if app is eligible for ExternalPurchaseCustomLink API (iOS 18.1+).
+ Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
Returns true if the app can use custom external purchase links.
Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/iseligible
+ See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios
"""
# Future
isEligibleForExternalPurchaseCustomLinkIOS: Boolean!
"""
- Get external purchase token for reporting to Apple (iOS 18.1+).
- Use this token with Apple's External Purchase Server API to report transactions.
+ Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
+ Use this token to report transactions made through ExternalPurchaseCustomLink.
Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/token(for:)
+ See: https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios
"""
# Future
getExternalPurchaseCustomLinkTokenIOS(
@@ -37,60 +42,71 @@ extend type Query {
tokenType: ExternalPurchaseCustomLinkTokenTypeIOS!
): ExternalPurchaseCustomLinkTokenResultIOS!
"""
- Retrieve all pending transactions in the StoreKit queue
+ List unfinished StoreKit transactions in the queue.
+ See: https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios
"""
# Future
getPendingTransactionsIOS: [PurchaseIOS!]!
"""
- Check introductory offer eligibility for a subscription group
+ Check intro-offer eligibility for a subscription group.
+ See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios
"""
# Future
isEligibleForIntroOfferIOS(groupID: String!): Boolean!
"""
- Get StoreKit 2 subscription status details (iOS 15+)
+ Get subscription status objects from StoreKit 2 (iOS 15+).
+ See: https://www.openiap.dev/docs/apis/ios/subscription-status-ios
"""
# Future
subscriptionStatusIOS(sku: String!): [SubscriptionStatusIOS!]!
"""
- Get current StoreKit 2 entitlements (iOS 15+)
+ Get the user's current entitlement for a product, using StoreKit 2 (iOS 15+).
+ See: https://www.openiap.dev/docs/apis/ios/current-entitlement-ios
"""
# Future
currentEntitlementIOS(sku: String!): PurchaseIOS
"""
- Get the latest transaction for a product using StoreKit 2
+ Get the latest verified transaction for a product, using StoreKit 2.
+ See: https://www.openiap.dev/docs/apis/ios/latest-transaction-ios
"""
# Future
latestTransactionIOS(sku: String!): PurchaseIOS
"""
- Verify a StoreKit 2 transaction signature
+ Check whether a transaction's JWS verification passed (StoreKit 2).
+ See: https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios
"""
# Future
isTransactionVerifiedIOS(sku: String!): Boolean!
"""
- Get the transaction JWS (StoreKit 2)
+ Return the JWS string for a transaction (StoreKit 2).
+ See: https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios
"""
# Future
getTransactionJwsIOS(sku: String!): String
"""
- Get base64-encoded receipt data for validation
+ Get base64-encoded receipt data (legacy validation).
+ See: https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios
"""
# Future
getReceiptDataIOS: String
"""
- Fetch the current app transaction (iOS 16+)
+ Fetch the app transaction (iOS 16+).
+ See: https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios
"""
# Future
getAppTransactionIOS: AppTransaction
"""
- Get the full StoreKit 2 transaction history as PurchaseIOS values.
+ List every StoreKit transaction (finished + unfinished) for the current user.
Requires the SK2ConsumableTransactionHistory Info.plist key in the host app
for finished consumables to be included (iOS 18+).
Unlike getAvailablePurchases, always returns the iOS-specific PurchaseIOS shape.
+ See: https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios
"""
# Future
getAllTransactionsIOS: [PurchaseIOS!]!
"""
- Validate a receipt for a specific product
+ Deprecated. Legacy App Store receipt validation — use verifyPurchase instead.
+ See: https://www.openiap.dev/docs/apis/ios/validate-receipt-ios
"""
# Future
validateReceiptIOS(options: VerifyPurchaseProps!): VerifyPurchaseResultIOS! @deprecated(reason: "Use verifyPurchase")
@@ -98,56 +114,64 @@ extend type Query {
extend type Mutation {
"""
- Clear pending transactions from the StoreKit payment queue
+ Clear pending transactions in the queue (sandbox helper).
+ See: https://www.openiap.dev/docs/apis/ios/clear-transaction-ios
"""
# Future
clearTransactionIOS: Boolean!
"""
- Purchase the promoted product surfaced by the App Store.
+ Buy the currently promoted product.
@deprecated Use promotedProductListenerIOS to receive the productId,
then call requestPurchase with that SKU instead. In StoreKit 2,
promoted products can be purchased directly via the standard purchase flow.
+ See: https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios
"""
# Future
requestPurchaseOnPromotedProductIOS: Boolean! @deprecated(reason: "Use promotedProductListenerIOS + requestPurchase instead")
"""
- Open subscription management UI and return changed purchases (iOS 15+)
+ Present the manage-subscriptions sheet and return changed purchases (iOS 15+).
+ See: https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios
"""
# Future
showManageSubscriptionsIOS: [PurchaseIOS!]!
"""
- Initiate a refund request for a product (iOS 15+)
+ Present the refund request sheet (iOS 15+). See also Features → Refund.
+ See: https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios
"""
# Future
beginRefundRequestIOS(sku: String!): String
"""
- Force a StoreKit sync for transactions (iOS 15+)
+ Force sync transactions with the App Store (iOS 15+).
+ See: https://www.openiap.dev/docs/apis/ios/sync-ios
"""
# Future
syncIOS: Boolean!
"""
- Present the App Store code redemption sheet
+ Show the App Store offer code redemption sheet.
+ See: https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios
"""
# Future
presentCodeRedemptionSheetIOS: Boolean!
"""
- Present external purchase notice sheet (iOS 17.4+).
- Uses ExternalPurchase.presentNoticeSheet() which returns a token when user continues.
+ Present the external purchase notice sheet (iOS 17.4+).
+ Uses ExternalPurchase.presentNoticeSheet() which returns a token when the user continues.
Reference: https://developer.apple.com/documentation/storekit/externalpurchase/presentnoticesheet()
+ See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios
"""
# Future
presentExternalPurchaseNoticeSheetIOS: ExternalPurchaseNoticeResultIOS!
"""
- Present external purchase custom link with StoreKit UI
+ Present an external purchase link, StoreKit External (iOS 16+).
+ See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios
"""
# Future
presentExternalPurchaseLinkIOS(url: String!): ExternalPurchaseLinkResultIOS!
"""
- Show ExternalPurchaseCustomLink notice sheet (iOS 18.1+).
- Displays the system disclosure notice sheet for custom external purchase links.
+ Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
Call this after a deliberate customer interaction before linking out to external purchases.
Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/shownotice(type:)
+ See: https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios
"""
# Future
showExternalPurchaseCustomLinkNoticeIOS(
diff --git a/packages/gql/src/api.graphql b/packages/gql/src/api.graphql
index a4e56824..b43b7cc8 100644
--- a/packages/gql/src/api.graphql
+++ b/packages/gql/src/api.graphql
@@ -3,27 +3,32 @@
# Product management
extend type Query {
"""
- Retrieve products or subscriptions from the store
+ Fetch products or subscriptions from the store.
+ See: https://www.openiap.dev/docs/apis/fetch-products
"""
# Future
fetchProducts(params: ProductRequest!): FetchProductsResult!
"""
- Get all available purchases for the current user
+ List active purchases for the current user.
+ See: https://www.openiap.dev/docs/apis/get-available-purchases
"""
# Future
getAvailablePurchases(options: PurchaseOptions): [Purchase!]!
"""
- Get active subscriptions (filters by subscriptionIds when provided)
+ Get details of all currently active subscriptions (filters by subscriptionIds when provided).
+ See: https://www.openiap.dev/docs/apis/get-active-subscriptions
"""
# Future
getActiveSubscriptions(subscriptionIds: [String!]): [ActiveSubscription!]!
"""
- Check whether the user has active subscriptions
+ Check whether the user has any active subscription.
+ See: https://www.openiap.dev/docs/apis/has-active-subscriptions
"""
# Future
hasActiveSubscriptions(subscriptionIds: [String!]): Boolean!
"""
- Get the current storefront country code
+ Return the user's storefront country code.
+ See: https://www.openiap.dev/docs/apis/get-storefront
"""
# Future
getStorefront: String!
@@ -32,22 +37,26 @@ extend type Query {
# Request APIs (event driven)
extend type Mutation {
"""
- Establish the platform billing connection
+ Initialize the store connection. Call before any IAP API.
+ See: https://www.openiap.dev/docs/apis/init-connection
"""
# Future
initConnection(config: InitConnectionConfig): Boolean!
"""
- Close the platform billing connection
+ Close the store connection and release resources.
+ See: https://www.openiap.dev/docs/apis/end-connection
"""
# Future
endConnection: Boolean!
"""
- Initiate a purchase flow; rely on events for final state
+ Initiate a purchase or subscription flow; rely on events for final state.
+ See: https://www.openiap.dev/docs/apis/request-purchase
"""
# Future
requestPurchase(params: RequestPurchaseProps!): RequestPurchaseResult
"""
- Finish a transaction after validating receipts
+ Complete a transaction after server-side verification. Required on Android within 3 days.
+ See: https://www.openiap.dev/docs/apis/finish-transaction
"""
# Future
finishTransaction(
@@ -55,27 +64,32 @@ extend type Mutation {
isConsumable: Boolean
): VoidResult!
"""
- Restore completed purchases across platforms
+ Restore non-consumable and active subscription purchases.
+ See: https://www.openiap.dev/docs/apis/restore-purchases
"""
# Future
restorePurchases: VoidResult!
"""
- Open the native subscription management surface
+ Open the platform's subscription management UI.
+ See: https://www.openiap.dev/docs/apis/deep-link-to-subscriptions
"""
# Future
deepLinkToSubscriptions(options: DeepLinkOptions): VoidResult!
"""
- Validate purchase receipts with the configured providers
+ Deprecated. Validate purchase receipts with the configured providers — use verifyPurchase instead.
+ See: https://www.openiap.dev/docs/features/validation#verify-purchase
"""
# Future
validateReceipt(options: VerifyPurchaseProps!): VerifyPurchaseResult! @deprecated(reason: "Use verifyPurchase")
"""
- Verify purchases with the configured providers
+ Verify a purchase against your own backend (returns isValid + raw store metadata).
+ See: https://www.openiap.dev/docs/features/validation#verify-purchase
"""
# Future
verifyPurchase(options: VerifyPurchaseProps!): VerifyPurchaseResult!
"""
- Verify purchases with a specific provider (e.g., IAPKit)
+ Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+ See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
"""
# Future
verifyPurchaseWithProvider(
diff --git a/packages/gql/src/generated/Types.kt b/packages/gql/src/generated/Types.kt
index d5151235..d07a59c8 100644
--- a/packages/gql/src/generated/Types.kt
+++ b/packages/gql/src/generated/Types.kt
@@ -4833,146 +4833,166 @@ public sealed interface VerifyPurchaseResult {
*/
public interface MutationResolver {
/**
- * Acknowledge a non-consumable purchase or subscription
+ * Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
+ * See: https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android
*/
suspend fun acknowledgePurchaseAndroid(purchaseToken: String): Boolean
/**
- * Initiate a refund request for a product (iOS 15+)
+ * Present the refund request sheet (iOS 15+). See also Features → Refund.
+ * See: https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios
*/
suspend fun beginRefundRequestIOS(sku: String): String?
/**
- * Check if alternative billing is available for this user/device
- * Step 1 of alternative billing flow
+ * Check whether alternative billing is available for the user. Step 1 of the alternative billing flow.
*
- * Returns true if available, false otherwise
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns true if available, false otherwise.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android
*/
suspend fun checkAlternativeBillingAvailabilityAndroid(): Boolean
/**
- * Clear pending transactions from the StoreKit payment queue
+ * Clear pending transactions in the queue (sandbox helper).
+ * See: https://www.openiap.dev/docs/apis/ios/clear-transaction-ios
*/
suspend fun clearTransactionIOS(): Boolean
/**
- * Consume a purchase token so it can be repurchased
+ * Consume a consumable purchase so it can be re-bought.
+ * See: https://www.openiap.dev/docs/apis/android/consume-purchase-android
*/
suspend fun consumePurchaseAndroid(purchaseToken: String): Boolean
/**
- * Create external transaction token for Google Play reporting
- * Step 3 of alternative billing flow
- * Must be called AFTER successful payment in your payment system
- * Token must be reported to Google Play backend within 24 hours
+ * Create a reporting token for an alternative billing flow. Step 3 of the alternative billing flow.
+ * Must be called AFTER successful payment in your payment system.
+ * Token must be reported to Google Play backend within 24 hours.
*
- * Returns token string, or null if creation failed
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns token string, or null if creation failed.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android
*/
suspend fun createAlternativeBillingTokenAndroid(): String?
/**
- * Create reporting details for a billing program
- * Replaces the deprecated createExternalOfferReportingDetailsAsync API
+ * Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+).
+ * Replaces the deprecated createExternalOfferReportingDetailsAsync API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Returns external transaction token needed for reporting external transactions
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns external transaction token needed for reporting external transactions.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android
*/
suspend fun createBillingProgramReportingDetailsAndroid(program: BillingProgramAndroid): BillingProgramReportingDetailsAndroid
/**
- * Open the native subscription management surface
+ * Open the platform's subscription management UI.
+ * See: https://www.openiap.dev/docs/apis/deep-link-to-subscriptions
*/
suspend fun deepLinkToSubscriptions(options: DeepLinkOptions? = null): Unit
/**
- * Close the platform billing connection
+ * Close the store connection and release resources.
+ * See: https://www.openiap.dev/docs/apis/end-connection
*/
suspend fun endConnection(): Boolean
/**
- * Finish a transaction after validating receipts
+ * Complete a transaction after server-side verification. Required on Android within 3 days.
+ * See: https://www.openiap.dev/docs/apis/finish-transaction
*/
suspend fun finishTransaction(purchase: PurchaseInput, isConsumable: Boolean? = null): Unit
/**
- * Establish the platform billing connection
+ * Initialize the store connection. Call before any IAP API.
+ * See: https://www.openiap.dev/docs/apis/init-connection
*/
suspend fun initConnection(config: InitConnectionConfig? = null): Boolean
/**
- * Check if a billing program is available for the current user
- * Replaces the deprecated isExternalOfferAvailableAsync API
+ * Check whether a billing program (e.g., External Payments) is available for the current user.
+ * Replaces the deprecated isExternalOfferAvailableAsync API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Returns availability result with isAvailable flag
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Available in Google Play Billing Library 8.2.0+.
+ * Returns availability result with isAvailable flag.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/is-billing-program-available-android
*/
suspend fun isBillingProgramAvailableAndroid(program: BillingProgramAndroid): BillingProgramAvailabilityResultAndroid
/**
- * Launch external link flow for external billing programs
- * Replaces the deprecated showExternalOfferInformationDialog API
+ * Launch an external content/offer link from inside the Billing Programs flow (Play Billing 8.2.0+).
+ * Replaces the deprecated showExternalOfferInformationDialog API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Shows Play Store dialog and optionally launches external URL
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Shows Play Store dialog and optionally launches external URL.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/launch-external-link-android
*/
suspend fun launchExternalLinkAndroid(params: LaunchExternalLinkParamsAndroid): Boolean
/**
- * Present the App Store code redemption sheet
+ * Show the App Store offer code redemption sheet.
+ * See: https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios
*/
suspend fun presentCodeRedemptionSheetIOS(): Boolean
/**
- * Present external purchase custom link with StoreKit UI
+ * Present an external purchase link, StoreKit External (iOS 16+).
+ * See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios
*/
suspend fun presentExternalPurchaseLinkIOS(url: String): ExternalPurchaseLinkResultIOS
/**
- * Present external purchase notice sheet (iOS 17.4+).
- * Uses ExternalPurchase.presentNoticeSheet() which returns a token when user continues.
+ * Present the external purchase notice sheet (iOS 17.4+).
+ * Uses ExternalPurchase.presentNoticeSheet() which returns a token when the user continues.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchase/presentnoticesheet()
+ * See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios
*/
suspend fun presentExternalPurchaseNoticeSheetIOS(): ExternalPurchaseNoticeResultIOS
/**
- * Initiate a purchase flow; rely on events for final state
+ * Initiate a purchase or subscription flow; rely on events for final state.
+ * See: https://www.openiap.dev/docs/apis/request-purchase
*/
suspend fun requestPurchase(params: RequestPurchaseProps): RequestPurchaseResult?
/**
- * Purchase the promoted product surfaced by the App Store.
+ * Buy the currently promoted product.
*
* @deprecated Use promotedProductListenerIOS to receive the productId,
* then call requestPurchase with that SKU instead. In StoreKit 2,
* promoted products can be purchased directly via the standard purchase flow.
+ * See: https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios
*/
suspend fun requestPurchaseOnPromotedProductIOS(): Boolean
/**
- * Restore completed purchases across platforms
+ * Restore non-consumable and active subscription purchases.
+ * See: https://www.openiap.dev/docs/apis/restore-purchases
*/
suspend fun restorePurchases(): Unit
/**
- * Show alternative billing information dialog to user
- * Step 2 of alternative billing flow
- * Must be called BEFORE processing payment in your payment system
+ * Display Google's alternative billing information dialog. Step 2 of the alternative billing flow.
+ * Must be called BEFORE processing payment in your payment system.
*
- * Returns true if user accepted, false if user canceled
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns true if user accepted, false if user canceled.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android
*/
suspend fun showAlternativeBillingDialogAndroid(): Boolean
/**
- * Show ExternalPurchaseCustomLink notice sheet (iOS 18.1+).
- * Displays the system disclosure notice sheet for custom external purchase links.
+ * Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
* Call this after a deliberate customer interaction before linking out to external purchases.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/shownotice(type:)
+ * See: https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios
*/
suspend fun showExternalPurchaseCustomLinkNoticeIOS(noticeType: ExternalPurchaseCustomLinkNoticeTypeIOS): ExternalPurchaseCustomLinkNoticeResultIOS
/**
- * Open subscription management UI and return changed purchases (iOS 15+)
+ * Present the manage-subscriptions sheet and return changed purchases (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios
*/
suspend fun showManageSubscriptionsIOS(): List
/**
- * Force a StoreKit sync for transactions (iOS 15+)
+ * Force sync transactions with the App Store (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/sync-ios
*/
suspend fun syncIOS(): Boolean
/**
- * Validate purchase receipts with the configured providers
+ * Deprecated. Validate purchase receipts with the configured providers — use verifyPurchase instead.
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase
*/
suspend fun validateReceipt(options: VerifyPurchaseProps): VerifyPurchaseResult
/**
- * Verify purchases with the configured providers
+ * Verify a purchase against your own backend (returns isValid + raw store metadata).
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase
*/
suspend fun verifyPurchase(options: VerifyPurchaseProps): VerifyPurchaseResult
/**
- * Verify purchases with a specific provider (e.g., IAPKit)
+ * Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
*/
suspend fun verifyPurchaseWithProvider(options: VerifyPurchaseWithProviderProps): VerifyPurchaseWithProviderResult
}
@@ -4982,95 +5002,116 @@ public interface MutationResolver {
*/
public interface QueryResolver {
/**
- * Check if external purchase notice sheet can be presented (iOS 17.4+)
- * Uses ExternalPurchase.canPresent
+ * Check eligibility for the external purchase notice sheet (iOS 17.4+).
+ * Uses ExternalPurchase.canPresent.
+ * See: https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios
*/
suspend fun canPresentExternalPurchaseNoticeIOS(): Boolean
/**
- * Get current StoreKit 2 entitlements (iOS 15+)
+ * Get the user's current entitlement for a product, using StoreKit 2 (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/current-entitlement-ios
*/
suspend fun currentEntitlementIOS(sku: String): PurchaseIOS?
/**
- * Retrieve products or subscriptions from the store
+ * Fetch products or subscriptions from the store.
+ * See: https://www.openiap.dev/docs/apis/fetch-products
*/
suspend fun fetchProducts(params: ProductRequest): FetchProductsResult
/**
- * Get active subscriptions (filters by subscriptionIds when provided)
+ * Get details of all currently active subscriptions (filters by subscriptionIds when provided).
+ * See: https://www.openiap.dev/docs/apis/get-active-subscriptions
*/
suspend fun getActiveSubscriptions(subscriptionIds: List? = null): List
/**
- * Get the full StoreKit 2 transaction history as PurchaseIOS values.
+ * List every StoreKit transaction (finished + unfinished) for the current user.
* Requires the SK2ConsumableTransactionHistory Info.plist key in the host app
* for finished consumables to be included (iOS 18+).
* Unlike getAvailablePurchases, always returns the iOS-specific PurchaseIOS shape.
+ * See: https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios
*/
suspend fun getAllTransactionsIOS(): List
/**
- * Fetch the current app transaction (iOS 16+)
+ * Fetch the app transaction (iOS 16+).
+ * See: https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios
*/
suspend fun getAppTransactionIOS(): AppTransaction?
/**
- * Get all available purchases for the current user
+ * List active purchases for the current user.
+ * See: https://www.openiap.dev/docs/apis/get-available-purchases
*/
suspend fun getAvailablePurchases(options: PurchaseOptions? = null): List
/**
- * Get external purchase token for reporting to Apple (iOS 18.1+).
- * Use this token with Apple's External Purchase Server API to report transactions.
+ * Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
+ * Use this token to report transactions made through ExternalPurchaseCustomLink.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/token(for:)
+ * See: https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios
*/
suspend fun getExternalPurchaseCustomLinkTokenIOS(tokenType: ExternalPurchaseCustomLinkTokenTypeIOS): ExternalPurchaseCustomLinkTokenResultIOS
/**
- * Retrieve all pending transactions in the StoreKit queue
+ * List unfinished StoreKit transactions in the queue.
+ * See: https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios
*/
suspend fun getPendingTransactionsIOS(): List
/**
- * Get the currently promoted product (iOS 11+)
+ * Read the App Store-promoted product, if any (iOS 11+).
+ * See: https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios
*/
suspend fun getPromotedProductIOS(): ProductIOS?
/**
- * Get base64-encoded receipt data for validation
+ * Get base64-encoded receipt data (legacy validation).
+ * See: https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios
*/
suspend fun getReceiptDataIOS(): String?
/**
- * Get the current storefront country code
+ * Return the user's storefront country code.
+ * See: https://www.openiap.dev/docs/apis/get-storefront
*/
suspend fun getStorefront(): String
/**
- * Get the current App Store storefront country code
+ * Deprecated. Get the current App Store storefront country code — use cross-platform getStorefront instead.
+ * See: https://www.openiap.dev/docs/apis/ios/get-storefront-ios
*/
suspend fun getStorefrontIOS(): String
/**
- * Get the transaction JWS (StoreKit 2)
+ * Return the JWS string for a transaction (StoreKit 2).
+ * See: https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios
*/
suspend fun getTransactionJwsIOS(sku: String): String?
/**
- * Check whether the user has active subscriptions
+ * Check whether the user has any active subscription.
+ * See: https://www.openiap.dev/docs/apis/has-active-subscriptions
*/
suspend fun hasActiveSubscriptions(subscriptionIds: List? = null): Boolean
/**
- * Check if app is eligible for ExternalPurchaseCustomLink API (iOS 18.1+).
+ * Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
* Returns true if the app can use custom external purchase links.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/iseligible
+ * See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios
*/
suspend fun isEligibleForExternalPurchaseCustomLinkIOS(): Boolean
/**
- * Check introductory offer eligibility for a subscription group
+ * Check intro-offer eligibility for a subscription group.
+ * See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios
*/
suspend fun isEligibleForIntroOfferIOS(groupID: String): Boolean
/**
- * Verify a StoreKit 2 transaction signature
+ * Check whether a transaction's JWS verification passed (StoreKit 2).
+ * See: https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios
*/
suspend fun isTransactionVerifiedIOS(sku: String): Boolean
/**
- * Get the latest transaction for a product using StoreKit 2
+ * Get the latest verified transaction for a product, using StoreKit 2.
+ * See: https://www.openiap.dev/docs/apis/ios/latest-transaction-ios
*/
suspend fun latestTransactionIOS(sku: String): PurchaseIOS?
/**
- * Get StoreKit 2 subscription status details (iOS 15+)
+ * Get subscription status objects from StoreKit 2 (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/subscription-status-ios
*/
suspend fun subscriptionStatusIOS(sku: String): List
/**
- * Validate a receipt for a specific product
+ * Deprecated. Legacy App Store receipt validation — use verifyPurchase instead.
+ * See: https://www.openiap.dev/docs/apis/ios/validate-receipt-ios
*/
suspend fun validateReceiptIOS(options: VerifyPurchaseProps): VerifyPurchaseResultIOS
}
diff --git a/packages/gql/src/generated/Types.swift b/packages/gql/src/generated/Types.swift
index a3547e12..4d823837 100644
--- a/packages/gql/src/generated/Types.swift
+++ b/packages/gql/src/generated/Types.swift
@@ -2334,150 +2334,191 @@ public enum VerifyPurchaseResult: Codable {
/// GraphQL root mutation operations.
public protocol MutationResolver {
- /// Acknowledge a non-consumable purchase or subscription
+ /// Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
+ /// See: https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android
func acknowledgePurchaseAndroid(_ purchaseToken: String) async throws -> Bool
- /// Initiate a refund request for a product (iOS 15+)
+ /// Present the refund request sheet (iOS 15+). See also Features → Refund.
+ /// See: https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios
func beginRefundRequestIOS(_ sku: String) async throws -> String?
- /// Check if alternative billing is available for this user/device
- /// Step 1 of alternative billing flow
+ /// Check whether alternative billing is available for the user. Step 1 of the alternative billing flow.
///
- /// Returns true if available, false otherwise
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Returns true if available, false otherwise.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android
func checkAlternativeBillingAvailabilityAndroid() async throws -> Bool
- /// Clear pending transactions from the StoreKit payment queue
+ /// Clear pending transactions in the queue (sandbox helper).
+ /// See: https://www.openiap.dev/docs/apis/ios/clear-transaction-ios
func clearTransactionIOS() async throws -> Bool
- /// Consume a purchase token so it can be repurchased
+ /// Consume a consumable purchase so it can be re-bought.
+ /// See: https://www.openiap.dev/docs/apis/android/consume-purchase-android
func consumePurchaseAndroid(_ purchaseToken: String) async throws -> Bool
- /// Create external transaction token for Google Play reporting
- /// Step 3 of alternative billing flow
- /// Must be called AFTER successful payment in your payment system
- /// Token must be reported to Google Play backend within 24 hours
+ /// Create a reporting token for an alternative billing flow. Step 3 of the alternative billing flow.
+ /// Must be called AFTER successful payment in your payment system.
+ /// Token must be reported to Google Play backend within 24 hours.
///
- /// Returns token string, or null if creation failed
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Returns token string, or null if creation failed.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android
func createAlternativeBillingTokenAndroid() async throws -> String?
- /// Create reporting details for a billing program
- /// Replaces the deprecated createExternalOfferReportingDetailsAsync API
+ /// Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+).
+ /// Replaces the deprecated createExternalOfferReportingDetailsAsync API.
///
- /// Available in Google Play Billing Library 8.2.0+
- /// Returns external transaction token needed for reporting external transactions
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Returns external transaction token needed for reporting external transactions.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android
func createBillingProgramReportingDetailsAndroid(_ program: BillingProgramAndroid) async throws -> BillingProgramReportingDetailsAndroid
- /// Open the native subscription management surface
+ /// Open the platform's subscription management UI.
+ /// See: https://www.openiap.dev/docs/apis/deep-link-to-subscriptions
func deepLinkToSubscriptions(_ options: DeepLinkOptions?) async throws -> Void
- /// Close the platform billing connection
+ /// Close the store connection and release resources.
+ /// See: https://www.openiap.dev/docs/apis/end-connection
func endConnection() async throws -> Bool
- /// Finish a transaction after validating receipts
+ /// Complete a transaction after server-side verification. Required on Android within 3 days.
+ /// See: https://www.openiap.dev/docs/apis/finish-transaction
func finishTransaction(purchase: PurchaseInput, isConsumable: Bool?) async throws -> Void
- /// Establish the platform billing connection
+ /// Initialize the store connection. Call before any IAP API.
+ /// See: https://www.openiap.dev/docs/apis/init-connection
func initConnection(_ config: InitConnectionConfig?) async throws -> Bool
- /// Check if a billing program is available for the current user
- /// Replaces the deprecated isExternalOfferAvailableAsync API
+ /// Check whether a billing program (e.g., External Payments) is available for the current user.
+ /// Replaces the deprecated isExternalOfferAvailableAsync API.
///
- /// Available in Google Play Billing Library 8.2.0+
- /// Returns availability result with isAvailable flag
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Available in Google Play Billing Library 8.2.0+.
+ /// Returns availability result with isAvailable flag.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/is-billing-program-available-android
func isBillingProgramAvailableAndroid(_ program: BillingProgramAndroid) async throws -> BillingProgramAvailabilityResultAndroid
- /// Launch external link flow for external billing programs
- /// Replaces the deprecated showExternalOfferInformationDialog API
+ /// Launch an external content/offer link from inside the Billing Programs flow (Play Billing 8.2.0+).
+ /// Replaces the deprecated showExternalOfferInformationDialog API.
///
- /// Available in Google Play Billing Library 8.2.0+
- /// Shows Play Store dialog and optionally launches external URL
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Shows Play Store dialog and optionally launches external URL.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/launch-external-link-android
func launchExternalLinkAndroid(_ params: LaunchExternalLinkParamsAndroid) async throws -> Bool
- /// Present the App Store code redemption sheet
+ /// Show the App Store offer code redemption sheet.
+ /// See: https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios
func presentCodeRedemptionSheetIOS() async throws -> Bool
- /// Present external purchase custom link with StoreKit UI
+ /// Present an external purchase link, StoreKit External (iOS 16+).
+ /// See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios
func presentExternalPurchaseLinkIOS(_ url: String) async throws -> ExternalPurchaseLinkResultIOS
- /// Present external purchase notice sheet (iOS 17.4+).
- /// Uses ExternalPurchase.presentNoticeSheet() which returns a token when user continues.
+ /// Present the external purchase notice sheet (iOS 17.4+).
+ /// Uses ExternalPurchase.presentNoticeSheet() which returns a token when the user continues.
/// Reference: https://developer.apple.com/documentation/storekit/externalpurchase/presentnoticesheet()
+ /// See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios
func presentExternalPurchaseNoticeSheetIOS() async throws -> ExternalPurchaseNoticeResultIOS
- /// Initiate a purchase flow; rely on events for final state
+ /// Initiate a purchase or subscription flow; rely on events for final state.
+ /// See: https://www.openiap.dev/docs/apis/request-purchase
func requestPurchase(_ params: RequestPurchaseProps) async throws -> RequestPurchaseResult?
- /// Purchase the promoted product surfaced by the App Store.
+ /// Buy the currently promoted product.
///
/// @deprecated Use promotedProductListenerIOS to receive the productId,
/// then call requestPurchase with that SKU instead. In StoreKit 2,
/// promoted products can be purchased directly via the standard purchase flow.
+ /// See: https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios
func requestPurchaseOnPromotedProductIOS() async throws -> Bool
- /// Restore completed purchases across platforms
+ /// Restore non-consumable and active subscription purchases.
+ /// See: https://www.openiap.dev/docs/apis/restore-purchases
func restorePurchases() async throws -> Void
- /// Show alternative billing information dialog to user
- /// Step 2 of alternative billing flow
- /// Must be called BEFORE processing payment in your payment system
+ /// Display Google's alternative billing information dialog. Step 2 of the alternative billing flow.
+ /// Must be called BEFORE processing payment in your payment system.
///
- /// Returns true if user accepted, false if user canceled
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Returns true if user accepted, false if user canceled.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android
func showAlternativeBillingDialogAndroid() async throws -> Bool
- /// Show ExternalPurchaseCustomLink notice sheet (iOS 18.1+).
- /// Displays the system disclosure notice sheet for custom external purchase links.
+ /// Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
/// Call this after a deliberate customer interaction before linking out to external purchases.
/// Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/shownotice(type:)
+ /// See: https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios
func showExternalPurchaseCustomLinkNoticeIOS(_ noticeType: ExternalPurchaseCustomLinkNoticeTypeIOS) async throws -> ExternalPurchaseCustomLinkNoticeResultIOS
- /// Open subscription management UI and return changed purchases (iOS 15+)
+ /// Present the manage-subscriptions sheet and return changed purchases (iOS 15+).
+ /// See: https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios
func showManageSubscriptionsIOS() async throws -> [PurchaseIOS]
- /// Force a StoreKit sync for transactions (iOS 15+)
+ /// Force sync transactions with the App Store (iOS 15+).
+ /// See: https://www.openiap.dev/docs/apis/ios/sync-ios
func syncIOS() async throws -> Bool
- /// Validate purchase receipts with the configured providers
+ /// Deprecated. Validate purchase receipts with the configured providers — use verifyPurchase instead.
+ /// See: https://www.openiap.dev/docs/features/validation#verify-purchase
func validateReceipt(_ options: VerifyPurchaseProps) async throws -> VerifyPurchaseResult
- /// Verify purchases with the configured providers
+ /// Verify a purchase against your own backend (returns isValid + raw store metadata).
+ /// See: https://www.openiap.dev/docs/features/validation#verify-purchase
func verifyPurchase(_ options: VerifyPurchaseProps) async throws -> VerifyPurchaseResult
- /// Verify purchases with a specific provider (e.g., IAPKit)
+ /// Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+ /// See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
func verifyPurchaseWithProvider(_ options: VerifyPurchaseWithProviderProps) async throws -> VerifyPurchaseWithProviderResult
}
/// GraphQL root query operations.
public protocol QueryResolver {
- /// Check if external purchase notice sheet can be presented (iOS 17.4+)
- /// Uses ExternalPurchase.canPresent
+ /// Check eligibility for the external purchase notice sheet (iOS 17.4+).
+ /// Uses ExternalPurchase.canPresent.
+ /// See: https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios
func canPresentExternalPurchaseNoticeIOS() async throws -> Bool
- /// Get current StoreKit 2 entitlements (iOS 15+)
+ /// Get the user's current entitlement for a product, using StoreKit 2 (iOS 15+).
+ /// See: https://www.openiap.dev/docs/apis/ios/current-entitlement-ios
func currentEntitlementIOS(_ sku: String) async throws -> PurchaseIOS?
- /// Retrieve products or subscriptions from the store
+ /// Fetch products or subscriptions from the store.
+ /// See: https://www.openiap.dev/docs/apis/fetch-products
func fetchProducts(_ params: ProductRequest) async throws -> FetchProductsResult
- /// Get active subscriptions (filters by subscriptionIds when provided)
+ /// Get details of all currently active subscriptions (filters by subscriptionIds when provided).
+ /// See: https://www.openiap.dev/docs/apis/get-active-subscriptions
func getActiveSubscriptions(_ subscriptionIds: [String]?) async throws -> [ActiveSubscription]
- /// Get the full StoreKit 2 transaction history as PurchaseIOS values.
+ /// List every StoreKit transaction (finished + unfinished) for the current user.
/// Requires the SK2ConsumableTransactionHistory Info.plist key in the host app
/// for finished consumables to be included (iOS 18+).
/// Unlike getAvailablePurchases, always returns the iOS-specific PurchaseIOS shape.
+ /// See: https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios
func getAllTransactionsIOS() async throws -> [PurchaseIOS]
- /// Fetch the current app transaction (iOS 16+)
+ /// Fetch the app transaction (iOS 16+).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios
func getAppTransactionIOS() async throws -> AppTransaction?
- /// Get all available purchases for the current user
+ /// List active purchases for the current user.
+ /// See: https://www.openiap.dev/docs/apis/get-available-purchases
func getAvailablePurchases(_ options: PurchaseOptions?) async throws -> [Purchase]
- /// Get external purchase token for reporting to Apple (iOS 18.1+).
- /// Use this token with Apple's External Purchase Server API to report transactions.
+ /// Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
+ /// Use this token to report transactions made through ExternalPurchaseCustomLink.
/// Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/token(for:)
+ /// See: https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios
func getExternalPurchaseCustomLinkTokenIOS(_ tokenType: ExternalPurchaseCustomLinkTokenTypeIOS) async throws -> ExternalPurchaseCustomLinkTokenResultIOS
- /// Retrieve all pending transactions in the StoreKit queue
+ /// List unfinished StoreKit transactions in the queue.
+ /// See: https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios
func getPendingTransactionsIOS() async throws -> [PurchaseIOS]
- /// Get the currently promoted product (iOS 11+)
+ /// Read the App Store-promoted product, if any (iOS 11+).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios
func getPromotedProductIOS() async throws -> ProductIOS?
- /// Get base64-encoded receipt data for validation
+ /// Get base64-encoded receipt data (legacy validation).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios
func getReceiptDataIOS() async throws -> String?
- /// Get the current storefront country code
+ /// Return the user's storefront country code.
+ /// See: https://www.openiap.dev/docs/apis/get-storefront
func getStorefront() async throws -> String
- /// Get the current App Store storefront country code
+ /// Deprecated. Get the current App Store storefront country code — use cross-platform getStorefront instead.
+ /// See: https://www.openiap.dev/docs/apis/ios/get-storefront-ios
func getStorefrontIOS() async throws -> String
- /// Get the transaction JWS (StoreKit 2)
+ /// Return the JWS string for a transaction (StoreKit 2).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios
func getTransactionJwsIOS(_ sku: String) async throws -> String?
- /// Check whether the user has active subscriptions
+ /// Check whether the user has any active subscription.
+ /// See: https://www.openiap.dev/docs/apis/has-active-subscriptions
func hasActiveSubscriptions(_ subscriptionIds: [String]?) async throws -> Bool
- /// Check if app is eligible for ExternalPurchaseCustomLink API (iOS 18.1+).
+ /// Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
/// Returns true if the app can use custom external purchase links.
/// Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/iseligible
+ /// See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios
func isEligibleForExternalPurchaseCustomLinkIOS() async throws -> Bool
- /// Check introductory offer eligibility for a subscription group
+ /// Check intro-offer eligibility for a subscription group.
+ /// See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios
func isEligibleForIntroOfferIOS(_ groupID: String) async throws -> Bool
- /// Verify a StoreKit 2 transaction signature
+ /// Check whether a transaction's JWS verification passed (StoreKit 2).
+ /// See: https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios
func isTransactionVerifiedIOS(_ sku: String) async throws -> Bool
- /// Get the latest transaction for a product using StoreKit 2
+ /// Get the latest verified transaction for a product, using StoreKit 2.
+ /// See: https://www.openiap.dev/docs/apis/ios/latest-transaction-ios
func latestTransactionIOS(_ sku: String) async throws -> PurchaseIOS?
- /// Get StoreKit 2 subscription status details (iOS 15+)
+ /// Get subscription status objects from StoreKit 2 (iOS 15+).
+ /// See: https://www.openiap.dev/docs/apis/ios/subscription-status-ios
func subscriptionStatusIOS(_ sku: String) async throws -> [SubscriptionStatusIOS]
- /// Validate a receipt for a specific product
+ /// Deprecated. Legacy App Store receipt validation — use verifyPurchase instead.
+ /// See: https://www.openiap.dev/docs/apis/ios/validate-receipt-ios
func validateReceiptIOS(_ options: VerifyPurchaseProps) async throws -> VerifyPurchaseResultIOS
}
diff --git a/packages/gql/src/generated/types.dart b/packages/gql/src/generated/types.dart
index ea75b5b3..696a9148 100644
--- a/packages/gql/src/generated/types.dart
+++ b/packages/gql/src/generated/types.dart
@@ -4846,118 +4846,138 @@ sealed class VerifyPurchaseResult {
/// GraphQL root mutation operations.
abstract class MutationResolver {
- /// Acknowledge a non-consumable purchase or subscription
+ /// Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
+ /// See: https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android
Future acknowledgePurchaseAndroid(String purchaseToken);
- /// Initiate a refund request for a product (iOS 15+)
+ /// Present the refund request sheet (iOS 15+). See also Features → Refund.
+ /// See: https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios
Future beginRefundRequestIOS(String sku);
- /// Check if alternative billing is available for this user/device
- /// Step 1 of alternative billing flow
+ /// Check whether alternative billing is available for the user. Step 1 of the alternative billing flow.
///
- /// Returns true if available, false otherwise
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Returns true if available, false otherwise.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android
Future checkAlternativeBillingAvailabilityAndroid();
- /// Clear pending transactions from the StoreKit payment queue
+ /// Clear pending transactions in the queue (sandbox helper).
+ /// See: https://www.openiap.dev/docs/apis/ios/clear-transaction-ios
Future clearTransactionIOS();
- /// Consume a purchase token so it can be repurchased
+ /// Consume a consumable purchase so it can be re-bought.
+ /// See: https://www.openiap.dev/docs/apis/android/consume-purchase-android
Future consumePurchaseAndroid(String purchaseToken);
- /// Create external transaction token for Google Play reporting
- /// Step 3 of alternative billing flow
- /// Must be called AFTER successful payment in your payment system
- /// Token must be reported to Google Play backend within 24 hours
+ /// Create a reporting token for an alternative billing flow. Step 3 of the alternative billing flow.
+ /// Must be called AFTER successful payment in your payment system.
+ /// Token must be reported to Google Play backend within 24 hours.
///
- /// Returns token string, or null if creation failed
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Returns token string, or null if creation failed.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android
Future createAlternativeBillingTokenAndroid();
- /// Create reporting details for a billing program
- /// Replaces the deprecated createExternalOfferReportingDetailsAsync API
+ /// Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+).
+ /// Replaces the deprecated createExternalOfferReportingDetailsAsync API.
///
- /// Available in Google Play Billing Library 8.2.0+
- /// Returns external transaction token needed for reporting external transactions
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Returns external transaction token needed for reporting external transactions.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android
Future createBillingProgramReportingDetailsAndroid(BillingProgramAndroid program);
- /// Open the native subscription management surface
+ /// Open the platform's subscription management UI.
+ /// See: https://www.openiap.dev/docs/apis/deep-link-to-subscriptions
Future deepLinkToSubscriptions({
String? packageNameAndroid,
String? skuAndroid,
});
- /// Close the platform billing connection
+ /// Close the store connection and release resources.
+ /// See: https://www.openiap.dev/docs/apis/end-connection
Future endConnection();
- /// Finish a transaction after validating receipts
+ /// Complete a transaction after server-side verification. Required on Android within 3 days.
+ /// See: https://www.openiap.dev/docs/apis/finish-transaction
Future finishTransaction({
required PurchaseInput purchase,
bool? isConsumable,
});
- /// Establish the platform billing connection
+ /// Initialize the store connection. Call before any IAP API.
+ /// See: https://www.openiap.dev/docs/apis/init-connection
Future initConnection({
AlternativeBillingModeAndroid? alternativeBillingModeAndroid,
BillingProgramAndroid? enableBillingProgramAndroid,
});
- /// Check if a billing program is available for the current user
- /// Replaces the deprecated isExternalOfferAvailableAsync API
+ /// Check whether a billing program (e.g., External Payments) is available for the current user.
+ /// Replaces the deprecated isExternalOfferAvailableAsync API.
///
- /// Available in Google Play Billing Library 8.2.0+
- /// Returns availability result with isAvailable flag
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Available in Google Play Billing Library 8.2.0+.
+ /// Returns availability result with isAvailable flag.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/is-billing-program-available-android
Future isBillingProgramAvailableAndroid(BillingProgramAndroid program);
- /// Launch external link flow for external billing programs
- /// Replaces the deprecated showExternalOfferInformationDialog API
+ /// Launch an external content/offer link from inside the Billing Programs flow (Play Billing 8.2.0+).
+ /// Replaces the deprecated showExternalOfferInformationDialog API.
///
- /// Available in Google Play Billing Library 8.2.0+
- /// Shows Play Store dialog and optionally launches external URL
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Shows Play Store dialog and optionally launches external URL.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/launch-external-link-android
Future launchExternalLinkAndroid({
required BillingProgramAndroid billingProgram,
required ExternalLinkLaunchModeAndroid launchMode,
required ExternalLinkTypeAndroid linkType,
required String linkUri,
});
- /// Present the App Store code redemption sheet
+ /// Show the App Store offer code redemption sheet.
+ /// See: https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios
Future presentCodeRedemptionSheetIOS();
- /// Present external purchase custom link with StoreKit UI
+ /// Present an external purchase link, StoreKit External (iOS 16+).
+ /// See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios
Future presentExternalPurchaseLinkIOS(String url);
- /// Present external purchase notice sheet (iOS 17.4+).
- /// Uses ExternalPurchase.presentNoticeSheet() which returns a token when user continues.
+ /// Present the external purchase notice sheet (iOS 17.4+).
+ /// Uses ExternalPurchase.presentNoticeSheet() which returns a token when the user continues.
/// Reference: https://developer.apple.com/documentation/storekit/externalpurchase/presentnoticesheet()
+ /// See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios
Future presentExternalPurchaseNoticeSheetIOS();
- /// Initiate a purchase flow; rely on events for final state
+ /// Initiate a purchase or subscription flow; rely on events for final state.
+ /// See: https://www.openiap.dev/docs/apis/request-purchase
Future requestPurchase(RequestPurchaseProps params);
- /// Purchase the promoted product surfaced by the App Store.
+ /// Buy the currently promoted product.
///
/// @deprecated Use promotedProductListenerIOS to receive the productId,
/// then call requestPurchase with that SKU instead. In StoreKit 2,
/// promoted products can be purchased directly via the standard purchase flow.
+ /// See: https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios
Future requestPurchaseOnPromotedProductIOS();
- /// Restore completed purchases across platforms
+ /// Restore non-consumable and active subscription purchases.
+ /// See: https://www.openiap.dev/docs/apis/restore-purchases
Future restorePurchases();
- /// Show alternative billing information dialog to user
- /// Step 2 of alternative billing flow
- /// Must be called BEFORE processing payment in your payment system
+ /// Display Google's alternative billing information dialog. Step 2 of the alternative billing flow.
+ /// Must be called BEFORE processing payment in your payment system.
///
- /// Returns true if user accepted, false if user canceled
- /// Throws OpenIapError.NotPrepared if billing client not ready
+ /// Returns true if user accepted, false if user canceled.
+ /// Throws OpenIapError.NotPrepared if billing client not ready.
+ /// See: https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android
Future showAlternativeBillingDialogAndroid();
- /// Show ExternalPurchaseCustomLink notice sheet (iOS 18.1+).
- /// Displays the system disclosure notice sheet for custom external purchase links.
+ /// Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
/// Call this after a deliberate customer interaction before linking out to external purchases.
/// Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/shownotice(type:)
+ /// See: https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios
Future showExternalPurchaseCustomLinkNoticeIOS(ExternalPurchaseCustomLinkNoticeTypeIOS noticeType);
- /// Open subscription management UI and return changed purchases (iOS 15+)
+ /// Present the manage-subscriptions sheet and return changed purchases (iOS 15+).
+ /// See: https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios
Future> showManageSubscriptionsIOS();
- /// Force a StoreKit sync for transactions (iOS 15+)
+ /// Force sync transactions with the App Store (iOS 15+).
+ /// See: https://www.openiap.dev/docs/apis/ios/sync-ios
Future syncIOS();
- /// Validate purchase receipts with the configured providers
+ /// Deprecated. Validate purchase receipts with the configured providers — use verifyPurchase instead.
+ /// See: https://www.openiap.dev/docs/features/validation#verify-purchase
Future validateReceipt({
VerifyPurchaseAppleOptions? apple,
VerifyPurchaseGoogleOptions? google,
VerifyPurchaseHorizonOptions? horizon,
});
- /// Verify purchases with the configured providers
+ /// Verify a purchase against your own backend (returns isValid + raw store metadata).
+ /// See: https://www.openiap.dev/docs/features/validation#verify-purchase
Future verifyPurchase({
VerifyPurchaseAppleOptions? apple,
VerifyPurchaseGoogleOptions? google,
VerifyPurchaseHorizonOptions? horizon,
});
- /// Verify purchases with a specific provider (e.g., IAPKit)
+ /// Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+ /// See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
Future verifyPurchaseWithProvider({
RequestVerifyPurchaseWithIapkitProps? iapkit,
required PurchaseVerificationProvider provider,
@@ -4966,62 +4986,83 @@ abstract class MutationResolver {
/// GraphQL root query operations.
abstract class QueryResolver {
- /// Check if external purchase notice sheet can be presented (iOS 17.4+)
- /// Uses ExternalPurchase.canPresent
+ /// Check eligibility for the external purchase notice sheet (iOS 17.4+).
+ /// Uses ExternalPurchase.canPresent.
+ /// See: https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios
Future canPresentExternalPurchaseNoticeIOS();
- /// Get current StoreKit 2 entitlements (iOS 15+)
+ /// Get the user's current entitlement for a product, using StoreKit 2 (iOS 15+).
+ /// See: https://www.openiap.dev/docs/apis/ios/current-entitlement-ios
Future currentEntitlementIOS(String sku);
- /// Retrieve products or subscriptions from the store
+ /// Fetch products or subscriptions from the store.
+ /// See: https://www.openiap.dev/docs/apis/fetch-products
Future fetchProducts({
required List skus,
ProductQueryType? type,
});
- /// Get active subscriptions (filters by subscriptionIds when provided)
+ /// Get details of all currently active subscriptions (filters by subscriptionIds when provided).
+ /// See: https://www.openiap.dev/docs/apis/get-active-subscriptions
Future> getActiveSubscriptions([List? subscriptionIds]);
- /// Get the full StoreKit 2 transaction history as PurchaseIOS values.
+ /// List every StoreKit transaction (finished + unfinished) for the current user.
/// Requires the SK2ConsumableTransactionHistory Info.plist key in the host app
/// for finished consumables to be included (iOS 18+).
/// Unlike getAvailablePurchases, always returns the iOS-specific PurchaseIOS shape.
+ /// See: https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios
Future> getAllTransactionsIOS();
- /// Fetch the current app transaction (iOS 16+)
+ /// Fetch the app transaction (iOS 16+).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios
Future getAppTransactionIOS();
- /// Get all available purchases for the current user
+ /// List active purchases for the current user.
+ /// See: https://www.openiap.dev/docs/apis/get-available-purchases
Future> getAvailablePurchases({
bool? alsoPublishToEventListenerIOS,
bool? includeSuspendedAndroid,
bool? onlyIncludeActiveItemsIOS,
});
- /// Get external purchase token for reporting to Apple (iOS 18.1+).
- /// Use this token with Apple's External Purchase Server API to report transactions.
+ /// Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
+ /// Use this token to report transactions made through ExternalPurchaseCustomLink.
/// Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/token(for:)
+ /// See: https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios
Future getExternalPurchaseCustomLinkTokenIOS(ExternalPurchaseCustomLinkTokenTypeIOS tokenType);
- /// Retrieve all pending transactions in the StoreKit queue
+ /// List unfinished StoreKit transactions in the queue.
+ /// See: https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios
Future> getPendingTransactionsIOS();
- /// Get the currently promoted product (iOS 11+)
+ /// Read the App Store-promoted product, if any (iOS 11+).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios
Future getPromotedProductIOS();
- /// Get base64-encoded receipt data for validation
+ /// Get base64-encoded receipt data (legacy validation).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios
Future getReceiptDataIOS();
- /// Get the current storefront country code
+ /// Return the user's storefront country code.
+ /// See: https://www.openiap.dev/docs/apis/get-storefront
Future getStorefront();
- /// Get the current App Store storefront country code
+ /// Deprecated. Get the current App Store storefront country code — use cross-platform getStorefront instead.
+ /// See: https://www.openiap.dev/docs/apis/ios/get-storefront-ios
Future getStorefrontIOS();
- /// Get the transaction JWS (StoreKit 2)
+ /// Return the JWS string for a transaction (StoreKit 2).
+ /// See: https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios
Future getTransactionJwsIOS(String sku);
- /// Check whether the user has active subscriptions
+ /// Check whether the user has any active subscription.
+ /// See: https://www.openiap.dev/docs/apis/has-active-subscriptions
Future hasActiveSubscriptions([List? subscriptionIds]);
- /// Check if app is eligible for ExternalPurchaseCustomLink API (iOS 18.1+).
+ /// Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
/// Returns true if the app can use custom external purchase links.
/// Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/iseligible
+ /// See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios
Future isEligibleForExternalPurchaseCustomLinkIOS();
- /// Check introductory offer eligibility for a subscription group
+ /// Check intro-offer eligibility for a subscription group.
+ /// See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios
Future isEligibleForIntroOfferIOS(String groupID);
- /// Verify a StoreKit 2 transaction signature
+ /// Check whether a transaction's JWS verification passed (StoreKit 2).
+ /// See: https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios
Future isTransactionVerifiedIOS(String sku);
- /// Get the latest transaction for a product using StoreKit 2
+ /// Get the latest verified transaction for a product, using StoreKit 2.
+ /// See: https://www.openiap.dev/docs/apis/ios/latest-transaction-ios
Future latestTransactionIOS(String sku);
- /// Get StoreKit 2 subscription status details (iOS 15+)
+ /// Get subscription status objects from StoreKit 2 (iOS 15+).
+ /// See: https://www.openiap.dev/docs/apis/ios/subscription-status-ios
Future> subscriptionStatusIOS(String sku);
- /// Validate a receipt for a specific product
+ /// Deprecated. Legacy App Store receipt validation — use verifyPurchase instead.
+ /// See: https://www.openiap.dev/docs/apis/ios/validate-receipt-ios
Future validateReceiptIOS({
VerifyPurchaseAppleOptions? apple,
VerifyPurchaseGoogleOptions? google,
diff --git a/packages/gql/src/generated/types.gd b/packages/gql/src/generated/types.gd
index f1b51f5a..a475be19 100644
--- a/packages/gql/src/generated/types.gd
+++ b/packages/gql/src/generated/types.gd
@@ -4800,7 +4800,7 @@ class Query:
const return_type = "Boolean"
const is_array = false
- ## Retrieve products or subscriptions from the store
+ ## Fetch products or subscriptions from the store.
class fetchProductsField:
const name = "fetchProducts"
const snake_name = "fetch_products"
@@ -4820,7 +4820,7 @@ class Query:
const return_type = "FetchProductsResult"
const is_array = false
- ## Get all available purchases for the current user
+ ## List active purchases for the current user.
class getAvailablePurchasesField:
const name = "getAvailablePurchases"
const snake_name = "get_available_purchases"
@@ -4840,7 +4840,7 @@ class Query:
const return_type = "Purchase"
const is_array = true
- ## Get active subscriptions (filters by subscriptionIds when provided)
+ ## Get details of all currently active subscriptions (filters by subscriptionIds when provided).
class getActiveSubscriptionsField:
const name = "getActiveSubscriptions"
const snake_name = "get_active_subscriptions"
@@ -4860,7 +4860,7 @@ class Query:
const return_type = "ActiveSubscription"
const is_array = true
- ## Check whether the user has active subscriptions
+ ## Check whether the user has any active subscription.
class hasActiveSubscriptionsField:
const name = "hasActiveSubscriptions"
const snake_name = "has_active_subscriptions"
@@ -4880,7 +4880,7 @@ class Query:
const return_type = "Boolean"
const is_array = false
- ## Get the current storefront country code
+ ## Return the user's storefront country code.
class getStorefrontField:
const name = "getStorefront"
const snake_name = "get_storefront"
@@ -4889,7 +4889,7 @@ class Query:
const return_type = "String"
const is_array = false
- ## Get the current App Store storefront country code
+ ## Deprecated. Get the current App Store storefront country code — use cross-platform getStorefront instead.
class getStorefrontIOSField:
const name = "getStorefrontIOS"
const snake_name = "get_storefront_ios"
@@ -4898,7 +4898,7 @@ class Query:
const return_type = "String"
const is_array = false
- ## Get the currently promoted product (iOS 11+)
+ ## Read the App Store-promoted product, if any (iOS 11+).
class getPromotedProductIOSField:
const name = "getPromotedProductIOS"
const snake_name = "get_promoted_product_ios"
@@ -4907,7 +4907,7 @@ class Query:
const return_type = "ProductIOS"
const is_array = false
- ## Check if external purchase notice sheet can be presented (iOS 17.4+)
+ ## Check eligibility for the external purchase notice sheet (iOS 17.4+).
class canPresentExternalPurchaseNoticeIOSField:
const name = "canPresentExternalPurchaseNoticeIOS"
const snake_name = "can_present_external_purchase_notice_ios"
@@ -4916,7 +4916,7 @@ class Query:
const return_type = "Boolean"
const is_array = false
- ## Check if app is eligible for ExternalPurchaseCustomLink API (iOS 18.1+).
+ ## Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
class isEligibleForExternalPurchaseCustomLinkIOSField:
const name = "isEligibleForExternalPurchaseCustomLinkIOS"
const snake_name = "is_eligible_for_external_purchase_custom_link_ios"
@@ -4925,7 +4925,7 @@ class Query:
const return_type = "Boolean"
const is_array = false
- ## Get external purchase token for reporting to Apple (iOS 18.1+).
+ ## Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
class getExternalPurchaseCustomLinkTokenIOSField:
const name = "getExternalPurchaseCustomLinkTokenIOS"
const snake_name = "get_external_purchase_custom_link_token_ios"
@@ -4953,7 +4953,7 @@ class Query:
const return_type = "ExternalPurchaseCustomLinkTokenResultIOS"
const is_array = false
- ## Retrieve all pending transactions in the StoreKit queue
+ ## List unfinished StoreKit transactions in the queue.
class getPendingTransactionsIOSField:
const name = "getPendingTransactionsIOS"
const snake_name = "get_pending_transactions_ios"
@@ -4962,7 +4962,7 @@ class Query:
const return_type = "PurchaseIOS"
const is_array = true
- ## Check introductory offer eligibility for a subscription group
+ ## Check intro-offer eligibility for a subscription group.
class isEligibleForIntroOfferIOSField:
const name = "isEligibleForIntroOfferIOS"
const snake_name = "is_eligible_for_intro_offer_ios"
@@ -4982,7 +4982,7 @@ class Query:
const return_type = "Boolean"
const is_array = false
- ## Get StoreKit 2 subscription status details (iOS 15+)
+ ## Get subscription status objects from StoreKit 2 (iOS 15+).
class subscriptionStatusIOSField:
const name = "subscriptionStatusIOS"
const snake_name = "subscription_status_ios"
@@ -5002,7 +5002,7 @@ class Query:
const return_type = "SubscriptionStatusIOS"
const is_array = true
- ## Get current StoreKit 2 entitlements (iOS 15+)
+ ## Get the user's current entitlement for a product, using StoreKit 2 (iOS 15+).
class currentEntitlementIOSField:
const name = "currentEntitlementIOS"
const snake_name = "current_entitlement_ios"
@@ -5022,7 +5022,7 @@ class Query:
const return_type = "PurchaseIOS"
const is_array = false
- ## Get the latest transaction for a product using StoreKit 2
+ ## Get the latest verified transaction for a product, using StoreKit 2.
class latestTransactionIOSField:
const name = "latestTransactionIOS"
const snake_name = "latest_transaction_ios"
@@ -5042,7 +5042,7 @@ class Query:
const return_type = "PurchaseIOS"
const is_array = false
- ## Verify a StoreKit 2 transaction signature
+ ## Check whether a transaction's JWS verification passed (StoreKit 2).
class isTransactionVerifiedIOSField:
const name = "isTransactionVerifiedIOS"
const snake_name = "is_transaction_verified_ios"
@@ -5062,7 +5062,7 @@ class Query:
const return_type = "Boolean"
const is_array = false
- ## Get the transaction JWS (StoreKit 2)
+ ## Return the JWS string for a transaction (StoreKit 2).
class getTransactionJwsIOSField:
const name = "getTransactionJwsIOS"
const snake_name = "get_transaction_jws_ios"
@@ -5082,7 +5082,7 @@ class Query:
const return_type = "String"
const is_array = false
- ## Get base64-encoded receipt data for validation
+ ## Get base64-encoded receipt data (legacy validation).
class getReceiptDataIOSField:
const name = "getReceiptDataIOS"
const snake_name = "get_receipt_data_ios"
@@ -5091,7 +5091,7 @@ class Query:
const return_type = "String"
const is_array = false
- ## Fetch the current app transaction (iOS 16+)
+ ## Fetch the app transaction (iOS 16+).
class getAppTransactionIOSField:
const name = "getAppTransactionIOS"
const snake_name = "get_app_transaction_ios"
@@ -5100,7 +5100,7 @@ class Query:
const return_type = "AppTransaction"
const is_array = false
- ## Get the full StoreKit 2 transaction history as PurchaseIOS values.
+ ## List every StoreKit transaction (finished + unfinished) for the current user.
class getAllTransactionsIOSField:
const name = "getAllTransactionsIOS"
const snake_name = "get_all_transactions_ios"
@@ -5109,7 +5109,7 @@ class Query:
const return_type = "PurchaseIOS"
const is_array = true
- ## Validate a receipt for a specific product
+ ## Deprecated. Legacy App Store receipt validation — use verifyPurchase instead.
class validateReceiptIOSField:
const name = "validateReceiptIOS"
const snake_name = "validate_receipt_ios"
@@ -5143,7 +5143,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Establish the platform billing connection
+ ## Initialize the store connection. Call before any IAP API.
class initConnectionField:
const name = "initConnection"
const snake_name = "init_connection"
@@ -5163,7 +5163,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Close the platform billing connection
+ ## Close the store connection and release resources.
class endConnectionField:
const name = "endConnection"
const snake_name = "end_connection"
@@ -5172,7 +5172,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Initiate a purchase flow; rely on events for final state
+ ## Initiate a purchase or subscription flow; rely on events for final state.
class requestPurchaseField:
const name = "requestPurchase"
const snake_name = "request_purchase"
@@ -5192,7 +5192,7 @@ class Mutation:
const return_type = "RequestPurchaseResult"
const is_array = false
- ## Finish a transaction after validating receipts
+ ## Complete a transaction after server-side verification. Required on Android within 3 days.
class finishTransactionField:
const name = "finishTransaction"
const snake_name = "finish_transaction"
@@ -5216,7 +5216,7 @@ class Mutation:
const return_type = "VoidResult"
const is_array = false
- ## Restore completed purchases across platforms
+ ## Restore non-consumable and active subscription purchases.
class restorePurchasesField:
const name = "restorePurchases"
const snake_name = "restore_purchases"
@@ -5225,7 +5225,7 @@ class Mutation:
const return_type = "VoidResult"
const is_array = false
- ## Open the native subscription management surface
+ ## Open the platform's subscription management UI.
class deepLinkToSubscriptionsField:
const name = "deepLinkToSubscriptions"
const snake_name = "deep_link_to_subscriptions"
@@ -5245,7 +5245,7 @@ class Mutation:
const return_type = "VoidResult"
const is_array = false
- ## Validate purchase receipts with the configured providers
+ ## Deprecated. Validate purchase receipts with the configured providers — use verifyPurchase instead.
class validateReceiptField:
const name = "validateReceipt"
const snake_name = "validate_receipt"
@@ -5265,7 +5265,7 @@ class Mutation:
const return_type = "VerifyPurchaseResult"
const is_array = false
- ## Verify purchases with the configured providers
+ ## Verify a purchase against your own backend (returns isValid + raw store metadata).
class verifyPurchaseField:
const name = "verifyPurchase"
const snake_name = "verify_purchase"
@@ -5285,7 +5285,7 @@ class Mutation:
const return_type = "VerifyPurchaseResult"
const is_array = false
- ## Verify purchases with a specific provider (e.g., IAPKit)
+ ## Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
class verifyPurchaseWithProviderField:
const name = "verifyPurchaseWithProvider"
const snake_name = "verify_purchase_with_provider"
@@ -5305,7 +5305,7 @@ class Mutation:
const return_type = "VerifyPurchaseWithProviderResult"
const is_array = false
- ## Clear pending transactions from the StoreKit payment queue
+ ## Clear pending transactions in the queue (sandbox helper).
class clearTransactionIOSField:
const name = "clearTransactionIOS"
const snake_name = "clear_transaction_ios"
@@ -5314,7 +5314,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Purchase the promoted product surfaced by the App Store.
+ ## Buy the currently promoted product.
class requestPurchaseOnPromotedProductIOSField:
const name = "requestPurchaseOnPromotedProductIOS"
const snake_name = "request_purchase_on_promoted_product_ios"
@@ -5323,7 +5323,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Open subscription management UI and return changed purchases (iOS 15+)
+ ## Present the manage-subscriptions sheet and return changed purchases (iOS 15+).
class showManageSubscriptionsIOSField:
const name = "showManageSubscriptionsIOS"
const snake_name = "show_manage_subscriptions_ios"
@@ -5332,7 +5332,7 @@ class Mutation:
const return_type = "PurchaseIOS"
const is_array = true
- ## Initiate a refund request for a product (iOS 15+)
+ ## Present the refund request sheet (iOS 15+). See also Features → Refund.
class beginRefundRequestIOSField:
const name = "beginRefundRequestIOS"
const snake_name = "begin_refund_request_ios"
@@ -5352,7 +5352,7 @@ class Mutation:
const return_type = "String"
const is_array = false
- ## Force a StoreKit sync for transactions (iOS 15+)
+ ## Force sync transactions with the App Store (iOS 15+).
class syncIOSField:
const name = "syncIOS"
const snake_name = "sync_ios"
@@ -5361,7 +5361,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Present the App Store code redemption sheet
+ ## Show the App Store offer code redemption sheet.
class presentCodeRedemptionSheetIOSField:
const name = "presentCodeRedemptionSheetIOS"
const snake_name = "present_code_redemption_sheet_ios"
@@ -5370,7 +5370,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Present external purchase notice sheet (iOS 17.4+).
+ ## Present the external purchase notice sheet (iOS 17.4+).
class presentExternalPurchaseNoticeSheetIOSField:
const name = "presentExternalPurchaseNoticeSheetIOS"
const snake_name = "present_external_purchase_notice_sheet_ios"
@@ -5379,7 +5379,7 @@ class Mutation:
const return_type = "ExternalPurchaseNoticeResultIOS"
const is_array = false
- ## Present external purchase custom link with StoreKit UI
+ ## Present an external purchase link, StoreKit External (iOS 16+).
class presentExternalPurchaseLinkIOSField:
const name = "presentExternalPurchaseLinkIOS"
const snake_name = "present_external_purchase_link_ios"
@@ -5399,7 +5399,7 @@ class Mutation:
const return_type = "ExternalPurchaseLinkResultIOS"
const is_array = false
- ## Show ExternalPurchaseCustomLink notice sheet (iOS 18.1+).
+ ## Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
class showExternalPurchaseCustomLinkNoticeIOSField:
const name = "showExternalPurchaseCustomLinkNoticeIOS"
const snake_name = "show_external_purchase_custom_link_notice_ios"
@@ -5427,7 +5427,7 @@ class Mutation:
const return_type = "ExternalPurchaseCustomLinkNoticeResultIOS"
const is_array = false
- ## Acknowledge a non-consumable purchase or subscription
+ ## Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
class acknowledgePurchaseAndroidField:
const name = "acknowledgePurchaseAndroid"
const snake_name = "acknowledge_purchase_android"
@@ -5447,7 +5447,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Consume a purchase token so it can be repurchased
+ ## Consume a consumable purchase so it can be re-bought.
class consumePurchaseAndroidField:
const name = "consumePurchaseAndroid"
const snake_name = "consume_purchase_android"
@@ -5467,7 +5467,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Check if alternative billing is available for this user/device
+ ## Check whether alternative billing is available for the user. Step 1 of the alternative billing flow.
class checkAlternativeBillingAvailabilityAndroidField:
const name = "checkAlternativeBillingAvailabilityAndroid"
const snake_name = "check_alternative_billing_availability_android"
@@ -5476,7 +5476,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Show alternative billing information dialog to user
+ ## Display Google's alternative billing information dialog. Step 2 of the alternative billing flow.
class showAlternativeBillingDialogAndroidField:
const name = "showAlternativeBillingDialogAndroid"
const snake_name = "show_alternative_billing_dialog_android"
@@ -5485,7 +5485,7 @@ class Mutation:
const return_type = "Boolean"
const is_array = false
- ## Create external transaction token for Google Play reporting
+ ## Create a reporting token for an alternative billing flow. Step 3 of the alternative billing flow.
class createAlternativeBillingTokenAndroidField:
const name = "createAlternativeBillingTokenAndroid"
const snake_name = "create_alternative_billing_token_android"
@@ -5494,7 +5494,7 @@ class Mutation:
const return_type = "String"
const is_array = false
- ## Check if a billing program is available for the current user
+ ## Check whether a billing program (e.g., External Payments) is available for the current user.
class isBillingProgramAvailableAndroidField:
const name = "isBillingProgramAvailableAndroid"
const snake_name = "is_billing_program_available_android"
@@ -5521,7 +5521,7 @@ class Mutation:
const return_type = "BillingProgramAvailabilityResultAndroid"
const is_array = false
- ## Create reporting details for a billing program
+ ## Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+).
class createBillingProgramReportingDetailsAndroidField:
const name = "createBillingProgramReportingDetailsAndroid"
const snake_name = "create_billing_program_reporting_details_android"
@@ -5548,7 +5548,7 @@ class Mutation:
const return_type = "BillingProgramReportingDetailsAndroid"
const is_array = false
- ## Launch external link flow for external billing programs
+ ## Launch an external content/offer link from inside the Billing Programs flow (Play Billing 8.2.0+).
class launchExternalLinkAndroidField:
const name = "launchExternalLinkAndroid"
const snake_name = "launch_external_link_android"
@@ -5576,7 +5576,7 @@ class Mutation:
# Query API helpers
-## Retrieve products or subscriptions from the store
+## Fetch products or subscriptions from the store.
static func fetch_products_args(params: ProductRequest) -> Dictionary:
var args = {}
if params != null:
@@ -5586,7 +5586,7 @@ static func fetch_products_args(params: ProductRequest) -> Dictionary:
args["params"] = params
return args
-## Get all available purchases for the current user
+## List active purchases for the current user.
static func get_available_purchases_args(options: PurchaseOptions) -> Dictionary:
var args = {}
if options != null:
@@ -5596,97 +5596,97 @@ static func get_available_purchases_args(options: PurchaseOptions) -> Dictionary
args["options"] = options
return args
-## Get active subscriptions (filters by subscriptionIds when provided)
+## Get details of all currently active subscriptions (filters by subscriptionIds when provided).
static func get_active_subscriptions_args(subscription_ids: Array[String]) -> Dictionary:
var args = {}
args["subscriptionIds"] = subscription_ids
return args
-## Check whether the user has active subscriptions
+## Check whether the user has any active subscription.
static func has_active_subscriptions_args(subscription_ids: Array[String]) -> Dictionary:
var args = {}
args["subscriptionIds"] = subscription_ids
return args
-## Get the current storefront country code
+## Return the user's storefront country code.
static func get_storefront_args() -> Dictionary:
return {}
-## Get the current App Store storefront country code
+## Deprecated. Get the current App Store storefront country code — use cross-platform getStorefront instead.
static func get_storefront_ios_args() -> Dictionary:
return {}
-## Get the currently promoted product (iOS 11+)
+## Read the App Store-promoted product, if any (iOS 11+).
static func get_promoted_product_ios_args() -> Dictionary:
return {}
-## Check if external purchase notice sheet can be presented (iOS 17.4+)
+## Check eligibility for the external purchase notice sheet (iOS 17.4+).
static func can_present_external_purchase_notice_ios_args() -> Dictionary:
return {}
-## Check if app is eligible for ExternalPurchaseCustomLink API (iOS 18.1+).
+## Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
static func is_eligible_for_external_purchase_custom_link_ios_args() -> Dictionary:
return {}
-## Get external purchase token for reporting to Apple (iOS 18.1+).
+## Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
static func get_external_purchase_custom_link_token_ios_args(token_type: ExternalPurchaseCustomLinkTokenTypeIOS) -> Dictionary:
var args = {}
args["tokenType"] = token_type
return args
-## Retrieve all pending transactions in the StoreKit queue
+## List unfinished StoreKit transactions in the queue.
static func get_pending_transactions_ios_args() -> Dictionary:
return {}
-## Check introductory offer eligibility for a subscription group
+## Check intro-offer eligibility for a subscription group.
static func is_eligible_for_intro_offer_ios_args(group_id: String) -> Dictionary:
var args = {}
args["groupID"] = group_id
return args
-## Get StoreKit 2 subscription status details (iOS 15+)
+## Get subscription status objects from StoreKit 2 (iOS 15+).
static func subscription_status_ios_args(sku: String) -> Dictionary:
var args = {}
args["sku"] = sku
return args
-## Get current StoreKit 2 entitlements (iOS 15+)
+## Get the user's current entitlement for a product, using StoreKit 2 (iOS 15+).
static func current_entitlement_ios_args(sku: String) -> Dictionary:
var args = {}
args["sku"] = sku
return args
-## Get the latest transaction for a product using StoreKit 2
+## Get the latest verified transaction for a product, using StoreKit 2.
static func latest_transaction_ios_args(sku: String) -> Dictionary:
var args = {}
args["sku"] = sku
return args
-## Verify a StoreKit 2 transaction signature
+## Check whether a transaction's JWS verification passed (StoreKit 2).
static func is_transaction_verified_ios_args(sku: String) -> Dictionary:
var args = {}
args["sku"] = sku
return args
-## Get the transaction JWS (StoreKit 2)
+## Return the JWS string for a transaction (StoreKit 2).
static func get_transaction_jws_ios_args(sku: String) -> Dictionary:
var args = {}
args["sku"] = sku
return args
-## Get base64-encoded receipt data for validation
+## Get base64-encoded receipt data (legacy validation).
static func get_receipt_data_ios_args() -> Dictionary:
return {}
-## Fetch the current app transaction (iOS 16+)
+## Fetch the app transaction (iOS 16+).
static func get_app_transaction_ios_args() -> Dictionary:
return {}
-## Get the full StoreKit 2 transaction history as PurchaseIOS values.
+## List every StoreKit transaction (finished + unfinished) for the current user.
static func get_all_transactions_ios_args() -> Dictionary:
return {}
-## Validate a receipt for a specific product
+## Deprecated. Legacy App Store receipt validation — use verifyPurchase instead.
static func validate_receipt_ios_args(options: VerifyPurchaseProps) -> Dictionary:
var args = {}
if options != null:
@@ -5698,7 +5698,7 @@ static func validate_receipt_ios_args(options: VerifyPurchaseProps) -> Dictionar
# Mutation API helpers
-## Establish the platform billing connection
+## Initialize the store connection. Call before any IAP API.
static func init_connection_args(config: InitConnectionConfig) -> Dictionary:
var args = {}
if config != null:
@@ -5708,11 +5708,11 @@ static func init_connection_args(config: InitConnectionConfig) -> Dictionary:
args["config"] = config
return args
-## Close the platform billing connection
+## Close the store connection and release resources.
static func end_connection_args() -> Dictionary:
return {}
-## Initiate a purchase flow; rely on events for final state
+## Initiate a purchase or subscription flow; rely on events for final state.
static func request_purchase_args(params: RequestPurchaseProps) -> Dictionary:
var args = {}
if params != null:
@@ -5722,7 +5722,7 @@ static func request_purchase_args(params: RequestPurchaseProps) -> Dictionary:
args["params"] = params
return args
-## Finish a transaction after validating receipts
+## Complete a transaction after server-side verification. Required on Android within 3 days.
static func finish_transaction_args(purchase: PurchaseInput, is_consumable: bool) -> Dictionary:
var args = {}
if purchase != null:
@@ -5733,11 +5733,11 @@ static func finish_transaction_args(purchase: PurchaseInput, is_consumable: bool
args["isConsumable"] = is_consumable
return args
-## Restore completed purchases across platforms
+## Restore non-consumable and active subscription purchases.
static func restore_purchases_args() -> Dictionary:
return {}
-## Open the native subscription management surface
+## Open the platform's subscription management UI.
static func deep_link_to_subscriptions_args(options: DeepLinkOptions) -> Dictionary:
var args = {}
if options != null:
@@ -5747,7 +5747,7 @@ static func deep_link_to_subscriptions_args(options: DeepLinkOptions) -> Diction
args["options"] = options
return args
-## Validate purchase receipts with the configured providers
+## Deprecated. Validate purchase receipts with the configured providers — use verifyPurchase instead.
static func validate_receipt_args(options: VerifyPurchaseProps) -> Dictionary:
var args = {}
if options != null:
@@ -5757,7 +5757,7 @@ static func validate_receipt_args(options: VerifyPurchaseProps) -> Dictionary:
args["options"] = options
return args
-## Verify purchases with the configured providers
+## Verify a purchase against your own backend (returns isValid + raw store metadata).
static func verify_purchase_args(options: VerifyPurchaseProps) -> Dictionary:
var args = {}
if options != null:
@@ -5767,7 +5767,7 @@ static func verify_purchase_args(options: VerifyPurchaseProps) -> Dictionary:
args["options"] = options
return args
-## Verify purchases with a specific provider (e.g., IAPKit)
+## Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
static func verify_purchase_with_provider_args(options: VerifyPurchaseWithProviderProps) -> Dictionary:
var args = {}
if options != null:
@@ -5777,85 +5777,85 @@ static func verify_purchase_with_provider_args(options: VerifyPurchaseWithProvid
args["options"] = options
return args
-## Clear pending transactions from the StoreKit payment queue
+## Clear pending transactions in the queue (sandbox helper).
static func clear_transaction_ios_args() -> Dictionary:
return {}
-## Purchase the promoted product surfaced by the App Store.
+## Buy the currently promoted product.
static func request_purchase_on_promoted_product_ios_args() -> Dictionary:
return {}
-## Open subscription management UI and return changed purchases (iOS 15+)
+## Present the manage-subscriptions sheet and return changed purchases (iOS 15+).
static func show_manage_subscriptions_ios_args() -> Dictionary:
return {}
-## Initiate a refund request for a product (iOS 15+)
+## Present the refund request sheet (iOS 15+). See also Features → Refund.
static func begin_refund_request_ios_args(sku: String) -> Dictionary:
var args = {}
args["sku"] = sku
return args
-## Force a StoreKit sync for transactions (iOS 15+)
+## Force sync transactions with the App Store (iOS 15+).
static func sync_ios_args() -> Dictionary:
return {}
-## Present the App Store code redemption sheet
+## Show the App Store offer code redemption sheet.
static func present_code_redemption_sheet_ios_args() -> Dictionary:
return {}
-## Present external purchase notice sheet (iOS 17.4+).
+## Present the external purchase notice sheet (iOS 17.4+).
static func present_external_purchase_notice_sheet_ios_args() -> Dictionary:
return {}
-## Present external purchase custom link with StoreKit UI
+## Present an external purchase link, StoreKit External (iOS 16+).
static func present_external_purchase_link_ios_args(url: String) -> Dictionary:
var args = {}
args["url"] = url
return args
-## Show ExternalPurchaseCustomLink notice sheet (iOS 18.1+).
+## Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
static func show_external_purchase_custom_link_notice_ios_args(notice_type: ExternalPurchaseCustomLinkNoticeTypeIOS) -> Dictionary:
var args = {}
args["noticeType"] = notice_type
return args
-## Acknowledge a non-consumable purchase or subscription
+## Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
static func acknowledge_purchase_android_args(purchase_token: String) -> Dictionary:
var args = {}
args["purchaseToken"] = purchase_token
return args
-## Consume a purchase token so it can be repurchased
+## Consume a consumable purchase so it can be re-bought.
static func consume_purchase_android_args(purchase_token: String) -> Dictionary:
var args = {}
args["purchaseToken"] = purchase_token
return args
-## Check if alternative billing is available for this user/device
+## Check whether alternative billing is available for the user. Step 1 of the alternative billing flow.
static func check_alternative_billing_availability_android_args() -> Dictionary:
return {}
-## Show alternative billing information dialog to user
+## Display Google's alternative billing information dialog. Step 2 of the alternative billing flow.
static func show_alternative_billing_dialog_android_args() -> Dictionary:
return {}
-## Create external transaction token for Google Play reporting
+## Create a reporting token for an alternative billing flow. Step 3 of the alternative billing flow.
static func create_alternative_billing_token_android_args() -> Dictionary:
return {}
-## Check if a billing program is available for the current user
+## Check whether a billing program (e.g., External Payments) is available for the current user.
static func is_billing_program_available_android_args(program: BillingProgramAndroid) -> Dictionary:
var args = {}
args["program"] = program
return args
-## Create reporting details for a billing program
+## Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+).
static func create_billing_program_reporting_details_android_args(program: BillingProgramAndroid) -> Dictionary:
var args = {}
args["program"] = program
return args
-## Launch external link flow for external billing programs
+## Launch an external content/offer link from inside the Billing Programs flow (Play Billing 8.2.0+).
static func launch_external_link_android_args(params: LaunchExternalLinkParamsAndroid) -> Dictionary:
var args = {}
if params != null:
diff --git a/packages/gql/src/generated/types.ts b/packages/gql/src/generated/types.ts
index 4afb30b7..f7d95686 100644
--- a/packages/gql/src/generated/types.ts
+++ b/packages/gql/src/generated/types.ts
@@ -585,118 +585,170 @@ export interface LimitedQuantityInfoAndroid {
}
export interface Mutation {
- /** Acknowledge a non-consumable purchase or subscription */
+ /**
+ * Acknowledge a non-consumable purchase. Required within 3 days or Google auto-refunds.
+ * See: https://www.openiap.dev/docs/apis/android/acknowledge-purchase-android
+ */
acknowledgePurchaseAndroid: Promise;
- /** Initiate a refund request for a product (iOS 15+) */
+ /**
+ * Present the refund request sheet (iOS 15+). See also Features → Refund.
+ * See: https://www.openiap.dev/docs/apis/ios/begin-refund-request-ios
+ */
beginRefundRequestIOS?: Promise<(string | null)>;
/**
- * Check if alternative billing is available for this user/device
- * Step 1 of alternative billing flow
+ * Check whether alternative billing is available for the user. Step 1 of the alternative billing flow.
*
- * Returns true if available, false otherwise
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns true if available, false otherwise.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/check-alternative-billing-availability-android
*/
checkAlternativeBillingAvailabilityAndroid: Promise;
- /** Clear pending transactions from the StoreKit payment queue */
+ /**
+ * Clear pending transactions in the queue (sandbox helper).
+ * See: https://www.openiap.dev/docs/apis/ios/clear-transaction-ios
+ */
clearTransactionIOS: Promise;
- /** Consume a purchase token so it can be repurchased */
+ /**
+ * Consume a consumable purchase so it can be re-bought.
+ * See: https://www.openiap.dev/docs/apis/android/consume-purchase-android
+ */
consumePurchaseAndroid: Promise;
/**
- * Create external transaction token for Google Play reporting
- * Step 3 of alternative billing flow
- * Must be called AFTER successful payment in your payment system
- * Token must be reported to Google Play backend within 24 hours
+ * Create a reporting token for an alternative billing flow. Step 3 of the alternative billing flow.
+ * Must be called AFTER successful payment in your payment system.
+ * Token must be reported to Google Play backend within 24 hours.
*
- * Returns token string, or null if creation failed
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns token string, or null if creation failed.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/create-alternative-billing-token-android
*/
createAlternativeBillingTokenAndroid?: Promise<(string | null)>;
/**
- * Create reporting details for a billing program
- * Replaces the deprecated createExternalOfferReportingDetailsAsync API
+ * Create the reporting payload Google requires after a Developer-Provided Billing transaction (Play Billing 8.3.0+).
+ * Replaces the deprecated createExternalOfferReportingDetailsAsync API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Returns external transaction token needed for reporting external transactions
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns external transaction token needed for reporting external transactions.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/create-billing-program-reporting-details-android
*/
createBillingProgramReportingDetailsAndroid: Promise;
- /** Open the native subscription management surface */
+ /**
+ * Open the platform's subscription management UI.
+ * See: https://www.openiap.dev/docs/apis/deep-link-to-subscriptions
+ */
deepLinkToSubscriptions: Promise;
- /** Close the platform billing connection */
+ /**
+ * Close the store connection and release resources.
+ * See: https://www.openiap.dev/docs/apis/end-connection
+ */
endConnection: Promise;
- /** Finish a transaction after validating receipts */
+ /**
+ * Complete a transaction after server-side verification. Required on Android within 3 days.
+ * See: https://www.openiap.dev/docs/apis/finish-transaction
+ */
finishTransaction: Promise;
- /** Establish the platform billing connection */
+ /**
+ * Initialize the store connection. Call before any IAP API.
+ * See: https://www.openiap.dev/docs/apis/init-connection
+ */
initConnection: Promise;
/**
- * Check if a billing program is available for the current user
- * Replaces the deprecated isExternalOfferAvailableAsync API
+ * Check whether a billing program (e.g., External Payments) is available for the current user.
+ * Replaces the deprecated isExternalOfferAvailableAsync API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Returns availability result with isAvailable flag
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Available in Google Play Billing Library 8.2.0+.
+ * Returns availability result with isAvailable flag.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/is-billing-program-available-android
*/
isBillingProgramAvailableAndroid: Promise;
/**
- * Launch external link flow for external billing programs
- * Replaces the deprecated showExternalOfferInformationDialog API
+ * Launch an external content/offer link from inside the Billing Programs flow (Play Billing 8.2.0+).
+ * Replaces the deprecated showExternalOfferInformationDialog API.
*
- * Available in Google Play Billing Library 8.2.0+
- * Shows Play Store dialog and optionally launches external URL
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Shows Play Store dialog and optionally launches external URL.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/launch-external-link-android
*/
launchExternalLinkAndroid: Promise;
- /** Present the App Store code redemption sheet */
+ /**
+ * Show the App Store offer code redemption sheet.
+ * See: https://www.openiap.dev/docs/apis/ios/present-code-redemption-sheet-ios
+ */
presentCodeRedemptionSheetIOS: Promise;
- /** Present external purchase custom link with StoreKit UI */
+ /**
+ * Present an external purchase link, StoreKit External (iOS 16+).
+ * See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-link-ios
+ */
presentExternalPurchaseLinkIOS: Promise;
/**
- * Present external purchase notice sheet (iOS 17.4+).
- * Uses ExternalPurchase.presentNoticeSheet() which returns a token when user continues.
+ * Present the external purchase notice sheet (iOS 17.4+).
+ * Uses ExternalPurchase.presentNoticeSheet() which returns a token when the user continues.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchase/presentnoticesheet()
+ * See: https://www.openiap.dev/docs/apis/ios/present-external-purchase-notice-sheet-ios
*/
presentExternalPurchaseNoticeSheetIOS: Promise;
- /** Initiate a purchase flow; rely on events for final state */
+ /**
+ * Initiate a purchase or subscription flow; rely on events for final state.
+ * See: https://www.openiap.dev/docs/apis/request-purchase
+ */
requestPurchase?: Promise<(Purchase | Purchase[] | null)>;
/**
- * Purchase the promoted product surfaced by the App Store.
+ * Buy the currently promoted product.
*
* @deprecated Use promotedProductListenerIOS to receive the productId,
* then call requestPurchase with that SKU instead. In StoreKit 2,
* promoted products can be purchased directly via the standard purchase flow.
+ * See: https://www.openiap.dev/docs/apis/ios/request-purchase-on-promoted-product-ios
* @deprecated Use promotedProductListenerIOS + requestPurchase instead
*/
requestPurchaseOnPromotedProductIOS: Promise;
- /** Restore completed purchases across platforms */
+ /**
+ * Restore non-consumable and active subscription purchases.
+ * See: https://www.openiap.dev/docs/apis/restore-purchases
+ */
restorePurchases: Promise;
/**
- * Show alternative billing information dialog to user
- * Step 2 of alternative billing flow
- * Must be called BEFORE processing payment in your payment system
+ * Display Google's alternative billing information dialog. Step 2 of the alternative billing flow.
+ * Must be called BEFORE processing payment in your payment system.
*
- * Returns true if user accepted, false if user canceled
- * Throws OpenIapError.NotPrepared if billing client not ready
+ * Returns true if user accepted, false if user canceled.
+ * Throws OpenIapError.NotPrepared if billing client not ready.
+ * See: https://www.openiap.dev/docs/apis/android/show-alternative-billing-dialog-android
*/
showAlternativeBillingDialogAndroid: Promise;
/**
- * Show ExternalPurchaseCustomLink notice sheet (iOS 18.1+).
- * Displays the system disclosure notice sheet for custom external purchase links.
+ * Present the disclosure sheet required before linking out via ExternalPurchaseCustomLink (iOS 18.1+).
* Call this after a deliberate customer interaction before linking out to external purchases.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/shownotice(type:)
+ * See: https://www.openiap.dev/docs/apis/ios/show-external-purchase-custom-link-notice-ios
*/
showExternalPurchaseCustomLinkNoticeIOS: Promise;
- /** Open subscription management UI and return changed purchases (iOS 15+) */
+ /**
+ * Present the manage-subscriptions sheet and return changed purchases (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/show-manage-subscriptions-ios
+ */
showManageSubscriptionsIOS: Promise;
- /** Force a StoreKit sync for transactions (iOS 15+) */
+ /**
+ * Force sync transactions with the App Store (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/sync-ios
+ */
syncIOS: Promise;
/**
- * Validate purchase receipts with the configured providers
+ * Deprecated. Validate purchase receipts with the configured providers — use verifyPurchase instead.
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase
* @deprecated Use verifyPurchase
*/
validateReceipt: Promise;
- /** Verify purchases with the configured providers */
+ /**
+ * Verify a purchase against your own backend (returns isValid + raw store metadata).
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase
+ */
verifyPurchase: Promise;
- /** Verify purchases with a specific provider (e.g., IAPKit) */
+ /**
+ * Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+ * See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
+ */
verifyPurchaseWithProvider: Promise;
}
@@ -1234,66 +1286,117 @@ export type PurchaseVerificationProvider = 'iapkit';
export interface Query {
/**
- * Check if external purchase notice sheet can be presented (iOS 17.4+)
- * Uses ExternalPurchase.canPresent
+ * Check eligibility for the external purchase notice sheet (iOS 17.4+).
+ * Uses ExternalPurchase.canPresent.
+ * See: https://www.openiap.dev/docs/apis/ios/can-present-external-purchase-notice-ios
*/
canPresentExternalPurchaseNoticeIOS: Promise;
- /** Get current StoreKit 2 entitlements (iOS 15+) */
+ /**
+ * Get the user's current entitlement for a product, using StoreKit 2 (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/current-entitlement-ios
+ */
currentEntitlementIOS?: Promise<(PurchaseIOS | null)>;
- /** Retrieve products or subscriptions from the store */
+ /**
+ * Fetch products or subscriptions from the store.
+ * See: https://www.openiap.dev/docs/apis/fetch-products
+ */
fetchProducts: Promise<(ProductOrSubscription[] | Product[] | ProductSubscription[] | null)>;
- /** Get active subscriptions (filters by subscriptionIds when provided) */
+ /**
+ * Get details of all currently active subscriptions (filters by subscriptionIds when provided).
+ * See: https://www.openiap.dev/docs/apis/get-active-subscriptions
+ */
getActiveSubscriptions: Promise;
/**
- * Get the full StoreKit 2 transaction history as PurchaseIOS values.
+ * List every StoreKit transaction (finished + unfinished) for the current user.
* Requires the SK2ConsumableTransactionHistory Info.plist key in the host app
* for finished consumables to be included (iOS 18+).
* Unlike getAvailablePurchases, always returns the iOS-specific PurchaseIOS shape.
+ * See: https://www.openiap.dev/docs/apis/ios/get-all-transactions-ios
*/
getAllTransactionsIOS: Promise;
- /** Fetch the current app transaction (iOS 16+) */
+ /**
+ * Fetch the app transaction (iOS 16+).
+ * See: https://www.openiap.dev/docs/apis/ios/get-app-transaction-ios
+ */
getAppTransactionIOS?: Promise<(AppTransaction | null)>;
- /** Get all available purchases for the current user */
+ /**
+ * List active purchases for the current user.
+ * See: https://www.openiap.dev/docs/apis/get-available-purchases
+ */
getAvailablePurchases: Promise;
/**
- * Get external purchase token for reporting to Apple (iOS 18.1+).
- * Use this token with Apple's External Purchase Server API to report transactions.
+ * Fetch a token for Apple's External Purchase Server reporting API (iOS 18.1+).
+ * Use this token to report transactions made through ExternalPurchaseCustomLink.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/token(for:)
+ * See: https://www.openiap.dev/docs/apis/ios/get-external-purchase-custom-link-token-ios
*/
getExternalPurchaseCustomLinkTokenIOS: Promise;
- /** Retrieve all pending transactions in the StoreKit queue */
+ /**
+ * List unfinished StoreKit transactions in the queue.
+ * See: https://www.openiap.dev/docs/apis/ios/get-pending-transactions-ios
+ */
getPendingTransactionsIOS: Promise;
- /** Get the currently promoted product (iOS 11+) */
+ /**
+ * Read the App Store-promoted product, if any (iOS 11+).
+ * See: https://www.openiap.dev/docs/apis/ios/get-promoted-product-ios
+ */
getPromotedProductIOS?: Promise<(ProductIOS | null)>;
- /** Get base64-encoded receipt data for validation */
+ /**
+ * Get base64-encoded receipt data (legacy validation).
+ * See: https://www.openiap.dev/docs/apis/ios/get-receipt-data-ios
+ */
getReceiptDataIOS?: Promise<(string | null)>;
- /** Get the current storefront country code */
+ /**
+ * Return the user's storefront country code.
+ * See: https://www.openiap.dev/docs/apis/get-storefront
+ */
getStorefront: Promise;
/**
- * Get the current App Store storefront country code
+ * Deprecated. Get the current App Store storefront country code — use cross-platform getStorefront instead.
+ * See: https://www.openiap.dev/docs/apis/ios/get-storefront-ios
* @deprecated Use getStorefront
*/
getStorefrontIOS: Promise;
- /** Get the transaction JWS (StoreKit 2) */
+ /**
+ * Return the JWS string for a transaction (StoreKit 2).
+ * See: https://www.openiap.dev/docs/apis/ios/get-transaction-jws-ios
+ */
getTransactionJwsIOS?: Promise<(string | null)>;
- /** Check whether the user has active subscriptions */
+ /**
+ * Check whether the user has any active subscription.
+ * See: https://www.openiap.dev/docs/apis/has-active-subscriptions
+ */
hasActiveSubscriptions: Promise;
/**
- * Check if app is eligible for ExternalPurchaseCustomLink API (iOS 18.1+).
+ * Check eligibility for the custom-link variant of external purchase (iOS 18.1+).
* Returns true if the app can use custom external purchase links.
* Reference: https://developer.apple.com/documentation/storekit/externalpurchasecustomlink/iseligible
+ * See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios
*/
isEligibleForExternalPurchaseCustomLinkIOS: Promise;
- /** Check introductory offer eligibility for a subscription group */
+ /**
+ * Check intro-offer eligibility for a subscription group.
+ * See: https://www.openiap.dev/docs/apis/ios/is-eligible-for-intro-offer-ios
+ */
isEligibleForIntroOfferIOS: Promise;
- /** Verify a StoreKit 2 transaction signature */
+ /**
+ * Check whether a transaction's JWS verification passed (StoreKit 2).
+ * See: https://www.openiap.dev/docs/apis/ios/is-transaction-verified-ios
+ */
isTransactionVerifiedIOS: Promise;
- /** Get the latest transaction for a product using StoreKit 2 */
+ /**
+ * Get the latest verified transaction for a product, using StoreKit 2.
+ * See: https://www.openiap.dev/docs/apis/ios/latest-transaction-ios
+ */
latestTransactionIOS?: Promise<(PurchaseIOS | null)>;
- /** Get StoreKit 2 subscription status details (iOS 15+) */
+ /**
+ * Get subscription status objects from StoreKit 2 (iOS 15+).
+ * See: https://www.openiap.dev/docs/apis/ios/subscription-status-ios
+ */
subscriptionStatusIOS: Promise;
/**
- * Validate a receipt for a specific product
+ * Deprecated. Legacy App Store receipt validation — use verifyPurchase instead.
+ * See: https://www.openiap.dev/docs/apis/ios/validate-receipt-ios
* @deprecated Use verifyPurchase
*/
validateReceiptIOS: Promise;
From 863eec945cedc604e69614d09ef2664bc6c30787 Mon Sep 17 00:00:00 2001
From: hyochan
Date: Sun, 26 Apr 2026 12:09:11 +0900
Subject: [PATCH 02/26] chore: prettier format on enriched docs pages
CI Format check failed because the API/Type page enrichment paragraphs
were inserted with hand-rolled JSX wrapping that didn't match this
repo's Prettier config. Re-ran `bunx prettier --write` on the 10 flagged
files; result is purely whitespace/wrap.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
.../docs/apis/android/acknowledge-purchase-android.tsx | 9 ++++++---
.../check-alternative-billing-availability-android.tsx | 5 +++--
.../android/is-billing-program-available-android.tsx | 5 ++++-
.../docs/apis/android/launch-external-link-android.tsx | 7 ++++---
.../src/pages/docs/apis/deep-link-to-subscriptions.tsx | 4 ++--
.../docs/src/pages/docs/apis/finish-transaction.tsx | 4 ++--
.../src/pages/docs/apis/get-active-subscriptions.tsx | 5 +++--
.../docs/apis/ios/is-eligible-for-intro-offer-ios.tsx | 5 +++--
.../docs/src/pages/docs/apis/restore-purchases.tsx | 10 +++++-----
.../docs/src/pages/docs/types/subscription-offer.tsx | 4 ++--
10 files changed, 34 insertions(+), 24 deletions(-)
diff --git a/packages/docs/src/pages/docs/apis/android/acknowledge-purchase-android.tsx b/packages/docs/src/pages/docs/apis/android/acknowledge-purchase-android.tsx
index a86bca13..ecfe6a1d 100644
--- a/packages/docs/src/pages/docs/apis/android/acknowledge-purchase-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/acknowledge-purchase-android.tsx
@@ -24,9 +24,12 @@ function AcknowledgePurchaseAndroid() {
days or the purchase will be refunded.
- Wraps BillingClient.acknowledgePurchase(AcknowledgePurchaseParams){' '}
- — required for non-consumables and subscriptions within 3 days, otherwise
- Google auto-refunds. See the{' '}
+ Wraps{' '}
+
+ BillingClient.acknowledgePurchase(AcknowledgePurchaseParams)
+ {' '}
+ — required for non-consumables and subscriptions within 3 days,
+ otherwise Google auto-refunds. See the{' '}
Wraps{' '}
- BillingClient.launchExternalLinkFlow(activity, params) —
- replaces showExternalOfferInformationDialog. Shows the Play
- disclosure dialog and (optionally) launches the URL. Play Billing
+
+ BillingClient.launchExternalLink(activity, params, listener)
+ {' '}
+ — replaces showExternalOfferInformationDialog. Shows the
+ Play disclosure dialog and (optionally) launches the URL. Play Billing
8.2.0+. See the{' '}
- Verify via a managed provider (IAPKit, Apple, Google, Horizon)
- without standing up your own server.
+ Verify via a managed provider without standing up your own
+ server. The PurchaseVerificationProvider enum
+ currently exposes only IAPKit.
diff --git a/packages/docs/src/pages/docs/apis/ios/present-code-redemption-sheet-ios.tsx b/packages/docs/src/pages/docs/apis/ios/present-code-redemption-sheet-ios.tsx
index db13aa29..da9eddf1 100644
--- a/packages/docs/src/pages/docs/apis/ios/present-code-redemption-sheet-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/present-code-redemption-sheet-ios.tsx
@@ -21,11 +21,12 @@ function PresentCodeRedemptionSheetIOS() {
Present the App Store promo code redemption sheet.
- Wraps AppStore.showManageSubscriptions(in:) — presents the
- system manage-subscriptions sheet. iOS 15+. See the{' '}
+ Opens Apple's subscription-management surface for the user. The current
+ iOS implementation forwards to the module's{' '}
+ deepLinkToSubscriptions(nil) path (which calls{' '}
+ AppStore.showManageSubscriptions(in:) when a window scene
+ is available, otherwise falls back to opening the App Store deep link).
+ iOS 15+. See the{' '}
Input to verifyPurchaseWithProvider — pick a managed
- validator (IAPKit, Apple, Google, Horizon). See{' '}
+ validator. The PurchaseVerificationProvider enum
+ currently exposes only IAPKit. See{' '}
request-purchase
*/
diff --git a/packages/gql/src/api.graphql b/packages/gql/src/api.graphql
index b43b7cc8..ee42f6d4 100644
--- a/packages/gql/src/api.graphql
+++ b/packages/gql/src/api.graphql
@@ -88,7 +88,9 @@ extend type Mutation {
# Future
verifyPurchase(options: VerifyPurchaseProps!): VerifyPurchaseResult!
"""
- Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+ Verify via a managed provider without standing up your own server. The
+ PurchaseVerificationProvider enum currently exposes only IAPKit; platform
+ availability may differ by implementation.
See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
"""
# Future
diff --git a/packages/gql/src/generated/Types.kt b/packages/gql/src/generated/Types.kt
index d07a59c8..dfddfd23 100644
--- a/packages/gql/src/generated/Types.kt
+++ b/packages/gql/src/generated/Types.kt
@@ -4991,7 +4991,9 @@ public interface MutationResolver {
*/
suspend fun verifyPurchase(options: VerifyPurchaseProps): VerifyPurchaseResult
/**
- * Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+ * Verify via a managed provider without standing up your own server. The
+ * PurchaseVerificationProvider enum currently exposes only IAPKit; platform
+ * availability may differ by implementation.
* See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
*/
suspend fun verifyPurchaseWithProvider(options: VerifyPurchaseWithProviderProps): VerifyPurchaseWithProviderResult
diff --git a/packages/gql/src/generated/Types.swift b/packages/gql/src/generated/Types.swift
index 4d823837..b3cef1c9 100644
--- a/packages/gql/src/generated/Types.swift
+++ b/packages/gql/src/generated/Types.swift
@@ -2442,7 +2442,9 @@ public protocol MutationResolver {
/// Verify a purchase against your own backend (returns isValid + raw store metadata).
/// See: https://www.openiap.dev/docs/features/validation#verify-purchase
func verifyPurchase(_ options: VerifyPurchaseProps) async throws -> VerifyPurchaseResult
- /// Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+ /// Verify via a managed provider without standing up your own server. The
+ /// PurchaseVerificationProvider enum currently exposes only IAPKit; platform
+ /// availability may differ by implementation.
/// See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
func verifyPurchaseWithProvider(_ options: VerifyPurchaseWithProviderProps) async throws -> VerifyPurchaseWithProviderResult
}
diff --git a/packages/gql/src/generated/types.dart b/packages/gql/src/generated/types.dart
index 696a9148..cd8365d8 100644
--- a/packages/gql/src/generated/types.dart
+++ b/packages/gql/src/generated/types.dart
@@ -4976,7 +4976,9 @@ abstract class MutationResolver {
VerifyPurchaseGoogleOptions? google,
VerifyPurchaseHorizonOptions? horizon,
});
- /// Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+ /// Verify via a managed provider without standing up your own server. The
+ /// PurchaseVerificationProvider enum currently exposes only IAPKit; platform
+ /// availability may differ by implementation.
/// See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
Future verifyPurchaseWithProvider({
RequestVerifyPurchaseWithIapkitProps? iapkit,
diff --git a/packages/gql/src/generated/types.gd b/packages/gql/src/generated/types.gd
index a475be19..d5f7ee68 100644
--- a/packages/gql/src/generated/types.gd
+++ b/packages/gql/src/generated/types.gd
@@ -5285,7 +5285,7 @@ class Mutation:
const return_type = "VerifyPurchaseResult"
const is_array = false
- ## Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+ ## Verify via a managed provider without standing up your own server. The
class verifyPurchaseWithProviderField:
const name = "verifyPurchaseWithProvider"
const snake_name = "verify_purchase_with_provider"
@@ -5767,7 +5767,7 @@ static func verify_purchase_args(options: VerifyPurchaseProps) -> Dictionary:
args["options"] = options
return args
-## Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+## Verify via a managed provider without standing up your own server. The
static func verify_purchase_with_provider_args(options: VerifyPurchaseWithProviderProps) -> Dictionary:
var args = {}
if options != null:
diff --git a/packages/gql/src/generated/types.ts b/packages/gql/src/generated/types.ts
index f7d95686..4651323a 100644
--- a/packages/gql/src/generated/types.ts
+++ b/packages/gql/src/generated/types.ts
@@ -746,7 +746,9 @@ export interface Mutation {
*/
verifyPurchase: Promise;
/**
- * Verify via a managed provider (IAPKit, Apple, Google, Horizon) without standing up your own server.
+ * Verify via a managed provider without standing up your own server. The
+ * PurchaseVerificationProvider enum currently exposes only IAPKit; platform
+ * availability may differ by implementation.
* See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider
*/
verifyPurchaseWithProvider: Promise;
From caf19d208b2320dafcc215984c4570941f16b01c Mon Sep 17 00:00:00 2001
From: hyochan
Date: Sun, 26 Apr 2026 13:21:10 +0900
Subject: [PATCH 04/26] docs: address Copilot follow-up on PR #107
- subscriptionStatusIOS API page (apis/ios/subscription-status-ios.tsx):
the 'Wraps Product.SubscriptionInfo.status' paragraph was still
claiming the wrapper exposes `transaction`, even after the type page
was corrected last round. Updated to say only `renewalInfo` + `state`
are surfaced and to point users at `latestTransactionIOS(sku)` if they
need the underlying transaction.
- useIAP `getAvailablePurchases` JSDoc: the `@example` had a
`const purchases = await getAvailablePurchases()` snippet that
contradicts the `Promise` signature (results land in the
reactive `availablePurchases` array per the hook semantics in
CLAUDE.md). Replaced with a hook-state pattern. Same fix applied
preemptively to the `fetchProducts` example for consistency.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
.../react-native-iap/src/hooks/useIAP.ts | 40 +++++++++++++------
.../docs/apis/ios/subscription-status-ios.tsx | 9 +++--
2 files changed, 34 insertions(+), 15 deletions(-)
diff --git a/libraries/react-native-iap/src/hooks/useIAP.ts b/libraries/react-native-iap/src/hooks/useIAP.ts
index 0afd9e79..87e9e1ca 100644
--- a/libraries/react-native-iap/src/hooks/useIAP.ts
+++ b/libraries/react-native-iap/src/hooks/useIAP.ts
@@ -93,18 +93,28 @@ type UseIap = {
* List the user's unfinished purchases — non-consumables, active subscriptions, and any
* pending transactions not yet finished.
*
- * @param options Optional `PurchaseOptions`. iOS-only flags:
- * `alsoPublishToEventListenerIOS`, `onlyIncludeActiveItemsIOS`.
+ * @param options Optional `PurchaseOptions`.
+ * - iOS: `alsoPublishToEventListenerIOS`, `onlyIncludeActiveItemsIOS`.
+ * - Android: `includeSuspendedAndroid` (include subscriptions in a paused/grace state).
* @returns Promise that resolves when the request is dispatched; results land in the
- * hook's reactive `availablePurchases` state.
+ * hook's reactive `availablePurchases` state — read from there, don't expect a return value.
* @throws When the platform query fails.
*
* @example
* ```ts
- * const purchases = await getAvailablePurchases();
- * for (const p of purchases) {
- * if (await verifyOnServer(p)) await finishTransaction({ purchase: p, isConsumable: false });
- * }
+ * const { availablePurchases, getAvailablePurchases, finishTransaction } = useIAP();
+ *
+ * useEffect(() => {
+ * void getAvailablePurchases();
+ * }, [getAvailablePurchases]);
+ *
+ * useEffect(() => {
+ * for (const p of availablePurchases) {
+ * void verifyOnServer(p).then((ok) => {
+ * if (ok) finishTransaction({ purchase: p, isConsumable: false });
+ * });
+ * }
+ * }, [availablePurchases, finishTransaction]);
* ```
*
* @see {@link https://www.openiap.dev/docs/apis/get-available-purchases}
@@ -116,15 +126,21 @@ type UseIap = {
* @param params `ProductRequest` — `skus` (string[]) and optional `type`
* (`'in-app' | 'subs' | 'all'`, defaults to `'in-app'`).
* @returns Promise that resolves when the request is dispatched; results land in the
- * hook's reactive `products` / `subscriptions` state.
+ * hook's reactive `products` / `subscriptions` state — read from there, don't expect a return value.
* @throws When the store rejects the request (unknown SKU, network, not connected).
*
* @example
* ```ts
- * const products = await fetchProducts({
- * skus: ['com.app.coins_100', 'com.app.premium'],
- * type: 'in-app',
- * });
+ * const { products, fetchProducts } = useIAP();
+ *
+ * useEffect(() => {
+ * void fetchProducts({
+ * skus: ['com.app.coins_100', 'com.app.premium'],
+ * type: 'in-app',
+ * });
+ * }, [fetchProducts]);
+ *
+ * // Render `products` directly from hook state.
* ```
*
* @remarks This is a regular promise-based call. Don't confuse with `request*` APIs
diff --git a/packages/docs/src/pages/docs/apis/ios/subscription-status-ios.tsx b/packages/docs/src/pages/docs/apis/ios/subscription-status-ios.tsx
index f9da5a3e..ef5a0184 100644
--- a/packages/docs/src/pages/docs/apis/ios/subscription-status-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/subscription-status-ios.tsx
@@ -20,9 +20,12 @@ function SubscriptionStatusIOS() {
Get detailed subscription status using StoreKit 2 (iOS 15+).
+ Optional input to{' '}
+
+ getAvailablePurchases
+
+ . PurchaseOptions does not have its own dedicated page — it lives here
+ next to Purchase because every field is platform-
+ specific and changes which subset of purchases the query returns.
+
+
+ All fields are optional; pass null / omit the argument
+ entirely to use defaults. iOS-only fields are ignored on Android (and
+ vice-versa).
+
+
+
+
+
Name
+
Platform
+
Default
+
Summary
+
+
+
+
+
+ alsoPublishToEventListenerIOS
+
+
iOS
+
+ false
+
+
+ When true, every purchase returned by the query is
+ also re-emitted on{' '}
+
+ purchaseUpdatedListener
+ {' '}
+ so existing listeners can process them with the same code path
+ used for live purchases.
+
+
+
+
+ onlyIncludeActiveItemsIOS
+
+
iOS
+
+ false
+
+
+ Switches the query from Transaction.all (full
+ StoreKit 2 history, including refunded / revoked entries) to{' '}
+ Transaction.currentEntitlements, which narrows the
+ result to active non-consumables and live subscriptions.
+
+
+
+
+ includeSuspendedAndroid
+
+
Android
+
+ false
+
+
+ When true, includes subscriptions in a paused or
+ grace-period state in the returned list. Suspended subscriptions
+ should not grant entitlements — see{' '}
+ isSuspendedAndroid on the Purchase fields above.
+
+
+
+
+
);
}
From c2eb94d543e86e0eeb8b8549b7bd37724ab29ebb Mon Sep 17 00:00:00 2001
From: hyochan
Date: Sun, 26 Apr 2026 14:18:34 +0900
Subject: [PATCH 11/26] docs: add Parameters / Returns sections to every API
page
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
User flagged that the API doc pages didn't surface request params and
result values prominently — the inline TS interface inside the
Signature CodeBlock was the only place readers could see them. Added a
dedicated `Parameters` table + `Returns` (+ `Throws` where relevant)
section to every API page so each function's contract is visible above
the Signature/Example blocks.
Coverage:
- 11 cross-platform pages (init/end/fetch/getAvailable/request/finish/
restore/getStorefront/getActive/hasActive/deepLink — validate-receipt
is a Navigate redirect so unchanged).
- 25 iOS pages (sync, getStorefront, clearTransaction, promoted
product/purchase, pending/all transactions, intro-offer eligibility,
subscriptionStatus, currentEntitlement/latestTransaction,
showManageSubscriptions, beginRefundRequest, JWS/verified/receipt
helpers, codeRedemption, appTransaction, all 6 external-purchase
helpers, validateReceiptIOS).
- 9 Android pages (acknowledge, consume, alternative-billing trio,
enable / availability / launch / reporting-details for billing
programs).
Each section is a `
` with Name / Type /
Required / Description columns. Type cells link to the matching
`/docs/types/...` page (e.g. `Purchase` →
`/docs/types/purchase`, `PurchaseOptions` →
`/docs/types/purchase#purchase-options`). Returns are a single `
+ Promise<boolean> — true once the
+ purchase has been acknowledged.
+
+
⚠️ Deprecated in Google Play Billing Library 8.2.0+.{' '}
diff --git a/packages/docs/src/pages/docs/apis/android/check-alternative-billing-availability-android.tsx b/packages/docs/src/pages/docs/apis/android/check-alternative-billing-availability-android.tsx
index 4adecfda..ccd6e3f3 100644
--- a/packages/docs/src/pages/docs/apis/android/check-alternative-billing-availability-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/check-alternative-billing-availability-android.tsx
@@ -1,3 +1,4 @@
+import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
@@ -37,6 +38,19 @@ function CheckAlternativeBillingAvailabilityAndroid() {
.
+
+ Parameters
+
+
None.
+
+
+ Returns
+
+
+ Promise<boolean> — Whether alternative billing is
+ available for this user/device (step 1 of 3).
+
+
Signature
{{
diff --git a/packages/docs/src/pages/docs/apis/android/consume-purchase-android.tsx b/packages/docs/src/pages/docs/apis/android/consume-purchase-android.tsx
index 5bf77ec2..d813a896 100644
--- a/packages/docs/src/pages/docs/apis/android/consume-purchase-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/consume-purchase-android.tsx
@@ -1,4 +1,5 @@
import { Link } from 'react-router-dom';
+import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
@@ -37,6 +38,40 @@ function ConsumePurchaseAndroid() {
.
+
+ Parameters
+
+
+
+
+
Name
+
Type
+
Required
+
Description
+
+
+
+
+
+ purchaseToken
+
+
+ string
+
+
Yes
+
Purchase token from the Play Billing transaction.
+
+
+
+
+
+ Returns
+
+
+ Promise<boolean> — true once the
+ purchase has been consumed.
+
+
⚠️ Deprecated in Google Play Billing Library 8.2.0+.{' '}
diff --git a/packages/docs/src/pages/docs/apis/android/create-alternative-billing-token-android.tsx b/packages/docs/src/pages/docs/apis/android/create-alternative-billing-token-android.tsx
index 08f9c031..3d762d9a 100644
--- a/packages/docs/src/pages/docs/apis/android/create-alternative-billing-token-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/create-alternative-billing-token-android.tsx
@@ -1,3 +1,4 @@
+import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
@@ -39,6 +40,20 @@ function CreateAlternativeBillingTokenAndroid() {
.
+
+ Parameters
+
+
None.
+
+
+ Returns
+
+
+ Promise<string | null> — Reporting token to send to
+ Google within 24h, or null if creation failed (step 3 of
+ 3).
+
+
Signature
{{
diff --git a/packages/docs/src/pages/docs/apis/android/create-billing-program-reporting-details-android.tsx b/packages/docs/src/pages/docs/apis/android/create-billing-program-reporting-details-android.tsx
index 59759773..5588cf66 100644
--- a/packages/docs/src/pages/docs/apis/android/create-billing-program-reporting-details-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/create-billing-program-reporting-details-android.tsx
@@ -1,3 +1,5 @@
+import { Link } from 'react-router-dom';
+import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
@@ -39,6 +41,46 @@ function CreateBillingProgramReportingDetailsAndroid() {
.
+
+ Parameters
+
+
+ Promise<FetchProductsResult> — Sealed union;{' '}
+ Product[] for 'in-app',{' '}
+ ProductSubscription[] for 'subs', mixed for{' '}
+ 'all', or null (legacy schema branch).
+
+
Note about request* APIs
diff --git a/packages/docs/src/pages/docs/apis/finish-transaction.tsx b/packages/docs/src/pages/docs/apis/finish-transaction.tsx
index 735c355e..9a8249b1 100644
--- a/packages/docs/src/pages/docs/apis/finish-transaction.tsx
+++ b/packages/docs/src/pages/docs/apis/finish-transaction.tsx
@@ -1,3 +1,5 @@
+import { Link } from 'react-router-dom';
+import AnchorLink from '../../../components/AnchorLink';
import CodeBlock from '../../../components/CodeBlock';
import LanguageTabs from '../../../components/LanguageTabs';
import SEO from '../../../components/SEO';
@@ -44,6 +46,61 @@ function FinishTransaction() {
.
+
+ Parameters
+
+
+
+
+
Name
+
Type
+
Required
+
Description
+
+
+
+
+
+ purchase
+
+
+
+ Purchase
+
+
+
Yes
+
The purchase to finalize.
+
+
+
+ isConsumable
+
+
+ boolean
+
+
No
+
+ Defaults to false. Pass true for
+ consumables (re-buyable like coins) so Android consumes the token;
+ non-consumables and subscriptions just get acknowledged.
+
+
+
+
+
+
+ Returns
+
+
+ Promise<void> — Resolves once the platform finalizes
+ the transaction.
+
+
+
+ Throws
+
+
When the platform finalize call fails.
+
Signature
{{
diff --git a/packages/docs/src/pages/docs/apis/get-active-subscriptions.tsx b/packages/docs/src/pages/docs/apis/get-active-subscriptions.tsx
index 891e663c..0a512b69 100644
--- a/packages/docs/src/pages/docs/apis/get-active-subscriptions.tsx
+++ b/packages/docs/src/pages/docs/apis/get-active-subscriptions.tsx
@@ -1,4 +1,5 @@
import { Link } from 'react-router-dom';
+import AnchorLink from '../../../components/AnchorLink';
import CodeBlock from '../../../components/CodeBlock';
import LanguageTabs from '../../../components/LanguageTabs';
import SEO from '../../../components/SEO';
@@ -45,6 +46,43 @@ function GetActiveSubscriptions() {
.
+
+ Parameters
+
+
+
+
+
Name
+
Type
+
Required
+
Description
+
+
+
+
+
+ subscriptionIds
+
+
+ string[]
+
+
No
+
When provided, narrows the result to these SKUs only.
+
+
+
+
+
+ Returns
+
+
+
+ Promise<ActiveSubscription[]>
+ {' '}
+ — Active subscription details (see ActiveSubscription{' '}
+ type).
+
+
Signature
{{
diff --git a/packages/docs/src/pages/docs/apis/get-available-purchases.tsx b/packages/docs/src/pages/docs/apis/get-available-purchases.tsx
index bae38951..d1f47439 100644
--- a/packages/docs/src/pages/docs/apis/get-available-purchases.tsx
+++ b/packages/docs/src/pages/docs/apis/get-available-purchases.tsx
@@ -1,4 +1,5 @@
import { Link } from 'react-router-dom';
+import AnchorLink from '../../../components/AnchorLink';
import CodeBlock from '../../../components/CodeBlock';
import LanguageTabs from '../../../components/LanguageTabs';
import SEO from '../../../components/SEO';
@@ -47,6 +48,47 @@ function GetAvailablePurchases() {
.
+
+ Parameters
+
+
{{
diff --git a/packages/docs/src/pages/docs/apis/ios/get-storefront-ios.tsx b/packages/docs/src/pages/docs/apis/ios/get-storefront-ios.tsx
index 6768002e..594a2c5d 100644
--- a/packages/docs/src/pages/docs/apis/ios/get-storefront-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/get-storefront-ios.tsx
@@ -1,4 +1,5 @@
import { Link } from 'react-router-dom';
+import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
@@ -40,6 +41,21 @@ function GetStorefrontIOS() {
+
+ Parameters
+
+
+ None. Deprecated — use getStorefront.
+
+
+
+ Returns
+
+
+ Promise<string> — ISO country code of the App Store
+ storefront.
+
+
Signature
{{
diff --git a/packages/docs/src/pages/docs/apis/ios/get-transaction-jws-ios.tsx b/packages/docs/src/pages/docs/apis/ios/get-transaction-jws-ios.tsx
index 24ebe16a..57c70d6c 100644
--- a/packages/docs/src/pages/docs/apis/ios/get-transaction-jws-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/get-transaction-jws-ios.tsx
@@ -1,4 +1,5 @@
import { Link } from 'react-router-dom';
+import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
@@ -33,6 +34,40 @@ function GetTransactionJwsIOS() {
.
+
+ Parameters
+
+
+
+
+
Name
+
Type
+
Required
+
Description
+
+
+
+
+
+ sku
+
+
+ string
+
+
Yes
+
Product identifier.
+
+
+
+
+
+ Returns
+
+
+ Promise<string | null> — Signed JWS for the latest
+ transaction, or null.
+
+
Signature
{{
diff --git a/packages/docs/src/pages/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios.tsx b/packages/docs/src/pages/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios.tsx
index e72a55ab..a9f0ec67 100644
--- a/packages/docs/src/pages/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/is-eligible-for-external-purchase-custom-link-ios.tsx
@@ -1,3 +1,4 @@
+import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
@@ -44,6 +45,19 @@ function IsEligibleForExternalPurchaseCustomLinkIOS() {
.
+
+ Parameters
+
+
None.
+
+
+ Returns
+
+
+ Promise<boolean> — Whether the app can use
+ ExternalPurchaseCustomLink (iOS 18.1+).
+
+
Signature
{{
diff --git a/packages/docs/src/pages/docs/apis/ios/is-eligible-for-intro-offer-ios.tsx b/packages/docs/src/pages/docs/apis/ios/is-eligible-for-intro-offer-ios.tsx
index 7ac91138..db194ae5 100644
--- a/packages/docs/src/pages/docs/apis/ios/is-eligible-for-intro-offer-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/is-eligible-for-intro-offer-ios.tsx
@@ -1,3 +1,4 @@
+import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
@@ -36,6 +37,40 @@ function IsEligibleForIntroOfferIOS() {
.
+
+ Parameters
+
+
+
+
+
Name
+
Type
+
Required
+
Description
+
+
+
+
+
+ groupID
+
+
+ string
+
+
Yes
+
Subscription group identifier.
+
+
+
+
+
+ Returns
+
+
+ Promise<boolean> — true if the user is
+ eligible for the group's introductory offer.
+
+
Signature
{{
diff --git a/packages/docs/src/pages/docs/apis/ios/is-transaction-verified-ios.tsx b/packages/docs/src/pages/docs/apis/ios/is-transaction-verified-ios.tsx
index de7fa538..665a511c 100644
--- a/packages/docs/src/pages/docs/apis/ios/is-transaction-verified-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/is-transaction-verified-ios.tsx
@@ -1,4 +1,5 @@
import { Link } from 'react-router-dom';
+import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
@@ -34,6 +35,40 @@ function IsTransactionVerifiedIOS() {
.
+
+ Parameters
+
+
{{
diff --git a/packages/docs/src/pages/docs/apis/ios/latest-transaction-ios.tsx b/packages/docs/src/pages/docs/apis/ios/latest-transaction-ios.tsx
index afb136e9..24069e5e 100644
--- a/packages/docs/src/pages/docs/apis/ios/latest-transaction-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/latest-transaction-ios.tsx
@@ -1,3 +1,4 @@
+import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
@@ -32,6 +33,40 @@ function LatestTransactionIOS() {
.
+
+ Parameters
+
+
+
+
+
Name
+
Type
+
Required
+
Description
+
+
+
+
+
+ sku
+
+
+ string
+
+
Yes
+
Product identifier.
+
+
+
+
+
+ Returns
+
+
+ Promise<PurchaseIOS | null> — The latest verified
+ transaction for the product.
+
+
Signature
{{
diff --git a/packages/docs/src/pages/docs/apis/ios/present-code-redemption-sheet-ios.tsx b/packages/docs/src/pages/docs/apis/ios/present-code-redemption-sheet-ios.tsx
index da9eddf1..2898bbcd 100644
--- a/packages/docs/src/pages/docs/apis/ios/present-code-redemption-sheet-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/present-code-redemption-sheet-ios.tsx
@@ -1,4 +1,5 @@
import { Link } from 'react-router-dom';
+import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
@@ -35,6 +36,19 @@ function PresentCodeRedemptionSheetIOS() {
.
+
+ Parameters
+
+
None.
+
+
+ Returns
+
+
+ Promise<boolean> — true once the
+ redemption sheet has been presented.
+
+
Signature
{{
diff --git a/packages/docs/src/pages/docs/apis/ios/present-external-purchase-link-ios.tsx b/packages/docs/src/pages/docs/apis/ios/present-external-purchase-link-ios.tsx
index ddb310cd..9c510d91 100644
--- a/packages/docs/src/pages/docs/apis/ios/present-external-purchase-link-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/present-external-purchase-link-ios.tsx
@@ -1,3 +1,4 @@
+import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
@@ -32,6 +33,40 @@ function PresentExternalPurchaseLinkIOS() {
.
+
+ Parameters
+
+
+
+
+
Name
+
Type
+
Required
+
Description
+
+
+
+
+
+ url
+
+
+ string
+
+
Yes
+
External purchase URL to present.
+
+
+
+
+
+ Returns
+
+
+ Promise<ExternalPurchaseLinkResultIOS> — Result
+ envelope.
+
+
Signature
{{
diff --git a/packages/docs/src/pages/docs/apis/ios/present-external-purchase-notice-sheet-ios.tsx b/packages/docs/src/pages/docs/apis/ios/present-external-purchase-notice-sheet-ios.tsx
index b673153f..e02d5914 100644
--- a/packages/docs/src/pages/docs/apis/ios/present-external-purchase-notice-sheet-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/present-external-purchase-notice-sheet-ios.tsx
@@ -1,3 +1,4 @@
+import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
@@ -32,6 +33,19 @@ function PresentExternalPurchaseNoticeSheetIOS() {
.
+
+ Parameters
+
+
None.
+
+
+ Returns
+
+
+ Promise<ExternalPurchaseNoticeResultIOS> — Carries a
+ token if the user accepts.
+
+
Signature
{{
diff --git a/packages/docs/src/pages/docs/apis/ios/request-purchase-on-promoted-product-ios.tsx b/packages/docs/src/pages/docs/apis/ios/request-purchase-on-promoted-product-ios.tsx
index 7c165ec3..41095a18 100644
--- a/packages/docs/src/pages/docs/apis/ios/request-purchase-on-promoted-product-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/request-purchase-on-promoted-product-ios.tsx
@@ -1,4 +1,5 @@
import { Link } from 'react-router-dom';
+import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
import SEO from '../../../../components/SEO';
@@ -45,6 +46,22 @@ function RequestPurchaseOnPromotedProductIOS() {
{{
diff --git a/packages/docs/src/pages/docs/apis/request-purchase.tsx b/packages/docs/src/pages/docs/apis/request-purchase.tsx
index f30ed7bd..97886d41 100644
--- a/packages/docs/src/pages/docs/apis/request-purchase.tsx
+++ b/packages/docs/src/pages/docs/apis/request-purchase.tsx
@@ -1,4 +1,5 @@
import { Link } from 'react-router-dom';
+import AnchorLink from '../../../components/AnchorLink';
import CodeBlock from '../../../components/CodeBlock';
import LanguageTabs from '../../../components/LanguageTabs';
import SEO from '../../../components/SEO';
@@ -83,6 +84,57 @@ function RequestPurchase() {
+
+ Parameters
+
+
+
+
+
Name
+
Type
+
Required
+
Description
+
+
+
+
+
+ props
+
+
+
+ RequestPurchaseProps
+
+
+
Yes
+
+ Discriminated by type: 'in-app' | 'subs'. Pass
+ platform fields under request.apple.sku (iOS) and/or{' '}
+ request.google.skus (Android); subscriptions also
+ need request.google.subscriptionOffers.
+
+
+
+
+
+
+ Returns
+
+
+ Promise<Purchase | null> — Dispatched purchase
+ payload. Do not rely on this for the actual outcome —
+ listen via purchaseUpdatedListener /{' '}
+ purchaseErrorListener instead.
+
+
+
+ Throws
+
+
+ Synchronous rejection from the store (E_NOT_PREPARED,
+ missing offerToken on subs, etc.).
+
+
Signature
{{
diff --git a/packages/docs/src/pages/docs/apis/restore-purchases.tsx b/packages/docs/src/pages/docs/apis/restore-purchases.tsx
index 9ad11609..68d12712 100644
--- a/packages/docs/src/pages/docs/apis/restore-purchases.tsx
+++ b/packages/docs/src/pages/docs/apis/restore-purchases.tsx
@@ -1,3 +1,4 @@
+import AnchorLink from '../../../components/AnchorLink';
import CodeBlock from '../../../components/CodeBlock';
import LanguageTabs from '../../../components/LanguageTabs';
import SEO from '../../../components/SEO';
@@ -43,6 +44,21 @@ function RestorePurchases() {
.
+
+ Parameters
+
+
None.
+
+
+ Returns
+
+
+ Promise<void> — Resolves once the platform finishes
+ the restore. The restored purchases are emitted via{' '}
+ purchaseUpdatedListener / surface as{' '}
+ getAvailablePurchases results, depending on platform.
+
+
Signature
{{
From 0e6410cefca8671e10b012a9b4fdf71feb00af90 Mon Sep 17 00:00:00 2001
From: hyochan
Date: Sun, 26 Apr 2026 14:27:03 +0900
Subject: [PATCH 12/26] docs: expand Params/Returns into field-level tables on
API pages
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Earlier round added Parameters/Returns sections but each table only
listed the wrapper type (e.g. \`params: ProductRequest\`) — readers had
to click through to a Type page to see what fields they were supposed
to pass. Expanded those sections so every wrapper input/output has its
fields enumerated inline:
- 11 cross-platform pages: fetch-products (skus, type), request-purchase
(type + 7 nested apple/google fields), get-available-purchases (3
PurchaseOptions fields), init-connection (2 InitConnectionConfig
fields), get-active-subscriptions (7-row ActiveSubscription field
table), deep-link-to-subscriptions (2 DeepLinkOptions Android fields
+ iOS-ignores note), finish-transaction (purchase + isConsumable
semantics), get-storefront / has-active-subscriptions (richer return
prose with cross-links). end-connection / restore-purchases left
alone (already minimal).
- 13 iOS pages with object returns/params: subscription-status-ios,
present-external-purchase-notice-sheet-ios, get-app-transaction-ios,
the 3 ExternalPurchaseCustomLink helpers, get-promoted-product-ios,
get/show pending+all transactions, current+latest entitlement,
show-manage-subscriptions-ios, validate-receipt-ios. Primitive-param
iOS pages left alone (12 files: sync, clear, intro-offer eligibility,
JWS/verified/receipt helpers, etc.).
- 3 Android pages: launch-external-link (program + url),
is-billing-program-available (3 result fields),
create-billing-program-reporting-details (3 result fields). Other 6
primitive-param Android pages left alone.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
...ling-program-reporting-details-android.tsx | 48 +++++++-
.../is-billing-program-available-android.tsx | 48 +++++++-
.../android/launch-external-link-android.tsx | 32 ++++-
.../docs/apis/deep-link-to-subscriptions.tsx | 38 ++++--
.../src/pages/docs/apis/fetch-products.tsx | 92 ++++++++++++--
.../pages/docs/apis/finish-transaction.tsx | 20 +++-
.../docs/apis/get-active-subscriptions.tsx | 96 ++++++++++++++-
.../docs/apis/get-available-purchases.tsx | 62 ++++++++--
.../src/pages/docs/apis/get-storefront.tsx | 4 +-
.../docs/apis/has-active-subscriptions.tsx | 14 ++-
.../src/pages/docs/apis/init-connection.tsx | 35 +++++-
.../docs/apis/ios/current-entitlement-ios.tsx | 8 +-
.../apis/ios/get-all-transactions-ios.tsx | 11 +-
.../docs/apis/ios/get-app-transaction-ios.tsx | 7 +-
...xternal-purchase-custom-link-token-ios.tsx | 9 +-
.../apis/ios/get-pending-transactions-ios.tsx | 11 +-
.../apis/ios/get-promoted-product-ios.tsx | 8 +-
.../docs/apis/ios/latest-transaction-ios.tsx | 8 +-
.../present-external-purchase-link-ios.tsx | 8 +-
...ent-external-purchase-notice-sheet-ios.tsx | 39 +++++-
...ternal-purchase-custom-link-notice-ios.tsx | 8 +-
.../ios/show-manage-subscriptions-ios.tsx | 9 +-
.../docs/apis/ios/subscription-status-ios.tsx | 44 ++++++-
.../docs/apis/ios/validate-receipt-ios.tsx | 8 +-
.../src/pages/docs/apis/request-purchase.tsx | 112 ++++++++++++++++--
25 files changed, 675 insertions(+), 104 deletions(-)
diff --git a/packages/docs/src/pages/docs/apis/android/create-billing-program-reporting-details-android.tsx b/packages/docs/src/pages/docs/apis/android/create-billing-program-reporting-details-android.tsx
index 5588cf66..dd0ae98a 100644
--- a/packages/docs/src/pages/docs/apis/android/create-billing-program-reporting-details-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/create-billing-program-reporting-details-android.tsx
@@ -73,13 +73,51 @@ function CreateBillingProgramReportingDetailsAndroid() {
Returns
@@ -64,22 +71,37 @@ function DeepLinkToSubscriptions() {
- options
+ skuAndroid
-
- DeepLinkOptions
-
+ string
No
- Android needs skuAndroid +{' '}
- packageNameAndroid to deep-link to a specific
- subscription; iOS ignores the argument.
+ Android. Subscription SKU to deep-link to.
+ Without it the user lands on the generic Play subscriptions page.
+
+
+
+
+ packageNameAndroid
+
+
+ string
+
+
No
+
+ Android. Defaults to the host app's package;
+ override only when proxying for another app.
+
+ iOS ignores all fields — the wrapper calls{' '}
+ AppStore.showManageSubscriptions(in:) with the active{' '}
+ UIWindowScene.
+
- Object with skus: string[] and optional{' '}
- type: 'in-app' | 'subs' | 'all' (defaults to{' '}
- 'in-app').
+ No (default 'in-app')
+
+
+ Filter by product kind. Use 'all' to query both in
+ one call.
@@ -79,11 +95,63 @@ function FetchProducts() {
Returns
- Promise<FetchProductsResult> — Sealed union;{' '}
- Product[] for 'in-app',{' '}
- ProductSubscription[] for 'subs', mixed for{' '}
- 'all', or null (legacy schema branch).
+ Promise<FetchProductsResult> — sealed union,
+ discriminated by the request type:
+
+
+
+
Variant
+
Returned for
+
Description
+
+
+
+
+
+
+ Product[]
+
+
+
+ type: 'in-app'
+
+
+ Array of one-time products. Empty array if none of the SKUs exist.
+
+
+
+
+
+ ProductSubscription[]
+
+
+
+ type: 'subs'
+
+
Array of subscription products with offer details.
+
+
+
+ (Product | ProductSubscription)[]
+
+
+ type: 'all'
+
+
+ Mixed array — use each entry's type field to
+ disambiguate.
+
+
+
+
+ null
+
+
(legacy)
+
Older schema branch retained for backwards compatibility.
+
+
+
Note about request* APIs
diff --git a/packages/docs/src/pages/docs/apis/finish-transaction.tsx b/packages/docs/src/pages/docs/apis/finish-transaction.tsx
index 9a8249b1..c4d4be8c 100644
--- a/packages/docs/src/pages/docs/apis/finish-transaction.tsx
+++ b/packages/docs/src/pages/docs/apis/finish-transaction.tsx
@@ -49,10 +49,11 @@ function FinishTransaction() {
Parameters
+
The transaction to close, plus an optional consumable flag:
-
Name
+
Field
Type
Required
Description
@@ -69,7 +70,11 @@ function FinishTransaction() {
Yes
-
The purchase to finalize.
+
+ The purchase / transaction to finalize. Must come from{' '}
+ requestPurchase or getAvailablePurchases
+ .
+
@@ -78,11 +83,14 @@ function FinishTransaction() {
boolean
-
No
- Defaults to false. Pass true for
- consumables (re-buyable like coins) so Android consumes the token;
- non-consumables and subscriptions just get acknowledged.
+ No (default false)
+
+
+ Android.true consumes the token
+ (re-buyable like coins); false just acknowledges
+ (non-consumables, subscriptions). iOS always calls{' '}
+ Transaction.finish() regardless.
diff --git a/packages/docs/src/pages/docs/apis/get-active-subscriptions.tsx b/packages/docs/src/pages/docs/apis/get-active-subscriptions.tsx
index 0a512b69..55d56a92 100644
--- a/packages/docs/src/pages/docs/apis/get-active-subscriptions.tsx
+++ b/packages/docs/src/pages/docs/apis/get-active-subscriptions.tsx
@@ -67,7 +67,11 @@ function GetActiveSubscriptions() {
string[]
No
-
When provided, narrows the result to these SKUs only.
+
+ If provided, the result is filtered to these SKUs. Omit / pass{' '}
+ null to return every active subscription the store
+ knows about.
+
@@ -79,9 +83,95 @@ function GetActiveSubscriptions() {
Promise<ActiveSubscription[]>
{' '}
- — Active subscription details (see ActiveSubscription{' '}
- type).
+ — one entry per active subscription. Each row carries:
+
+
+
+
Field
+
Type
+
Description
+
+
+
+
+
+ productId
+
+
+ string
+
+
Subscription product identifier.
+
+
+
+ basePlanId
+
+
+ string?
+
+
+ Android. Base plan identifier when applicable.
+
+
+
+
+ isActive
+
+
+ boolean
+
+
+ true while the subscription is in a paying or grace
+ state.
+
+
+
+
+ willExpireSoon
+
+
+ boolean?
+
+
Hint that renewal is imminent (cancelled or grace period).
+
+
+
+ expirationDateIOS
+
+
+ number?
+
+
+ iOS. Epoch ms expiration timestamp.
+
+
+
+
+ environmentIOS
+
+
+ string?
+
+
+ iOS."Sandbox" or{' '}
+ "Production".
+
+
+
+
+ autoRenewingAndroid
+
+
+ boolean?
+
+
+ Android. Whether Play will auto-renew at the next
+ cycle.
+
+
+
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/get-available-purchases.tsx b/packages/docs/src/pages/docs/apis/get-available-purchases.tsx
index d1f47439..86cc7b61 100644
--- a/packages/docs/src/pages/docs/apis/get-available-purchases.tsx
+++ b/packages/docs/src/pages/docs/apis/get-available-purchases.tsx
@@ -51,10 +51,17 @@ function GetAvailablePurchases() {
Parameters
+
+ iOS. Switch from Transaction.all{' '}
+ (full history) to Transaction.currentEntitlements{' '}
+ (active only).
+
+
+
+
+ includeSuspendedAndroid
+
+
+ boolean
-
- PurchaseOptions
-
+ No (default false)
-
No
- Platform-specific filters (
- alsoPublishToEventListenerIOS,{' '}
- onlyIncludeActiveItemsIOS,{' '}
- includeSuspendedAndroid).
+ Android. Include subscriptions in a paused/grace
+ state.
@@ -85,8 +121,10 @@ function GetAvailablePurchases() {
Returns
- Promise<Purchase[]> — Owned/available purchases held
- by the store.
+
+ Promise<Purchase[]>
+ {' '}
+ — owned/available purchases held by the store.
Signature
diff --git a/packages/docs/src/pages/docs/apis/get-storefront.tsx b/packages/docs/src/pages/docs/apis/get-storefront.tsx
index 34c8e4d0..93790718 100644
--- a/packages/docs/src/pages/docs/apis/get-storefront.tsx
+++ b/packages/docs/src/pages/docs/apis/get-storefront.tsx
@@ -51,7 +51,9 @@ function GetStorefront() {
Promise<string> — ISO 3166-1 alpha-2 country code of
- the user's storefront.
+ the user's storefront (e.g. "US", "KR").
+ Returns the App Store / Play Store account region, NOT the device
+ locale.
Signature
diff --git a/packages/docs/src/pages/docs/apis/has-active-subscriptions.tsx b/packages/docs/src/pages/docs/apis/has-active-subscriptions.tsx
index eecddc19..fd0d4b73 100644
--- a/packages/docs/src/pages/docs/apis/has-active-subscriptions.tsx
+++ b/packages/docs/src/pages/docs/apis/has-active-subscriptions.tsx
@@ -1,3 +1,4 @@
+import { Link } from 'react-router-dom';
import AnchorLink from '../../../components/AnchorLink';
import CodeBlock from '../../../components/CodeBlock';
import LanguageTabs from '../../../components/LanguageTabs';
@@ -62,7 +63,10 @@ function HasActiveSubscriptions() {
string[]
No
-
When provided, checks only these SKUs.
+
+ If provided, only these SKUs are checked. Omit to ask "any active
+ subscription at all?".
+
@@ -71,8 +75,12 @@ function HasActiveSubscriptions() {
Returns
- Promise<boolean> — true if any
- (matching) subscription is active.
+ Promise<boolean> — true when at least
+ one (matching) subscription is in an active state. Convenience over{' '}
+
+ getActiveSubscriptions
+ {' '}
+ when you only need a yes/no answer.
Signature
diff --git a/packages/docs/src/pages/docs/apis/init-connection.tsx b/packages/docs/src/pages/docs/apis/init-connection.tsx
index 5875d50c..76c438f6 100644
--- a/packages/docs/src/pages/docs/apis/init-connection.tsx
+++ b/packages/docs/src/pages/docs/apis/init-connection.tsx
@@ -49,10 +49,17 @@ function InitConnection() {
Parameters
+
- Connection config (e.g. enableBillingProgramAndroid{' '}
- for Play Billing 8.2.0+; iOS ignores Android-specific fields).
+ Android. Enable a Play Billing 8.2.0+ program
+ (External Payments etc.) at connection time.
diff --git a/packages/docs/src/pages/docs/apis/ios/current-entitlement-ios.tsx b/packages/docs/src/pages/docs/apis/ios/current-entitlement-ios.tsx
index b312457a..ec71c4b9 100644
--- a/packages/docs/src/pages/docs/apis/ios/current-entitlement-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/current-entitlement-ios.tsx
@@ -1,3 +1,4 @@
+import { Link } from 'react-router-dom';
import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
@@ -63,8 +64,11 @@ function CurrentEntitlementIOS() {
Returns
- Promise<PurchaseIOS | null> — Current entitlement for
- the product, or null.
+
+ Promise<PurchaseIOS | null>
+ {' '}
+ — iOS purchase shape, or null if the SKU has no matching
+ transaction.
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/get-all-transactions-ios.tsx b/packages/docs/src/pages/docs/apis/ios/get-all-transactions-ios.tsx
index 5843fe31..e937dc75 100644
--- a/packages/docs/src/pages/docs/apis/ios/get-all-transactions-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/get-all-transactions-ios.tsx
@@ -1,3 +1,4 @@
+import { Link } from 'react-router-dom';
import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
@@ -47,8 +48,14 @@ function GetAllTransactionsIOS() {
Returns
- Promise<PurchaseIOS[]> — Every StoreKit transaction
- (finished + unfinished).
+
+ Promise<PurchaseIOS[]>
+ {' '}
+ — array of StoreKit transactions in the iOS-specific shape. See{' '}
+
+ Purchase
+ {' '}
+ for the full field reference.
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/get-app-transaction-ios.tsx b/packages/docs/src/pages/docs/apis/ios/get-app-transaction-ios.tsx
index 9ebcc3e4..a87d52eb 100644
--- a/packages/docs/src/pages/docs/apis/ios/get-app-transaction-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/get-app-transaction-ios.tsx
@@ -43,8 +43,11 @@ function GetAppTransactionIOS() {
Returns
- Promise<AppTransaction | null> — JWS-verified record
- of how the app was acquired (iOS 16+).
+
+ Promise<AppTransaction | null>
+ {' '}
+ — JWS-verified record of how the app was acquired. Returns{' '}
+ null on iOS < 16 or when no transaction is available.
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/get-external-purchase-custom-link-token-ios.tsx b/packages/docs/src/pages/docs/apis/ios/get-external-purchase-custom-link-token-ios.tsx
index 10a99285..85f1d64e 100644
--- a/packages/docs/src/pages/docs/apis/ios/get-external-purchase-custom-link-token-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/get-external-purchase-custom-link-token-ios.tsx
@@ -1,3 +1,4 @@
+import { Link } from 'react-router-dom';
import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
@@ -78,8 +79,12 @@ function GetExternalPurchaseCustomLinkTokenIOS() {
Returns
- Promise<ExternalPurchaseCustomLinkTokenResultIOS> —
- Token for Apple's External Purchase Server reporting API.
+
+ Promise<ExternalPurchaseCustomLinkTokenResultIOS>
+ {' '}
+ — token plus its acquired/expiry metadata. Send the token{' '}
+ field to Apple's External Purchase Server within the documented validity
+ window.
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/get-pending-transactions-ios.tsx b/packages/docs/src/pages/docs/apis/ios/get-pending-transactions-ios.tsx
index 6e6fe87f..cf4bec03 100644
--- a/packages/docs/src/pages/docs/apis/ios/get-pending-transactions-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/get-pending-transactions-ios.tsx
@@ -1,3 +1,4 @@
+import { Link } from 'react-router-dom';
import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
@@ -42,8 +43,14 @@ function GetPendingTransactionsIOS() {
Returns
- Promise<PurchaseIOS[]> — Unfinished StoreKit
- transactions in the queue.
+
+ Promise<PurchaseIOS[]>
+ {' '}
+ — array of StoreKit transactions in the iOS-specific shape. See{' '}
+
+ Purchase
+ {' '}
+ for the full field reference.
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/get-promoted-product-ios.tsx b/packages/docs/src/pages/docs/apis/ios/get-promoted-product-ios.tsx
index b7fa76e2..3e133257 100644
--- a/packages/docs/src/pages/docs/apis/ios/get-promoted-product-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/get-promoted-product-ios.tsx
@@ -1,3 +1,4 @@
+import { Link } from 'react-router-dom';
import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
@@ -43,8 +44,11 @@ function GetPromotedProductIOS() {
Returns
- Promise<ProductIOS | null> — The currently promoted
- product, or null if none is queued.
+
+ Promise<ProductIOS | null>
+ {' '}
+ — the App Store-promoted product, or null if no campaign is
+ currently queued.
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/latest-transaction-ios.tsx b/packages/docs/src/pages/docs/apis/ios/latest-transaction-ios.tsx
index 24069e5e..f1ca6178 100644
--- a/packages/docs/src/pages/docs/apis/ios/latest-transaction-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/latest-transaction-ios.tsx
@@ -1,3 +1,4 @@
+import { Link } from 'react-router-dom';
import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
@@ -63,8 +64,11 @@ function LatestTransactionIOS() {
Returns
- Promise<PurchaseIOS | null> — The latest verified
- transaction for the product.
+
+ Promise<PurchaseIOS | null>
+ {' '}
+ — iOS purchase shape, or null if the SKU has no matching
+ transaction.
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/present-external-purchase-link-ios.tsx b/packages/docs/src/pages/docs/apis/ios/present-external-purchase-link-ios.tsx
index 9c510d91..017eee3a 100644
--- a/packages/docs/src/pages/docs/apis/ios/present-external-purchase-link-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/present-external-purchase-link-ios.tsx
@@ -1,3 +1,4 @@
+import { Link } from 'react-router-dom';
import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
@@ -63,8 +64,11 @@ function PresentExternalPurchaseLinkIOS() {
Returns
- Promise<ExternalPurchaseLinkResultIOS> — Result
- envelope.
+
+ Promise<ExternalPurchaseLinkResultIOS>
+ {' '}
+ — carries the result of opening the external link (success flag + any
+ error string from StoreKit).
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/present-external-purchase-notice-sheet-ios.tsx b/packages/docs/src/pages/docs/apis/ios/present-external-purchase-notice-sheet-ios.tsx
index e02d5914..5198a9fc 100644
--- a/packages/docs/src/pages/docs/apis/ios/present-external-purchase-notice-sheet-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/present-external-purchase-notice-sheet-ios.tsx
@@ -1,3 +1,4 @@
+import { Link } from 'react-router-dom';
import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
@@ -42,9 +43,43 @@ function PresentExternalPurchaseNoticeSheetIOS() {
Returns
- Promise<ExternalPurchaseNoticeResultIOS> — Carries a
- token if the user accepts.
+
+ Promise<ExternalPurchaseNoticeResultIOS>
+ {' '}
+ — carries:
+
+
+
+
Field
+
Type
+
Description
+
+
+
+
+
+ result
+
+
+ 'continue' | 'cancelled'
+
+
Whether the user accepted the notice or dismissed it.
+
+
+
+ token
+
+
+ string?
+
+
+ Reporting token returned by Apple when the user continues. Pass to
+ your backend.
+
+
+
+
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/show-external-purchase-custom-link-notice-ios.tsx b/packages/docs/src/pages/docs/apis/ios/show-external-purchase-custom-link-notice-ios.tsx
index 03ece045..ec7cb29c 100644
--- a/packages/docs/src/pages/docs/apis/ios/show-external-purchase-custom-link-notice-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/show-external-purchase-custom-link-notice-ios.tsx
@@ -1,3 +1,4 @@
+import { Link } from 'react-router-dom';
import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
@@ -75,8 +76,11 @@ function ShowExternalPurchaseCustomLinkNoticeIOS() {
Returns
- Promise<ExternalPurchaseCustomLinkNoticeResultIOS> —
- Disclosure result.
+
+ Promise<ExternalPurchaseCustomLinkNoticeResultIOS>
+ {' '}
+ — the user's response (continue / cancelled)
+ plus the disclosure type that was shown.
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/show-manage-subscriptions-ios.tsx b/packages/docs/src/pages/docs/apis/ios/show-manage-subscriptions-ios.tsx
index 03a05635..fe38c834 100644
--- a/packages/docs/src/pages/docs/apis/ios/show-manage-subscriptions-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/show-manage-subscriptions-ios.tsx
@@ -1,3 +1,4 @@
+import { Link } from 'react-router-dom';
import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
@@ -50,8 +51,12 @@ function ShowManageSubscriptionsIOS() {
Returns
- Promise<PurchaseIOS[]> — Purchases whose status
- changed while the sheet was presented.
+
+ Promise<PurchaseIOS[]>
+ {' '}
+ — purchases whose status changed while the manage-subscriptions sheet
+ was on screen (e.g. cancelled or auto-renew toggled). Empty array when
+ nothing changed.
Signature
diff --git a/packages/docs/src/pages/docs/apis/ios/subscription-status-ios.tsx b/packages/docs/src/pages/docs/apis/ios/subscription-status-ios.tsx
index 4edd3b70..be6afc84 100644
--- a/packages/docs/src/pages/docs/apis/ios/subscription-status-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/subscription-status-ios.tsx
@@ -1,3 +1,4 @@
+import { Link } from 'react-router-dom';
import AnchorLink from '../../../../components/AnchorLink';
import CodeBlock from '../../../../components/CodeBlock';
import LanguageTabs from '../../../../components/LanguageTabs';
@@ -67,9 +68,48 @@ function SubscriptionStatusIOS() {
Returns
- Promise<SubscriptionStatusIOS[]> — Status objects
- from Product.SubscriptionInfo.status.
+
+ Promise<SubscriptionStatusIOS[]>
+ {' '}
+ — one entry per status the user has on the subscription:
diff --git a/packages/docs/src/pages/docs/apis/request-purchase.tsx b/packages/docs/src/pages/docs/apis/request-purchase.tsx
index 97886d41..cb830244 100644
--- a/packages/docs/src/pages/docs/apis/request-purchase.tsx
+++ b/packages/docs/src/pages/docs/apis/request-purchase.tsx
@@ -87,10 +87,17 @@ function RequestPurchase() {
Parameters
+
+ Pass a single{' '}
+
+ RequestPurchaseProps
+
+ , discriminated by type:
+
-
Name
+
Field
Type
Required
Description
@@ -99,20 +106,94 @@ function RequestPurchase() {
- props
+ type
-
- RequestPurchaseProps
-
+ 'in-app' | 'subs'
Yes
- Discriminated by type: 'in-app' | 'subs'. Pass
- platform fields under request.apple.sku (iOS) and/or{' '}
- request.google.skus (Android); subscriptions also
- need request.google.subscriptionOffers.
+ Selects the request shape. Use 'in-app' for one-time
+ products and 'subs' for subscriptions.
+
+
+
+
+ request.apple.sku
+
+
+ string
+
+
iOS only
+
Single SKU for the iOS purchase.
+
+
+
+ request.apple.appAccountToken
+
+
+ string
+
+
No
+
+ UUID-format account token forwarded to Apple. Non-UUID values land
+ as null on the resulting Purchase.
+
+
+
+
+ request.apple.quantity
+
+
+ number
+
+
No
+
Quantity for consumable bulk purchases.
+
+
+
+ request.google.skus
+
+
+ string[]
+
+
Android only
+
Product SKUs to launch the Play purchase flow for.
+
+
+
+ request.google.subscriptionOffers
+
+
+ {`{ sku: string; offerToken: string }[]`}
+
+
+ 'subs' only
+
+
+ Android. Required for subscription requests; pair
+ each SKU with its offerToken from fetchProducts.
+
+
+
+
+ request.google.obfuscatedAccountIdAndroid
+
+
+ string
+
+
No
+
Optional account identifier passed to Play.
+
+
+
+ request.google.obfuscatedProfileIdAndroid
+
+
+ string
+
No
+
Optional profile identifier passed to Play.
@@ -121,10 +202,17 @@ function RequestPurchase() {
Returns
- Promise<Purchase | null> — Dispatched purchase
+ Promise<Purchase | null> — dispatched purchase
payload. Do not rely on this for the actual outcome —
- listen via purchaseUpdatedListener /{' '}
- purchaseErrorListener instead.
+ listen via{' '}
+
+ purchaseUpdatedListener
+ {' '}
+ /{' '}
+
+ purchaseErrorListener
+ {' '}
+ instead.
From db1a9186929286c1e84fb135e3333820fb539e81 Mon Sep 17 00:00:00 2001
From: hyochan
Date: Sun, 26 Apr 2026 14:37:53 +0900
Subject: [PATCH 13/26] docs: add 5-language Signature + Example tabs to
iOS/Android API pages
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
iOS-specific and Android-specific API pages previously only showed the
native Swift / Kotlin signature and had NO Example block — but the
framework wrappers (expo-iap, react-native-iap, kmp-iap, flutter,
godot-iap) all expose the *IOS / *Android methods, so users on those
SDKs had no idea how to call them.
Updated all 25 iOS pages and 9 Android pages so each now has:
- 5-language Signature tabs: native (Swift / Kotlin) + Kotlin (KMP) +
TypeScript + Dart + GDScript.
- A new Example block with realistic per-language calls. TypeScript
examples wrap calls in `Platform.OS === 'ios'` / `'android'`; Dart
in `Platform.isIOS` / `isAndroid`; GDScript in
`iap.get_platform() == "iOS"`; KMP examples note "iOS/Android
targets only — no-op on the other platform".
Naming conventions preserved per CLAUDE.md:
- packages/google `OpenIapStore` kotlin tab uses the un-suffixed name
(`acknowledgePurchase`); kmp / TS / Dart / GDScript wrappers use
the `Android` suffix (`acknowledgePurchaseAndroid`).
- iOS: every wrapper keeps the `IOS` suffix (camelCase) /
`_ios` (snake_case in GDScript).
Deprecated APIs (`getStorefrontIOS`, `requestPurchaseOnPromotedProductIOS`,
`validateReceiptIOS`) carry the deprecation note in each language's
example.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
.../android/acknowledge-purchase-android.tsx | 38 ++++++++-
...ternative-billing-availability-android.tsx | 43 ++++++++++
.../apis/android/consume-purchase-android.tsx | 44 ++++++++++
...eate-alternative-billing-token-android.tsx | 43 ++++++++++
...ling-program-reporting-details-android.tsx | 62 ++++++++++++++
.../enable-billing-program-android.tsx | 83 +++++++++++++++----
.../is-billing-program-available-android.tsx | 56 +++++++++++++
.../android/launch-external-link-android.tsx | 76 +++++++++++++++++
...how-alternative-billing-dialog-android.tsx | 43 ++++++++++
.../apis/ios/begin-refund-request-ios.tsx | 43 ++++++++++
...n-present-external-purchase-notice-ios.tsx | 43 ++++++++++
.../docs/apis/ios/clear-transaction-ios.tsx | 42 ++++++++++
.../docs/apis/ios/current-entitlement-ios.tsx | 43 ++++++++++
.../apis/ios/get-all-transactions-ios.tsx | 42 ++++++++++
.../docs/apis/ios/get-app-transaction-ios.tsx | 42 ++++++++++
...xternal-purchase-custom-link-token-ios.tsx | 56 +++++++++++++
.../apis/ios/get-pending-transactions-ios.tsx | 42 ++++++++++
.../apis/ios/get-promoted-product-ios.tsx | 42 ++++++++++
.../docs/apis/ios/get-receipt-data-ios.tsx | 64 +++++---------
.../docs/apis/ios/get-storefront-ios.tsx | 49 +++++++++++
.../docs/apis/ios/get-transaction-jws-ios.tsx | 67 +++++----------
...-for-external-purchase-custom-link-ios.tsx | 43 ++++++++++
.../ios/is-eligible-for-intro-offer-ios.tsx | 43 ++++++++++
.../apis/ios/is-transaction-verified-ios.tsx | 63 +++++---------
.../docs/apis/ios/latest-transaction-ios.tsx | 43 ++++++++++
.../ios/present-code-redemption-sheet-ios.tsx | 42 ++++++++++
.../present-external-purchase-link-ios.tsx | 43 ++++++++++
...ent-external-purchase-notice-sheet-ios.tsx | 43 ++++++++++
...quest-purchase-on-promoted-product-ios.tsx | 48 +++++++++++
...ternal-purchase-custom-link-notice-ios.tsx | 55 ++++++++++++
.../ios/show-manage-subscriptions-ios.tsx | 43 ++++++++++
.../docs/apis/ios/subscription-status-ios.tsx | 43 ++++++++++
.../docs/src/pages/docs/apis/ios/sync-ios.tsx | 42 ++++++++++
.../docs/apis/ios/validate-receipt-ios.tsx | 45 ++++++++++
34 files changed, 1512 insertions(+), 147 deletions(-)
diff --git a/packages/docs/src/pages/docs/apis/android/acknowledge-purchase-android.tsx b/packages/docs/src/pages/docs/apis/android/acknowledge-purchase-android.tsx
index 93a080af..4a2cdcf5 100644
--- a/packages/docs/src/pages/docs/apis/android/acknowledge-purchase-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/acknowledge-purchase-android.tsx
@@ -91,15 +91,15 @@ function AcknowledgePurchaseAndroid() {
+ User action on the notice sheet — see{' '}
+ ExternalPurchaseNoticeAction.
-
Whether the user accepted the notice or dismissed it.
- token
+ externalPurchaseToken
string?
- Reporting token returned by Apple when the user continues. Pass to
- your backend.
+ Reporting token returned by Apple when the user continues (
+ result === 'continue'). Pass to your backend / send
+ to Apple's External Purchase Server API.
+
+
+
+
+ error
+
+
+ string?
+
Populated when the sheet failed to present.
diff --git a/packages/docs/src/pages/docs/apis/ios/show-external-purchase-custom-link-notice-ios.tsx b/packages/docs/src/pages/docs/apis/ios/show-external-purchase-custom-link-notice-ios.tsx
index ed7a980b..e320dfe5 100644
--- a/packages/docs/src/pages/docs/apis/ios/show-external-purchase-custom-link-notice-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/show-external-purchase-custom-link-notice-ios.tsx
@@ -76,7 +76,7 @@ function ShowExternalPurchaseCustomLinkNoticeIOS() {
Returns
+ Whether the user accepted the disclosure notice or dismissed it.
+
+
+
+
+ noticeType
+
+
+ ExternalPurchaseCustomLinkNoticeTypeIOS
+
+
Echoes the disclosure type that was shown.
+
+
+
+ error
+
+
+ string?
+
+
Populated when the sheet failed to present.
+
+
+
+
{{
typescript: (
From 5a1e06998104eaa27420728b887c97f518c79180 Mon Sep 17 00:00:00 2001
From: hyochan
Date: Sun, 26 Apr 2026 14:52:06 +0900
Subject: [PATCH 15/26] docs: convert API page Params/Returns tables to prose
lists
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
User flagged that the 4-column doc-tables (Field / Type / Required /
Description) get crammed unreadably narrow on the docs site. Switched
every API page over to a `
with the wrapper-type intro line preserved as a regular `
` above the
list when there is one.
Also dropped the entire Parameters block (heading + body) on every page
where the function takes no arguments — no more "
None.
" filler.
Coverage:
- 11 cross-platform pages (Parameters dropped on end-connection,
restore-purchases, get-storefront).
- 25 iOS pages (Parameters dropped on 14 zero-arg APIs: sync, clear,
getPromoted, requestPurchaseOnPromoted, getPending, getAll,
getStorefrontIOS, getReceiptData, presentCodeRedemption,
getAppTransaction, canPresentExternalPurchaseNotice,
presentExternalPurchaseNoticeSheet,
isEligibleForExternalPurchaseCustomLink, showManageSubscriptions).
- 9 Android pages (Parameters dropped on the 3 alternative-billing
no-arg helpers).
- Returns tables (multi-field) also converted to lists on
fetch-products, get-active-subscriptions,
is-billing-program-available-android,
create-billing-program-reporting-details-android,
subscription-status-ios, present-external-purchase-notice-sheet-ios.
Layout consistency audit: 0 stale tables in API pages, 0 `
diff --git a/packages/docs/src/pages/docs/apis/android/enable-billing-program-android.tsx b/packages/docs/src/pages/docs/apis/android/enable-billing-program-android.tsx
index 63dc215b..9ea9010b 100644
--- a/packages/docs/src/pages/docs/apis/android/enable-billing-program-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/enable-billing-program-android.tsx
@@ -51,34 +51,20 @@ function EnableBillingProgramAndroid() {
Parameters
-
-
-
-
Name
-
Type
-
Required
-
Description
-
-
-
-
-
- billingProgramAndroid
-
-
-
- BillingProgramAndroid
-
-
-
Yes
-
- Note: this is a config field of InitConnectionConfig{' '}
- passed to initConnection(), not a standalone
- mutation.
-
-
-
-
+
+
+ billingProgramAndroid{' '}
+
+ (required,{' '}
+
+ BillingProgramAndroid
+
+ )
+ {' '}
+ — Note: this is a config field of InitConnectionConfig{' '}
+ passed to initConnection(), not a standalone mutation.
+
- Android. Subscription SKU to deep-link to.
- Without it the user lands on the generic Play subscriptions page.
-
-
-
-
- packageNameAndroid
-
-
- string
-
-
No
-
- Android. Defaults to the host app's package;
- override only when proxying for another app.
-
-
-
-
+
+
+ skuAndroid{' '}
+
+ (optional, string)
+ {' '}
+ — Android. Subscription SKU to deep-link to. Without
+ it the user lands on the generic Play subscriptions page.
+
+
+ packageNameAndroid{' '}
+
+ (optional, string)
+ {' '}
+ — Android. Defaults to the host app's package;
+ override only when proxying for another app.
+
+
iOS ignores all fields — the wrapper calls{' '}
AppStore.showManageSubscriptions(in:) with the active{' '}
diff --git a/packages/docs/src/pages/docs/apis/end-connection.tsx b/packages/docs/src/pages/docs/apis/end-connection.tsx
index 4b5de144..e2242b93 100644
--- a/packages/docs/src/pages/docs/apis/end-connection.tsx
+++ b/packages/docs/src/pages/docs/apis/end-connection.tsx
@@ -43,11 +43,6 @@ function EndConnection() {
.
- If provided, the result is filtered to these SKUs. Omit / pass{' '}
- null to return every active subscription the store
- knows about.
-
-
-
-
+
+
+ subscriptionIds{' '}
+
+ (optional, string[])
+ {' '}
+ — If provided, the result is filtered to these SKUs. Omit / pass{' '}
+ null to return every active subscription the store knows
+ about.
+
+
Returns
@@ -85,93 +70,60 @@ function GetActiveSubscriptions() {
{' '}
— one entry per active subscription. Each row carries:
-
-
-
-
Field
-
Type
-
Description
-
-
-
-
-
- productId
-
-
- string
-
-
Subscription product identifier.
-
-
-
- basePlanId
-
-
- string?
-
-
- Android. Base plan identifier when applicable.
-
-
-
-
- isActive
-
-
- boolean
-
-
- true while the subscription is in a paying or grace
- state.
-
-
-
-
- willExpireSoon
-
-
- boolean?
-
-
Hint that renewal is imminent (cancelled or grace period).
-
-
-
- expirationDateIOS
-
-
- number?
-
-
- iOS. Epoch ms expiration timestamp.
-
-
-
-
- environmentIOS
-
-
- string?
-
-
- iOS."Sandbox" or{' '}
- "Production".
-
-
-
-
- autoRenewingAndroid
-
-
- boolean?
-
-
- Android. Whether Play will auto-renew at the next
- cycle.
-
- If provided, only these SKUs are checked. Omit to ask "any active
- subscription at all?".
-
-
-
-
+
+
+ subscriptionIds{' '}
+
+ (optional, string[])
+ {' '}
+ — If provided, only these SKUs are checked. Omit to ask "any active
+ subscription at all?".
+
- User action on the notice sheet — see{' '}
- ExternalPurchaseNoticeAction.
-
-
-
-
- externalPurchaseToken
-
-
- string?
-
-
- Reporting token returned by Apple when the user continues (
- result === 'continue'). Pass to your backend / send
- to Apple's External Purchase Server API.
-
-
-
-
- error
-
-
- string?
-
-
Populated when the sheet failed to present.
-
-
-
+
+
+ result{' '}
+
+ ('continue' | 'dismissed')
+ {' '}
+ — User action on the notice sheet — see{' '}
+ ExternalPurchaseNoticeAction.
+
+
+ externalPurchaseToken{' '}
+
+ (string?)
+ {' '}
+ — Reporting token returned by Apple when the user continues (
+ result === 'continue'). Pass to your backend / send to
+ Apple's External Purchase Server API.
+
+
+ error{' '}
+
+ (string?)
+ {' '}
+ — Populated when the sheet failed to present.
+
- billingProgramAndroid{' '}
-
- (required,{' '}
-
- BillingProgramAndroid
-
- )
- {' '}
- — Note: this is a config field of InitConnectionConfig{' '}
- passed to initConnection(), not a standalone mutation.
-
-
-
-
- Returns
-
-
- Promise<void> — Resolves once the program is enabled.
-
+ billingProgramAndroid{' '}
+
+ (required,{' '}
+
+ BillingProgramAndroid
+
+ )
+ {' '}
+ — Note: this is a config field of InitConnectionConfig{' '}
+ passed to initConnection(), not a standalone mutation.
+
+
+
+
+ Returns
+
+
+ Promise<void> — Resolves once the program is enabled.
+
- Promise<string> — ISO 3166-1 alpha-2 country code of
- the user's storefront (e.g. "US", "KR").
- Returns the App Store / Play Store account region, NOT the device
- locale.
-
+ Promise<string> — ISO 3166-1 alpha-2 country code of
+ the user's storefront (e.g. "US", "KR").
+ Returns the App Store / Play Store account region, NOT the device
+ locale.
+
-
- Promise<PurchaseIOS[]>
- {' '}
- — array of StoreKit transactions in the iOS-specific shape. See{' '}
-
- Purchase
- {' '}
- for the full field reference.
-
+
+ Promise<PurchaseIOS[]>
+ {' '}
+ — array of StoreKit transactions in the iOS-specific shape. See{' '}
+
+ Purchase
+ {' '}
+ for the full field reference.
+
-
- Promise<AppTransaction | null>
- {' '}
- — JWS-verified record of how the app was acquired. Returns{' '}
- null on iOS < 16 or when no transaction is available.
-
+
+ Promise<AppTransaction | null>
+ {' '}
+ — JWS-verified record of how the app was acquired. Returns{' '}
+ null on iOS < 16 or when no transaction is available.
+
-
- Promise<ExternalPurchaseCustomLinkTokenResultIOS>
- {' '}
- — token plus its acquired/expiry metadata. Send the token{' '}
- field to Apple's External Purchase Server within the documented validity
- window.
-
+
+ Promise<ExternalPurchaseCustomLinkTokenResultIOS>
+ {' '}
+ — token plus its acquired/expiry metadata. Send the token{' '}
+ field to Apple's External Purchase Server within the documented validity
+ window.
+
-
- Promise<PurchaseIOS[]>
- {' '}
- — array of StoreKit transactions in the iOS-specific shape. See{' '}
-
- Purchase
- {' '}
- for the full field reference.
-
+
+ Promise<PurchaseIOS[]>
+ {' '}
+ — array of StoreKit transactions in the iOS-specific shape. See{' '}
+
+ Purchase
+ {' '}
+ for the full field reference.
+
-
- Promise<ExternalPurchaseLinkResultIOS>
- {' '}
- — carries the result of opening the external link (success flag + any
- error string from StoreKit).
-
+
+ Promise<ExternalPurchaseLinkResultIOS>
+ {' '}
+ — carries the result of opening the external link (success flag + any
+ error string from StoreKit).
+
-
- Promise<ExternalPurchaseCustomLinkNoticeResultIOS>
- {' '}
- — the user's response (continue / cancelled)
- plus the disclosure type that was shown.
-
+
+ Promise<ExternalPurchaseCustomLinkNoticeResultIOS>
+ {' '}
+ — the user's response (continue / cancelled)
+ plus the disclosure type that was shown.
+
-
- Promise<PurchaseIOS[]>
- {' '}
- — purchases whose status changed while the manage-subscriptions sheet
- was on screen (e.g. cancelled or auto-renew toggled). Empty array when
- nothing changed.
-
+
+ Promise<PurchaseIOS[]>
+ {' '}
+ — purchases whose status changed while the manage-subscriptions sheet
+ was on screen (e.g. cancelled or auto-renew toggled). Empty array when
+ nothing changed.
+
+ Promise<void> — Resolves once the platform finishes
+ the restore. The restored purchases are emitted via{' '}
+ purchaseUpdatedListener / surface as{' '}
+ getAvailablePurchases results, depending on platform.
+
+
Example
{{
From 2a589061e7a90a0bc49041d93b68a4ac1bde09da Mon Sep 17 00:00:00 2001
From: hyochan
Date: Sun, 26 Apr 2026 15:16:11 +0900
Subject: [PATCH 17/26] =?UTF-8?q?docs:=20address=20Coderabbit=20Round=209?=
=?UTF-8?q?=20=E2=80=94=20Safari=20regex=20+=20casing=20+=20bad=20links?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- CodeBlock.tsx: removed both negative-lookbehind regexes
\`(?])\\b([A-Z]...)\\b\` (TS/JS branch + Swift/Kotlin/Dart/GDScript
branch). Vite's default \`build.target: 'modules'\` still includes
Safari versions that ship ES modules but not regex lookbehind
(Safari < 16.4) — those would throw a SyntaxError on load.
Replaced with a \`linkifyTypesInTextSegments(html)\` helper that
splits the already-marked-up string on \`<...>\` tag boundaries via
\`html.split(/(<[^>]+>)/)\` and applies the capitals-regex ONLY to
the text segments in between. Same effect (skip text inside
highlight spans), portable to every browser.
- expo-iap useIAP.ts + react-native-iap useIAP.ts: doc-comment said
the enum exposes only "Iapkit" but the actual TypeScript literal is
the lowercase \`iapkit\`. Reworded to "currently only \`iapkit\`
(IAPKit)" to match real values without losing the product-name spelling.
- validate-receipt-ios.tsx Returns: the "use verifyPurchase" link
pointed to \`/docs/apis/get-active-subscriptions\` (totally
unrelated). Retargeted to \`/docs/features/validation#verify-purchase\`.
- enable-billing-program-android.tsx: dropped the Parameters/Returns
sections (they implied a callable mutation that doesn't exist) and
replaced them with a "Config field" section that documents
\`enableBillingProgramAndroid\` as an \`InitConnectionConfig\` field
passed to \`initConnection()\`, which is what the rest of the page
already says.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
libraries/expo-iap/src/useIAP.ts | 2 +-
.../react-native-iap/src/hooks/useIAP.ts | 2 +-
packages/docs/src/components/CodeBlock.tsx | 40 ++++++++++---------
.../enable-billing-program-android.tsx | 40 +++++++++----------
.../docs/apis/ios/validate-receipt-ios.tsx | 5 ++-
5 files changed, 46 insertions(+), 43 deletions(-)
diff --git a/libraries/expo-iap/src/useIAP.ts b/libraries/expo-iap/src/useIAP.ts
index 8ba12a15..a8615bd0 100644
--- a/libraries/expo-iap/src/useIAP.ts
+++ b/libraries/expo-iap/src/useIAP.ts
@@ -588,7 +588,7 @@ export function useIAP(options?: UseIAPOptions): UseIap {
}, []);
/**
- * Verify via a managed provider (currently IAPKit; the PurchaseVerificationProvider enum exposes only Iapkit today).
+ * Verify via a managed provider — currently only `iapkit` (IAPKit). The PurchaseVerificationProvider enum exposes no other provider literal today.
*
* @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider}
*/
diff --git a/libraries/react-native-iap/src/hooks/useIAP.ts b/libraries/react-native-iap/src/hooks/useIAP.ts
index 87e9e1ca..89d297f6 100644
--- a/libraries/react-native-iap/src/hooks/useIAP.ts
+++ b/libraries/react-native-iap/src/hooks/useIAP.ts
@@ -197,7 +197,7 @@ type UseIap = {
options: VerifyPurchaseProps,
) => Promise;
/**
- * Verify via a managed provider (currently IAPKit; the PurchaseVerificationProvider enum exposes only Iapkit today).
+ * Verify via a managed provider — currently only `iapkit` (IAPKit). The PurchaseVerificationProvider enum exposes no other provider literal today.
*
* @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider}
*/
diff --git a/packages/docs/src/components/CodeBlock.tsx b/packages/docs/src/components/CodeBlock.tsx
index e465ea65..fa3eaf7d 100644
--- a/packages/docs/src/components/CodeBlock.tsx
+++ b/packages/docs/src/components/CodeBlock.tsx
@@ -113,6 +113,25 @@ function linkifyType(name: string): string {
return `${name}`;
}
+// Split an already-marked-up HTML string on `<...>` tag boundaries and
+// run the capitalized-identifier linkify pass ONLY on the text segments
+// in between. This avoids regex lookbehind (Safari < 16.4 doesn't
+// support it under Vite's default `target: 'modules'`) and stops
+// keywords already wrapped by upstream passes — Dart `Future`,
+// GDScript `String`, etc. — from being re-wrapped as class-name and
+// clobbering their original token color.
+function linkifyTypesInTextSegments(html: string): string {
+ return html
+ .split(/(<[^>]+>)/)
+ .map((segment) => {
+ if (segment.startsWith('<')) return segment;
+ return segment.replace(/\b([A-Z][a-zA-Z0-9_]*)\b/g, (_, name: string) =>
+ linkifyType(name)
+ );
+ })
+ .join('');
+}
+
function CodeBlock({ children, language = 'graphql' }: CodeBlockProps) {
const codeRef = useRef(null);
const [copied, setCopied] = useState(false);
@@ -272,16 +291,7 @@ function highlightCode(element: HTMLElement, language: string) {
// Capitalized identifiers → linkify known OpenIAP types (so e.g.
// `ProductRequest`, `Purchase[]`, `Promise` in
// a TS signature jump to /docs/types/...).
- // The negative lookbehind `(?])` skips capitals that sit
- // immediately after an HTML attribute quote or a closing `>` —
- // i.e. text already wrapped by the keyword / function passes
- // above. Without it we'd nest tags (e.g. wrap `Future` inside
- // `Future`) and clobber the
- // upstream token color.
- processed = processed.replace(
- /(?])\b([A-Z][a-zA-Z0-9_]*)\b/g,
- (_, name: string) => linkifyType(name)
- );
+ processed = linkifyTypesInTextSegments(processed);
result += processed;
}
@@ -385,15 +395,7 @@ function highlightCode(element: HTMLElement, language: string) {
// Types (capitalized words). Known OpenIAP type names render as
// anchors to /docs/types/...; unknown ones stay as plain class-name
// spans so styling is identical.
- // Negative lookbehind `(?])` skips capitals already inside
- // tags emitted by the keyword/function/decorator passes above —
- // languages like Dart treat `Future`/`Function` and GDScript treats
- // `String`/`Array` as keywords, so the bare `\b[A-Z]...\b` pattern
- // would re-wrap them and override the upstream token color.
- processed = processed.replace(
- /(?])\b([A-Z][a-zA-Z0-9_]*)\b/g,
- (_, name: string) => linkifyType(name)
- );
+ processed = linkifyTypesInTextSegments(processed);
// Annotations/Attributes
processed = processed.replace(
diff --git a/packages/docs/src/pages/docs/apis/android/enable-billing-program-android.tsx b/packages/docs/src/pages/docs/apis/android/enable-billing-program-android.tsx
index 46cc08f5..26e6c982 100644
--- a/packages/docs/src/pages/docs/apis/android/enable-billing-program-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/enable-billing-program-android.tsx
@@ -86,29 +86,27 @@ func init_connection(config: InitConnectionConfig) -> bool`}
}}
-
- Parameters
-
-
-
- billingProgramAndroid{' '}
-
- (required,{' '}
-
- BillingProgramAndroid
-
- )
- {' '}
- — Note: this is a config field of InitConnectionConfig{' '}
- passed to initConnection(), not a standalone mutation.
-
-
-
-
- Returns
+
+ Config field
- Promise<void> — Resolves once the program is enabled.
+ enableBillingProgramAndroid on{' '}
+
+ InitConnectionConfig
+
+ : optional{' '}
+
+ BillingProgramAndroid
+
+ . Pass the program identifier you want to enable (e.g.{' '}
+ 'external-offer') as part of the config you hand to{' '}
+
+ initConnection()
+
+ ; the connection succeeds with the program enabled, and{' '}
+ initConnection()'s own Promise<boolean>{' '}
+ return value indicates the overall connection result. There is no
+ separate enableBillingProgramAndroid() call.
From 5c8ea3ee165d3b4f8ff9299b6e22b62088b027e9 Mon Sep 17 00:00:00 2001
From: hyochan
Date: Sun, 26 Apr 2026 15:44:11 +0900
Subject: [PATCH 18/26] fix(docs): table column squeeze + horizontal scroll
fallback
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
User screenshot showed the External Purchase APIs table on
/docs/types/external-purchase-link with the "AVAILABILITY" column
header rendering one letter per row — a 3-column table where the
identifier and description columns refused to wrap was squeezing the
last column to per-character width.
Root cause: the rule "non-last columns: nowrap, width:1%" applied to
EVERY non-last column, including middle Description-style columns.
On 2-column tables this was fine; on 3+ column tables it forced the
last column to absorb impossible width.
Fix:
- Only the FIRST column (identifier name) keeps `width:1%; nowrap`.
- All other columns wrap normally with `overflow-wrap: anywhere` as a
safety net.
- Added `display: block; overflow-x: auto` on the table itself so
pathological cases (very narrow phones with many columns) scroll
horizontally instead of squeezing.
How to prevent this class of bug in future:
1. Don't apply `nowrap` to any column other than the identifier.
2. Trust browser table layout — it handles 2/3/4 column cases when
given normal `white-space`.
3. For mobile-first reads, an `overflow-x: auto` table fallback is
cheap insurance.
4. When a table starts feeling cramped (like the parameters tables we
just converted to `
` lists), prefer the prose list pattern;
tables are right for grid-of-fields data, not for narrative.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
packages/docs/src/styles/documentation.css | 40 +++++++++++++---------
1 file changed, 24 insertions(+), 16 deletions(-)
diff --git a/packages/docs/src/styles/documentation.css b/packages/docs/src/styles/documentation.css
index c2b3b636..6abd14a0 100644
--- a/packages/docs/src/styles/documentation.css
+++ b/packages/docs/src/styles/documentation.css
@@ -563,16 +563,21 @@
opacity: 1;
}
-/* Tables — full-width table layout. Non-last columns shrink to fit their
- nowrap content; the last column absorbs remaining width and wraps. */
+/* Tables — full-width layout, but allow horizontal scrolling when the
+ minimum content width exceeds the available space (rare, but
+ prevents catastrophic squeeze on phones). The `display: block`
+ trick + `overflow-x: auto` is the most portable way to scope the
+ scroll to the table without needing a wrapper element. */
.error-table,
.doc-page table {
+ display: block;
width: 100%;
+ max-width: 100%;
+ overflow-x: auto;
border-collapse: collapse;
margin: 1.5rem 0;
background: var(--bg-primary);
border-radius: 0.5rem;
- overflow: hidden;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
@@ -600,24 +605,27 @@
border-bottom: 1px solid var(--border-color);
}
-/* Non-last columns (Name, Type, etc.) shrink to fit their content and
- keep identifiers on one line. */
-.error-table th:not(:last-child),
-.error-table td:not(:last-child),
-.doc-page table th:not(:last-child),
-.doc-page table td:not(:last-child) {
+/* Only the FIRST column (identifier name) stays on one line — applying
+ `nowrap; width:1%` to every non-last column also forced middle
+ columns like Description to refuse to wrap, which then squeezed the
+ last column (e.g. Availability `iOS 17.4+`) to per-character width
+ on narrow viewports. */
+.error-table th:first-child,
+.error-table td:first-child,
+.doc-page table th:first-child,
+.doc-page table td:first-child {
width: 1%;
white-space: nowrap;
vertical-align: top;
}
-/* Last column (Summary/Description) absorbs remaining width and wraps at
- word boundaries only — never breaks single characters per line. */
-.error-table th:last-child,
-.error-table td:last-child,
-.doc-page table th:last-child,
-.doc-page table td:last-child {
- width: auto;
+/* All other columns wrap at word boundaries; long fields like
+ identifiers stay readable thanks to overflow-wrap: anywhere as a
+ safety net (no per-character wrap unless absolutely necessary). */
+.error-table th:not(:first-child),
+.error-table td:not(:first-child),
+.doc-page table th:not(:first-child),
+.doc-page table td:not(:first-child) {
white-space: normal;
vertical-align: top;
overflow-wrap: anywhere;
From e58c27c1acb0873332ce3a3d489892fe2a3e3b83 Mon Sep 17 00:00:00 2001
From: hyochan
Date: Sun, 26 Apr 2026 16:02:22 +0900
Subject: [PATCH 19/26] =?UTF-8?q?docs:=20address=20Coderabbit=20Round=2011?=
=?UTF-8?q?=20=E2=80=94=20type/field=20accuracy=20+=20Safari=20fix?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- CodeBlock.tsx: linkifyTypesInTextSegments was still wrapping text
inside existing keyword/function spans because splitting on
`<...>` boundaries doesn't tell you whether you're INSIDE a tag.
Added a depth counter so capitals are only linkified at depth 0 —
Dart `Future`, GDScript `String`, etc. now keep their keyword color
instead of getting nested under a class-name span.
- is-billing-program-available-android.tsx: Returns table fields
corrected to match the canonical `BillingProgramAvailabilityResultAndroid`
type (`billingProgram` + `isAvailable`); removed the
`responseCode`/`debugMessage` rows that were pure invention.
- launch-external-link-android.tsx: Parameters list and TS/Dart/GDScript
examples used non-existent `program` and `url` fields. Replaced
with the real `LaunchExternalLinkParamsAndroid` shape:
`billingProgram` + `launchMode` + `linkType` + `linkUri`.
- get-available-purchases.tsx: aligned `includeSuspendedAndroid`
description with schema wording — "suspended subscriptions
(Android Billing 8.1+)" + warning that suspended entries must NOT
grant entitlements.
- get-storefront.tsx: folded the orphan trailing
"empty string when storefront can't be determined" paragraph into
the Returns section so anchor-linkers see the full contract.
- init-connection.tsx: clarified that
`enableBillingProgramAndroid: 'external-payments'` needs Play
Billing 8.3.0+ (Japan only); the 8.2.0+ programs are
`EXTERNAL_CONTENT_LINK` / `EXTERNAL_OFFER`.
- begin-refund-request-ios.tsx: GDScript signature corrected to
`(product_id: String) -> Types.RefundResultIOS` (was `(sku) ->
Variant`); GDScript example dropped the `await` because the impl
is synchronous; TS example now imports `Platform` from
`react-native`.
- is-eligible-for-intro-offer-ios.tsx: TypeScript signature uses
`groupId` (camelCase wrapper) while keeping `groupID` (Swift
convention) on the Swift / Kotlin tabs; Parameters note explains
the discrepancy.
- present-code-redemption-sheet-ios.tsx + sync-ios.tsx: GDScript
`-> Variant` corrected to `-> Types.VoidResult` (matches the
godot-iap docstring + actual return).
- show-external-purchase-custom-link-notice-ios.tsx + the External
Purchase Link type page: rewrote the Notice noticeType + result
shape — the only valid `ExternalPurchaseCustomLinkNoticeTypeIOS`
is `'browser'` (Apple's canonical name), and the result is
`{ continued: boolean; error?: string }`, not the invented
`result: 'continue' | 'cancelled'` + `noticeType` echo.
- restore-purchases.tsx: rewrote the iOS sentence — `restorePurchases`
delegates to `syncIOS()` which calls `AppStore.sync()` to refresh
StoreKit's transaction state; restored purchases are then read via
`getAvailablePurchases`. Android docs anchor changed from `#fetch`
(doesn't exist on the integration page) to the integration page
itself.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
packages/docs/src/components/CodeBlock.tsx | 24 +++++++----
.../is-billing-program-available-android.tsx | 23 +++++------
.../android/launch-external-link-android.tsx | 40 ++++++++++++++-----
.../docs/apis/get-available-purchases.tsx | 7 +++-
.../src/pages/docs/apis/get-storefront.tsx | 10 ++---
.../src/pages/docs/apis/init-connection.tsx | 6 ++-
.../apis/ios/begin-refund-request-ios.tsx | 6 ++-
.../ios/is-eligible-for-intro-offer-ios.tsx | 8 ++--
.../ios/present-code-redemption-sheet-ios.tsx | 2 +-
...ternal-purchase-custom-link-notice-ios.tsx | 36 ++++++++++++-----
.../docs/src/pages/docs/apis/ios/sync-ios.tsx | 2 +-
.../src/pages/docs/apis/restore-purchases.tsx | 11 +++--
.../docs/types/external-purchase-link.tsx | 15 ++-----
13 files changed, 117 insertions(+), 73 deletions(-)
diff --git a/packages/docs/src/components/CodeBlock.tsx b/packages/docs/src/components/CodeBlock.tsx
index fa3eaf7d..b1ede0d7 100644
--- a/packages/docs/src/components/CodeBlock.tsx
+++ b/packages/docs/src/components/CodeBlock.tsx
@@ -114,17 +114,27 @@ function linkifyType(name: string): string {
}
// Split an already-marked-up HTML string on `<...>` tag boundaries and
-// run the capitalized-identifier linkify pass ONLY on the text segments
-// in between. This avoids regex lookbehind (Safari < 16.4 doesn't
-// support it under Vite's default `target: 'modules'`) and stops
-// keywords already wrapped by upstream passes — Dart `Future`,
-// GDScript `String`, etc. — from being re-wrapped as class-name and
-// clobbering their original token color.
+// run the capitalized-identifier linkify pass ONLY on text segments
+// that sit OUTSIDE every existing tag. Tracks a tag-depth counter so
+// text content INSIDE a `…` emitted by an
+// upstream pass (Dart `Future`/`Function`, GDScript `String`/`Array`,
+// already-wrapped function names, …) is skipped — without the depth
+// check we'd nest a class-name span inside the keyword span and clobber
+// its color. Avoids regex lookbehind (Safari < 16.4 doesn't support it
+// under Vite's default `target: 'modules'`).
function linkifyTypesInTextSegments(html: string): string {
+ let depth = 0;
return html
.split(/(<[^>]+>)/)
.map((segment) => {
- if (segment.startsWith('<')) return segment;
+ if (segment.startsWith('<')) {
+ // Self-closing ` ` etc. don't change depth.
+ if (segment.endsWith('/>')) return segment;
+ if (segment.startsWith('')) depth = Math.max(0, depth - 1);
+ else depth += 1;
+ return segment;
+ }
+ if (depth > 0) return segment;
return segment.replace(/\b([A-Z][a-zA-Z0-9_]*)\b/g, (_, name: string) =>
linkifyType(name)
);
diff --git a/packages/docs/src/pages/docs/apis/android/is-billing-program-available-android.tsx b/packages/docs/src/pages/docs/apis/android/is-billing-program-available-android.tsx
index 4bfbd1d0..76839d0b 100644
--- a/packages/docs/src/pages/docs/apis/android/is-billing-program-available-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/is-billing-program-available-android.tsx
@@ -101,25 +101,22 @@ suspend fun isBillingProgramAvailable(
- isAvailable{' '}
-
- (boolean)
- {' '}
- — Whether the billing program is available for this user/device.
-
-
- responseCode{' '}
+ billingProgram{' '}
- (number?)
+ (
+
+ BillingProgramAndroid
+
+ )
{' '}
- — Raw Play Billing response code (when Play returned one).
+ — Echoes back the program that was checked.
- debugMessage{' '}
+ isAvailable{' '}
- (string?)
+ (boolean)
{' '}
- — Optional debug message from Play.
+ — Whether the billing program is available for this user/device.
diff --git a/packages/docs/src/pages/docs/apis/android/launch-external-link-android.tsx b/packages/docs/src/pages/docs/apis/android/launch-external-link-android.tsx
index 6e59048f..3a895da0 100644
--- a/packages/docs/src/pages/docs/apis/android/launch-external-link-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/launch-external-link-android.tsx
@@ -94,7 +94,7 @@ suspend fun launchExternalLink(
- program{' '}
+ billingProgram{' '}
(required,{' '}
@@ -103,14 +103,28 @@ suspend fun launchExternalLink(
)
{' '}
— Billing program the link belongs to (e.g.{' '}
- EXTERNAL_OFFER).
+ EXTERNAL_CONTENT_LINK or EXTERNAL_OFFER).
- url{' '}
+ launchMode{' '}
+
+ (required, ExternalLinkLaunchModeAndroid)
+ {' '}
+ — How the link is presented (in-app browser, system browser, etc.).
+
+
+ linkType{' '}
+
+ (required, ExternalLinkTypeAndroid)
+ {' '}
+ — Type of the external link (e.g. offer page).
+
+
+ linkUri{' '}
(required, string)
{' '}
- — External URL to launch after the Play disclosure dialog dismisses.
+ — External URI to launch after the Play disclosure dialog dismisses.
@@ -153,8 +167,10 @@ import { launchExternalLinkAndroid } from 'expo-iap';
if (Platform.OS === 'android') {
await launchExternalLinkAndroid({
- program: 'external-offer',
- url: 'https://example.com/offer',
+ billingProgram: 'external-offer',
+ launchMode: 'in-app-browser',
+ linkType: 'offer',
+ linkUri: 'https://example.com/offer',
});
}`}
),
@@ -162,8 +178,10 @@ if (Platform.OS === 'android') {
{`if (Platform.isAndroid) {
await FlutterInappPurchase.instance.launchExternalLinkAndroid(
LaunchExternalLinkParamsAndroid(
- program: BillingProgramAndroid.externalOffer,
- url: 'https://example.com/offer',
+ billingProgram: BillingProgramAndroid.externalOffer,
+ launchMode: ExternalLinkLaunchModeAndroid.inAppBrowser,
+ linkType: ExternalLinkTypeAndroid.offer,
+ linkUri: 'https://example.com/offer',
),
);
}`}
@@ -171,8 +189,10 @@ if (Platform.OS === 'android') {
gdscript: (
{`if iap.get_platform() == "Android":
var params = LaunchExternalLinkParamsAndroid.new()
- params.program = BillingProgramAndroid.EXTERNAL_OFFER
- params.url = "https://example.com/offer"
+ params.billing_program = BillingProgramAndroid.EXTERNAL_OFFER
+ params.launch_mode = ExternalLinkLaunchModeAndroid.IN_APP_BROWSER
+ params.link_type = ExternalLinkTypeAndroid.OFFER
+ params.link_uri = "https://example.com/offer"
await iap.launch_external_link_android(params)`}
),
}}
diff --git a/packages/docs/src/pages/docs/apis/get-available-purchases.tsx b/packages/docs/src/pages/docs/apis/get-available-purchases.tsx
index 573aa16e..b15a0850 100644
--- a/packages/docs/src/pages/docs/apis/get-available-purchases.tsx
+++ b/packages/docs/src/pages/docs/apis/get-available-purchases.tsx
@@ -110,8 +110,11 @@ interface PurchaseOptions {
(optional, boolean, default false)
{' '}
- — Android. Include subscriptions in a paused/grace
- state.
+ — Android (Billing 8.1+). Include suspended
+ subscriptions in the result. Suspended entries (
+ isSuspendedAndroid === true) should NOT grant
+ entitlements — direct the user to the subscription center to resolve
+ payment first.
diff --git a/packages/docs/src/pages/docs/apis/get-storefront.tsx b/packages/docs/src/pages/docs/apis/get-storefront.tsx
index dcdf3144..47c71311 100644
--- a/packages/docs/src/pages/docs/apis/get-storefront.tsx
+++ b/packages/docs/src/pages/docs/apis/get-storefront.tsx
@@ -70,9 +70,9 @@ function GetStorefront() {
Promise<string> — ISO 3166-1 alpha-2 country code of
- the user's storefront (e.g. "US", "KR").
- Returns the App Store / Play Store account region, NOT the device
- locale.
+ the user's storefront (e.g. "US", "KR"), or an
+ empty string when the storefront can't be determined. Returns the App
+ Store / Play Store account region, NOT the device locale.
Example
@@ -123,10 +123,6 @@ function StorefrontBadge() {
}}
-
- Returns the ISO 3166-1 alpha-2 country code. Returns an empty string
- when the storefront cannot be determined.
-
);
}
diff --git a/packages/docs/src/pages/docs/apis/init-connection.tsx b/packages/docs/src/pages/docs/apis/init-connection.tsx
index e3d79635..1b1f7f84 100644
--- a/packages/docs/src/pages/docs/apis/init-connection.tsx
+++ b/packages/docs/src/pages/docs/apis/init-connection.tsx
@@ -102,8 +102,10 @@ function InitConnection() {
)
{' '}
- — Android. Enable a Play Billing 8.2.0+ program
- (External Payments etc.) at connection time.
+ — Android. Enable a Play Billing 8.2.0+ program (
+ EXTERNAL_CONTENT_LINK / EXTERNAL_OFFER) at
+ connection time. EXTERNAL_PAYMENTS is gated to Billing
+ 8.3.0+ (Japan only).
diff --git a/packages/docs/src/pages/docs/apis/ios/begin-refund-request-ios.tsx b/packages/docs/src/pages/docs/apis/ios/begin-refund-request-ios.tsx
index 86c97d09..5b718d27 100644
--- a/packages/docs/src/pages/docs/apis/ios/begin-refund-request-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/begin-refund-request-ios.tsx
@@ -53,7 +53,7 @@ function BeginRefundRequestIOS() {
{`Future beginRefundRequestIOS(String sku);`}
),
gdscript: (
- {`func begin_refund_request_ios(sku: String) -> Variant`}
+ {`func begin_refund_request_ios(product_id: String) -> Types.RefundResultIOS`}
),
}}
@@ -91,6 +91,7 @@ val status = kmpIAP.beginRefundRequestIOS(sku = "com.app.premium")`}
),
typescript: (
{`// expo-iap (also exported from react-native-iap)
+import { Platform } from 'react-native';
import { beginRefundRequestIOS } from 'expo-iap';
if (Platform.OS === 'ios') {
@@ -105,7 +106,8 @@ if (Platform.OS === 'ios') {
),
gdscript: (
{`if iap.get_platform() == "iOS":
- var status = await iap.begin_refund_request_ios("com.app.premium")`}
+ # Synchronous — no await; returns Types.RefundResultIOS directly.
+ var result = iap.begin_refund_request_ios("com.app.premium")`}
),
}}
diff --git a/packages/docs/src/pages/docs/apis/ios/is-eligible-for-intro-offer-ios.tsx b/packages/docs/src/pages/docs/apis/ios/is-eligible-for-intro-offer-ios.tsx
index 0385c56d..d81fb882 100644
--- a/packages/docs/src/pages/docs/apis/ios/is-eligible-for-intro-offer-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/is-eligible-for-intro-offer-ios.tsx
@@ -47,7 +47,7 @@ function IsEligibleForIntroOfferIOS() {
{`suspend fun isEligibleForIntroOfferIOS(groupID: String): Boolean`}
),
typescript: (
- {`isEligibleForIntroOfferIOS(groupID: string): Promise`}
+ {`isEligibleForIntroOfferIOS(groupId: string): Promise`}
),
dart: (
{`Future isEligibleForIntroOfferIOS(String groupID);`}
@@ -63,11 +63,13 @@ function IsEligibleForIntroOfferIOS() {
- groupID{' '}
+ groupId{' '}
(required, string)
{' '}
- — Subscription group identifier.
+ — Subscription group identifier. (Native Swift / Kotlin signatures
+ spell it groupID; the JavaScript / Dart wrappers expose
+ it as groupId.)
diff --git a/packages/docs/src/pages/docs/apis/ios/present-code-redemption-sheet-ios.tsx b/packages/docs/src/pages/docs/apis/ios/present-code-redemption-sheet-ios.tsx
index 0cc09f47..8f88b09f 100644
--- a/packages/docs/src/pages/docs/apis/ios/present-code-redemption-sheet-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/present-code-redemption-sheet-ios.tsx
@@ -52,7 +52,7 @@ function PresentCodeRedemptionSheetIOS() {
{`Future presentCodeRedemptionSheetIOS();`}
),
gdscript: (
- {`func present_code_redemption_sheet_ios() -> Variant`}
+ {`func present_code_redemption_sheet_ios() -> Types.VoidResult`}
),
}}
diff --git a/packages/docs/src/pages/docs/apis/ios/show-external-purchase-custom-link-notice-ios.tsx b/packages/docs/src/pages/docs/apis/ios/show-external-purchase-custom-link-notice-ios.tsx
index 1ea2a7fa..d7b2483a 100644
--- a/packages/docs/src/pages/docs/apis/ios/show-external-purchase-custom-link-notice-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/show-external-purchase-custom-link-notice-ios.tsx
@@ -96,50 +96,66 @@ function ShowExternalPurchaseCustomLinkNoticeIOS() {
Promise<ExternalPurchaseCustomLinkNoticeResultIOS>
{' '}
- — the user's response (continue / cancelled)
- plus the disclosure type that was shown.
+ — carries:
+
+
+ continued{' '}
+
+ (boolean)
+ {' '}
+ — Whether the user chose to continue to the external purchase.
+
+
+ error{' '}
+
+ (string?)
+ {' '}
+ — Populated when the sheet fails to present.
+
+
Example
{{
swift: (
{`let result = try await OpenIapModule.shared.showExternalPurchaseCustomLinkNoticeIOS(
- noticeType: .continue
+ noticeType: .browser
)`}
),
kotlin: (
{`// kmp-iap (iOS targets only — no-op on Android)
val result = kmpIAP.showExternalPurchaseCustomLinkNoticeIOS(
- noticeType = ExternalPurchaseCustomLinkNoticeTypeIOS.CONTINUE
+ noticeType = ExternalPurchaseCustomLinkNoticeTypeIOS.Browser
)`}
),
typescript: (
{`// expo-iap (also exported from react-native-iap)
+import { Platform } from 'react-native';
import { showExternalPurchaseCustomLinkNoticeIOS } from 'expo-iap';
if (Platform.OS === 'ios') {
- await showExternalPurchaseCustomLinkNoticeIOS('continue');
+ await showExternalPurchaseCustomLinkNoticeIOS('browser');
}`}
),
dart: (
{`if (Platform.isIOS) {
await FlutterInappPurchase.instance.showExternalPurchaseCustomLinkNoticeIOS(
- ExternalPurchaseCustomLinkNoticeTypeIOS.continue_,
+ ExternalPurchaseCustomLinkNoticeTypeIOS.Browser,
);
}`}
),
gdscript: (
{`if iap.get_platform() == "iOS":
- var result = await iap.show_external_purchase_custom_link_notice_ios("continue")`}
+ var result = await iap.show_external_purchase_custom_link_notice_ios("browser")`}
),
}}
- noticeType picks the disclosure style required by the flow
- you are entering (e.g. .acquisition for first-time
- payments, .services for ongoing services).
+ ExternalPurchaseCustomLinkNoticeTypeIOS currently has a
+ single value: 'browser' (case-sensitive — Swift / Kotlin /
+ Dart spell it as .browser / .Browser).
);
diff --git a/packages/docs/src/pages/docs/apis/ios/sync-ios.tsx b/packages/docs/src/pages/docs/apis/ios/sync-ios.tsx
index ed11cfa8..7810f718 100644
--- a/packages/docs/src/pages/docs/apis/ios/sync-ios.tsx
+++ b/packages/docs/src/pages/docs/apis/ios/sync-ios.tsx
@@ -49,7 +49,7 @@ function SyncIOS() {
{`Future syncIOS();`}
),
gdscript: (
- {`func sync_ios() -> Variant`}
+ {`func sync_ios() -> Types.VoidResult`}
),
}}
diff --git a/packages/docs/src/pages/docs/apis/restore-purchases.tsx b/packages/docs/src/pages/docs/apis/restore-purchases.tsx
index f1f75159..73dcb683 100644
--- a/packages/docs/src/pages/docs/apis/restore-purchases.tsx
+++ b/packages/docs/src/pages/docs/apis/restore-purchases.tsx
@@ -1,3 +1,4 @@
+import { Link } from 'react-router-dom';
import AnchorLink from '../../../components/AnchorLink';
import CodeBlock from '../../../components/CodeBlock';
import LanguageTabs from '../../../components/LanguageTabs';
@@ -21,8 +22,12 @@ function RestorePurchases() {
Purchases" button for users who reinstall the app.
+ )}
);
diff --git a/packages/docs/src/pages/docs/index.tsx b/packages/docs/src/pages/docs/index.tsx
index b68c0515..2eabdcd1 100644
--- a/packages/docs/src/pages/docs/index.tsx
+++ b/packages/docs/src/pages/docs/index.tsx
@@ -1,4 +1,5 @@
import { useState, useEffect } from 'react';
+import { createPortal } from 'react-dom';
import {
Route,
Routes,
@@ -151,29 +152,49 @@ function Docs() {
return () => window.removeEventListener('scroll', handleScroll);
}, []);
+ // Portal the sidebar toggle to document.body so it sits OUTSIDE any
+ // ancestor's stacking context, AND fully unmount it while the drawer
+ // is open. Earlier rounds left the toggle in the DOM with
+ // `.hidden { opacity: 0; pointer-events: none }` while the drawer was
+ // open, which on iOS Safari still let the toggle absorb taps that
+ // landed on the drawer's first menu item ("APIs" header sits at
+ // y≈88-120px, exactly where the fixed toggle at top: 70px lives).
+ // Removing the element from the DOM entirely guarantees the drawer
+ // items underneath get every tap they should.
+ const sidebarToggle = isSidebarOpen
+ ? null
+ : createPortal(
+ ,
+ document.body
+ );
+
return (
-
+ {sidebarToggle}
{isSidebarOpen && (
diff --git a/packages/docs/src/styles/documentation.css b/packages/docs/src/styles/documentation.css
index 964c624e..2f1d21ce 100644
--- a/packages/docs/src/styles/documentation.css
+++ b/packages/docs/src/styles/documentation.css
@@ -896,8 +896,14 @@
pointer-events: auto;
}
+/* When the user scrolls, keep the toggle clear of the sticky top nav
+ (56px tall) instead of jumping it up to `top: 1rem` which lands the
+ button INSIDE the nav's bounding box. Even with z-index 9001 vs the
+ nav's 100, taps in the overlap zone were flaky on mobile WebKit —
+ keeping the toggle below the nav avoids the geometry collision
+ entirely. */
.docs-sidebar-toggle.scrolled {
- top: 1rem;
+ top: 64px;
}
.docs-sidebar-toggle svg {
@@ -976,13 +982,22 @@
background: var(--bg-secondary);
z-index: 9000;
transition:
+ transform 0.25s ease,
opacity 0.2s ease,
visibility 0.2s ease;
border-right: 1px solid var(--border-color);
padding: var(--spacing-xl) 0;
box-shadow: 4px 0 24px rgba(0, 0, 0, 0.15);
+ /* Closed state: slide fully off-screen, hide visually, AND disable
+ pointer events. iOS Safari has been observed to still deliver taps
+ to children of a `visibility: hidden; opacity: 0` fixed element,
+ so we belt-and-braces it: translateX moves the geometry out of the
+ hit-test area, and pointer-events: none turns off hit-testing for
+ this entire subtree even if the transform isn't honored. */
+ transform: translateX(-100%);
opacity: 0;
visibility: hidden;
+ pointer-events: none;
overflow-y: auto;
box-sizing: border-box;
}
@@ -994,8 +1009,10 @@
}
.docs-sidebar.open {
+ transform: translateX(0);
opacity: 1;
visibility: visible;
+ pointer-events: auto;
}
.docs-content {
From 33df55ac09a894f10682e72e594ac704ab297d8c Mon Sep 17 00:00:00 2001
From: hyochan
Date: Sun, 26 Apr 2026 22:14:19 +0900
Subject: [PATCH 24/26] docs: address coderabbit Round 13 findings
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- launch-external-link-android: replace fictional enum members
(IN_APP_BROWSER, OFFER, in-app-browser, offer, .inAppBrowser, .offer)
with the canonical values from each binding —
ExternalLinkLaunchModeAndroid.LaunchInExternalBrowserOrApp /
launch-in-external-browser-or-app /
LAUNCH_IN_EXTERNAL_BROWSER_OR_APP, and ExternalLinkTypeAndroid
.LinkToDigitalContentOffer / link-to-digital-content-offer /
LINK_TO_DIGITAL_CONTENT_OFFER — so all 5 example tabs actually
compile.
- canPresentExternalPurchaseNoticeIOS JSDoc in expo-iap and
react-native-iap: was "iOS 18.2+", but ExternalPurchase.canPresent
has been available since iOS 17.4. The notice sheet itself remains
iOS 18.2+; clarified in the comment so callers don't conflate the
two.
- scripts/audit-docs.ts: wrap main() in .catch so unhandled
rejections from walkTsxFiles / buildTypeIndex / file I/O surface
as a clear "audit-docs: fatal error" message and exit code 2,
instead of bubbling up as a confusing trace.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
libraries/expo-iap/src/modules/ios.ts | 6 +++++-
libraries/react-native-iap/src/index.ts | 6 +++++-
.../android/launch-external-link-android.tsx | 20 +++++++++----------
scripts/audit-docs.ts | 6 +++++-
4 files changed, 25 insertions(+), 13 deletions(-)
diff --git a/libraries/expo-iap/src/modules/ios.ts b/libraries/expo-iap/src/modules/ios.ts
index e610a563..7c0a9df8 100644
--- a/libraries/expo-iap/src/modules/ios.ts
+++ b/libraries/expo-iap/src/modules/ios.ts
@@ -443,7 +443,11 @@ export const deepLinkToSubscriptionsIOS = (): Promise =>
Linking.openURL('https://apps.apple.com/account/subscriptions');
/**
- * Check if the device can present an external purchase notice sheet (iOS 18.2+).
+ * Check if the device can present an external purchase notice sheet (iOS 17.4+).
+ *
+ * Wraps `ExternalPurchase.canPresent`, which Apple introduced in iOS 17.4.
+ * Note: the notice sheet itself (`presentExternalPurchaseNoticeSheetIOS`)
+ * still requires iOS 18.2+; only the eligibility check is available earlier.
*
* @returns Promise resolving to true if the notice sheet can be presented
* @platform iOS
diff --git a/libraries/react-native-iap/src/index.ts b/libraries/react-native-iap/src/index.ts
index f81d9173..4160c759 100644
--- a/libraries/react-native-iap/src/index.ts
+++ b/libraries/react-native-iap/src/index.ts
@@ -2895,7 +2895,11 @@ export const launchExternalLinkAndroid: MutationField<
// ------------------------------
/**
- * Check if the device can present an external purchase notice sheet (iOS 18.2+).
+ * Check if the device can present an external purchase notice sheet (iOS 17.4+).
+ *
+ * Wraps `ExternalPurchase.canPresent`, which Apple introduced in iOS 17.4.
+ * Note: the notice sheet itself (`presentExternalPurchaseNoticeSheetIOS`)
+ * still requires iOS 18.2+; only the eligibility check is available earlier.
*
* @returns Promise - true if notice sheet can be presented
* @platform iOS
diff --git a/packages/docs/src/pages/docs/apis/android/launch-external-link-android.tsx b/packages/docs/src/pages/docs/apis/android/launch-external-link-android.tsx
index 3a895da0..ec028a31 100644
--- a/packages/docs/src/pages/docs/apis/android/launch-external-link-android.tsx
+++ b/packages/docs/src/pages/docs/apis/android/launch-external-link-android.tsx
@@ -144,8 +144,8 @@ suspend fun launchExternalLink(
activity,
LaunchExternalLinkParamsAndroid(
billingProgram = BillingProgramAndroid.ExternalOffer,
- launchMode = ExternalLinkLaunchModeAndroid.IN_APP_BROWSER,
- linkType = ExternalLinkTypeAndroid.OFFER,
+ launchMode = ExternalLinkLaunchModeAndroid.LaunchInExternalBrowserOrApp,
+ linkType = ExternalLinkTypeAndroid.LinkToDigitalContentOffer,
linkUri = "https://example.com/offer"
)
)`}
@@ -155,8 +155,8 @@ suspend fun launchExternalLink(
kmpIAP.launchExternalLinkAndroid(
LaunchExternalLinkParamsAndroid(
billingProgram = BillingProgramAndroid.ExternalOffer,
- launchMode = ExternalLinkLaunchModeAndroid.IN_APP_BROWSER,
- linkType = ExternalLinkTypeAndroid.OFFER,
+ launchMode = ExternalLinkLaunchModeAndroid.LaunchInExternalBrowserOrApp,
+ linkType = ExternalLinkTypeAndroid.LinkToDigitalContentOffer,
linkUri = "https://example.com/offer"
)
)`}
@@ -168,8 +168,8 @@ import { launchExternalLinkAndroid } from 'expo-iap';
if (Platform.OS === 'android') {
await launchExternalLinkAndroid({
billingProgram: 'external-offer',
- launchMode: 'in-app-browser',
- linkType: 'offer',
+ launchMode: 'launch-in-external-browser-or-app',
+ linkType: 'link-to-digital-content-offer',
linkUri: 'https://example.com/offer',
});
}`}
@@ -179,8 +179,8 @@ if (Platform.OS === 'android') {
await FlutterInappPurchase.instance.launchExternalLinkAndroid(
LaunchExternalLinkParamsAndroid(
billingProgram: BillingProgramAndroid.externalOffer,
- launchMode: ExternalLinkLaunchModeAndroid.inAppBrowser,
- linkType: ExternalLinkTypeAndroid.offer,
+ launchMode: ExternalLinkLaunchModeAndroid.LaunchInExternalBrowserOrApp,
+ linkType: ExternalLinkTypeAndroid.LinkToDigitalContentOffer,
linkUri: 'https://example.com/offer',
),
);
@@ -190,8 +190,8 @@ if (Platform.OS === 'android') {
{`if iap.get_platform() == "Android":
var params = LaunchExternalLinkParamsAndroid.new()
params.billing_program = BillingProgramAndroid.EXTERNAL_OFFER
- params.launch_mode = ExternalLinkLaunchModeAndroid.IN_APP_BROWSER
- params.link_type = ExternalLinkTypeAndroid.OFFER
+ params.launch_mode = ExternalLinkLaunchModeAndroid.LAUNCH_IN_EXTERNAL_BROWSER_OR_APP
+ params.link_type = ExternalLinkTypeAndroid.LINK_TO_DIGITAL_CONTENT_OFFER
params.link_uri = "https://example.com/offer"
await iap.launch_external_link_android(params)`}
),
diff --git a/scripts/audit-docs.ts b/scripts/audit-docs.ts
index 04ab2261..d391541d 100644
--- a/scripts/audit-docs.ts
+++ b/scripts/audit-docs.ts
@@ -491,4 +491,8 @@ async function main() {
process.exit(0);
}
-main();
+main().catch((err) => {
+ console.error('audit-docs: fatal error');
+ console.error(err);
+ process.exit(2);
+});
From 4cd0df36057086b9bac331f9924664bfcf2508c7 Mon Sep 17 00:00:00 2001
From: hyochan
Date: Sun, 26 Apr 2026 22:17:44 +0900
Subject: [PATCH 25/26] docs(fetch-products): show both Builder and DSL
patterns for KMP
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The KMP example only showed the constructor approach, missing the
trailing-lambda DSL form that kmp-iap exposes via the
ProductsRequestBuilder extension. Updated the kmp tab to demonstrate
both:
1) Builder (constructor) — pass ProductRequest, get
FetchProductsResult to unwrap by variant.
2) DSL — trailing-lambda builder, returns List directly.
requestPurchase already shows both Kotlin DSL and Dart
requestPurchaseWithBuilder; fetchProducts has no builder API in
Dart (no fetchProductsWithBuilder exists), so KMP is the only tab
that needed updating. The TypeScript tab already includes both
root-API and useIAP hook examples.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
.../src/pages/docs/apis/fetch-products.tsx | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/packages/docs/src/pages/docs/apis/fetch-products.tsx b/packages/docs/src/pages/docs/apis/fetch-products.tsx
index 235c70d4..745e8a8c 100644
--- a/packages/docs/src/pages/docs/apis/fetch-products.tsx
+++ b/packages/docs/src/pages/docs/apis/fetch-products.tsx
@@ -252,12 +252,25 @@ function ProductList() {
),
kmp: (
{`import io.github.hyochan.kmpiap.KmpIAP
+import io.github.hyochan.kmpiap.fetchProducts // DSL extension
val kmpIAP = KmpIAP()
-val products = kmpIAP.fetchProducts(
- ProductRequest(skus = listOf("com.app.premium"), type = ProductQueryType.InApp)
-)`}
+// 1) Builder pattern — pass a ProductRequest data class directly.
+// Returns the sealed FetchProductsResult union; unwrap by variant.
+val result = kmpIAP.fetchProducts(
+ ProductRequest(
+ skus = listOf("com.app.premium"),
+ type = ProductQueryType.InApp,
+ )
+)
+
+// 2) DSL pattern — trailing-lambda builder.
+// Returns List directly (already unwrapped).
+val products = kmpIAP.fetchProducts {
+ skus = listOf("com.app.premium")
+ type = ProductQueryType.InApp
+}`}
),
dart: (
{`final FetchProductsResult result = await FlutterInappPurchase.instance.fetchProducts(
From 50efd5b680efe47c831fa8f2434b927985055705 Mon Sep 17 00:00:00 2001
From: hyochan
Date: Sun, 26 Apr 2026 22:58:53 +0900
Subject: [PATCH 26/26] docs: address copilot Round 14 findings
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- fetchProducts JSDoc (`@throws`) in expo-iap and react-native-iap
(root + useIAP hook): the underlying StoreKit/Play call returns an
empty array for unknown SKUs, so "unknown SKU" was misleading.
Reworded to "empty `skus`, not connected, network/store error" and
added a clarifying note that unknown SKUs are silently omitted.
- fetch-products docs page iOS blurb: same correction —
`Product.products(for:)` does not validate SKUs; only transport
failures throw.
- present-external-purchase-link-ios: the openiap-apple
implementation calls `UIApplication.open` after a `canOpenURL`
guard, not StoreKit's `ExternalPurchaseLink.open(url:)`. Updated
the description and the reference link to match what the code
actually does, while keeping the "production builds still need
the StoreKit external-purchase entitlement" caveat.
- Navigation.tsx: stop hiding the top-nav hamburger and dropdown on
/docs routes — that stranded Introduction / Languages / Tutorials /
Sponsors behind only the logo link on mobile. The earlier
tap-conflict between this menu and the docs sidebar toggle was
fixed at the source (closed docs sidebar uses
`pointer-events: none` + `translateX(-100%)`); the two affordances
also don't overlap geometrically (top-right vs. left-below-nav).
Auto-close the dropdown on every route change for safety.
Co-Authored-By: Claude Opus 4.7 (1M context)
---
libraries/expo-iap/src/index.ts | 3 +-
libraries/expo-iap/src/useIAP.ts | 3 +-
.../react-native-iap/src/hooks/useIAP.ts | 3 +-
libraries/react-native-iap/src/index.ts | 3 +-
packages/docs/src/components/Navigation.tsx | 181 +++++++++---------
.../src/pages/docs/apis/fetch-products.tsx | 5 +-
.../present-external-purchase-link-ios.tsx | 14 +-
7 files changed, 107 insertions(+), 105 deletions(-)
diff --git a/libraries/expo-iap/src/index.ts b/libraries/expo-iap/src/index.ts
index f9920d44..d7038da2 100644
--- a/libraries/expo-iap/src/index.ts
+++ b/libraries/expo-iap/src/index.ts
@@ -368,7 +368,8 @@ export const endConnection: MutationField<'endConnection'> = async () =>
* (`'in-app' | 'subs' | 'all'`, defaults to `'in-app'`).
* @returns Promise resolving to a `FetchProductsResult` union — `Product[]` for `'in-app'`,
* `ProductSubscription[]` for `'subs'`, or a mixed array for `'all'`.
- * @throws When the store rejects the request (unknown SKU, network, not connected).
+ * @throws When the store rejects the request (empty `skus`, not connected,
+ * network/store error). Unknown SKUs are simply omitted from the result, not thrown.
*
* @example
* ```ts
diff --git a/libraries/expo-iap/src/useIAP.ts b/libraries/expo-iap/src/useIAP.ts
index a8615bd0..90853a68 100644
--- a/libraries/expo-iap/src/useIAP.ts
+++ b/libraries/expo-iap/src/useIAP.ts
@@ -259,7 +259,8 @@ export function useIAP(options?: UseIAPOptions): UseIap {
* (`'in-app' | 'subs' | 'all'`, defaults to `'in-app'`).
* @returns Promise that resolves when the request is dispatched; results land in the
* hook's reactive `products` / `subscriptions` state.
- * @throws When the store rejects the request (unknown SKU, network, not connected).
+ * @throws When the store rejects the request (empty `skus`, not connected,
+ * network/store error). Unknown SKUs are simply omitted from the result, not thrown.
*
* @example
* ```ts
diff --git a/libraries/react-native-iap/src/hooks/useIAP.ts b/libraries/react-native-iap/src/hooks/useIAP.ts
index 89d297f6..cf47efd5 100644
--- a/libraries/react-native-iap/src/hooks/useIAP.ts
+++ b/libraries/react-native-iap/src/hooks/useIAP.ts
@@ -127,7 +127,8 @@ type UseIap = {
* (`'in-app' | 'subs' | 'all'`, defaults to `'in-app'`).
* @returns Promise that resolves when the request is dispatched; results land in the
* hook's reactive `products` / `subscriptions` state — read from there, don't expect a return value.
- * @throws When the store rejects the request (unknown SKU, network, not connected).
+ * @throws When the store rejects the request (empty `skus`, not connected,
+ * network/store error). Unknown SKUs are simply omitted from the result, not thrown.
*
* @example
* ```ts
diff --git a/libraries/react-native-iap/src/index.ts b/libraries/react-native-iap/src/index.ts
index 4160c759..11d53380 100644
--- a/libraries/react-native-iap/src/index.ts
+++ b/libraries/react-native-iap/src/index.ts
@@ -669,7 +669,8 @@ export const subscriptionBillingIssueListener = (
* @returns Promise resolving to a `FetchProductsResult` union — `Product[]` for `'in-app'`,
* `ProductSubscription[]` for `'subs'`, a mixed array for `'all'`, or `null`
* (the schema retains the nullable branch for backwards compatibility).
- * @throws When the store rejects the request (unknown SKU, network, not connected).
+ * @throws When the store rejects the request (empty `skus`, not connected,
+ * network/store error). Unknown SKUs are simply omitted from the result, not thrown.
*
* @example
* ```ts
diff --git a/packages/docs/src/components/Navigation.tsx b/packages/docs/src/components/Navigation.tsx
index 75ad605d..28d99c02 100644
--- a/packages/docs/src/components/Navigation.tsx
+++ b/packages/docs/src/components/Navigation.tsx
@@ -9,24 +9,22 @@ import { IAPKIT_URL, LOGO_PATH, trackIapKitClick } from '../lib/config';
function Navigation() {
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
const location = useLocation();
- // Docs pages have their own sticky "Menu" toggle for the docs sidebar.
- // The top nav's mobile hamburger ☰ sits in the same vertical area on
- // mobile and was visually-and-tap competing with that toggle — users
- // reported tapping the docs Menu button but having the top nav menu
- // open instead. Hide the top hamburger on docs routes so the docs
- // sidebar toggle is the only "open menu" affordance there.
- const isDocsRoute = location.pathname.startsWith('/docs');
const closeMobileMenu = () => {
setIsMobileMenuOpen(false);
};
- // Force-close the top nav menu whenever the user navigates onto a
- // docs route (covers the "I had the top menu open, then tapped a
- // docs link" path).
+ // Auto-close the top nav menu on route change so a stale dropdown doesn't
+ // sit open over the new page (especially relevant when crossing into /docs
+ // where the docs sidebar takes over as the primary navigation surface).
+ // The top-nav hamburger stays mounted on every route — Introduction /
+ // Languages / Tutorials / Sponsors must remain reachable on mobile from
+ // /docs too, and the closed docs sidebar already uses
+ // `pointer-events: none` + `translateX(-100%)` so the two menus don't
+ // compete for taps.
useEffect(() => {
- if (isDocsRoute) setIsMobileMenuOpen(false);
- }, [isDocsRoute]);
+ setIsMobileMenuOpen(false);
+ }, [location.pathname]);
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
@@ -133,90 +131,85 @@ function Navigation() {
- {/* Mobile Menu Button — hidden on /docs routes so it can't
- compete with the docs sidebar's own Menu toggle. */}
- {!isDocsRoute && (
-
- )}
+ {/* Mobile Menu Button — visible on every route. Top-level pages
+ (Introduction / Languages / Tutorials / Sponsors) must remain
+ reachable on mobile, including from /docs. */}
+
- {/* Mobile Menu Dropdown — also hidden on /docs to remove its
- invisible-but-present 0-height absolute box from the DOM. */}
- {!isDocsRoute && (
-
);
diff --git a/packages/docs/src/pages/docs/apis/fetch-products.tsx b/packages/docs/src/pages/docs/apis/fetch-products.tsx
index 745e8a8c..dd3a5c6c 100644
--- a/packages/docs/src/pages/docs/apis/fetch-products.tsx
+++ b/packages/docs/src/pages/docs/apis/fetch-products.tsx
@@ -20,8 +20,9 @@ function FetchProducts() {
Retrieve products or subscriptions from the store by SKU.
iOS: Wraps Product.products(for:){' '}
- (StoreKit 2). Fetches the localized price/title for each SKU; throws if
- any SKU is invalid.{' '}
+ (StoreKit 2). Fetches the localized price/title for each SKU. Unknown
+ SKUs are simply omitted from the returned array — only transport
+ failures (network, store unavailable, etc.) throw.{' '}
iOS{' '}
presentExternalPurchaseLinkIOS
-