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 ExternalPurchaseCustomLink.isEligible — iOS 18.1+. + See the{' '} + + Apple StoreKit reference + + . +

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 0bc4e4fe..0a7667e4 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 @@ -22,6 +22,18 @@ function IsEligibleForIntroOfferIOS() { Check introductory offer eligibility for a subscription group (iOS 12.2+).

+

+ Wraps Product.SubscriptionInfo.isEligibleForIntroOffer(for:){' '} + — checks subscription-group level eligibility. See the{' '} + + Apple StoreKit reference + + . +

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 04617fa1..de7fa538 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 @@ -20,6 +20,19 @@ function IsTransactionVerifiedIOS() { isTransactionVerifiedIOS

Verify a StoreKit 2 transaction signature (iOS 15+).

+

+ Inspects the VerificationResult from{' '} + Transaction.latest(for:).verified vs{' '} + .unverified. See the{' '} + + Apple StoreKit reference + + . +

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 1e96ec05..afb136e9 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 @@ -19,6 +19,18 @@ function LatestTransactionIOS() { latestTransactionIOS

Get the most recent transaction for a product (iOS 15+).

+

+ Wraps Transaction.latest(for:) — returns the most recent + verified transaction (success or refund). See the{' '} + + Apple StoreKit reference + + . +

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 6feaff79..db13aa29 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 @@ -20,6 +20,19 @@ function PresentCodeRedemptionSheetIOS() { presentCodeRedemptionSheetIOS

Present the App Store promo code redemption sheet.

+

+ Wraps SKPaymentQueue.presentCodeRedemptionSheet() (UIKit) /{' '} + AppStore.presentOfferCodeRedeemSheet(in:) (StoreKit 2). See + the{' '} + + Apple StoreKit reference + + . +

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 74e4f15d..ddb310cd 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 @@ -19,6 +19,18 @@ function PresentExternalPurchaseLinkIOS() { presentExternalPurchaseLinkIOS

Open external purchase URL in Safari (iOS 18.2+).

+

+ Wraps ExternalPurchaseLink.open(url:) — StoreKit External, + iOS 16+ (EU app store). See the{' '} + + Apple StoreKit reference + + . +

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 0b98c30c..b673153f 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 @@ -19,6 +19,18 @@ function PresentExternalPurchaseNoticeSheetIOS() { presentExternalPurchaseNoticeSheetIOS

Present Apple's compliance notice sheet (iOS 17.4+).

+

+ 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 + + ). +

Native references:{' '} +

+ Modes for opting into Google's alternative-billing programs.{' '} + Android only — passed via{' '} + InitConnectionConfig.alternativeBillingModeAndroid{' '} + (deprecated; prefer enableBillingProgramAndroid) ( + + Google docs + + ). +

Native references:{' '} Discounts feature guide.

+

+ Android only. Mirrors{' '} + ProductDetails.OneTimePurchaseOfferDetails ( + + Google docs + + ). +

Native reference:{' '} {' '} one-to-one.

+

+ Android only. Mirrors{' '} + ProductDetails.PricingPhase — one billing-cycle phase of + a subscription's pricing schedule ( + + Google docs + + ). +

diff --git a/packages/docs/src/pages/docs/types/android/subscription-offer-android.tsx b/packages/docs/src/pages/docs/types/android/subscription-offer-android.tsx index 777a97be..36981b88 100644 --- a/packages/docs/src/pages/docs/types/android/subscription-offer-android.tsx +++ b/packages/docs/src/pages/docs/types/android/subscription-offer-android.tsx @@ -28,6 +28,20 @@ function SubscriptionOfferAndroid() { (cross-platform) instead.

Offer details for subscription purchases:

+

+ Android only. Mirrors{' '} + ProductDetails.SubscriptionOfferDetails — the + offerToken-bearing offer payload required for subscription{' '} + requestPurchase ( + + Google docs + + ). +

Native reference:{' '} +

+ Identifiers for Play Billing 8.2.0+ programs (External Payments, + etc.). Android only ( + + Google docs + + ). +

Native references:{' '} ; iOS does not support one-time product discounts.

+

+ Cross-platform discount-offer envelope. iOS: maps to + a signed Product.SubscriptionOffer ( + + Apple docs + + ). Android: maps to a Play{' '} + SubscriptionOfferDetails entry ( + + Google docs + + ). +

Native references:{' '} ExternalPurchase API. Available from iOS 17.4+ (notice sheet) and iOS 18.2+ (custom links).

+

+ Result of presentExternalPurchaseLinkIOS.{' '} + iOS only — wraps{' '} + ExternalPurchaseLink.open(url:) ( + + Apple docs + + ). +

Native references:{' '} . Contains metadata about the app's purchase and installation.

+

+ iOS only. Mirrors AppTransaction (iOS + 16+) — the JWS-verified record of how the app was acquired ( + + Apple docs + + ). +

Native reference:{' '}

Discount info returned as part of product details:

+

+ iOS only. Mirrors{' '} + Product.SubscriptionOffer for promotional/intro discounts + ( + + Apple docs + + ). +

Native reference:{' '} +

+ iOS only. Signed-discount payload for{' '} + Product.purchase(options:) ( + + Apple docs + + ). +

Native reference:{' '}

Payment mode for offers:

+

+ iOS only. Mirrors{' '} + Product.SubscriptionOffer.PaymentMode ( + payAsYouGo, payUpFront,{' '} + freeTrial) ( + + Apple docs + + ). +

Native reference:{' '} +

+ iOS only. Mirrors{' '} + Product.SubscriptionInfo.RenewalInfo — autoRenewStatus, + renewalDate, expirationReason ( + + Apple docs + + ). +

diff --git a/packages/docs/src/pages/docs/types/ios/subscription-period-ios.tsx b/packages/docs/src/pages/docs/types/ios/subscription-period-ios.tsx index 5997494d..2367807b 100644 --- a/packages/docs/src/pages/docs/types/ios/subscription-period-ios.tsx +++ b/packages/docs/src/pages/docs/types/ios/subscription-period-ios.tsx @@ -19,6 +19,19 @@ function SubscriptionPeriodIos() { SubscriptionPeriodIOS

Subscription period units:

+

+ iOS only. Mirrors{' '} + Product.SubscriptionPeriodunit and{' '} + value ( + + Apple docs + + ). +

Native reference:{' '} subscriptionStatusIOS(sku) to get detailed subscription state.

+

+ iOS only. Mirrors{' '} + Product.SubscriptionInfo.Status — combines{' '} + transaction, renewalInfo, and{' '} + state ( + + Apple docs + + ). +

Native reference:{' '} .

+

+ Input to fetchProducts. iOS: passed to{' '} + Product.products(for:) ( + + Apple docs + + ). Android: passed to{' '} + BillingClient.queryProductDetailsAsync ( + + Google docs + + ). +

Native references:{' '} , discriminated by the platform field.

+

+ Cross-platform one-time product shape returned by{' '} + fetchProducts. iOS: derived from{' '} + Product ( + + Apple docs + + ). Android: derived from ProductDetails{' '} + ( + + Google docs + + ). +

Native references:{' '} , discriminated by the platform field.

+

+ Normalized purchase / transaction record. iOS:{' '} + derived from Transaction ( + + Apple docs + + ). Android: derived from Purchase ( + + Google docs + + ). +

Native references:{' '} .

+

+ Discriminated input to requestPurchase ( + type: 'in-app' | 'subs').{' '} + iOS: maps to Product.purchase(options:){' '} + ( + + Apple docs + + ). Android: maps to{' '} + BillingClient.launchBillingFlow ( + + Google docs + + ). +

Native references:{' '} .

+

+ Country-code shape returned by getStorefront.{' '} + iOS: Storefront.current ( + + Apple docs + + ). Android: BillingConfig.countryCode ( + + Google docs + + ). +

Native references:{' '} +

+ Cross-platform subscription-offer envelope. iOS:{' '} + maps to Product.SubscriptionOffer ( + + Apple docs + + ). Android: maps to{' '} + SubscriptionOfferDetails ( + + Google docs + + ). +

Native references:{' '} +

+ Cross-platform subscription product shape. iOS:{' '} + derived from Product with subscription{' '} + populated ( + + Apple docs + + ). Android: derived from ProductDetails{' '} + with subscriptionOfferDetails ( + + Google docs + + ). +

Native references:{' '} .

+

+ Input to verifyPurchaseWithProvider — pick a managed + validator (IAPKit, Apple, Google, Horizon). See{' '} + + Validation 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.isAlternativeBillingOnlyAvailableAsync(){' '} - — step 1 of the alternative billing flow. Returns whether the user/device + Wraps{' '} + BillingClient.isAlternativeBillingOnlyAvailableAsync() — + step 1 of the alternative billing flow. Returns whether the user/device is eligible. See the{' '}

- Wraps BillingClient.isBillingProgramAvailableAsync(BillingProgram){' '} + Wraps{' '} + + BillingClient.isBillingProgramAvailableAsync(BillingProgram) + {' '} — replaces isExternalOfferAvailableAsync. Play Billing 8.2.0+. See the{' '}

- Wraps BillingClient.launchExternalLinkFlow(activity, params){' '} - — replaces showExternalOfferInformationDialog. Shows the - Play disclosure dialog and (optionally) launches the URL. Play Billing + Wraps{' '} + BillingClient.launchExternalLinkFlow(activity, params) — + replaces showExternalOfferInformationDialog. Shows the Play + disclosure dialog and (optionally) launches the URL. Play Billing 8.2.0+. See the{' '} Apple docs - . Android: Opens the Play Store subscription - management deep link{' '} + . Android: Opens the Play Store subscription management + deep link{' '} https://play.google.com/store/account/subscriptions?package=<pkg>&sku=<sku> diff --git a/packages/docs/src/pages/docs/apis/finish-transaction.tsx b/packages/docs/src/pages/docs/apis/finish-transaction.tsx index 230ce424..735c355e 100644 --- a/packages/docs/src/pages/docs/apis/finish-transaction.tsx +++ b/packages/docs/src/pages/docs/apis/finish-transaction.tsx @@ -20,8 +20,8 @@ function FinishTransaction() { purchase to remove it from the queue.

- iOS: Calls Transaction.finish(). Until - you do, the same transaction replays through{' '} + iOS: Calls Transaction.finish(). Until you + do, the same transaction replays through{' '} Transaction.updates on every app launch.{' '} . Android: Calls queryPurchasesAsync(SUBS){' '} - and treats purchaseState == PURCHASED && autoRenewing{' '} - as active.{' '} + and treats{' '} + purchaseState == PURCHASED && autoRenewing as + active.{' '}

- Wraps Product.SubscriptionInfo.isEligibleForIntroOffer(for:){' '} - — checks subscription-group level eligibility. See the{' '} + Wraps{' '} + Product.SubscriptionInfo.isEligibleForIntroOffer(for:) — + checks subscription-group level eligibility. See the{' '}

- iOS: Triggers AppStore.sync() and - re-emits entitlements on Transaction.currentEntitlements. - Asks the user to authenticate.{' '} + iOS: Triggers AppStore.sync() and re-emits + entitlements on Transaction.currentEntitlements. Asks the + user to authenticate.{' '} . Android: Calls queryPurchasesAsync for - both INAPP and SUBS. No system-level UI - prompt — Play has no concept of an explicit "restore" action.{' '} + both INAPP and SUBS. No system-level UI prompt + — Play has no concept of an explicit "restore" action.{' '}

- Cross-platform subscription-offer envelope. iOS:{' '} - maps to Product.SubscriptionOffer ( + Cross-platform subscription-offer envelope. iOS: maps + to Product.SubscriptionOffer ( Date: Sun, 26 Apr 2026 12:39:01 +0900 Subject: [PATCH 03/26] docs: address coderabbit review (provider list, defaults, API mappings) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes 14 unresolved review threads on PR #107: - Provider list — `verifyPurchaseWithProvider` docs claimed support for IAPKit/Apple/Google/Horizon but `PurchaseVerificationProvider` only exposes `IAPKit`. Tightened the GraphQL schema description (so all generated Types files re-flow on next codegen) and updated every hand-written wrapper doc + the `apis` listing page + the `verify-purchase-with-provider-props` type page. - Apple `fetchProducts` doc default `.inApp` → `.all` to match the implementation's `params.type ?? .all`. - Apple `getAvailablePurchases` doc no longer claims "unfinished only"; describes the `Transaction.all` (default) vs `Transaction.currentEntitlements` (when `onlyIncludeActiveItemsIOS`) branches. - Godot `init_connection` doc dropped the bogus `config` parameter — the GDScript wrapper currently takes no arguments. - Godot `fetch_products` return-type doc corrected to reflect the wrapper output (`ProductAndroid`/`ProductIOS`, not `ProductSubscription`). - react-native-iap `fetchProducts` `@returns` mentions the nullable branch from `FetchProductsResult`. - react-native-iap `getAvailablePurchases` `@param options` documents the Android-only `includeSuspendedAndroid` flag. - launch-external-link-android.tsx: `BillingClient.launchExternalLinkFlow` → `BillingClient.launchExternalLink(activity, params, listener)` (matches the Play Billing 8.2.0+ API). - present-code-redemption-sheet-ios.tsx: drop the StoreKit 2 `AppStore.presentOfferCodeRedeemSheet(in:)` mention; the wrapper only calls `SKPaymentQueue.default().presentCodeRedemptionSheet()`. - show-manage-subscriptions-ios.tsx: clarify that the wrapper forwards to `deepLinkToSubscriptions(nil)` (which itself reaches `AppStore.showManageSubscriptions(in:)` when a window scene exists). - subscription-status-ios.tsx (type doc): the OpenIAP wrapper exposes only `renewalInfo` + `state`, not Apple's full `transaction` field. - packages/google `OpenIapStore.kt`: replaced the broken `currentError` reference with `OpenIapStore.status.lastError`. Co-Authored-By: Claude Opus 4.7 (1M context) --- libraries/expo-iap/src/types.ts | 4 +++- libraries/expo-iap/src/useIAP.ts | 2 +- .../lib/flutter_inapp_purchase.dart | 2 +- .../flutter_inapp_purchase/lib/types.dart | 4 +++- .../godot-iap/addons/godot-iap/godot_iap.gd | 18 ++++++++---------- libraries/godot-iap/addons/godot-iap/types.gd | 4 ++-- .../hyochan/kmpiap/InAppPurchaseAndroid.kt | 2 +- .../io/github/hyochan/kmpiap/openiap/Types.kt | 4 +++- .../github/hyochan/kmpiap/InAppPurchaseIOS.kt | 2 +- libraries/react-native-iap/src/hooks/useIAP.ts | 2 +- libraries/react-native-iap/src/index.ts | 8 +++++--- libraries/react-native-iap/src/types.ts | 4 +++- packages/apple/Sources/Models/Types.swift | 4 +++- packages/apple/Sources/OpenIapModule.swift | 18 +++++++++++------- .../android/launch-external-link-android.tsx | 8 +++++--- packages/docs/src/pages/docs/apis/index.tsx | 5 +++-- .../ios/present-code-redemption-sheet-ios.tsx | 9 +++++---- .../apis/ios/show-manage-subscriptions-ios.tsx | 8 ++++++-- .../docs/types/ios/subscription-status-ios.tsx | 8 ++++---- .../verify-purchase-with-provider-props.tsx | 3 ++- .../src/main/java/dev/hyo/openiap/Types.kt | 4 +++- .../java/dev/hyo/openiap/store/OpenIapStore.kt | 3 ++- packages/gql/src/api.graphql | 4 +++- packages/gql/src/generated/Types.kt | 4 +++- packages/gql/src/generated/Types.swift | 4 +++- packages/gql/src/generated/types.dart | 4 +++- packages/gql/src/generated/types.gd | 4 ++-- packages/gql/src/generated/types.ts | 4 +++- 28 files changed, 93 insertions(+), 57 deletions(-) diff --git a/libraries/expo-iap/src/types.ts b/libraries/expo-iap/src/types.ts index f7d95686..4651323a 100644 --- a/libraries/expo-iap/src/types.ts +++ b/libraries/expo-iap/src/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; diff --git a/libraries/expo-iap/src/useIAP.ts b/libraries/expo-iap/src/useIAP.ts index e56299d6..8ba12a15 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 (IAPKit, Apple, Google, Horizon). + * Verify via a managed provider (currently IAPKit; the PurchaseVerificationProvider enum exposes only Iapkit today). * * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider} */ diff --git a/libraries/flutter_inapp_purchase/lib/flutter_inapp_purchase.dart b/libraries/flutter_inapp_purchase/lib/flutter_inapp_purchase.dart index 79693890..27d418a0 100644 --- a/libraries/flutter_inapp_purchase/lib/flutter_inapp_purchase.dart +++ b/libraries/flutter_inapp_purchase/lib/flutter_inapp_purchase.dart @@ -1676,7 +1676,7 @@ class FlutterInappPurchase with RequestPurchaseBuilderApi { ); }; - /// Verify via a managed provider (IAPKit, Apple, Google, Horizon). + /// Verify via a managed provider (currently IAPKit; the PurchaseVerificationProvider enum exposes only Iapkit today). /// /// See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider gentype.MutationVerifyPurchaseWithProviderHandler diff --git a/libraries/flutter_inapp_purchase/lib/types.dart b/libraries/flutter_inapp_purchase/lib/types.dart index 696a9148..cd8365d8 100644 --- a/libraries/flutter_inapp_purchase/lib/types.dart +++ b/libraries/flutter_inapp_purchase/lib/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/libraries/godot-iap/addons/godot-iap/godot_iap.gd b/libraries/godot-iap/addons/godot-iap/godot_iap.gd index 83c4bb74..f0cd5564 100644 --- a/libraries/godot-iap/addons/godot-iap/godot_iap.gd +++ b/libraries/godot-iap/addons/godot-iap/godot_iap.gd @@ -202,19 +202,14 @@ func _on_android_subscription_billing_issue(purchase_json: String) -> void: ## 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. +## This wrapper currently takes no arguments — Android billing-program flags +## (e.g. [code]enable_billing_program_android[/code]) live on the underlying +## [InitConnectionConfig] but are not yet plumbed through the GDScript API. ## ## 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 @@ -272,8 +267,11 @@ func is_store_connected() -> bool: ## [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. +## types. The wrapper maps results to platform-specific objects: +## [Array][[Types.ProductAndroid]] on Android and [Array][[Types.ProductIOS]] on iOS, +## regardless of whether the request was IN_APP, SUBS, or ALL. Use the platform-specific +## fields ([code]subscription_offer_details_android[/code], [code]subscription_*_ios[/code]) +## to distinguish subscriptions from one-time products at the call site. ## ## [codeblock] ## var request = ProductRequest.new() diff --git a/libraries/godot-iap/addons/godot-iap/types.gd b/libraries/godot-iap/addons/godot-iap/types.gd index a475be19..d5f7ee68 100644 --- a/libraries/godot-iap/addons/godot-iap/types.gd +++ b/libraries/godot-iap/addons/godot-iap/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/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 690d43eb..4ee32fe2 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 @@ -1101,7 +1101,7 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife } /** - * Verify via a managed provider (IAPKit, Apple, Google, Horizon). + * Verify via a managed provider (currently IAPKit; the PurchaseVerificationProvider enum exposes only Iapkit today). * * @see https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider */ 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 521b22cb..f97576b1 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 @@ -4993,7 +4993,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/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 55cfb5c6..6f4941ac 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 @@ -919,7 +919,7 @@ internal class InAppPurchaseIOS : KmpInAppPurchase { } /** - * Verify via a managed provider (IAPKit, Apple, Google, Horizon). + * Verify via a managed provider (currently IAPKit; the PurchaseVerificationProvider enum exposes only Iapkit today). * * @see 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 fbc88e68..0afd9e79 100644 --- a/libraries/react-native-iap/src/hooks/useIAP.ts +++ b/libraries/react-native-iap/src/hooks/useIAP.ts @@ -181,7 +181,7 @@ type UseIap = { options: VerifyPurchaseProps, ) => Promise; /** - * Verify via a managed provider (IAPKit, Apple, Google, Horizon). + * Verify via a managed provider (currently IAPKit; the PurchaseVerificationProvider enum exposes only Iapkit today). * * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider} */ diff --git a/libraries/react-native-iap/src/index.ts b/libraries/react-native-iap/src/index.ts index d65f71ef..ba1e7b7c 100644 --- a/libraries/react-native-iap/src/index.ts +++ b/libraries/react-native-iap/src/index.ts @@ -667,7 +667,8 @@ export const subscriptionBillingIssueListener = ( * @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'`. + * `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). * * @example @@ -798,8 +799,9 @@ export const fetchProducts: QueryField<'fetchProducts'> = async (request) => { * 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 resolving to an array of `Purchase` currently held by the store. * @throws When the platform query fails. * diff --git a/libraries/react-native-iap/src/types.ts b/libraries/react-native-iap/src/types.ts index f7d95686..4651323a 100644 --- a/libraries/react-native-iap/src/types.ts +++ b/libraries/react-native-iap/src/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; diff --git a/packages/apple/Sources/Models/Types.swift b/packages/apple/Sources/Models/Types.swift index 4d823837..b3cef1c9 100644 --- a/packages/apple/Sources/Models/Types.swift +++ b/packages/apple/Sources/Models/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/apple/Sources/OpenIapModule.swift b/packages/apple/Sources/OpenIapModule.swift index 89d4c679..c9dd18d1 100644 --- a/packages/apple/Sources/OpenIapModule.swift +++ b/packages/apple/Sources/OpenIapModule.swift @@ -103,7 +103,8 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol { /// 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`). + /// optional `type` (`.inApp`, `.subs`, or `.all`; defaults to `.all` when omitted — + /// the implementation falls back to `params.type ?? .all`). /// - 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). @@ -512,12 +513,15 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol { _ = 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. + /// List the user's purchases held by StoreKit. By default reads `Transaction.all` (the + /// full history including refunded / revoked entries). Pass + /// `onlyIncludeActiveItemsIOS = true` to switch to `Transaction.currentEntitlements`, + /// which narrows the result to active non-consumables and live subscriptions. /// - /// - Parameter options: Optional iOS-specific flags - /// (`alsoPublishToEventListenerIOS`, `onlyIncludeActiveItemsIOS`). - /// - Returns: An array of `Purchase` values currently held by StoreKit. + /// - Parameter options: Optional iOS-specific flags. `onlyIncludeActiveItemsIOS` + /// toggles between `Transaction.all` (default) and `Transaction.currentEntitlements`. + /// `alsoPublishToEventListenerIOS` re-emits each purchase on the update listener. + /// - Returns: An array of `Purchase` values matching the selected scope. /// - Throws: When the StoreKit query fails. /// /// See: https://www.openiap.dev/docs/apis/get-available-purchases @@ -763,7 +767,7 @@ public final class OpenIapModule: NSObject, OpenIapModuleProtocol { return .verifyPurchaseResultIos(iosResult) } - /// Verify via a managed provider (IAPKit, Apple, Google, Horizon). + /// Verify via a managed provider (currently IAPKit; the PurchaseVerificationProvider enum exposes only Iapkit today). /// See: https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider public func verifyPurchaseWithProvider(_ props: VerifyPurchaseWithProviderProps) async throws -> VerifyPurchaseWithProviderResult { try await ensureConnection() 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 b9184244..cdbc0193 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 @@ -24,9 +24,11 @@ function LaunchExternalLinkAndroid() {

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{' '}

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 SKPaymentQueue.presentCodeRedemptionSheet() (UIKit) /{' '} - AppStore.presentOfferCodeRedeemSheet(in:) (StoreKit 2). See - the{' '} + Calls SKPaymentQueue.default().presentCodeRedemptionSheet(){' '} + (the StoreKit 1 API — the StoreKit 2 equivalent{' '} + AppStore.presentOfferCodeRedeemSheet(in:) is not currently + wired through this wrapper). See the{' '} 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 1d4b2c4f..c5a6a82e 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 @@ -24,8 +24,12 @@ function ShowManageSubscriptionsIOS() { changed.

- 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{' '}

- iOS only. Mirrors{' '} - Product.SubscriptionInfo.Status — combines{' '} - transaction, renewalInfo, and{' '} - state ( + iOS only. A trimmed projection of Apple's{' '} + Product.SubscriptionInfo.Status — the OpenIAP wrapper + exposes renewalInfo and state only;{' '} + transaction from the Apple type is not surfaced (

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+).

- Wraps Product.SubscriptionInfo.status — returns the array - of Status objects with transaction,{' '} - renewalInfo, state. iOS 15+. See the{' '} + Wraps Product.SubscriptionInfo.status — returns an array + projected onto SubscriptionStatusIOS, which exposes only{' '} + renewalInfo and state. The{' '} + transaction field on Apple's Status type is + not surfaced by this wrapper; if you need the underlying transaction, + call latestTransactionIOS(sku) separately. iOS 15+. See the{' '} Date: Sun, 26 Apr 2026 13:29:16 +0900 Subject: [PATCH 05/26] docs: address coderabbit Round 3 on PR #107 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - KMP requestPurchase KDoc parameter name mismatch — `@param props` but the actual method parameter is `request` (Android) / `params` (iOS). Renamed each `@param` to match its actual signature and clarified the OUTER vs INNER `request` field path (`.request.apple.sku` etc.) so Dokka/IDE tooling stop warning about "missing parameter docs". - `verifyPurchase` schema description was overly iOS-biased ("returns isValid + raw store metadata"), but `VerifyPurchaseResult` is a union — only `VerifyPurchaseResultIOS` exposes `isValid`, `VerifyPurchaseResultAndroid` carries Play Store fields with no isValid, and `VerifyPurchaseResultHorizon` uses `success`. Updated the GraphQL schema description to describe each variant; codegen re-flowed all generated Types files. Co-Authored-By: Claude Opus 4.7 (1M context) --- libraries/expo-iap/src/types.ts | 6 +++++- libraries/flutter_inapp_purchase/lib/types.dart | 6 +++++- libraries/godot-iap/addons/godot-iap/types.gd | 4 ++-- .../kotlin/io/github/hyochan/kmpiap/InAppPurchaseAndroid.kt | 6 ++++-- .../kotlin/io/github/hyochan/kmpiap/openiap/Types.kt | 6 +++++- .../kotlin/io/github/hyochan/kmpiap/InAppPurchaseIOS.kt | 6 ++++-- libraries/react-native-iap/src/types.ts | 6 +++++- packages/apple/Sources/Models/Types.swift | 6 +++++- .../google/openiap/src/main/java/dev/hyo/openiap/Types.kt | 6 +++++- packages/gql/src/api.graphql | 6 +++++- packages/gql/src/generated/Types.kt | 6 +++++- packages/gql/src/generated/Types.swift | 6 +++++- packages/gql/src/generated/types.dart | 6 +++++- packages/gql/src/generated/types.gd | 4 ++-- packages/gql/src/generated/types.ts | 6 +++++- 15 files changed, 67 insertions(+), 19 deletions(-) diff --git a/libraries/expo-iap/src/types.ts b/libraries/expo-iap/src/types.ts index 4651323a..48f0103b 100644 --- a/libraries/expo-iap/src/types.ts +++ b/libraries/expo-iap/src/types.ts @@ -741,7 +741,11 @@ export interface Mutation { */ validateReceipt: Promise; /** - * Verify a purchase against your own backend (returns isValid + raw store metadata). + * Verify a purchase against your own backend. Returns a platform-specific + * variant of VerifyPurchaseResult — VerifyPurchaseResultIOS exposes isValid + * + receipt/JWS metadata, VerifyPurchaseResultAndroid carries Play Store + * receipt fields (no isValid), and VerifyPurchaseResultHorizon uses success. + * Inspect the concrete variant before reading fields. * See: https://www.openiap.dev/docs/features/validation#verify-purchase */ verifyPurchase: Promise; diff --git a/libraries/flutter_inapp_purchase/lib/types.dart b/libraries/flutter_inapp_purchase/lib/types.dart index cd8365d8..1645922e 100644 --- a/libraries/flutter_inapp_purchase/lib/types.dart +++ b/libraries/flutter_inapp_purchase/lib/types.dart @@ -4969,7 +4969,11 @@ abstract class MutationResolver { VerifyPurchaseGoogleOptions? google, VerifyPurchaseHorizonOptions? horizon, }); - /// Verify a purchase against your own backend (returns isValid + raw store metadata). + /// Verify a purchase against your own backend. Returns a platform-specific + /// variant of VerifyPurchaseResult — VerifyPurchaseResultIOS exposes isValid + /// + receipt/JWS metadata, VerifyPurchaseResultAndroid carries Play Store + /// receipt fields (no isValid), and VerifyPurchaseResultHorizon uses success. + /// Inspect the concrete variant before reading fields. /// See: https://www.openiap.dev/docs/features/validation#verify-purchase Future verifyPurchase({ VerifyPurchaseAppleOptions? apple, diff --git a/libraries/godot-iap/addons/godot-iap/types.gd b/libraries/godot-iap/addons/godot-iap/types.gd index d5f7ee68..bc96928f 100644 --- a/libraries/godot-iap/addons/godot-iap/types.gd +++ b/libraries/godot-iap/addons/godot-iap/types.gd @@ -5265,7 +5265,7 @@ class Mutation: const return_type = "VerifyPurchaseResult" const is_array = false - ## Verify a purchase against your own backend (returns isValid + raw store metadata). + ## Verify a purchase against your own backend. Returns a platform-specific class verifyPurchaseField: const name = "verifyPurchase" const snake_name = "verify_purchase" @@ -5757,7 +5757,7 @@ static func validate_receipt_args(options: VerifyPurchaseProps) -> Dictionary: args["options"] = options return args -## Verify a purchase against your own backend (returns isValid + raw store metadata). +## Verify a purchase against your own backend. Returns a platform-specific static func verify_purchase_args(options: VerifyPurchaseProps) -> Dictionary: var args = {} if options != 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 4ee32fe2..66437930 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 @@ -523,8 +523,10 @@ internal class InAppPurchaseAndroid : KmpInAppPurchase, Application.ActivityLife * 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`. + * @param request [RequestPurchaseProps]. The OUTER `request` is the props envelope; + * the INNER `RequestPurchaseProps.request` field carries the per-platform payload — + * set `request.request.apple.sku` (iOS) and/or `request.request.google.skus` + * (Android). Subscriptions also need `subscriptionOffers` on Android. * @return The dispatched purchase payload (do not rely on this for the outcome). * @throws PurchaseException on synchronous rejection (billing not ready, missing offerToken). * 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 f97576b1..2c749a69 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 @@ -4988,7 +4988,11 @@ public interface MutationResolver { */ suspend fun validateReceipt(options: VerifyPurchaseProps): VerifyPurchaseResult /** - * Verify a purchase against your own backend (returns isValid + raw store metadata). + * Verify a purchase against your own backend. Returns a platform-specific + * variant of VerifyPurchaseResult — VerifyPurchaseResultIOS exposes isValid + * + receipt/JWS metadata, VerifyPurchaseResultAndroid carries Play Store + * receipt fields (no isValid), and VerifyPurchaseResultHorizon uses success. + * Inspect the concrete variant before reading fields. * See: https://www.openiap.dev/docs/features/validation#verify-purchase */ suspend fun verifyPurchase(options: VerifyPurchaseProps): VerifyPurchaseResult 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 6f4941ac..6ee42735 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 @@ -193,8 +193,10 @@ 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`. + * @param params [RequestPurchaseProps]. The OUTER `params` is the props envelope; + * the INNER `RequestPurchaseProps.request` field carries the per-platform payload — + * set `params.request.apple.sku` (iOS) and/or `params.request.google.skus` (Android). + * Subscriptions also need `subscriptionOffers` on Android. * @return The dispatched purchase payload (do not rely on this for the outcome). * @throws PurchaseException on synchronous rejection (billing not ready, missing offerToken). * diff --git a/libraries/react-native-iap/src/types.ts b/libraries/react-native-iap/src/types.ts index 4651323a..48f0103b 100644 --- a/libraries/react-native-iap/src/types.ts +++ b/libraries/react-native-iap/src/types.ts @@ -741,7 +741,11 @@ export interface Mutation { */ validateReceipt: Promise; /** - * Verify a purchase against your own backend (returns isValid + raw store metadata). + * Verify a purchase against your own backend. Returns a platform-specific + * variant of VerifyPurchaseResult — VerifyPurchaseResultIOS exposes isValid + * + receipt/JWS metadata, VerifyPurchaseResultAndroid carries Play Store + * receipt fields (no isValid), and VerifyPurchaseResultHorizon uses success. + * Inspect the concrete variant before reading fields. * See: https://www.openiap.dev/docs/features/validation#verify-purchase */ verifyPurchase: Promise; diff --git a/packages/apple/Sources/Models/Types.swift b/packages/apple/Sources/Models/Types.swift index b3cef1c9..efacb85c 100644 --- a/packages/apple/Sources/Models/Types.swift +++ b/packages/apple/Sources/Models/Types.swift @@ -2439,7 +2439,11 @@ public protocol MutationResolver { /// 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 a purchase against your own backend (returns isValid + raw store metadata). + /// Verify a purchase against your own backend. Returns a platform-specific + /// variant of VerifyPurchaseResult — VerifyPurchaseResultIOS exposes isValid + /// + receipt/JWS metadata, VerifyPurchaseResultAndroid carries Play Store + /// receipt fields (no isValid), and VerifyPurchaseResultHorizon uses success. + /// Inspect the concrete variant before reading fields. /// See: https://www.openiap.dev/docs/features/validation#verify-purchase func verifyPurchase(_ options: VerifyPurchaseProps) async throws -> VerifyPurchaseResult /// Verify via a managed provider without standing up your own server. The 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 a051765c..9697826f 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 @@ -4897,7 +4897,11 @@ public interface MutationResolver { */ suspend fun validateReceipt(options: VerifyPurchaseProps): VerifyPurchaseResult /** - * Verify a purchase against your own backend (returns isValid + raw store metadata). + * Verify a purchase against your own backend. Returns a platform-specific + * variant of VerifyPurchaseResult — VerifyPurchaseResultIOS exposes isValid + * + receipt/JWS metadata, VerifyPurchaseResultAndroid carries Play Store + * receipt fields (no isValid), and VerifyPurchaseResultHorizon uses success. + * Inspect the concrete variant before reading fields. * See: https://www.openiap.dev/docs/features/validation#verify-purchase */ suspend fun verifyPurchase(options: VerifyPurchaseProps): VerifyPurchaseResult diff --git a/packages/gql/src/api.graphql b/packages/gql/src/api.graphql index ee42f6d4..8c7e357b 100644 --- a/packages/gql/src/api.graphql +++ b/packages/gql/src/api.graphql @@ -82,7 +82,11 @@ extend type Mutation { # Future validateReceipt(options: VerifyPurchaseProps!): VerifyPurchaseResult! @deprecated(reason: "Use verifyPurchase") """ - Verify a purchase against your own backend (returns isValid + raw store metadata). + Verify a purchase against your own backend. Returns a platform-specific + variant of VerifyPurchaseResult — VerifyPurchaseResultIOS exposes isValid + + receipt/JWS metadata, VerifyPurchaseResultAndroid carries Play Store + receipt fields (no isValid), and VerifyPurchaseResultHorizon uses success. + Inspect the concrete variant before reading fields. See: https://www.openiap.dev/docs/features/validation#verify-purchase """ # Future diff --git a/packages/gql/src/generated/Types.kt b/packages/gql/src/generated/Types.kt index dfddfd23..75ffa755 100644 --- a/packages/gql/src/generated/Types.kt +++ b/packages/gql/src/generated/Types.kt @@ -4986,7 +4986,11 @@ public interface MutationResolver { */ suspend fun validateReceipt(options: VerifyPurchaseProps): VerifyPurchaseResult /** - * Verify a purchase against your own backend (returns isValid + raw store metadata). + * Verify a purchase against your own backend. Returns a platform-specific + * variant of VerifyPurchaseResult — VerifyPurchaseResultIOS exposes isValid + * + receipt/JWS metadata, VerifyPurchaseResultAndroid carries Play Store + * receipt fields (no isValid), and VerifyPurchaseResultHorizon uses success. + * Inspect the concrete variant before reading fields. * See: https://www.openiap.dev/docs/features/validation#verify-purchase */ suspend fun verifyPurchase(options: VerifyPurchaseProps): VerifyPurchaseResult diff --git a/packages/gql/src/generated/Types.swift b/packages/gql/src/generated/Types.swift index b3cef1c9..efacb85c 100644 --- a/packages/gql/src/generated/Types.swift +++ b/packages/gql/src/generated/Types.swift @@ -2439,7 +2439,11 @@ public protocol MutationResolver { /// 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 a purchase against your own backend (returns isValid + raw store metadata). + /// Verify a purchase against your own backend. Returns a platform-specific + /// variant of VerifyPurchaseResult — VerifyPurchaseResultIOS exposes isValid + /// + receipt/JWS metadata, VerifyPurchaseResultAndroid carries Play Store + /// receipt fields (no isValid), and VerifyPurchaseResultHorizon uses success. + /// Inspect the concrete variant before reading fields. /// See: https://www.openiap.dev/docs/features/validation#verify-purchase func verifyPurchase(_ options: VerifyPurchaseProps) async throws -> VerifyPurchaseResult /// Verify via a managed provider without standing up your own server. The diff --git a/packages/gql/src/generated/types.dart b/packages/gql/src/generated/types.dart index cd8365d8..1645922e 100644 --- a/packages/gql/src/generated/types.dart +++ b/packages/gql/src/generated/types.dart @@ -4969,7 +4969,11 @@ abstract class MutationResolver { VerifyPurchaseGoogleOptions? google, VerifyPurchaseHorizonOptions? horizon, }); - /// Verify a purchase against your own backend (returns isValid + raw store metadata). + /// Verify a purchase against your own backend. Returns a platform-specific + /// variant of VerifyPurchaseResult — VerifyPurchaseResultIOS exposes isValid + /// + receipt/JWS metadata, VerifyPurchaseResultAndroid carries Play Store + /// receipt fields (no isValid), and VerifyPurchaseResultHorizon uses success. + /// Inspect the concrete variant before reading fields. /// See: https://www.openiap.dev/docs/features/validation#verify-purchase Future verifyPurchase({ VerifyPurchaseAppleOptions? apple, diff --git a/packages/gql/src/generated/types.gd b/packages/gql/src/generated/types.gd index d5f7ee68..bc96928f 100644 --- a/packages/gql/src/generated/types.gd +++ b/packages/gql/src/generated/types.gd @@ -5265,7 +5265,7 @@ class Mutation: const return_type = "VerifyPurchaseResult" const is_array = false - ## Verify a purchase against your own backend (returns isValid + raw store metadata). + ## Verify a purchase against your own backend. Returns a platform-specific class verifyPurchaseField: const name = "verifyPurchase" const snake_name = "verify_purchase" @@ -5757,7 +5757,7 @@ static func validate_receipt_args(options: VerifyPurchaseProps) -> Dictionary: args["options"] = options return args -## Verify a purchase against your own backend (returns isValid + raw store metadata). +## Verify a purchase against your own backend. Returns a platform-specific static func verify_purchase_args(options: VerifyPurchaseProps) -> Dictionary: var args = {} if options != null: diff --git a/packages/gql/src/generated/types.ts b/packages/gql/src/generated/types.ts index 4651323a..48f0103b 100644 --- a/packages/gql/src/generated/types.ts +++ b/packages/gql/src/generated/types.ts @@ -741,7 +741,11 @@ export interface Mutation { */ validateReceipt: Promise; /** - * Verify a purchase against your own backend (returns isValid + raw store metadata). + * Verify a purchase against your own backend. Returns a platform-specific + * variant of VerifyPurchaseResult — VerifyPurchaseResultIOS exposes isValid + * + receipt/JWS metadata, VerifyPurchaseResultAndroid carries Play Store + * receipt fields (no isValid), and VerifyPurchaseResultHorizon uses success. + * Inspect the concrete variant before reading fields. * See: https://www.openiap.dev/docs/features/validation#verify-purchase */ verifyPurchase: Promise; From 2fb40e551ff57332c146fa620433613d4aaa3573 Mon Sep 17 00:00:00 2001 From: hyochan Date: Sun, 26 Apr 2026 13:38:52 +0900 Subject: [PATCH 06/26] docs(init-connection): correct iOS description to match impl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Copilot caught that the iOS paragraph claimed `initConnection` calls `AppStore.sync()`, but the implementation in `OpenIapModule.swift` verifies `AppStore.canMakePayments`, registers an `SKPaymentQueue` observer for promoted IAPs, and starts a `Transaction.updates` listener — `AppStore.sync()` is what `syncIOS` calls, not `initConnection`. Updated the prose to describe what initConnection actually does; the existing `Transaction.updates` Apple docs link is now accurate. Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/docs/src/pages/docs/apis/init-connection.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/docs/src/pages/docs/apis/init-connection.tsx b/packages/docs/src/pages/docs/apis/init-connection.tsx index 949c7c16..f4bea93d 100644 --- a/packages/docs/src/pages/docs/apis/init-connection.tsx +++ b/packages/docs/src/pages/docs/apis/init-connection.tsx @@ -21,8 +21,10 @@ function InitConnection() { other IAP operations.

- iOS: Calls AppStore.sync() lazily and - verifies StoreKit 2 is available; safe to call repeatedly.{' '} + iOS: Verifies AppStore.canMakePayments, + registers the SKPaymentQueue observer for promoted IAPs, + and starts a Transaction.updates listener that drives the + purchase event stream. Safe to call repeatedly.{' '} Date: Sun, 26 Apr 2026 13:45:50 +0900 Subject: [PATCH 07/26] =?UTF-8?q?docs:=20address=20Copilot=20Round=205=20?= =?UTF-8?q?=E2=80=94=20accurate=20iOS/Android=20impl=20mappings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - deep-link-to-subscriptions.tsx: iOS doc no longer claims a universal link to apps.apple.com — the wrapper calls AppStore.showManageSubscriptions(in:) with the active UIWindowScene and throws if no scene is available; tvOS / watchOS / macOS aren't wired through yet. - show-manage-subscriptions-ios.tsx: removed the false "falls back to the App Store deep link" claim — the impl throws when no UIWindowScene is available. - get-available-purchases.tsx: rewrote the iOS paragraph; the wrapper defaults to Transaction.all (full StoreKit 2 history including refunded/revoked) and only switches to Transaction.currentEntitlements when onlyIncludeActiveItemsIOS=true. Avoided the "unfinished" framing since Transaction.all is broader. - packages/google OpenIapStore.kt: KDoc no longer calls Android results "unfinished purchases"; uses "owned/available purchases held by Play Billing" since the Android query is queryPurchasesAsync (INAPP+SUBS) on the user's owned set, not pending-queue semantics. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../pages/docs/apis/deep-link-to-subscriptions.tsx | 9 +++++---- .../pages/docs/apis/get-available-purchases.tsx | 14 ++++++++------ .../apis/ios/show-manage-subscriptions-ios.tsx | 8 ++++---- .../java/dev/hyo/openiap/store/OpenIapStore.kt | 10 +++++++--- 4 files changed, 24 insertions(+), 17 deletions(-) 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 c4ec091e..b8fed3dd 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 @@ -21,11 +21,12 @@ function DeepLinkToSubscriptions() { and manage their subscriptions.

- iOS: Opens{' '} - https://apps.apple.com/account/subscriptions (universal - link) so the user can manage subscriptions in the App Store.{' '} + iOS: Calls{' '} + AppStore.showManageSubscriptions(in:) with the active{' '} + UIWindowScene; throws if no window scene is available. Not + supported on tvOS / watchOS / macOS in the current implementation.{' '} 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 d4b89ba1..bae38951 100644 --- a/packages/docs/src/pages/docs/apis/get-available-purchases.tsx +++ b/packages/docs/src/pages/docs/apis/get-available-purchases.tsx @@ -17,15 +17,17 @@ function GetAvailablePurchases() { />

getAvailablePurchases

- Get all available (unfinished) purchases for the current user. Use this - to restore purchases or check for pending transactions. + Get the user's purchases held by the store — owned non-consumables, + active subscriptions, and any pending transactions not yet finished.

- iOS: Iterates{' '} - Transaction.currentEntitlements (StoreKit 2). Excludes - revoked / refunded transactions by default.{' '} + iOS: By default iterates Transaction.all{' '} + (the full StoreKit 2 history, including refunded / revoked entries). + Pass onlyIncludeActiveItemsIOS = true to switch to{' '} + Transaction.currentEntitlements, which narrows the result + to active non-consumables and live subscriptions.{' '} 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 c5a6a82e..e0251890 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 @@ -26,10 +26,10 @@ function ShowManageSubscriptionsIOS() {

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{' '} + deepLinkToSubscriptions(nil) path, which calls{' '} + AppStore.showManageSubscriptions(in:) with the active{' '} + UIWindowScene; if no scene is available the call throws + instead of falling back to a URL. iOS 15+. See the{' '} get-available-purchases From 92eec3db797b3936828cb5ebd4d66343135ba74f Mon Sep 17 00:00:00 2001 From: hyochan Date: Sun, 26 Apr 2026 13:55:22 +0900 Subject: [PATCH 08/26] feat(docs): make type identifiers in CodeBlock signatures clickable Capitalized identifiers in code blocks (Swift/Kotlin/Dart/GDScript class-name tokens, plus a new TypeScript pass) now render as anchors to /docs/types/ when the name matches a known OpenIAP type. So in a Swift signature like: func fetchProducts(_ params: ProductRequest) async throws -> FetchProductsResult both `ProductRequest` and `FetchProductsResult` link to their type pages; in: func getAvailablePurchases(options: PurchaseOptions? = nil) async throws -> [Purchase] `PurchaseOptions` and `Purchase` link out too. Implementation: - New `TYPE_LINKS` map in CodeBlock.tsx (cross-platform + iOS + Android type pages, plus a few aliases like `Promise` type wrappers, sealed `Purchase[Android|IOS]` variants, etc.). - `linkifyType` helper wraps known names in ``; unknown names stay as plain class-name spans for identical styling. - Added a class-name pass to the TypeScript highlighter so TS signatures link out too (the existing pass only covered Swift/Kotlin/Dart/GDScript). - code.css adds a `.token.type-ref` rule: inherit class-name color, no anchor underline, hover-underline for discoverability. Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/docs/src/components/CodeBlock.tsx | 107 ++++++++++++++++++++- packages/docs/src/styles/code.css | 15 +++ 2 files changed, 120 insertions(+), 2 deletions(-) diff --git a/packages/docs/src/components/CodeBlock.tsx b/packages/docs/src/components/CodeBlock.tsx index f1864c13..d914dd30 100644 --- a/packages/docs/src/components/CodeBlock.tsx +++ b/packages/docs/src/components/CodeBlock.tsx @@ -20,6 +20,99 @@ interface CodeBlockProps { | 'properties'; } +// Identifier → Type doc page slug. Used by `linkifyType` so capitalized +// identifiers (Swift/Kotlin/Dart/GDScript class-name tokens, TypeScript +// type references) render as clickable anchors that jump to the matching +// `/docs/types/...` page. Add new entries here when a new type page ships. +const TYPE_LINKS: Record = { + // Cross-platform + ActiveSubscription: '/docs/types/active-subscription', + AlternativeBillingModeAndroid: '/docs/types/alternative-billing-types', + AlternativeBillingTypes: '/docs/types/alternative-billing-types', + BillingProgramAndroid: '/docs/types/billing-programs', + BillingProgramAvailabilityResultAndroid: '/docs/types/billing-programs', + BillingProgramReportingDetailsAndroid: '/docs/types/billing-programs', + DeepLinkOptions: '/docs/types#common', + DiscountOffer: '/docs/types/discount-offer', + ExternalPurchaseLinkResultIOS: '/docs/types/external-purchase-link', + ExternalPurchaseNoticeResultIOS: '/docs/types/external-purchase-link', + ExternalPurchaseCustomLinkNoticeResultIOS: + '/docs/types/external-purchase-link', + ExternalPurchaseCustomLinkTokenResultIOS: + '/docs/types/external-purchase-link', + ExternalPurchaseCustomLinkNoticeTypeIOS: '/docs/types/external-purchase-link', + ExternalPurchaseCustomLinkTokenTypeIOS: '/docs/types/external-purchase-link', + FetchProductsResult: '/docs/types/product-request', + InitConnectionConfig: + '/docs/types/alternative-billing-types#init-connection-config', + LaunchExternalLinkParamsAndroid: '/docs/types/billing-programs', + Product: '/docs/types/product', + ProductAndroid: '/docs/types/product', + ProductIOS: '/docs/types/product', + ProductOrSubscription: '/docs/types/product', + ProductQueryType: '/docs/types/product-request', + ProductRequest: '/docs/types/product-request', + ProductSubscription: '/docs/types/subscription-product', + ProductSubscriptionAndroid: '/docs/types/subscription-product', + ProductSubscriptionIOS: '/docs/types/subscription-product', + Purchase: '/docs/types/purchase', + PurchaseAndroid: '/docs/types/purchase', + PurchaseIOS: '/docs/types/purchase', + PurchaseInput: '/docs/types/purchase', + PurchaseOptions: '/docs/types/purchase', + PurchaseVerificationProvider: + '/docs/types/verify-purchase-with-provider-props', + RequestPurchaseAndroidProps: '/docs/types/request-purchase-props', + RequestPurchaseIosProps: '/docs/types/request-purchase-props', + RequestPurchaseProps: '/docs/types/request-purchase-props', + RequestPurchasePropsByPlatforms: '/docs/types/request-purchase-props', + RequestPurchaseResult: '/docs/types/request-purchase-props', + RequestSubscriptionPropsByPlatforms: '/docs/types/request-purchase-props', + Storefront: '/docs/types/storefront', + SubscriptionOffer: '/docs/types/subscription-offer', + SubscriptionProduct: '/docs/types/subscription-product', + VerifyPurchase: '/docs/types/verify-purchase', + VerifyPurchaseProps: '/docs/types/verify-purchase', + VerifyPurchaseResult: '/docs/types/verify-purchase', + VerifyPurchaseResultAndroid: '/docs/types/verify-purchase', + VerifyPurchaseResultHorizon: '/docs/types/verify-purchase', + VerifyPurchaseResultIOS: '/docs/types/verify-purchase', + VerifyPurchaseWithProviderProps: + '/docs/types/verify-purchase-with-provider-props', + VerifyPurchaseWithProviderResult: + '/docs/types/verify-purchase-with-provider-result', + VoidResult: '/docs/types#common', + // iOS-only + AppTransaction: '/docs/types/ios/app-transaction-ios', + AppTransactionIOS: '/docs/types/ios/app-transaction-ios', + Discount: '/docs/types/ios/discount-ios', + DiscountIOS: '/docs/types/ios/discount-ios', + DiscountOfferIOS: '/docs/types/ios/discount-offer-ios', + PaymentMode: '/docs/types/ios/payment-mode-ios', + PaymentModeIOS: '/docs/types/ios/payment-mode-ios', + RenewalInfo: '/docs/types/ios/renewal-info-ios', + RenewalInfoIOS: '/docs/types/ios/renewal-info-ios', + SubscriptionPeriod: '/docs/types/ios/subscription-period-ios', + SubscriptionPeriodIOS: '/docs/types/ios/subscription-period-ios', + SubscriptionStatus: '/docs/types/ios/subscription-status-ios', + SubscriptionStatusIOS: '/docs/types/ios/subscription-status-ios', + // Android-only + OneTimePurchaseOfferDetailAndroid: + '/docs/types/android/one-time-purchase-offer-detail-android', + PricingPhaseAndroid: '/docs/types/android/pricing-phase-android', + SubscriptionOfferAndroid: '/docs/types/android/subscription-offer-android', +}; + +// Wraps a class-name token in an anchor when it matches a known type. +// Caller is responsible for HTML-escaping the input. +function linkifyType(name: string): string { + const href = TYPE_LINKS[name]; + if (href) { + return `${name}`; + } + return `${name}`; +} + function CodeBlock({ children, language = 'graphql' }: CodeBlockProps) { const codeRef = useRef(null); const [copied, setCopied] = useState(false); @@ -176,6 +269,14 @@ function highlightCode(element: HTMLElement, language: string) { '$1' ); + // Capitalized identifiers → linkify known OpenIAP types (so e.g. + // `ProductRequest`, `Purchase[]`, `Promise` in + // a TS signature jump to /docs/types/...). + processed = processed.replace( + /\b([A-Z][a-zA-Z0-9_]*)\b/g, + (_, name: string) => linkifyType(name) + ); + result += processed; } }); @@ -275,10 +376,12 @@ function highlightCode(element: HTMLElement, language: string) { '$1' ); - // Types (capitalized words not after a dot) + // 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. processed = processed.replace( /\b([A-Z][a-zA-Z0-9_]*)\b/g, - '$1' + (_, name: string) => linkifyType(name) ); // Annotations/Attributes diff --git a/packages/docs/src/styles/code.css b/packages/docs/src/styles/code.css index fb92f2ca..ba349b14 100644 --- a/packages/docs/src/styles/code.css +++ b/packages/docs/src/styles/code.css @@ -363,6 +363,21 @@ pre code { font-weight: 500; } +/* Linkified type names (anchors emitted by `linkifyType` in CodeBlock.tsx). + Inherit the class-name color, no anchor underline by default, but show one + on hover to make it discoverable. */ +.code-block a.token.type-ref, +.code-snippet a.token.type-ref { + color: inherit; + text-decoration: none; + cursor: pointer; +} + +.code-block a.token.type-ref:hover, +.code-snippet a.token.type-ref:hover { + text-decoration: underline; +} + .code-block .token.decorator, .code-snippet .token.decorator { color: #6f42c1; From 8e29cf839b4702a108b3cd168ae779c639fec664 Mon Sep 17 00:00:00 2001 From: hyochan Date: Sun, 26 Apr 2026 14:07:01 +0900 Subject: [PATCH 09/26] fix(docs): linkifyType regex skips text already inside highlight spans MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Copilot caught that the type-linkification pass ran AFTER the keyword / function / decorator passes and matched capitalized identifiers via `\b([A-Z]...)\b`. That regex doesn't know whether the text it lands on is raw code or content of a `` tag emitted upstream — so capitalized keywords like Dart `Future` / `Function` and GDScript `String` / `Array` got re-wrapped, producing nested tags and overriding the keyword color via `.token.class-name`. Fix: prepend a negative lookbehind `(?])` to both class-name passes (TypeScript and Swift/Kotlin/Dart/GDScript). The character immediately before a capital that is INSIDE an existing tag is always either `>` (end of an opening tag) or `"` (an HTML attribute boundary), so the lookbehind cleanly excludes those positions and leaves only raw code. Type-linkification remains correctly applied to capitals at the start of a line, after spaces, after `(`, after `:`, etc. — all positions that show up in real signatures (`-> FetchProductsResult`, `(_ params: ProductRequest)`). Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/docs/src/components/CodeBlock.tsx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/docs/src/components/CodeBlock.tsx b/packages/docs/src/components/CodeBlock.tsx index d914dd30..e465ea65 100644 --- a/packages/docs/src/components/CodeBlock.tsx +++ b/packages/docs/src/components/CodeBlock.tsx @@ -272,8 +272,14 @@ 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, + /(?])\b([A-Z][a-zA-Z0-9_]*)\b/g, (_, name: string) => linkifyType(name) ); @@ -379,8 +385,13 @@ 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, + /(?])\b([A-Z][a-zA-Z0-9_]*)\b/g, (_, name: string) => linkifyType(name) ); From e184475b9f7d38543506628332329f0f3e509f95 Mon Sep 17 00:00:00 2001 From: hyochan Date: Sun, 26 Apr 2026 14:10:44 +0900 Subject: [PATCH 10/26] docs(types/purchase): add PurchaseOptions section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User flagged that the in-code-block linkify routes `PurchaseOptions` to `/docs/types/purchase` but the Purchase type page didn't actually document the options shape. Added a dedicated `PurchaseOptions` section near the bottom that lists every field with its platform, default, and behaviour: - alsoPublishToEventListenerIOS — re-emits results on purchaseUpdatedListener - onlyIncludeActiveItemsIOS — switches Transaction.all → Transaction.currentEntitlements - includeSuspendedAndroid — includes paused/grace-period subscriptions Co-Authored-By: Claude Opus 4.7 (1M context) --- .../docs/src/pages/docs/types/purchase.tsx | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/packages/docs/src/pages/docs/types/purchase.tsx b/packages/docs/src/pages/docs/types/purchase.tsx index 00572e3b..f9a2bfc3 100644 --- a/packages/docs/src/pages/docs/types/purchase.tsx +++ b/packages/docs/src/pages/docs/types/purchase.tsx @@ -677,6 +677,86 @@ function Purchase() { }} + +

+ + PurchaseOptions + +

+ 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). +

+
- 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.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NamePlatformDefaultSummary
+ 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 `

` with the full type and a one-line description; functions returning `void` say so explicitly. Throws blocks call out the platform-specific failure modes. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../android/acknowledge-purchase-android.tsx | 35 ++++++++++++ ...ternative-billing-availability-android.tsx | 14 +++++ .../apis/android/consume-purchase-android.tsx | 35 ++++++++++++ ...eate-alternative-billing-token-android.tsx | 15 +++++ ...ling-program-reporting-details-android.tsx | 42 ++++++++++++++ .../enable-billing-program-android.tsx | 40 +++++++++++++ .../is-billing-program-available-android.tsx | 42 ++++++++++++++ .../android/launch-external-link-android.tsx | 38 +++++++++++++ ...how-alternative-billing-dialog-android.tsx | 15 +++++ .../docs/apis/deep-link-to-subscriptions.tsx | 48 ++++++++++++++++ .../src/pages/docs/apis/end-connection.tsx | 14 +++++ .../src/pages/docs/apis/fetch-products.tsx | 42 ++++++++++++++ .../pages/docs/apis/finish-transaction.tsx | 57 +++++++++++++++++++ .../docs/apis/get-active-subscriptions.tsx | 38 +++++++++++++ .../docs/apis/get-available-purchases.tsx | 42 ++++++++++++++ .../src/pages/docs/apis/get-storefront.tsx | 14 +++++ .../docs/apis/has-active-subscriptions.tsx | 35 ++++++++++++ .../src/pages/docs/apis/init-connection.tsx | 45 +++++++++++++++ .../apis/ios/begin-refund-request-ios.tsx | 35 ++++++++++++ ...n-present-external-purchase-notice-ios.tsx | 14 +++++ .../docs/apis/ios/clear-transaction-ios.tsx | 14 +++++ .../docs/apis/ios/current-entitlement-ios.tsx | 35 ++++++++++++ .../apis/ios/get-all-transactions-ios.tsx | 14 +++++ .../docs/apis/ios/get-app-transaction-ios.tsx | 14 +++++ ...xternal-purchase-custom-link-token-ios.tsx | 38 +++++++++++++ .../apis/ios/get-pending-transactions-ios.tsx | 14 +++++ .../apis/ios/get-promoted-product-ios.tsx | 14 +++++ .../docs/apis/ios/get-receipt-data-ios.tsx | 14 +++++ .../docs/apis/ios/get-storefront-ios.tsx | 16 ++++++ .../docs/apis/ios/get-transaction-jws-ios.tsx | 35 ++++++++++++ ...-for-external-purchase-custom-link-ios.tsx | 14 +++++ .../ios/is-eligible-for-intro-offer-ios.tsx | 35 ++++++++++++ .../apis/ios/is-transaction-verified-ios.tsx | 35 ++++++++++++ .../docs/apis/ios/latest-transaction-ios.tsx | 35 ++++++++++++ .../ios/present-code-redemption-sheet-ios.tsx | 14 +++++ .../present-external-purchase-link-ios.tsx | 35 ++++++++++++ ...ent-external-purchase-notice-sheet-ios.tsx | 14 +++++ ...quest-purchase-on-promoted-product-ios.tsx | 17 ++++++ ...ternal-purchase-custom-link-notice-ios.tsx | 35 ++++++++++++ .../ios/show-manage-subscriptions-ios.tsx | 14 +++++ .../docs/apis/ios/subscription-status-ios.tsx | 35 ++++++++++++ .../docs/src/pages/docs/apis/ios/sync-ios.tsx | 14 +++++ .../docs/apis/ios/validate-receipt-ios.tsx | 38 +++++++++++++ .../src/pages/docs/apis/request-purchase.tsx | 52 +++++++++++++++++ .../src/pages/docs/apis/restore-purchases.tsx | 16 ++++++ 45 files changed, 1271 insertions(+) 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 ecfe6a1d..93a080af 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 @@ -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,40 @@ function AcknowledgePurchaseAndroid() { .

+ + Parameters + +
+ + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ purchaseToken + + string + YesPurchase token from the Play Billing transaction.
+ + + Returns + +

+ 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 + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ purchaseToken + + string + YesPurchase 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 + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ program + + + BillingProgramAndroid + + YesBilling program identifier.
+ + + Returns + +

+ Promise<BillingProgramReportingDetailsAndroid> — + External transaction token + metadata for reporting. See{' '} + + BillingProgramReportingDetailsAndroid + + . +

+

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 c8d720ee..3ac64d1e 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 @@ -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,45 @@ function EnableBillingProgramAndroid() { .

+ + Parameters + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ billingProgramAndroid + + + BillingProgramAndroid + + Yes + Note: this is a config field of InitConnectionConfig{' '} + passed to initConnection(), not a standalone + mutation. +
+ + + Returns + +

+ Promise<void> — Resolves once the program is enabled. +

+

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 d49515f8..7d369e3d 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 @@ -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 IsBillingProgramAvailableAndroid() { .

+ + Parameters + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ program + + + BillingProgramAndroid + + YesBilling program identifier.
+ + + Returns + +

+ Promise<BillingProgramAvailabilityResultAndroid> — + Availability result with isAvailable flag. See{' '} + + BillingProgramAvailabilityResultAndroid + + . +

+

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 cdbc0193..1cc91d6d 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 @@ -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'; @@ -40,6 +42,42 @@ function LaunchExternalLinkAndroid() { .

+ + Parameters + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ params + + + LaunchExternalLinkParamsAndroid + + YesIncludes the external URL plus per-program options.
+ + + Returns + +

+ Promise<boolean>true once the Play + disclosure dialog finished and (optionally) the URL was opened. +

+

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 b1f8cb25..17dcacea 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 @@ -1,3 +1,4 @@ +import AnchorLink from '../../../../components/AnchorLink'; import CodeBlock from '../../../../components/CodeBlock'; import LanguageTabs from '../../../../components/LanguageTabs'; import SEO from '../../../../components/SEO'; @@ -40,6 +41,20 @@ function ShowAlternativeBillingDialogAndroid() { .

+ + Parameters + +

None.

+ + + Returns + +

+ Promise<boolean>true if the user + accepts the disclosure dialog, false if they cancel (step 2 + of 3). +

+

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 b8fed3dd..4c3f4189 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 @@ -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'; @@ -48,6 +49,53 @@ function DeepLinkToSubscriptions() { .

+ + Parameters + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ options + + + DeepLinkOptions + + No + Android needs skuAndroid +{' '} + packageNameAndroid to deep-link to a specific + subscription; iOS ignores the argument. +
+ + + Returns + +

+ Promise<void> — Resolves when the system surface is + presented (or the deep link is opened on Android). +

+ + + Throws + +

+ iOS: When no UIWindowScene is available. +

+

Signature

{{ diff --git a/packages/docs/src/pages/docs/apis/end-connection.tsx b/packages/docs/src/pages/docs/apis/end-connection.tsx index 1ccccd69..4b5de144 100644 --- a/packages/docs/src/pages/docs/apis/end-connection.tsx +++ b/packages/docs/src/pages/docs/apis/end-connection.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'; @@ -42,6 +43,19 @@ function EndConnection() { .

+ + Parameters + +

None.

+ + + Returns + +

+ Promise<boolean>true when the + connection was closed cleanly. +

+

Signature

{{ diff --git a/packages/docs/src/pages/docs/apis/fetch-products.tsx b/packages/docs/src/pages/docs/apis/fetch-products.tsx index 5799f62c..9a48a2db 100644 --- a/packages/docs/src/pages/docs/apis/fetch-products.tsx +++ b/packages/docs/src/pages/docs/apis/fetch-products.tsx @@ -43,6 +43,48 @@ function FetchProducts() { .

+ + Parameters + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ params + + + ProductRequest + + Yes + Object with skus: string[] and optional{' '} + type: 'in-app' | 'subs' | 'all' (defaults to{' '} + 'in-app'). +
+ + + Returns + +

+ 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 + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ purchase + + + Purchase + + YesThe 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 + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ subscriptionIds + + string[] + NoWhen 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 + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ options + + + PurchaseOptions + + No + Platform-specific filters ( + alsoPublishToEventListenerIOS,{' '} + onlyIncludeActiveItemsIOS,{' '} + includeSuspendedAndroid). +
+ + + Returns + +

+ 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 c0e1b46a..34c8e4d0 100644 --- a/packages/docs/src/pages/docs/apis/get-storefront.tsx +++ b/packages/docs/src/pages/docs/apis/get-storefront.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'; @@ -40,6 +41,19 @@ function GetStorefront() { .

+ + Parameters + +

None.

+ + + Returns + +

+ Promise<string> — ISO 3166-1 alpha-2 country code of + the user's storefront. +

+

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 d8e7d417..eecddc19 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 AnchorLink from '../../../components/AnchorLink'; import CodeBlock from '../../../components/CodeBlock'; import LanguageTabs from '../../../components/LanguageTabs'; import SEO from '../../../components/SEO'; @@ -40,6 +41,40 @@ function HasActiveSubscriptions() { .

+ + Parameters + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ subscriptionIds + + string[] + NoWhen provided, checks only these SKUs.
+ + + Returns + +

+ Promise<boolean>true if any + (matching) subscription is active. +

+

Signature

{{ diff --git a/packages/docs/src/pages/docs/apis/init-connection.tsx b/packages/docs/src/pages/docs/apis/init-connection.tsx index f4bea93d..5875d50c 100644 --- a/packages/docs/src/pages/docs/apis/init-connection.tsx +++ b/packages/docs/src/pages/docs/apis/init-connection.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,50 @@ function InitConnection() { .

+ + Parameters + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ config + + + InitConnectionConfig + + No + Connection config (e.g. enableBillingProgramAndroid{' '} + for Play Billing 8.2.0+; iOS ignores Android-specific fields). +
+ + + Returns + +

+ Promise<boolean>true once the + platform billing client is connected. +

+ + + Throws + +

When the platform billing client fails to initialize.

+

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 691a535e..9c536785 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 @@ -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'; @@ -36,6 +37,40 @@ function BeginRefundRequestIOS() { .

+ + Parameters + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ sku + + string + YesProduct identifier to refund.
+ + + Returns + +

+ Promise<string | null> — Refund request status + string, or null if the user dismissed the sheet. +

+

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 0f5ff22c..b7716154 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 @@ -1,3 +1,4 @@ +import AnchorLink from '../../../../components/AnchorLink'; import CodeBlock from '../../../../components/CodeBlock'; import LanguageTabs from '../../../../components/LanguageTabs'; import SEO from '../../../../components/SEO'; @@ -34,6 +35,19 @@ function CanPresentExternalPurchaseNoticeIOS() { .

+ + Parameters + +

None.

+ + + Returns + +

+ Promise<boolean>true if the + external-purchase notice sheet can be presented (iOS 17.4+). +

+

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 2d705269..83015f6f 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 @@ -1,3 +1,4 @@ +import AnchorLink from '../../../../components/AnchorLink'; import CodeBlock from '../../../../components/CodeBlock'; import LanguageTabs from '../../../../components/LanguageTabs'; import SEO from '../../../../components/SEO'; @@ -33,6 +34,19 @@ function ClearTransactionIOS() { .

+ + Parameters + +

None.

+ + + Returns + +

+ Promise<boolean>true once unfinished + transactions in the queue have been cleared. +

+

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 b9d01fc3..b312457a 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 AnchorLink from '../../../../components/AnchorLink'; import CodeBlock from '../../../../components/CodeBlock'; import LanguageTabs from '../../../../components/LanguageTabs'; import SEO from '../../../../components/SEO'; @@ -32,6 +33,40 @@ function CurrentEntitlementIOS() { .

+ + Parameters + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ sku + + string + YesProduct identifier.
+ + + Returns + +

+ Promise<PurchaseIOS | null> — Current entitlement for + the product, or null. +

+

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 a779c289..5843fe31 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 AnchorLink from '../../../../components/AnchorLink'; import CodeBlock from '../../../../components/CodeBlock'; import LanguageTabs from '../../../../components/LanguageTabs'; import SEO from '../../../../components/SEO'; @@ -37,6 +38,19 @@ function GetAllTransactionsIOS() { .

+ + Parameters + +

None.

+ + + Returns + +

+ Promise<PurchaseIOS[]> — Every StoreKit transaction + (finished + unfinished). +

+

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 25b9041d..9ebcc3e4 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 @@ -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,19 @@ function GetAppTransactionIOS() { .

+ + Parameters + +

None.

+ + + Returns + +

+ Promise<AppTransaction | null> — JWS-verified record + of how the app was acquired (iOS 16+). +

+

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 97bf2a32..10a99285 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 AnchorLink from '../../../../components/AnchorLink'; import CodeBlock from '../../../../components/CodeBlock'; import LanguageTabs from '../../../../components/LanguageTabs'; import SEO from '../../../../components/SEO'; @@ -44,6 +45,43 @@ function GetExternalPurchaseCustomLinkTokenIOS() { .

+ + Parameters + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ tokenType + + ExternalPurchaseCustomLinkTokenTypeIOS + Yes + acquisition (new customers) or services{' '} + (existing customers). +
+ + + Returns + +

+ Promise<ExternalPurchaseCustomLinkTokenResultIOS> — + Token for Apple's External Purchase Server reporting API. +

+

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 ac6d9e1b..6e6fe87f 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 AnchorLink from '../../../../components/AnchorLink'; import CodeBlock from '../../../../components/CodeBlock'; import LanguageTabs from '../../../../components/LanguageTabs'; import SEO from '../../../../components/SEO'; @@ -32,6 +33,19 @@ function GetPendingTransactionsIOS() { .

+ + Parameters + +

None.

+ + + Returns + +

+ Promise<PurchaseIOS[]> — Unfinished StoreKit + transactions in the queue. +

+

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 5843af06..b7fa76e2 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 AnchorLink from '../../../../components/AnchorLink'; import CodeBlock from '../../../../components/CodeBlock'; import LanguageTabs from '../../../../components/LanguageTabs'; import SEO from '../../../../components/SEO'; @@ -33,6 +34,19 @@ function GetPromotedProductIOS() { .

+ + Parameters + +

None.

+ + + Returns + +

+ Promise<ProductIOS | null> — The currently promoted + product, or null if none is queued. +

+

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 cacb57ad..4a1e2f9a 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 @@ -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,19 @@ function GetReceiptDataIOS() { .

+ + Parameters + +

None.

+ + + Returns + +

+ Promise<string | null> — Base64-encoded receipt data + (legacy StoreKit 1 path). +

+

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 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 + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ sku + + string + YesProduct 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 + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ groupID + + string + YesSubscription 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 + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ sku + + string + YesProduct identifier.
+ + + Returns + +

+ Promise<boolean> — Whether the latest transaction for{' '} + sku passed JWS verification. +

+

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 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 + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ sku + + string + YesProduct 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 + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ url + + string + YesExternal 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() {

+ + Parameters + +

+ None. Deprecated — use{' '} + promotedProductListenerIOS + requestPurchase. +

+ + + Returns + +

+ Promise<boolean>true if the request + was dispatched. +

+

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 6f927500..03ece045 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 AnchorLink from '../../../../components/AnchorLink'; import CodeBlock from '../../../../components/CodeBlock'; import LanguageTabs from '../../../../components/LanguageTabs'; import SEO from '../../../../components/SEO'; @@ -44,6 +45,40 @@ function ShowExternalPurchaseCustomLinkNoticeIOS() { .

+ + Parameters + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ noticeType + + ExternalPurchaseCustomLinkNoticeTypeIOS + YesDisclosure style.
+ + + Returns + +

+ Promise<ExternalPurchaseCustomLinkNoticeResultIOS> — + Disclosure result. +

+

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 e0251890..03a05635 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 AnchorLink from '../../../../components/AnchorLink'; import CodeBlock from '../../../../components/CodeBlock'; import LanguageTabs from '../../../../components/LanguageTabs'; import SEO from '../../../../components/SEO'; @@ -40,6 +41,19 @@ function ShowManageSubscriptionsIOS() { .

+ + Parameters + +

None.

+ + + Returns + +

+ Promise<PurchaseIOS[]> — Purchases whose status + changed while the sheet was presented. +

+

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 ef5a0184..4edd3b70 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 AnchorLink from '../../../../components/AnchorLink'; import CodeBlock from '../../../../components/CodeBlock'; import LanguageTabs from '../../../../components/LanguageTabs'; import SEO from '../../../../components/SEO'; @@ -36,6 +37,40 @@ function SubscriptionStatusIOS() { .

+ + Parameters + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ sku + + string + YesSubscription product identifier.
+ + + Returns + +

+ Promise<SubscriptionStatusIOS[]> — Status objects + from Product.SubscriptionInfo.status. +

+

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 e9ee3cac..e16c7914 100644 --- a/packages/docs/src/pages/docs/apis/ios/sync-ios.tsx +++ b/packages/docs/src/pages/docs/apis/ios/sync-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 SyncIOS() { .

+ + Parameters + +

None.

+ + + Returns + +

+ Promise<boolean>true once the App + Store sync completes. +

+

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 196b9c03..992952b7 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 @@ -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 ValidateReceiptIOS() {

+ + Parameters + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ options + + VerifyPurchaseProps + Yes + Receipt props. Deprecated — use{' '} + verifyPurchase. +
+ + + Returns + +

+ Promise<VerifyPurchaseResultIOS> — Legacy receipt + validation result. +

+

Signature

{{ 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 + + + + + + + + + + + + + + + + + + +
NameTypeRequiredDescription
+ 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

- Promise<BillingProgramReportingDetailsAndroid> — - External transaction token + metadata for reporting. See{' '} - BillingProgramReportingDetailsAndroid - - . + Promise<BillingProgramReportingDetailsAndroid> + {' '} + — payload to report a Developer-Provided Billing transaction:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
+ externalTransactionToken + + string + + Token to send to Google's reporting API. Required for compliance. +
+ responseCode + + number? + Raw Play Billing response code (when Play returned one).
+ debugMessage + + string? + Optional debug message from Play.

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 7d369e3d..2c4fb4d5 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 @@ -73,13 +73,51 @@ function IsBillingProgramAvailableAndroid() { Returns

- Promise<BillingProgramAvailabilityResultAndroid> — - Availability result with isAvailable flag. See{' '} - BillingProgramAvailabilityResultAndroid - - . + Promise<BillingProgramAvailabilityResultAndroid> + {' '} + — carries:

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
+ isAvailable + + boolean + + Whether the billing program is available for this user/device. +
+ responseCode + + number? + Raw Play Billing response code (when Play returned one).
+ debugMessage + + string? + Optional debug message from Play.

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 1cc91d6d..cbd95251 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 @@ -45,10 +45,17 @@ function LaunchExternalLinkAndroid() { Parameters +

+ Pass a single{' '} + + LaunchExternalLinkParamsAndroid + + : +

- + @@ -57,15 +64,30 @@ function LaunchExternalLinkAndroid() { - + + + + + + +
NameField Type Required Description
- params + program - - LaunchExternalLinkParamsAndroid + + BillingProgramAndroid YesIncludes the external URL plus per-program options. + Billing program the link belongs to (e.g.{' '} + EXTERNAL_OFFER). +
+ url + + string + Yes + External URL to launch after the Play disclosure dialog dismisses. +
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 4c3f4189..5dc1a899 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 @@ -52,10 +52,17 @@ function DeepLinkToSubscriptions() { Parameters +

+ Pass an optional{' '} + + DeepLinkOptions + + : +

- + @@ -64,22 +71,37 @@ function DeepLinkToSubscriptions() { + + + + + +
NameField Type Required Description
- 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. +

Returns diff --git a/packages/docs/src/pages/docs/apis/fetch-products.tsx b/packages/docs/src/pages/docs/apis/fetch-products.tsx index 9a48a2db..48bda4b6 100644 --- a/packages/docs/src/pages/docs/apis/fetch-products.tsx +++ b/packages/docs/src/pages/docs/apis/fetch-products.tsx @@ -46,10 +46,17 @@ function FetchProducts() { Parameters +

+ Pass a single{' '} + + ProductRequest + {' '} + object: +

- + @@ -58,18 +65,27 @@ function FetchProducts() { + + + + + + @@ -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:

+
NameField Type Required Description
- params + skus - - ProductRequest - + string[] YesProduct identifiers to fetch.
+ type + + 'in-app' | 'subs' | 'all' + - 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.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
VariantReturned forDescription
+ + 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:

- + @@ -69,7 +70,11 @@ function FinishTransaction() { - + - + 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[] - +
NameField Type Required Description YesThe 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.
NoWhen 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:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
+ 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 +

+ Pass an optional{' '} + + PurchaseOptions + + : +

- + @@ -63,19 +70,48 @@ function GetAvailablePurchases() { + + + + + + + + + + + + + - @@ -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[] - +
NameField Type Required Description
- options + alsoPublishToEventListenerIOS + + boolean + + No (default false) + + iOS. Re-emit results on{' '} + purchaseUpdatedListener. +
+ onlyIncludeActiveItemsIOS + + boolean + + No (default false) + + 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.
NoWhen 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 +

+ Pass an optional{' '} + + InitConnectionConfig + + : +

- + @@ -61,17 +68,33 @@ function InitConnection() { + + + + + + 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:

+
NameField Type Required Description
- config + alternativeBillingModeAndroid + + + AlternativeBillingModeAndroid + + No + Android · deprecated. Opt into Google's + user-choice billing flow. Prefer{' '} + enableBillingProgramAndroid. +
+ enableBillingProgramAndroid - - InitConnectionConfig + + BillingProgramAndroid No - 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.
+ + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
+ 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:

+ + + + + + + + + + + + + + + + + + + + +
FieldTypeDescription
+ state + + string + + StoreKit 2 renewal state (e.g. "subscribed",{' '} + "inGracePeriod", "expired"). +
+ renewalInfo + + + RenewalInfoIOS? + + + Renewal metadata (auto-renew flag, renewal date, expiration + reason). May be null. +

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 992952b7..dd59b961 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 @@ -79,8 +79,12 @@ function ValidateReceiptIOS() { Returns

- Promise<VerifyPurchaseResultIOS> — Legacy receipt - validation result. + + Promise<VerifyPurchaseResultIOS> + {' '} + — legacy receipt validation result. Carries isValid + + receipt/JWS metadata. Deprecated — use{' '} + verifyPurchase.

Signature

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: +

- + @@ -99,20 +106,94 @@ function RequestPurchase() { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameField Type Required Description
- 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 onlySingle 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 + NoQuantity for consumable bulk purchases.
+ request.google.skus + + string[] + Android onlyProduct 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 + NoOptional account identifier passed to Play.
+ request.google.obfuscatedProfileIdAndroid + + string NoOptional 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() {

Signature

{{ - typescript: ( - {`acknowledgePurchaseAndroid(purchaseToken: string): Promise`} - ), kotlin: ( {`suspend fun acknowledgePurchase(purchaseToken: String): Boolean`} ), kmp: ( {`suspend fun acknowledgePurchaseAndroid(purchaseToken: String): Boolean`} ), + typescript: ( + {`acknowledgePurchaseAndroid(purchaseToken: string): Promise`} + ), dart: ( {`Future acknowledgePurchaseAndroid(String purchaseToken);`} ), @@ -109,6 +109,38 @@ function AcknowledgePurchaseAndroid() { }} +

Example

+ + {{ + kotlin: ( + {`openIapStore.acknowledgePurchase(purchase.purchaseToken)`} + ), + kmp: ( + {`// kmp-iap (Android targets only — no-op on iOS) +kmpIAP.acknowledgePurchaseAndroid(purchase.purchaseToken)`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) +import { acknowledgePurchaseAndroid } from 'expo-iap'; + +if (Platform.OS === 'android') { + await acknowledgePurchaseAndroid(purchase.purchaseToken); +}`} + ), + dart: ( + {`if (Platform.isAndroid) { + await FlutterInappPurchase.instance.acknowledgePurchaseAndroid( + purchase.purchaseToken, + ); +}`} + ), + gdscript: ( + {`if iap.get_platform() == "Android": + await iap.acknowledge_purchase_android(purchase.purchase_token)`} + ), + }} + +

Note: Called automatically by{' '} finishTransaction() when{' '} 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 ccd6e3f3..86acb519 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 @@ -59,6 +59,49 @@ function CheckAlternativeBillingAvailabilityAndroid() { // Throws OpenIapError.NotPrepared if billing client not ready suspend fun checkAlternativeBillingAvailability(): Boolean`} ), + kmp: ( + {`suspend fun checkAlternativeBillingAvailabilityAndroid(): Boolean`} + ), + typescript: ( + {`checkAlternativeBillingAvailabilityAndroid(): Promise`} + ), + dart: ( + {`Future checkAlternativeBillingAvailabilityAndroid();`} + ), + gdscript: ( + {`func check_alternative_billing_availability_android() -> bool`} + ), + }} + + +

Example

+ + {{ + kotlin: ( + {`val ok = openIapStore.checkAlternativeBillingAvailability()`} + ), + kmp: ( + {`// kmp-iap (Android targets only — no-op on iOS) +val ok = kmpIAP.checkAlternativeBillingAvailabilityAndroid()`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) +import { checkAlternativeBillingAvailabilityAndroid } from 'expo-iap'; + +if (Platform.OS === 'android') { + const ok = await checkAlternativeBillingAvailabilityAndroid(); +}`} + ), + dart: ( + {`if (Platform.isAndroid) { + final ok = await FlutterInappPurchase.instance + .checkAlternativeBillingAvailabilityAndroid(); +}`} + ), + gdscript: ( + {`if iap.get_platform() == "Android": + var ok: bool = await iap.check_alternative_billing_availability_android()`} + ), }}
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 d813a896..a68b11bd 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 @@ -91,6 +91,50 @@ function ConsumePurchaseAndroid() { kotlin: ( {`suspend fun consumePurchase(purchaseToken: String): Boolean`} ), + kmp: ( + {`suspend fun consumePurchaseAndroid(purchaseToken: String): Boolean`} + ), + typescript: ( + {`consumePurchaseAndroid(purchaseToken: string): Promise`} + ), + dart: ( + {`Future consumePurchaseAndroid(String purchaseToken);`} + ), + gdscript: ( + {`func consume_purchase_android(purchase_token: String) -> bool`} + ), + }} +
+ +

Example

+ + {{ + kotlin: ( + {`openIapStore.consumePurchase(purchase.purchaseToken)`} + ), + kmp: ( + {`// kmp-iap (Android targets only — no-op on iOS) +kmpIAP.consumePurchaseAndroid(purchase.purchaseToken)`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) +import { consumePurchaseAndroid } from 'expo-iap'; + +if (Platform.OS === 'android') { + await consumePurchaseAndroid(purchase.purchaseToken); +}`} + ), + dart: ( + {`if (Platform.isAndroid) { + await FlutterInappPurchase.instance.consumePurchaseAndroid( + purchase.purchaseToken, + ); +}`} + ), + gdscript: ( + {`if iap.get_platform() == "Android": + await iap.consume_purchase_android(purchase.purchase_token)`} + ), }} 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 3d762d9a..3b1a13c8 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 @@ -62,6 +62,49 @@ function CreateAlternativeBillingTokenAndroid() { // Returns token string, or null if creation failed suspend fun createAlternativeBillingToken(): String?`} ), + kmp: ( + {`suspend fun createAlternativeBillingTokenAndroid(): String?`} + ), + typescript: ( + {`createAlternativeBillingTokenAndroid(): Promise`} + ), + dart: ( + {`Future createAlternativeBillingTokenAndroid();`} + ), + gdscript: ( + {`func create_alternative_billing_token_android() -> String`} + ), + }} +
+ +

Example

+ + {{ + kotlin: ( + {`val token = openIapStore.createAlternativeBillingToken()`} + ), + kmp: ( + {`// kmp-iap (Android targets only — no-op on iOS) +val token = kmpIAP.createAlternativeBillingTokenAndroid()`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) +import { createAlternativeBillingTokenAndroid } from 'expo-iap'; + +if (Platform.OS === 'android') { + const token = await createAlternativeBillingTokenAndroid(); +}`} + ), + dart: ( + {`if (Platform.isAndroid) { + final token = await FlutterInappPurchase.instance + .createAlternativeBillingTokenAndroid(); +}`} + ), + gdscript: ( + {`if iap.get_platform() == "Android": + var token: String = await iap.create_alternative_billing_token_android()`} + ), }}
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 dd0ae98a..4c7f2c76 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 @@ -130,6 +130,68 @@ suspend fun createBillingProgramReportingDetails( program: BillingProgramAndroid ): BillingProgramReportingDetailsAndroid`} ), + kmp: ( + {`suspend fun createBillingProgramReportingDetailsAndroid( + program: BillingProgramAndroid +): BillingProgramReportingDetailsAndroid`} + ), + typescript: ( + {`createBillingProgramReportingDetailsAndroid( + program: BillingProgramAndroid +): Promise`} + ), + dart: ( + {`Future + createBillingProgramReportingDetailsAndroid( + BillingProgramAndroid program, +);`} + ), + gdscript: ( + {`func create_billing_program_reporting_details_android( + program: int +) -> BillingProgramReportingDetailsAndroid`} + ), + }} +
+ +

Example

+ + {{ + kotlin: ( + {`val details = openIapStore.createBillingProgramReportingDetails( + BillingProgramAndroid.ExternalOffer +)`} + ), + kmp: ( + {`// kmp-iap (Android targets only — no-op on iOS) +val details = kmpIAP.createBillingProgramReportingDetailsAndroid( + BillingProgramAndroid.ExternalOffer +)`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) +import { createBillingProgramReportingDetailsAndroid } from 'expo-iap'; + +if (Platform.OS === 'android') { + const details = await createBillingProgramReportingDetailsAndroid( + 'external-offer', + ); +}`} + ), + dart: ( + {`if (Platform.isAndroid) { + final details = await FlutterInappPurchase.instance + .createBillingProgramReportingDetailsAndroid( + BillingProgramAndroid.externalOffer, + ); +}`} + ), + gdscript: ( + {`if iap.get_platform() == "Android": + var details = await iap.create_billing_program_reporting_details_android( + BillingProgramAndroid.EXTERNAL_OFFER + )`} + ), }}
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 3ac64d1e..63dc215b 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 @@ -90,11 +90,62 @@ function EnableBillingProgramAndroid() {

Signature

{{ + kotlin: ( + {`// Config field on InitConnectionConfig — wired via initConnection() +data class InitConnectionConfig( + val enableBillingProgramAndroid: BillingProgramAndroid? = null, + // ...other fields +)`} + ), + kmp: ( + {`// Config field on InitConnectionConfig (kmp-iap) +data class InitConnectionConfig( + val enableBillingProgramAndroid: BillingProgramAndroid? = null, + // ...other fields +)`} + ), typescript: ( - {`// expo-iap + {`initConnection(config?: { + enableBillingProgramAndroid?: BillingProgramAndroid; + // ...other fields +}): Promise`} + ), + dart: ( + {`Future initConnection({InitConnectionConfig? config}); + +class InitConnectionConfig { + final BillingProgramAndroid? enableBillingProgramAndroid; + // ...other fields +}`} + ), + gdscript: ( + {`# InitConnectionConfig.enable_billing_program_android: BillingProgramAndroid +func init_connection(config: InitConnectionConfig) -> bool`} + ), + }} + + +

Example

+ + {{ + kotlin: ( + {`openIapStore.initConnection( + InitConnectionConfig( + enableBillingProgramAndroid = BillingProgramAndroid.ExternalOffer + ) +)`} + ), + kmp: ( + {`// kmp-iap (Android targets only) +kmpIAP.initConnection( + InitConnectionConfig( + enableBillingProgramAndroid = BillingProgramAndroid.ExternalOffer + ) +)`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) import { initConnection } from 'expo-iap'; -// Same API in react-native-iap: -// import { initConnection } from 'react-native-iap'; await initConnection({ enableBillingProgramAndroid: 'external-offer', @@ -112,25 +163,21 @@ function App() { return ; }`} - ), - kotlin: ( - {`openIapStore.initConnection( - InitConnectionConfig( - enableBillingProgramAndroid = BillingProgramAndroid.ExternalOffer - ) -)`} ), dart: ( - {`await FlutterInappPurchase.instance.initConnection( - config: InitConnectionConfig( - enableBillingProgramAndroid: BillingProgramAndroid.externalOffer, - ), -);`} + {`if (Platform.isAndroid) { + await FlutterInappPurchase.instance.initConnection( + config: InitConnectionConfig( + enableBillingProgramAndroid: BillingProgramAndroid.externalOffer, + ), + ); +}`} ), gdscript: ( - {`var config = InitConnectionConfig.new() -config.enable_billing_program_android = BillingProgramAndroid.EXTERNAL_OFFER -await iap.init_connection(config)`} + {`if iap.get_platform() == "Android": + var config = InitConnectionConfig.new() + config.enable_billing_program_android = BillingProgramAndroid.EXTERNAL_OFFER + await iap.init_connection(config)`} ), }} 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 2c4fb4d5..7fe75839 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 @@ -129,6 +129,62 @@ suspend fun isBillingProgramAvailable( program: BillingProgramAndroid ): BillingProgramAvailabilityResultAndroid`} ), + kmp: ( + {`suspend fun isBillingProgramAvailableAndroid( + program: BillingProgramAndroid +): BillingProgramAvailabilityResultAndroid`} + ), + typescript: ( + {`isBillingProgramAvailableAndroid( + program: BillingProgramAndroid +): Promise`} + ), + dart: ( + {`Future + isBillingProgramAvailableAndroid(BillingProgramAndroid program);`} + ), + gdscript: ( + {`func is_billing_program_available_android( + program: int +) -> BillingProgramAvailabilityResultAndroid`} + ), + }} + + +

Example

+ + {{ + kotlin: ( + {`val result = openIapStore.isBillingProgramAvailable( + BillingProgramAndroid.ExternalOffer +)`} + ), + kmp: ( + {`// kmp-iap (Android targets only — no-op on iOS) +val result = kmpIAP.isBillingProgramAvailableAndroid( + BillingProgramAndroid.ExternalOffer +)`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) +import { isBillingProgramAvailableAndroid } from 'expo-iap'; + +if (Platform.OS === 'android') { + const result = await isBillingProgramAvailableAndroid('external-offer'); +}`} + ), + dart: ( + {`if (Platform.isAndroid) { + final result = await FlutterInappPurchase.instance + .isBillingProgramAvailableAndroid(BillingProgramAndroid.externalOffer); +}`} + ), + gdscript: ( + {`if iap.get_platform() == "Android": + var result = await iap.is_billing_program_available_android( + BillingProgramAndroid.EXTERNAL_OFFER + )`} + ), }} 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 cbd95251..06f49bdc 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 @@ -117,6 +117,82 @@ suspend fun launchExternalLink( // - linkType: ExternalLinkTypeAndroid // - linkUri: String`} ), + kmp: ( + {`suspend fun launchExternalLinkAndroid( + params: LaunchExternalLinkParamsAndroid +): Boolean`} + ), + typescript: ( + {`launchExternalLinkAndroid( + params: LaunchExternalLinkParamsAndroid +): Promise`} + ), + dart: ( + {`Future launchExternalLinkAndroid( + LaunchExternalLinkParamsAndroid params, +);`} + ), + gdscript: ( + {`func launch_external_link_android( + params: LaunchExternalLinkParamsAndroid +) -> bool`} + ), + }} + + +

Example

+ + {{ + kotlin: ( + {`openIapStore.launchExternalLink( + activity, + LaunchExternalLinkParamsAndroid( + billingProgram = BillingProgramAndroid.ExternalOffer, + launchMode = ExternalLinkLaunchModeAndroid.IN_APP_BROWSER, + linkType = ExternalLinkTypeAndroid.OFFER, + linkUri = "https://example.com/offer" + ) +)`} + ), + kmp: ( + {`// kmp-iap (Android targets only — no-op on iOS) +kmpIAP.launchExternalLinkAndroid( + LaunchExternalLinkParamsAndroid( + billingProgram = BillingProgramAndroid.ExternalOffer, + launchMode = ExternalLinkLaunchModeAndroid.IN_APP_BROWSER, + linkType = ExternalLinkTypeAndroid.OFFER, + linkUri = "https://example.com/offer" + ) +)`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) +import { launchExternalLinkAndroid } from 'expo-iap'; + +if (Platform.OS === 'android') { + await launchExternalLinkAndroid({ + program: 'external-offer', + url: 'https://example.com/offer', + }); +}`} + ), + dart: ( + {`if (Platform.isAndroid) { + await FlutterInappPurchase.instance.launchExternalLinkAndroid( + LaunchExternalLinkParamsAndroid( + program: BillingProgramAndroid.externalOffer, + url: 'https://example.com/offer', + ), + ); +}`} + ), + gdscript: ( + {`if iap.get_platform() == "Android": + var params = LaunchExternalLinkParamsAndroid.new() + params.program = BillingProgramAndroid.EXTERNAL_OFFER + params.url = "https://example.com/offer" + await iap.launch_external_link_android(params)`} + ), }} 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 17dcacea..cc05f076 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 @@ -63,6 +63,49 @@ function ShowAlternativeBillingDialogAndroid() { // Throws OpenIapError.NotPrepared if billing client not ready suspend fun showAlternativeBillingDialog(): Boolean`} ), + kmp: ( + {`suspend fun showAlternativeBillingDialogAndroid(): Boolean`} + ), + typescript: ( + {`showAlternativeBillingDialogAndroid(): Promise`} + ), + dart: ( + {`Future showAlternativeBillingDialogAndroid();`} + ), + gdscript: ( + {`func show_alternative_billing_dialog_android() -> bool`} + ), + }} + + +

Example

+ + {{ + kotlin: ( + {`val accepted = openIapStore.showAlternativeBillingDialog()`} + ), + kmp: ( + {`// kmp-iap (Android targets only — no-op on iOS) +val accepted = kmpIAP.showAlternativeBillingDialogAndroid()`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) +import { showAlternativeBillingDialogAndroid } from 'expo-iap'; + +if (Platform.OS === 'android') { + const accepted = await showAlternativeBillingDialogAndroid(); +}`} + ), + dart: ( + {`if (Platform.isAndroid) { + final accepted = await FlutterInappPurchase.instance + .showAlternativeBillingDialogAndroid(); +}`} + ), + gdscript: ( + {`if iap.get_platform() == "Android": + var accepted: bool = await iap.show_alternative_billing_dialog_android()`} + ), }} 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 9c536785..ef3a187c 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 @@ -77,6 +77,49 @@ function BeginRefundRequestIOS() { swift: ( {`func beginRefundRequestIOS(sku: String) async throws -> String?`} ), + kotlin: ( + {`suspend fun beginRefundRequestIOS(sku: String): String?`} + ), + typescript: ( + {`beginRefundRequestIOS(sku: string): Promise`} + ), + dart: ( + {`Future beginRefundRequestIOS(String sku);`} + ), + gdscript: ( + {`func begin_refund_request_ios(sku: String) -> Variant`} + ), + }} + + +

Example

+ + {{ + swift: ( + {`let status = try await OpenIapModule.shared.beginRefundRequestIOS(sku: "com.app.premium")`} + ), + kotlin: ( + {`// kmp-iap (iOS targets only — no-op on Android) +val status = kmpIAP.beginRefundRequestIOS(sku = "com.app.premium")`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) +import { beginRefundRequestIOS } from 'expo-iap'; + +if (Platform.OS === 'ios') { + const status = await beginRefundRequestIOS('com.app.premium'); +}`} + ), + dart: ( + {`if (Platform.isIOS) { + final status = await FlutterInappPurchase.instance + .beginRefundRequestIOS('com.app.premium'); +}`} + ), + gdscript: ( + {`if iap.get_platform() == "iOS": + var status = await iap.begin_refund_request_ios("com.app.premium")`} + ), }} 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 b7716154..dec0e025 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 @@ -54,6 +54,49 @@ function CanPresentExternalPurchaseNoticeIOS() { swift: ( {`func canPresentExternalPurchaseNoticeIOS() async throws -> Bool`} ), + kotlin: ( + {`suspend fun canPresentExternalPurchaseNoticeIOS(): Boolean`} + ), + typescript: ( + {`canPresentExternalPurchaseNoticeIOS(): Promise`} + ), + dart: ( + {`Future canPresentExternalPurchaseNoticeIOS();`} + ), + gdscript: ( + {`func can_present_external_purchase_notice_ios() -> Variant`} + ), + }} + + +

Example

+ + {{ + swift: ( + {`let can = try await OpenIapModule.shared.canPresentExternalPurchaseNoticeIOS()`} + ), + kotlin: ( + {`// kmp-iap (iOS targets only — no-op on Android) +val can = kmpIAP.canPresentExternalPurchaseNoticeIOS()`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) +import { canPresentExternalPurchaseNoticeIOS } from 'expo-iap'; + +if (Platform.OS === 'ios') { + const can = await canPresentExternalPurchaseNoticeIOS(); +}`} + ), + dart: ( + {`if (Platform.isIOS) { + final can = await FlutterInappPurchase.instance + .canPresentExternalPurchaseNoticeIOS(); +}`} + ), + gdscript: ( + {`if iap.get_platform() == "iOS": + var can = await iap.can_present_external_purchase_notice_ios()`} + ), }} 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 83015f6f..f1189860 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 @@ -53,6 +53,48 @@ function ClearTransactionIOS() { swift: ( {`func clearTransactionIOS() async throws -> Bool`} ), + kotlin: ( + {`suspend fun clearTransactionIOS(): Boolean`} + ), + typescript: ( + {`clearTransactionIOS(): Promise`} + ), + dart: ( + {`Future clearTransactionIOS();`} + ), + gdscript: ( + {`func clear_transaction_ios() -> Variant`} + ), + }} + + +

Example

+ + {{ + swift: ( + {`try await OpenIapModule.shared.clearTransactionIOS()`} + ), + kotlin: ( + {`// kmp-iap (iOS targets only — no-op on Android) +kmpIAP.clearTransactionIOS()`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) +import { clearTransactionIOS } from 'expo-iap'; + +if (Platform.OS === 'ios') { + await clearTransactionIOS(); +}`} + ), + dart: ( + {`if (Platform.isIOS) { + await FlutterInappPurchase.instance.clearTransactionIOS(); +}`} + ), + gdscript: ( + {`if iap.get_platform() == "iOS": + var result = await iap.clear_transaction_ios()`} + ), }} 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 ec71c4b9..65a0d0a3 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 @@ -77,6 +77,49 @@ function CurrentEntitlementIOS() { swift: ( {`func currentEntitlementIOS(sku: String) async throws -> Purchase?`} ), + kotlin: ( + {`suspend fun currentEntitlementIOS(sku: String): PurchaseIOS?`} + ), + typescript: ( + {`currentEntitlementIOS(sku: string): Promise`} + ), + dart: ( + {`Future currentEntitlementIOS(String sku);`} + ), + gdscript: ( + {`func current_entitlement_ios(sku: String) -> Variant`} + ), + }} + + +

Example

+ + {{ + swift: ( + {`let entitlement = try await OpenIapModule.shared.currentEntitlementIOS(sku: "com.app.premium")`} + ), + kotlin: ( + {`// kmp-iap (iOS targets only — no-op on Android) +val entitlement = kmpIAP.currentEntitlementIOS(sku = "com.app.premium")`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) +import { currentEntitlementIOS } from 'expo-iap'; + +if (Platform.OS === 'ios') { + const entitlement = await currentEntitlementIOS('com.app.premium'); +}`} + ), + dart: ( + {`if (Platform.isIOS) { + final entitlement = await FlutterInappPurchase.instance + .currentEntitlementIOS('com.app.premium'); +}`} + ), + gdscript: ( + {`if iap.get_platform() == "iOS": + var entitlement = await iap.current_entitlement_ios("com.app.premium")`} + ), }} 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 e937dc75..8980ebaa 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 @@ -64,6 +64,48 @@ function GetAllTransactionsIOS() { swift: ( {`func getAllTransactionsIOS() async throws -> [PurchaseIOS]`} ), + kotlin: ( + {`suspend fun getAllTransactionsIOS(): List`} + ), + typescript: ( + {`getAllTransactionsIOS(): Promise`} + ), + dart: ( + {`Future> getAllTransactionsIOS();`} + ), + gdscript: ( + {`func get_all_transactions_ios() -> Variant`} + ), + }} + + +

Example

+ + {{ + swift: ( + {`let txs = try await OpenIapModule.shared.getAllTransactionsIOS()`} + ), + kotlin: ( + {`// kmp-iap (iOS targets only — no-op on Android) +val txs = kmpIAP.getAllTransactionsIOS()`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) +import { getAllTransactionsIOS } from 'expo-iap'; + +if (Platform.OS === 'ios') { + const txs = await getAllTransactionsIOS(); +}`} + ), + dart: ( + {`if (Platform.isIOS) { + final txs = await FlutterInappPurchase.instance.getAllTransactionsIOS(); +}`} + ), + gdscript: ( + {`if iap.get_platform() == "iOS": + var txs = await iap.get_all_transactions_ios()`} + ), }} 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 a87d52eb..58bf351d 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 @@ -56,6 +56,48 @@ function GetAppTransactionIOS() { swift: ( {`func getAppTransactionIOS() async throws -> AppTransactionIOS?`} ), + kotlin: ( + {`suspend fun getAppTransactionIOS(): AppTransaction?`} + ), + typescript: ( + {`getAppTransactionIOS(): Promise`} + ), + dart: ( + {`Future getAppTransactionIOS();`} + ), + gdscript: ( + {`func get_app_transaction_ios() -> Variant`} + ), + }} + + +

Example

+ + {{ + swift: ( + {`let appTx = try await OpenIapModule.shared.getAppTransactionIOS()`} + ), + kotlin: ( + {`// kmp-iap (iOS targets only — no-op on Android) +val appTx = kmpIAP.getAppTransactionIOS()`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) +import { getAppTransactionIOS } from 'expo-iap'; + +if (Platform.OS === 'ios') { + const appTx = await getAppTransactionIOS(); +}`} + ), + dart: ( + {`if (Platform.isIOS) { + final appTx = await FlutterInappPurchase.instance.getAppTransactionIOS(); +}`} + ), + gdscript: ( + {`if iap.get_platform() == "iOS": + var app_tx = await iap.get_app_transaction_ios()`} + ), }} 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 85f1d64e..87f7518b 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 @@ -95,6 +95,62 @@ function GetExternalPurchaseCustomLinkTokenIOS() { tokenType: ExternalPurchaseCustomLinkTokenTypeIOS ) async throws -> ExternalPurchaseCustomLinkTokenResultIOS`} ), + kotlin: ( + {`suspend fun getExternalPurchaseCustomLinkTokenIOS( + tokenType: ExternalPurchaseCustomLinkTokenTypeIOS +): ExternalPurchaseCustomLinkTokenResultIOS`} + ), + typescript: ( + {`getExternalPurchaseCustomLinkTokenIOS( + tokenType: ExternalPurchaseCustomLinkTokenTypeIOS, +): Promise`} + ), + dart: ( + {`Future + getExternalPurchaseCustomLinkTokenIOS( + ExternalPurchaseCustomLinkTokenTypeIOS tokenType, +);`} + ), + gdscript: ( + {`func get_external_purchase_custom_link_token_ios(token_type: String) -> Variant`} + ), + }} + + +

Example

+ + {{ + swift: ( + {`let token = try await OpenIapModule.shared.getExternalPurchaseCustomLinkTokenIOS( + tokenType: .acquisition +)`} + ), + kotlin: ( + {`// kmp-iap (iOS targets only — no-op on Android) +val token = kmpIAP.getExternalPurchaseCustomLinkTokenIOS( + tokenType = ExternalPurchaseCustomLinkTokenTypeIOS.ACQUISITION +)`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) +import { getExternalPurchaseCustomLinkTokenIOS } from 'expo-iap'; + +if (Platform.OS === 'ios') { + const token = await getExternalPurchaseCustomLinkTokenIOS('acquisition'); +}`} + ), + dart: ( + {`if (Platform.isIOS) { + final token = await FlutterInappPurchase.instance + .getExternalPurchaseCustomLinkTokenIOS( + ExternalPurchaseCustomLinkTokenTypeIOS.acquisition, + ); +}`} + ), + gdscript: ( + {`if iap.get_platform() == "iOS": + var token = await iap.get_external_purchase_custom_link_token_ios("acquisition")`} + ), }} 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 cf4bec03..2918e3a4 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 @@ -59,6 +59,48 @@ function GetPendingTransactionsIOS() { swift: ( {`func getPendingTransactionsIOS() async throws -> [Purchase]`} ), + kotlin: ( + {`suspend fun getPendingTransactionsIOS(): List`} + ), + typescript: ( + {`getPendingTransactionsIOS(): Promise`} + ), + dart: ( + {`Future> getPendingTransactionsIOS();`} + ), + gdscript: ( + {`func get_pending_transactions_ios() -> Variant`} + ), + }} + + +

Example

+ + {{ + swift: ( + {`let txs = try await OpenIapModule.shared.getPendingTransactionsIOS()`} + ), + kotlin: ( + {`// kmp-iap (iOS targets only — no-op on Android) +val txs = kmpIAP.getPendingTransactionsIOS()`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) +import { getPendingTransactionsIOS } from 'expo-iap'; + +if (Platform.OS === 'ios') { + const txs = await getPendingTransactionsIOS(); +}`} + ), + dart: ( + {`if (Platform.isIOS) { + final txs = await FlutterInappPurchase.instance.getPendingTransactionsIOS(); +}`} + ), + gdscript: ( + {`if iap.get_platform() == "iOS": + var txs = await iap.get_pending_transactions_ios()`} + ), }} 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 3e133257..e1ae37f0 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 @@ -57,6 +57,48 @@ function GetPromotedProductIOS() { swift: ( {`func getPromotedProductIOS() async throws -> Product?`} ), + kotlin: ( + {`suspend fun getPromotedProductIOS(): ProductIOS?`} + ), + typescript: ( + {`getPromotedProductIOS(): Promise`} + ), + dart: ( + {`Future getPromotedProductIOS();`} + ), + gdscript: ( + {`func get_promoted_product_ios() -> Variant`} + ), + }} + + +

Example

+ + {{ + swift: ( + {`let product = try await OpenIapModule.shared.getPromotedProductIOS()`} + ), + kotlin: ( + {`// kmp-iap (iOS targets only — no-op on Android) +val product = kmpIAP.getPromotedProductIOS()`} + ), + typescript: ( + {`// expo-iap (also exported from react-native-iap) +import { getPromotedProductIOS } from 'expo-iap'; + +if (Platform.OS === 'ios') { + const product = await getPromotedProductIOS(); +}`} + ), + dart: ( + {`if (Platform.isIOS) { + final product = await FlutterInappPurchase.instance.getPromotedProductIOS(); +}`} + ), + gdscript: ( + {`if iap.get_platform() == "iOS": + var product = await iap.get_promoted_product_ios()`} + ), }} 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 4a1e2f9a..25f8b590 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 @@ -51,70 +51,50 @@ function GetReceiptDataIOS() {

Signature

{{ - typescript: ( - {`getReceiptDataIOS(): Promise`} - ), swift: ( {`func getReceiptDataIOS() async throws -> String?`} ), kotlin: ( {`suspend fun getReceiptDataIOS(): String?`} ), - kmp: ( - {`suspend fun getReceiptDataIOS(): String?`} + typescript: ( + {`getReceiptDataIOS(): Promise`} ), dart: ( {`Future getReceiptDataIOS();`} ), + gdscript: ( + {`func get_receipt_data_ios() -> Variant`} + ), }}

Example

{{ - typescript: ( - {`// expo-iap -import { getReceiptDataIOS } from 'expo-iap'; -// Same API in react-native-iap: -// import { getReceiptDataIOS } from 'react-native-iap'; - -const receipt = await getReceiptDataIOS(); -// Send the base64-encoded receipt to your server for legacy verifyReceipt. -console.log(receipt?.length ?? 0, 'bytes'); - -// --- Or alongside the useIAP() hook (also exported from react-native-iap) --- -// getReceiptDataIOS is a module-level helper; useIAP doesn't expose it on the -// hook return, so call the module function from inside your component once -// the hook reports the connection is ready. -import { useIAP } from 'expo-iap'; - -function ReceiptUploader() { - const { connected } = useIAP(); - - const upload = async () => { - if (!connected) return; - const receipt = await getReceiptDataIOS(); - if (!receipt) return; - await fetch('/api/validate-receipt', { - method: 'POST', - body: JSON.stringify({ receipt }), - }); - }; - - return