expo-iap 4.2.2 → 4.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/build/index.d.ts +126 -33
  2. package/build/index.d.ts.map +1 -1
  3. package/build/index.js +123 -33
  4. package/build/index.js.map +1 -1
  5. package/build/kit-api.d.ts +54 -0
  6. package/build/kit-api.d.ts.map +1 -0
  7. package/build/kit-api.js +156 -0
  8. package/build/kit-api.js.map +1 -0
  9. package/build/modules/android.d.ts +22 -0
  10. package/build/modules/android.d.ts.map +1 -1
  11. package/build/modules/android.js +37 -0
  12. package/build/modules/android.js.map +1 -1
  13. package/build/modules/ios.d.ts +69 -1
  14. package/build/modules/ios.d.ts.map +1 -1
  15. package/build/modules/ios.js +73 -1
  16. package/build/modules/ios.js.map +1 -1
  17. package/build/types.d.ts +241 -75
  18. package/build/types.d.ts.map +1 -1
  19. package/build/types.js.map +1 -1
  20. package/build/useIAP.d.ts.map +1 -1
  21. package/build/useIAP.js +125 -3
  22. package/build/useIAP.js.map +1 -1
  23. package/build/useWebhookEvents.d.ts +26 -0
  24. package/build/useWebhookEvents.d.ts.map +1 -0
  25. package/build/useWebhookEvents.js +105 -0
  26. package/build/useWebhookEvents.js.map +1 -0
  27. package/build/webhook-client.d.ts +82 -0
  28. package/build/webhook-client.d.ts.map +1 -0
  29. package/build/webhook-client.js +176 -0
  30. package/build/webhook-client.js.map +1 -0
  31. package/openiap-versions.json +2 -2
  32. package/package.json +1 -1
  33. package/src/index.ts +141 -33
  34. package/src/kit-api.ts +229 -0
  35. package/src/modules/android.ts +47 -0
  36. package/src/modules/ios.ts +74 -1
  37. package/src/types.ts +247 -75
  38. package/src/useIAP.ts +125 -3
  39. package/src/useWebhookEvents.ts +155 -0
  40. package/src/webhook-client.ts +314 -0
@@ -1 +1 @@
1
- {"version":3,"file":"useIAP.d.ts","sourceRoot":"","sources":["../src/useIAP.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useIAP.d.ts","sourceRoot":"","sources":["../src/useIAP.ts"],"names":[],"mappings":"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"}
package/build/useIAP.js CHANGED
@@ -75,6 +75,30 @@ export function useIAP(options) {
75
75
  optionsRef.current.onError(error instanceof Error ? error : new Error(String(error)));
76
76
  }
77
77
  }, []);
78
+ /**
79
+ * Retrieve products or subscriptions from the store by SKU.
80
+ *
81
+ * @param params `ProductRequest` — `skus` (string[]) and optional `type`
82
+ * (`'in-app' | 'subs' | 'all'`, defaults to `'in-app'`).
83
+ * @returns Promise that resolves when the request is dispatched; results land in the
84
+ * hook's reactive `products` / `subscriptions` state.
85
+ * @throws When the store rejects the request (empty `skus`, not connected,
86
+ * network/store error). Unknown SKUs are simply omitted from the result, not thrown.
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * const { fetchProducts, products } = useIAP();
91
+ * await fetchProducts({
92
+ * skus: ['com.app.coins_100', 'com.app.premium'],
93
+ * type: 'in-app',
94
+ * });
95
+ * ```
96
+ *
97
+ * @remarks This is a regular promise-based call. Don't confuse with `request*` APIs
98
+ * (`requestPurchase`), which are event-based.
99
+ *
100
+ * @see {@link https://www.openiap.dev/docs/apis/fetch-products}
101
+ */
78
102
  const fetchProductsInternal = useCallback(async (params) => {
79
103
  try {
80
104
  const queryType = normalizeProductQueryType(params.type);
@@ -130,6 +154,27 @@ export function useIAP(options) {
130
154
  mergeWithDuplicateCheck,
131
155
  normalizeProductQueryType,
132
156
  ]);
157
+ /**
158
+ * List the user's unfinished purchases — non-consumables, active subscriptions, and any
159
+ * pending transactions not yet finished.
160
+ *
161
+ * @param options Optional `PurchaseOptions`. iOS-only flags:
162
+ * `alsoPublishToEventListenerIOS`, `onlyIncludeActiveItemsIOS`.
163
+ * @returns Promise that resolves when the request is dispatched; results land in the
164
+ * hook's reactive `availablePurchases` state.
165
+ * @throws When the platform query fails.
166
+ *
167
+ * @example
168
+ * ```ts
169
+ * const { getAvailablePurchases, availablePurchases } = useIAP();
170
+ * await getAvailablePurchases();
171
+ * for (const p of availablePurchases) {
172
+ * if (await verifyOnServer(p)) await finishTransaction({ purchase: p, isConsumable: false });
173
+ * }
174
+ * ```
175
+ *
176
+ * @see {@link https://www.openiap.dev/docs/apis/get-available-purchases}
177
+ */
133
178
  const getAvailablePurchasesInternal = useCallback(async (options) => {
134
179
  try {
135
180
  const result = await getAvailablePurchases({
@@ -145,6 +190,11 @@ export function useIAP(options) {
145
190
  throw error;
146
191
  }
147
192
  }, [invokeOnError]);
193
+ /**
194
+ * Get details of all currently active subscriptions.
195
+ *
196
+ * @see {@link https://www.openiap.dev/docs/apis/get-active-subscriptions}
197
+ */
148
198
  const getActiveSubscriptionsInternal = useCallback(async (subscriptionIds) => {
149
199
  try {
150
200
  const result = await getActiveSubscriptions(subscriptionIds);
@@ -156,6 +206,11 @@ export function useIAP(options) {
156
206
  throw error;
157
207
  }
158
208
  }, [invokeOnError]);
209
+ /**
210
+ * Check whether the user has any active subscription.
211
+ *
212
+ * @see {@link https://www.openiap.dev/docs/apis/has-active-subscriptions}
213
+ */
159
214
  const hasActiveSubscriptionsInternal = useCallback(async (subscriptionIds) => {
160
215
  try {
161
216
  return await hasActiveSubscriptions(subscriptionIds);
@@ -165,12 +220,62 @@ export function useIAP(options) {
165
220
  return false;
166
221
  }
167
222
  }, []);
223
+ /**
224
+ * Complete a purchase transaction. Call after server-side verification to remove it
225
+ * from the queue.
226
+ *
227
+ * @param args.purchase The `Purchase` to finalize.
228
+ * @param args.isConsumable `true` for consumables (consumes the token so the SKU can be
229
+ * re-bought, e.g. coins); `false` (default) for non-consumables and subscriptions.
230
+ * @returns Promise that resolves once the platform finalizes the transaction.
231
+ * @throws When the platform finalize call fails.
232
+ *
233
+ * @example
234
+ * ```ts
235
+ * // Inside purchaseUpdatedListener:
236
+ * if (await verifyOnServer(purchase)) {
237
+ * await finishTransaction({ purchase, isConsumable: false });
238
+ * }
239
+ * ```
240
+ *
241
+ * @remarks **Critical:** Android purchases must be finalized within 3 days or Google
242
+ * auto-refunds. iOS unfinished transactions replay on every app launch.
243
+ *
244
+ * @see {@link https://www.openiap.dev/docs/apis/finish-transaction}
245
+ */
168
246
  const finishTransaction = useCallback(async ({ purchase, isConsumable, }) => {
169
247
  await finishTransactionInternal({
170
248
  purchase: toPurchaseInput(purchase),
171
249
  isConsumable,
172
250
  });
173
251
  }, [toPurchaseInput]);
252
+ /**
253
+ * Initiate a purchase or subscription flow. The result is delivered through
254
+ * `purchaseUpdatedListener` — NOT the return value.
255
+ *
256
+ * @param props `RequestPurchaseProps`, discriminated by `type`:
257
+ * - `type: 'in-app'` — pass `request.apple.sku` (iOS) and/or `request.google.skus` (Android).
258
+ * - `type: 'subs'` — same shape, plus `request.google.subscriptionOffers: [{ sku, offerToken }]`.
259
+ * @returns Promise that resolves when the request is dispatched; the actual purchase
260
+ * outcome lands in the hook's `onPurchaseSuccess` / `onPurchaseError` callbacks.
261
+ * @throws Synchronous rejection from the store (e.g. `E_NOT_PREPARED`, validation failure).
262
+ *
263
+ * @example
264
+ * ```ts
265
+ * await requestPurchase({
266
+ * request: {
267
+ * apple: { sku: 'com.app.premium' },
268
+ * google: { skus: ['com.app.premium'] },
269
+ * },
270
+ * type: 'in-app',
271
+ * });
272
+ * ```
273
+ *
274
+ * @remarks Event-based. Listen for the result via {@link purchaseUpdatedListener} /
275
+ * {@link purchaseErrorListener}, or use `useIAP({ onPurchaseSuccess, onPurchaseError })`.
276
+ *
277
+ * @see {@link https://www.openiap.dev/docs/apis/request-purchase}
278
+ */
174
279
  const requestPurchaseWithReset = useCallback((requestObj) => {
175
280
  return requestPurchaseInternal(requestObj);
176
281
  }, []);
@@ -190,9 +295,11 @@ export function useIAP(options) {
190
295
  getAvailablePurchasesInternal,
191
296
  getActiveSubscriptionsInternal,
192
297
  ]);
193
- // Restore completed transactions with cross-platform behavior.
194
- // iOS: best-effort sync (ignore sync errors) then fetch available purchases.
195
- // Android: fetch available purchases directly.
298
+ /**
299
+ * Restore non-consumable and active subscription purchases.
300
+ *
301
+ * @see {@link https://www.openiap.dev/docs/apis/restore-purchases}
302
+ */
196
303
  const restorePurchasesInternal = useCallback(async (options) => {
197
304
  try {
198
305
  // iOS: Try to sync first, but don't fail if sync errors occur
@@ -212,12 +319,27 @@ export function useIAP(options) {
212
319
  throw error;
213
320
  }
214
321
  }, [invokeOnError]);
322
+ /**
323
+ * Deprecated. Use verifyPurchase instead — same input/output shape.
324
+ *
325
+ * @see {@link https://www.openiap.dev/docs/apis/validate-receipt}
326
+ */
215
327
  const validateReceipt = useCallback(async (props) => {
216
328
  return validateReceiptInternal(props);
217
329
  }, []);
330
+ /**
331
+ * Verify a purchase against your own backend (returns isValid + raw store metadata).
332
+ *
333
+ * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase}
334
+ */
218
335
  const verifyPurchase = useCallback(async (props) => {
219
336
  return verifyPurchaseInternal(props);
220
337
  }, []);
338
+ /**
339
+ * Verify via a managed provider — currently only `iapkit` (IAPKit). The PurchaseVerificationProvider enum exposes no other provider literal today.
340
+ *
341
+ * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider}
342
+ */
221
343
  const verifyPurchaseWithProvider = useCallback(async (props) => {
222
344
  return verifyPurchaseWithProviderInternal(props);
223
345
  }, []);
@@ -1 +1 @@
1
- {"version":3,"file":"useIAP.js","sourceRoot":"","sources":["../src/useIAP.ts"],"names":[],"mappings":"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","sourcesContent":["// External dependencies\nimport {useCallback, useEffect, useState, useRef} from 'react';\nimport {Platform} from 'react-native';\nimport {EventSubscription} from 'expo-modules-core';\n\n// Internal modules\nimport {\n endConnection,\n initConnection,\n purchaseErrorListener,\n purchaseUpdatedListener,\n promotedProductListenerIOS,\n getAvailablePurchases,\n finishTransaction as finishTransactionInternal,\n requestPurchase as requestPurchaseInternal,\n fetchProducts,\n validateReceipt as validateReceiptInternal,\n verifyPurchase as verifyPurchaseInternal,\n verifyPurchaseWithProvider as verifyPurchaseWithProviderInternal,\n getActiveSubscriptions,\n hasActiveSubscriptions,\n type ActiveSubscription,\n type ProductTypeInput,\n} from './index';\nimport {ExpoIapConsole} from './utils/debug';\nimport {\n getPromotedProductIOS,\n requestPurchaseOnPromotedProductIOS,\n syncIOS,\n} from './modules/ios';\nimport {\n checkAlternativeBillingAvailabilityAndroid,\n showAlternativeBillingDialogAndroid,\n createAlternativeBillingTokenAndroid,\n} from './modules/android';\n\n// Types\nimport type {\n Product,\n ProductSubscription,\n ProductQueryType,\n ProductRequest,\n Purchase,\n MutationRequestPurchaseArgs,\n PurchaseInput,\n VerifyPurchaseProps,\n VerifyPurchaseResult,\n VerifyPurchaseWithProviderProps,\n VerifyPurchaseWithProviderResult,\n ProductAndroid,\n ProductSubscriptionIOS,\n PurchaseOptions,\n} from './types';\nimport {ErrorCode} from './types';\nimport type {PurchaseError} from './utils/errorMapping';\nimport {\n getUserFriendlyErrorMessage,\n isUserCancelledError,\n isRecoverableError,\n} from './utils/errorMapping';\n\ntype UseIap = {\n connected: boolean;\n products: Product[];\n subscriptions: ProductSubscription[];\n availablePurchases: Purchase[];\n promotedProductIOS?: Product;\n activeSubscriptions: ActiveSubscription[];\n finishTransaction: ({\n purchase,\n isConsumable,\n }: {\n purchase: Purchase;\n isConsumable?: boolean;\n }) => Promise<void>;\n getAvailablePurchases: (options?: PurchaseOptions) => Promise<void>;\n fetchProducts: (params: {\n skus: string[];\n type?: ProductTypeInput;\n }) => Promise<void>;\n\n requestPurchase: (\n params: MutationRequestPurchaseArgs,\n ) => ReturnType<typeof requestPurchaseInternal>;\n /** @deprecated Use verifyPurchase instead */\n validateReceipt: (\n props: VerifyPurchaseProps,\n ) => Promise<VerifyPurchaseResult>;\n verifyPurchase: (props: VerifyPurchaseProps) => Promise<VerifyPurchaseResult>;\n verifyPurchaseWithProvider: (\n props: VerifyPurchaseWithProviderProps,\n ) => Promise<VerifyPurchaseWithProviderResult>;\n restorePurchases: (options?: PurchaseOptions) => Promise<void>;\n getPromotedProductIOS: () => Promise<Product | null>;\n /**\n * @deprecated Use promotedProductListenerIOS to receive the productId,\n * then call requestPurchase with that SKU instead.\n */\n requestPurchaseOnPromotedProductIOS: () => Promise<boolean>;\n getActiveSubscriptions: (subscriptionIds?: string[]) => Promise<void>;\n hasActiveSubscriptions: (subscriptionIds?: string[]) => Promise<boolean>;\n /**\n * Manually retry the store connection.\n * Useful when the initial auto-connect fails (e.g., Play Store not ready at mount time).\n * Updates the `connected` state on success.\n */\n reconnect: () => Promise<boolean>;\n checkAlternativeBillingAvailabilityAndroid: () => Promise<boolean>;\n showAlternativeBillingDialogAndroid: () => Promise<boolean>;\n createAlternativeBillingTokenAndroid: (\n sku?: string,\n ) => Promise<string | null>;\n};\n\nexport interface UseIAPOptions {\n onPurchaseSuccess?: (purchase: Purchase) => void;\n onPurchaseError?: (error: PurchaseError) => void;\n /**\n * Callback for general errors from hook methods like fetchProducts,\n * getAvailablePurchases, getActiveSubscriptions, restorePurchases, etc.\n * These are Promise-based operations that can fail due to network issues\n * or store unavailability.\n */\n onError?: (error: Error) => void;\n onPromotedProductIOS?: (product: Product) => void;\n /**\n * Alternative billing mode for Android\n * If not specified, defaults to NONE (standard Google Play billing)\n * @deprecated Use enableBillingProgramAndroid instead.\n * - 'user-choice' → 'user-choice-billing'\n * - 'alternative-only' → 'external-offer'\n */\n alternativeBillingModeAndroid?: 'none' | 'user-choice' | 'alternative-only';\n /**\n * Enable a specific billing program for Android (8.2.0+)\n * When set, enables the specified billing program for external transactions.\n * Use 'external-payments' for Developer Provided Billing (Japan only, 8.3.0+).\n * Use 'user-choice-billing' for User Choice Billing (7.0+).\n */\n enableBillingProgramAndroid?:\n | 'unspecified'\n | 'external-content-link'\n | 'external-offer'\n | 'external-payments'\n | 'user-choice-billing';\n}\n\n/**\n * React Hook for managing In-App Purchases.\n * See documentation at https://hyochan.github.io/expo-iap/docs/hooks/useIAP\n */\nexport function useIAP(options?: UseIAPOptions): UseIap {\n const [connected, setConnected] = useState<boolean>(false);\n const [products, setProducts] = useState<Product[]>([]);\n const [subscriptions, setSubscriptions] = useState<ProductSubscription[]>([]);\n\n const [availablePurchases, setAvailablePurchases] = useState<Purchase[]>([]);\n const [promotedProductIOS, setPromotedProductIOS] = useState<Product>();\n const [activeSubscriptions, setActiveSubscriptions] = useState<\n ActiveSubscription[]\n >([]);\n\n const optionsRef = useRef<UseIAPOptions | undefined>(options);\n const connectedRef = useRef<boolean>(false);\n\n // Helper function to merge arrays with duplicate checking\n const mergeWithDuplicateCheck = useCallback(\n <T>(\n existingItems: T[],\n newItems: T[],\n getKey: (item: T) => string,\n ): T[] => {\n const merged = [...existingItems];\n newItems.forEach((newItem) => {\n const isDuplicate = merged.some(\n (existingItem) => getKey(existingItem) === getKey(newItem),\n );\n if (!isDuplicate) {\n merged.push(newItem);\n }\n });\n return merged;\n },\n [],\n );\n\n useEffect(() => {\n optionsRef.current = options;\n }, [options]);\n\n useEffect(() => {\n connectedRef.current = connected;\n }, [connected]);\n\n const subscriptionsRef = useRef<{\n purchaseUpdate?: EventSubscription;\n purchaseError?: EventSubscription;\n promotedProductIOS?: EventSubscription;\n }>({});\n\n const subscriptionsRefState = useRef<ProductSubscription[]>([]);\n\n useEffect(() => {\n subscriptionsRefState.current = subscriptions;\n }, [subscriptions]);\n\n const normalizeProductQueryType = useCallback(\n (type?: ProductTypeInput): ProductQueryType => {\n if (!type || type === 'inapp' || type === 'in-app') {\n return 'in-app';\n }\n return type;\n },\n [],\n );\n\n const canonicalProductType = useCallback(\n (value?: string): ProductQueryType => {\n if (!value) {\n return 'in-app';\n }\n\n const normalized = value.trim().toLowerCase().replace(/[_-]/g, '');\n return normalized === 'subs' ? 'subs' : 'in-app';\n },\n [],\n );\n\n const toPurchaseInput = useCallback(\n (purchase: Purchase): PurchaseInput => ({\n id: purchase.id,\n ids: purchase.ids ?? undefined,\n isAutoRenewing: purchase.isAutoRenewing,\n platform: purchase.platform,\n productId: purchase.productId,\n purchaseState: purchase.purchaseState,\n purchaseToken: purchase.purchaseToken ?? null,\n quantity: purchase.quantity,\n store: purchase.store,\n transactionDate: purchase.transactionDate,\n transactionId: purchase.transactionId,\n }),\n [],\n );\n\n // Helper function to invoke onError callback\n const invokeOnError = useCallback((error: unknown) => {\n if (optionsRef.current?.onError) {\n optionsRef.current.onError(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }, []);\n\n const fetchProductsInternal = useCallback(\n async (params: {\n skus: string[];\n type?: ProductTypeInput;\n }): Promise<void> => {\n try {\n const queryType = normalizeProductQueryType(params.type);\n const request: ProductRequest = {skus: params.skus, type: queryType};\n const result = await fetchProducts(request);\n const items = (result ?? []) as (Product | ProductSubscription)[];\n\n ExpoIapConsole.debug('Fetched products:', items);\n\n if (queryType === 'subs') {\n const subscriptionsResult = items as ProductSubscription[];\n setSubscriptions((prevSubscriptions) =>\n mergeWithDuplicateCheck(\n prevSubscriptions,\n subscriptionsResult,\n (subscription) => subscription.id,\n ),\n );\n } else if (queryType === 'in-app') {\n const productsResult = items as Product[];\n setProducts((prevProducts) =>\n mergeWithDuplicateCheck(\n prevProducts,\n productsResult,\n (product) => product.id,\n ),\n );\n } else {\n // For 'all' type, need to properly distinguish between products and subscriptions\n // On Android, check subscriptionOfferDetailsAndroid to determine if it's a real subscription\n const productItems = items.filter((item) => {\n // iOS: check type\n if (Platform.OS === 'ios') {\n return canonicalProductType(item.type as string) === 'in-app';\n }\n // Android: check if it has actual subscription details\n const androidItem = item as ProductAndroid;\n return (\n !androidItem.subscriptionOfferDetailsAndroid ||\n (Array.isArray(androidItem.subscriptionOfferDetailsAndroid) &&\n androidItem.subscriptionOfferDetailsAndroid.length === 0)\n );\n }) as Product[];\n\n const subscriptionItems = items.filter((item) => {\n // iOS: check type\n if (Platform.OS === 'ios') {\n return (\n canonicalProductType(\n item.type as ProductSubscriptionIOS['type'],\n ) === 'subs'\n );\n }\n // Android: check if it has actual subscription details\n const androidItem = item as ProductAndroid;\n\n return (\n androidItem.subscriptionOfferDetailsAndroid &&\n Array.isArray(androidItem.subscriptionOfferDetailsAndroid) &&\n androidItem.subscriptionOfferDetailsAndroid.length > 0\n );\n }) as ProductSubscription[];\n\n setProducts((prevProducts) =>\n mergeWithDuplicateCheck(\n prevProducts,\n productItems,\n (product) => product.id,\n ),\n );\n\n setSubscriptions((prevSubscriptions) =>\n mergeWithDuplicateCheck(\n prevSubscriptions,\n subscriptionItems,\n (subscription) => subscription.id,\n ),\n );\n }\n } catch (error) {\n ExpoIapConsole.error('Error fetching products:', error);\n invokeOnError(error);\n throw error;\n }\n },\n [\n canonicalProductType,\n invokeOnError,\n mergeWithDuplicateCheck,\n normalizeProductQueryType,\n ],\n );\n\n const getAvailablePurchasesInternal = useCallback(\n async (options?: PurchaseOptions): Promise<void> => {\n try {\n const result = await getAvailablePurchases({\n alsoPublishToEventListenerIOS:\n options?.alsoPublishToEventListenerIOS ?? false,\n onlyIncludeActiveItemsIOS: options?.onlyIncludeActiveItemsIOS ?? true,\n includeSuspendedAndroid: options?.includeSuspendedAndroid ?? false,\n });\n setAvailablePurchases(result);\n } catch (error) {\n ExpoIapConsole.error('Error fetching available purchases:', error);\n invokeOnError(error);\n throw error;\n }\n },\n [invokeOnError],\n );\n\n const getActiveSubscriptionsInternal = useCallback(\n async (subscriptionIds?: string[]): Promise<void> => {\n try {\n const result = await getActiveSubscriptions(subscriptionIds);\n setActiveSubscriptions(result);\n } catch (error) {\n ExpoIapConsole.error('Error getting active subscriptions:', error);\n invokeOnError(error);\n throw error;\n }\n },\n [invokeOnError],\n );\n\n const hasActiveSubscriptionsInternal = useCallback(\n async (subscriptionIds?: string[]): Promise<boolean> => {\n try {\n return await hasActiveSubscriptions(subscriptionIds);\n } catch (error) {\n ExpoIapConsole.error('Error checking active subscriptions:', error);\n return false;\n }\n },\n [],\n );\n\n const finishTransaction = useCallback(\n async ({\n purchase,\n isConsumable,\n }: {\n purchase: Purchase;\n isConsumable?: boolean;\n }): Promise<void> => {\n await finishTransactionInternal({\n purchase: toPurchaseInput(purchase),\n isConsumable,\n });\n },\n [toPurchaseInput],\n );\n\n const requestPurchaseWithReset = useCallback(\n (requestObj: MutationRequestPurchaseArgs) => {\n return requestPurchaseInternal(requestObj);\n },\n [],\n );\n\n const refreshSubscriptionStatus = useCallback(\n async (productId: string) => {\n try {\n if (subscriptionsRefState.current.some((sub) => sub.id === productId)) {\n await fetchProductsInternal({skus: [productId], type: 'subs'});\n await getAvailablePurchasesInternal();\n await getActiveSubscriptionsInternal();\n }\n } catch (error) {\n ExpoIapConsole.warn('Failed to refresh subscription status:', error);\n }\n },\n [\n fetchProductsInternal,\n getAvailablePurchasesInternal,\n getActiveSubscriptionsInternal,\n ],\n );\n\n // Restore completed transactions with cross-platform behavior.\n // iOS: best-effort sync (ignore sync errors) then fetch available purchases.\n // Android: fetch available purchases directly.\n const restorePurchasesInternal = useCallback(\n async (options?: PurchaseOptions): Promise<void> => {\n try {\n // iOS: Try to sync first, but don't fail if sync errors occur\n if (Platform.OS === 'ios') {\n await syncIOS().catch(() => undefined); // syncIOS returns Promise<boolean>, we don't need the result\n }\n\n const purchases = await getAvailablePurchases({\n alsoPublishToEventListenerIOS:\n options?.alsoPublishToEventListenerIOS ?? false,\n onlyIncludeActiveItemsIOS: options?.onlyIncludeActiveItemsIOS ?? true,\n includeSuspendedAndroid: options?.includeSuspendedAndroid ?? false,\n });\n setAvailablePurchases(purchases);\n } catch (error) {\n ExpoIapConsole.warn('Failed to restore purchases:', error);\n invokeOnError(error);\n throw error;\n }\n },\n [invokeOnError],\n );\n\n const validateReceipt = useCallback(async (props: VerifyPurchaseProps) => {\n return validateReceiptInternal(props);\n }, []);\n\n const verifyPurchase = useCallback(async (props: VerifyPurchaseProps) => {\n return verifyPurchaseInternal(props);\n }, []);\n\n const verifyPurchaseWithProvider = useCallback(\n async (props: VerifyPurchaseWithProviderProps) => {\n return verifyPurchaseWithProviderInternal(props);\n },\n [],\n );\n\n // Build config from options (prefer new enableBillingProgramAndroid over deprecated alternativeBillingModeAndroid)\n const buildConnectionConfig = useCallback(() => {\n return optionsRef.current?.enableBillingProgramAndroid ||\n optionsRef.current?.alternativeBillingModeAndroid\n ? {\n enableBillingProgramAndroid:\n optionsRef.current.enableBillingProgramAndroid,\n alternativeBillingModeAndroid:\n optionsRef.current.alternativeBillingModeAndroid,\n }\n : undefined;\n }, []);\n\n const initIapWithSubscriptions = useCallback(async (): Promise<void> => {\n // CRITICAL: Register listeners BEFORE initConnection to avoid race condition\n // Events might fire immediately after initConnection, so listeners must be ready\n // Register purchase update listener BEFORE initConnection to avoid race conditions.\n subscriptionsRef.current.purchaseUpdate = purchaseUpdatedListener(\n async (purchase: Purchase) => {\n // Refresh subscription status for both iOS and Android subscription purchases.\n // refreshSubscriptionStatus internally checks whether the product is a known\n // subscription, so it is safe to call unconditionally for any purchase event.\n await refreshSubscriptionStatus(purchase.productId);\n\n if (optionsRef.current?.onPurchaseSuccess) {\n optionsRef.current.onPurchaseSuccess(purchase);\n }\n },\n );\n\n // Register purchase error listener EARLY. Ignore init-related errors until connected.\n subscriptionsRef.current.purchaseError = purchaseErrorListener(\n (error: PurchaseError) => {\n if (!connectedRef.current && error.code === ErrorCode.InitConnection) {\n return; // Ignore initialization error before connected\n }\n const friendly = getUserFriendlyErrorMessage(error);\n if (!isUserCancelledError(error) && !isRecoverableError(error)) {\n ExpoIapConsole.warn('[useIAP] Purchase error:', friendly);\n }\n\n if (optionsRef.current?.onPurchaseError) {\n optionsRef.current.onPurchaseError(error);\n }\n },\n );\n\n if (Platform.OS === 'ios') {\n // iOS promoted products listener\n subscriptionsRef.current.promotedProductIOS = promotedProductListenerIOS(\n (product: Product) => {\n setPromotedProductIOS(product);\n\n if (optionsRef.current?.onPromotedProductIOS) {\n optionsRef.current.onPromotedProductIOS(product);\n }\n },\n );\n }\n\n // NOW call initConnection after listeners are ready\n const config = buildConnectionConfig();\n\n try {\n const result = await initConnection(config);\n setConnected(result);\n if (!result) {\n // If connection failed, clean up listeners\n ExpoIapConsole.warn(\n '[useIAP] Connection failed, cleaning up listeners...',\n );\n subscriptionsRef.current.purchaseUpdate?.remove();\n subscriptionsRef.current.promotedProductIOS?.remove();\n subscriptionsRef.current.purchaseUpdate = undefined;\n subscriptionsRef.current.promotedProductIOS = undefined;\n // Keep purchaseError listener registered to capture subsequent retries\n }\n } catch (error) {\n ExpoIapConsole.error('initConnection failed:', error);\n invokeOnError(error);\n // Clean up listeners on error\n subscriptionsRef.current.purchaseUpdate?.remove();\n subscriptionsRef.current.promotedProductIOS?.remove();\n subscriptionsRef.current.purchaseUpdate = undefined;\n subscriptionsRef.current.promotedProductIOS = undefined;\n }\n }, [buildConnectionConfig, refreshSubscriptionStatus, invokeOnError]);\n\n // Manual reconnect method for when the initial auto-connect fails.\n // Re-runs initConnection and updates the connected state.\n // Re-registers event listeners if they were cleaned up during a previous failure.\n const reconnect = useCallback(async (): Promise<boolean> => {\n const config = buildConnectionConfig();\n\n try {\n const result = await initConnection(config);\n setConnected(result);\n\n if (result) {\n // Re-register listeners if they were cleaned up during a previous failure\n if (!subscriptionsRef.current.purchaseUpdate) {\n subscriptionsRef.current.purchaseUpdate = purchaseUpdatedListener(\n async (purchase: Purchase) => {\n await refreshSubscriptionStatus(purchase.productId);\n\n if (optionsRef.current?.onPurchaseSuccess) {\n optionsRef.current.onPurchaseSuccess(purchase);\n }\n },\n );\n }\n\n if (\n Platform.OS === 'ios' &&\n !subscriptionsRef.current.promotedProductIOS\n ) {\n subscriptionsRef.current.promotedProductIOS =\n promotedProductListenerIOS((product: Product) => {\n setPromotedProductIOS(product);\n\n if (optionsRef.current?.onPromotedProductIOS) {\n optionsRef.current.onPromotedProductIOS(product);\n }\n });\n }\n }\n\n return result;\n } catch (error) {\n ExpoIapConsole.error('[useIAP] reconnect failed:', error);\n invokeOnError(error);\n return false;\n }\n }, [buildConnectionConfig, refreshSubscriptionStatus, invokeOnError]);\n\n useEffect(() => {\n initIapWithSubscriptions();\n const currentSubscriptions = subscriptionsRef.current;\n\n return () => {\n currentSubscriptions.purchaseUpdate?.remove();\n currentSubscriptions.purchaseError?.remove();\n currentSubscriptions.promotedProductIOS?.remove();\n endConnection();\n setConnected(false);\n };\n }, [initIapWithSubscriptions]);\n\n return {\n connected,\n products,\n subscriptions,\n finishTransaction,\n availablePurchases,\n promotedProductIOS,\n activeSubscriptions,\n getAvailablePurchases: getAvailablePurchasesInternal,\n fetchProducts: fetchProductsInternal,\n requestPurchase: requestPurchaseWithReset,\n validateReceipt,\n verifyPurchase,\n verifyPurchaseWithProvider,\n restorePurchases: restorePurchasesInternal,\n // internal getters kept for hook state management\n getPromotedProductIOS,\n requestPurchaseOnPromotedProductIOS,\n getActiveSubscriptions: getActiveSubscriptionsInternal,\n hasActiveSubscriptions: hasActiveSubscriptionsInternal,\n // Reconnect method for manual retry\n reconnect,\n // Alternative billing methods (Android only)\n checkAlternativeBillingAvailabilityAndroid,\n showAlternativeBillingDialogAndroid,\n createAlternativeBillingTokenAndroid,\n };\n}\n"]}
1
+ {"version":3,"file":"useIAP.js","sourceRoot":"","sources":["../src/useIAP.ts"],"names":[],"mappings":"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","sourcesContent":["// External dependencies\nimport {useCallback, useEffect, useState, useRef} from 'react';\nimport {Platform} from 'react-native';\nimport {EventSubscription} from 'expo-modules-core';\n\n// Internal modules\nimport {\n endConnection,\n initConnection,\n purchaseErrorListener,\n purchaseUpdatedListener,\n promotedProductListenerIOS,\n getAvailablePurchases,\n finishTransaction as finishTransactionInternal,\n requestPurchase as requestPurchaseInternal,\n fetchProducts,\n validateReceipt as validateReceiptInternal,\n verifyPurchase as verifyPurchaseInternal,\n verifyPurchaseWithProvider as verifyPurchaseWithProviderInternal,\n getActiveSubscriptions,\n hasActiveSubscriptions,\n type ActiveSubscription,\n type ProductTypeInput,\n} from './index';\nimport {ExpoIapConsole} from './utils/debug';\nimport {\n getPromotedProductIOS,\n requestPurchaseOnPromotedProductIOS,\n syncIOS,\n} from './modules/ios';\nimport {\n checkAlternativeBillingAvailabilityAndroid,\n showAlternativeBillingDialogAndroid,\n createAlternativeBillingTokenAndroid,\n} from './modules/android';\n\n// Types\nimport type {\n Product,\n ProductSubscription,\n ProductQueryType,\n ProductRequest,\n Purchase,\n MutationRequestPurchaseArgs,\n PurchaseInput,\n VerifyPurchaseProps,\n VerifyPurchaseResult,\n VerifyPurchaseWithProviderProps,\n VerifyPurchaseWithProviderResult,\n ProductAndroid,\n ProductSubscriptionIOS,\n PurchaseOptions,\n} from './types';\nimport {ErrorCode} from './types';\nimport type {PurchaseError} from './utils/errorMapping';\nimport {\n getUserFriendlyErrorMessage,\n isUserCancelledError,\n isRecoverableError,\n} from './utils/errorMapping';\n\ntype UseIap = {\n connected: boolean;\n products: Product[];\n subscriptions: ProductSubscription[];\n availablePurchases: Purchase[];\n promotedProductIOS?: Product;\n activeSubscriptions: ActiveSubscription[];\n finishTransaction: ({\n purchase,\n isConsumable,\n }: {\n purchase: Purchase;\n isConsumable?: boolean;\n }) => Promise<void>;\n getAvailablePurchases: (options?: PurchaseOptions) => Promise<void>;\n fetchProducts: (params: {\n skus: string[];\n type?: ProductTypeInput;\n }) => Promise<void>;\n\n requestPurchase: (\n params: MutationRequestPurchaseArgs,\n ) => ReturnType<typeof requestPurchaseInternal>;\n /** @deprecated Use verifyPurchase instead */\n validateReceipt: (\n props: VerifyPurchaseProps,\n ) => Promise<VerifyPurchaseResult>;\n verifyPurchase: (props: VerifyPurchaseProps) => Promise<VerifyPurchaseResult>;\n verifyPurchaseWithProvider: (\n props: VerifyPurchaseWithProviderProps,\n ) => Promise<VerifyPurchaseWithProviderResult>;\n restorePurchases: (options?: PurchaseOptions) => Promise<void>;\n getPromotedProductIOS: () => Promise<Product | null>;\n /**\n * @deprecated Use promotedProductListenerIOS to receive the productId,\n * then call requestPurchase with that SKU instead.\n */\n requestPurchaseOnPromotedProductIOS: () => Promise<boolean>;\n getActiveSubscriptions: (subscriptionIds?: string[]) => Promise<void>;\n hasActiveSubscriptions: (subscriptionIds?: string[]) => Promise<boolean>;\n /**\n * Manually retry the store connection.\n * Useful when the initial auto-connect fails (e.g., Play Store not ready at mount time).\n * Updates the `connected` state on success.\n */\n reconnect: () => Promise<boolean>;\n checkAlternativeBillingAvailabilityAndroid: () => Promise<boolean>;\n showAlternativeBillingDialogAndroid: () => Promise<boolean>;\n createAlternativeBillingTokenAndroid: (\n sku?: string,\n ) => Promise<string | null>;\n};\n\nexport interface UseIAPOptions {\n onPurchaseSuccess?: (purchase: Purchase) => void;\n onPurchaseError?: (error: PurchaseError) => void;\n /**\n * Callback for general errors from hook methods like fetchProducts,\n * getAvailablePurchases, getActiveSubscriptions, restorePurchases, etc.\n * These are Promise-based operations that can fail due to network issues\n * or store unavailability.\n */\n onError?: (error: Error) => void;\n onPromotedProductIOS?: (product: Product) => void;\n /**\n * Alternative billing mode for Android\n * If not specified, defaults to NONE (standard Google Play billing)\n * @deprecated Use enableBillingProgramAndroid instead.\n * - 'user-choice' → 'user-choice-billing'\n * - 'alternative-only' → 'external-offer'\n */\n alternativeBillingModeAndroid?: 'none' | 'user-choice' | 'alternative-only';\n /**\n * Enable a specific billing program for Android (8.2.0+)\n * When set, enables the specified billing program for external transactions.\n * Use 'external-payments' for Developer Provided Billing (Japan only, 8.3.0+).\n * Use 'user-choice-billing' for User Choice Billing (7.0+).\n */\n enableBillingProgramAndroid?:\n | 'unspecified'\n | 'external-content-link'\n | 'external-offer'\n | 'external-payments'\n | 'user-choice-billing';\n}\n\n/**\n * React Hook for managing In-App Purchases.\n * See documentation at https://hyochan.github.io/expo-iap/docs/hooks/useIAP\n */\nexport function useIAP(options?: UseIAPOptions): UseIap {\n const [connected, setConnected] = useState<boolean>(false);\n const [products, setProducts] = useState<Product[]>([]);\n const [subscriptions, setSubscriptions] = useState<ProductSubscription[]>([]);\n\n const [availablePurchases, setAvailablePurchases] = useState<Purchase[]>([]);\n const [promotedProductIOS, setPromotedProductIOS] = useState<Product>();\n const [activeSubscriptions, setActiveSubscriptions] = useState<\n ActiveSubscription[]\n >([]);\n\n const optionsRef = useRef<UseIAPOptions | undefined>(options);\n const connectedRef = useRef<boolean>(false);\n\n // Helper function to merge arrays with duplicate checking\n const mergeWithDuplicateCheck = useCallback(\n <T>(\n existingItems: T[],\n newItems: T[],\n getKey: (item: T) => string,\n ): T[] => {\n const merged = [...existingItems];\n newItems.forEach((newItem) => {\n const isDuplicate = merged.some(\n (existingItem) => getKey(existingItem) === getKey(newItem),\n );\n if (!isDuplicate) {\n merged.push(newItem);\n }\n });\n return merged;\n },\n [],\n );\n\n useEffect(() => {\n optionsRef.current = options;\n }, [options]);\n\n useEffect(() => {\n connectedRef.current = connected;\n }, [connected]);\n\n const subscriptionsRef = useRef<{\n purchaseUpdate?: EventSubscription;\n purchaseError?: EventSubscription;\n promotedProductIOS?: EventSubscription;\n }>({});\n\n const subscriptionsRefState = useRef<ProductSubscription[]>([]);\n\n useEffect(() => {\n subscriptionsRefState.current = subscriptions;\n }, [subscriptions]);\n\n const normalizeProductQueryType = useCallback(\n (type?: ProductTypeInput): ProductQueryType => {\n if (!type || type === 'inapp' || type === 'in-app') {\n return 'in-app';\n }\n return type;\n },\n [],\n );\n\n const canonicalProductType = useCallback(\n (value?: string): ProductQueryType => {\n if (!value) {\n return 'in-app';\n }\n\n const normalized = value.trim().toLowerCase().replace(/[_-]/g, '');\n return normalized === 'subs' ? 'subs' : 'in-app';\n },\n [],\n );\n\n const toPurchaseInput = useCallback(\n (purchase: Purchase): PurchaseInput => ({\n id: purchase.id,\n ids: purchase.ids ?? undefined,\n isAutoRenewing: purchase.isAutoRenewing,\n platform: purchase.platform,\n productId: purchase.productId,\n purchaseState: purchase.purchaseState,\n purchaseToken: purchase.purchaseToken ?? null,\n quantity: purchase.quantity,\n store: purchase.store,\n transactionDate: purchase.transactionDate,\n transactionId: purchase.transactionId,\n }),\n [],\n );\n\n // Helper function to invoke onError callback\n const invokeOnError = useCallback((error: unknown) => {\n if (optionsRef.current?.onError) {\n optionsRef.current.onError(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n }, []);\n\n /**\n * Retrieve products or subscriptions from the store by SKU.\n *\n * @param params `ProductRequest` — `skus` (string[]) and optional `type`\n * (`'in-app' | 'subs' | 'all'`, defaults to `'in-app'`).\n * @returns Promise that resolves when the request is dispatched; results land in the\n * hook's reactive `products` / `subscriptions` state.\n * @throws When the store rejects the request (empty `skus`, not connected,\n * network/store error). Unknown SKUs are simply omitted from the result, not thrown.\n *\n * @example\n * ```ts\n * const { fetchProducts, products } = useIAP();\n * await fetchProducts({\n * skus: ['com.app.coins_100', 'com.app.premium'],\n * type: 'in-app',\n * });\n * ```\n *\n * @remarks This is a regular promise-based call. Don't confuse with `request*` APIs\n * (`requestPurchase`), which are event-based.\n *\n * @see {@link https://www.openiap.dev/docs/apis/fetch-products}\n */\n const fetchProductsInternal = useCallback(\n async (params: {\n skus: string[];\n type?: ProductTypeInput;\n }): Promise<void> => {\n try {\n const queryType = normalizeProductQueryType(params.type);\n const request: ProductRequest = {skus: params.skus, type: queryType};\n const result = await fetchProducts(request);\n const items = (result ?? []) as (Product | ProductSubscription)[];\n\n ExpoIapConsole.debug('Fetched products:', items);\n\n if (queryType === 'subs') {\n const subscriptionsResult = items as ProductSubscription[];\n setSubscriptions((prevSubscriptions) =>\n mergeWithDuplicateCheck(\n prevSubscriptions,\n subscriptionsResult,\n (subscription) => subscription.id,\n ),\n );\n } else if (queryType === 'in-app') {\n const productsResult = items as Product[];\n setProducts((prevProducts) =>\n mergeWithDuplicateCheck(\n prevProducts,\n productsResult,\n (product) => product.id,\n ),\n );\n } else {\n // For 'all' type, need to properly distinguish between products and subscriptions\n // On Android, check subscriptionOfferDetailsAndroid to determine if it's a real subscription\n const productItems = items.filter((item) => {\n // iOS: check type\n if (Platform.OS === 'ios') {\n return canonicalProductType(item.type as string) === 'in-app';\n }\n // Android: check if it has actual subscription details\n const androidItem = item as ProductAndroid;\n return (\n !androidItem.subscriptionOfferDetailsAndroid ||\n (Array.isArray(androidItem.subscriptionOfferDetailsAndroid) &&\n androidItem.subscriptionOfferDetailsAndroid.length === 0)\n );\n }) as Product[];\n\n const subscriptionItems = items.filter((item) => {\n // iOS: check type\n if (Platform.OS === 'ios') {\n return (\n canonicalProductType(\n item.type as ProductSubscriptionIOS['type'],\n ) === 'subs'\n );\n }\n // Android: check if it has actual subscription details\n const androidItem = item as ProductAndroid;\n\n return (\n androidItem.subscriptionOfferDetailsAndroid &&\n Array.isArray(androidItem.subscriptionOfferDetailsAndroid) &&\n androidItem.subscriptionOfferDetailsAndroid.length > 0\n );\n }) as ProductSubscription[];\n\n setProducts((prevProducts) =>\n mergeWithDuplicateCheck(\n prevProducts,\n productItems,\n (product) => product.id,\n ),\n );\n\n setSubscriptions((prevSubscriptions) =>\n mergeWithDuplicateCheck(\n prevSubscriptions,\n subscriptionItems,\n (subscription) => subscription.id,\n ),\n );\n }\n } catch (error) {\n ExpoIapConsole.error('Error fetching products:', error);\n invokeOnError(error);\n throw error;\n }\n },\n [\n canonicalProductType,\n invokeOnError,\n mergeWithDuplicateCheck,\n normalizeProductQueryType,\n ],\n );\n\n /**\n * List the user's unfinished purchases — non-consumables, active subscriptions, and any\n * pending transactions not yet finished.\n *\n * @param options Optional `PurchaseOptions`. iOS-only flags:\n * `alsoPublishToEventListenerIOS`, `onlyIncludeActiveItemsIOS`.\n * @returns Promise that resolves when the request is dispatched; results land in the\n * hook's reactive `availablePurchases` state.\n * @throws When the platform query fails.\n *\n * @example\n * ```ts\n * const { getAvailablePurchases, availablePurchases } = useIAP();\n * await getAvailablePurchases();\n * for (const p of availablePurchases) {\n * if (await verifyOnServer(p)) await finishTransaction({ purchase: p, isConsumable: false });\n * }\n * ```\n *\n * @see {@link https://www.openiap.dev/docs/apis/get-available-purchases}\n */\n const getAvailablePurchasesInternal = useCallback(\n async (options?: PurchaseOptions): Promise<void> => {\n try {\n const result = await getAvailablePurchases({\n alsoPublishToEventListenerIOS:\n options?.alsoPublishToEventListenerIOS ?? false,\n onlyIncludeActiveItemsIOS: options?.onlyIncludeActiveItemsIOS ?? true,\n includeSuspendedAndroid: options?.includeSuspendedAndroid ?? false,\n });\n setAvailablePurchases(result);\n } catch (error) {\n ExpoIapConsole.error('Error fetching available purchases:', error);\n invokeOnError(error);\n throw error;\n }\n },\n [invokeOnError],\n );\n\n /**\n * Get details of all currently active subscriptions.\n *\n * @see {@link https://www.openiap.dev/docs/apis/get-active-subscriptions}\n */\n const getActiveSubscriptionsInternal = useCallback(\n async (subscriptionIds?: string[]): Promise<void> => {\n try {\n const result = await getActiveSubscriptions(subscriptionIds);\n setActiveSubscriptions(result);\n } catch (error) {\n ExpoIapConsole.error('Error getting active subscriptions:', error);\n invokeOnError(error);\n throw error;\n }\n },\n [invokeOnError],\n );\n\n /**\n * Check whether the user has any active subscription.\n *\n * @see {@link https://www.openiap.dev/docs/apis/has-active-subscriptions}\n */\n const hasActiveSubscriptionsInternal = useCallback(\n async (subscriptionIds?: string[]): Promise<boolean> => {\n try {\n return await hasActiveSubscriptions(subscriptionIds);\n } catch (error) {\n ExpoIapConsole.error('Error checking active subscriptions:', error);\n return false;\n }\n },\n [],\n );\n\n /**\n * Complete a purchase transaction. Call after server-side verification to remove it\n * from the queue.\n *\n * @param args.purchase The `Purchase` to finalize.\n * @param args.isConsumable `true` for consumables (consumes the token so the SKU can be\n * re-bought, e.g. coins); `false` (default) for non-consumables and subscriptions.\n * @returns Promise that resolves once the platform finalizes the transaction.\n * @throws When the platform finalize call fails.\n *\n * @example\n * ```ts\n * // Inside purchaseUpdatedListener:\n * if (await verifyOnServer(purchase)) {\n * await finishTransaction({ purchase, isConsumable: false });\n * }\n * ```\n *\n * @remarks **Critical:** Android purchases must be finalized within 3 days or Google\n * auto-refunds. iOS unfinished transactions replay on every app launch.\n *\n * @see {@link https://www.openiap.dev/docs/apis/finish-transaction}\n */\n const finishTransaction = useCallback(\n async ({\n purchase,\n isConsumable,\n }: {\n purchase: Purchase;\n isConsumable?: boolean;\n }): Promise<void> => {\n await finishTransactionInternal({\n purchase: toPurchaseInput(purchase),\n isConsumable,\n });\n },\n [toPurchaseInput],\n );\n\n /**\n * Initiate a purchase or subscription flow. The result is delivered through\n * `purchaseUpdatedListener` — NOT the return value.\n *\n * @param props `RequestPurchaseProps`, discriminated by `type`:\n * - `type: 'in-app'` — pass `request.apple.sku` (iOS) and/or `request.google.skus` (Android).\n * - `type: 'subs'` — same shape, plus `request.google.subscriptionOffers: [{ sku, offerToken }]`.\n * @returns Promise that resolves when the request is dispatched; the actual purchase\n * outcome lands in the hook's `onPurchaseSuccess` / `onPurchaseError` callbacks.\n * @throws Synchronous rejection from the store (e.g. `E_NOT_PREPARED`, validation failure).\n *\n * @example\n * ```ts\n * await requestPurchase({\n * request: {\n * apple: { sku: 'com.app.premium' },\n * google: { skus: ['com.app.premium'] },\n * },\n * type: 'in-app',\n * });\n * ```\n *\n * @remarks Event-based. Listen for the result via {@link purchaseUpdatedListener} /\n * {@link purchaseErrorListener}, or use `useIAP({ onPurchaseSuccess, onPurchaseError })`.\n *\n * @see {@link https://www.openiap.dev/docs/apis/request-purchase}\n */\n const requestPurchaseWithReset = useCallback(\n (requestObj: MutationRequestPurchaseArgs) => {\n return requestPurchaseInternal(requestObj);\n },\n [],\n );\n\n const refreshSubscriptionStatus = useCallback(\n async (productId: string) => {\n try {\n if (subscriptionsRefState.current.some((sub) => sub.id === productId)) {\n await fetchProductsInternal({skus: [productId], type: 'subs'});\n await getAvailablePurchasesInternal();\n await getActiveSubscriptionsInternal();\n }\n } catch (error) {\n ExpoIapConsole.warn('Failed to refresh subscription status:', error);\n }\n },\n [\n fetchProductsInternal,\n getAvailablePurchasesInternal,\n getActiveSubscriptionsInternal,\n ],\n );\n\n /**\n * Restore non-consumable and active subscription purchases.\n *\n * @see {@link https://www.openiap.dev/docs/apis/restore-purchases}\n */\n const restorePurchasesInternal = useCallback(\n async (options?: PurchaseOptions): Promise<void> => {\n try {\n // iOS: Try to sync first, but don't fail if sync errors occur\n if (Platform.OS === 'ios') {\n await syncIOS().catch(() => undefined); // syncIOS returns Promise<boolean>, we don't need the result\n }\n\n const purchases = await getAvailablePurchases({\n alsoPublishToEventListenerIOS:\n options?.alsoPublishToEventListenerIOS ?? false,\n onlyIncludeActiveItemsIOS: options?.onlyIncludeActiveItemsIOS ?? true,\n includeSuspendedAndroid: options?.includeSuspendedAndroid ?? false,\n });\n setAvailablePurchases(purchases);\n } catch (error) {\n ExpoIapConsole.warn('Failed to restore purchases:', error);\n invokeOnError(error);\n throw error;\n }\n },\n [invokeOnError],\n );\n\n /**\n * Deprecated. Use verifyPurchase instead — same input/output shape.\n *\n * @see {@link https://www.openiap.dev/docs/apis/validate-receipt}\n */\n const validateReceipt = useCallback(async (props: VerifyPurchaseProps) => {\n return validateReceiptInternal(props);\n }, []);\n\n /**\n * Verify a purchase against your own backend (returns isValid + raw store metadata).\n *\n * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase}\n */\n const verifyPurchase = useCallback(async (props: VerifyPurchaseProps) => {\n return verifyPurchaseInternal(props);\n }, []);\n\n /**\n * Verify via a managed provider — currently only `iapkit` (IAPKit). The PurchaseVerificationProvider enum exposes no other provider literal today.\n *\n * @see {@link https://www.openiap.dev/docs/features/validation#verify-purchase-with-provider}\n */\n const verifyPurchaseWithProvider = useCallback(\n async (props: VerifyPurchaseWithProviderProps) => {\n return verifyPurchaseWithProviderInternal(props);\n },\n [],\n );\n\n // Build config from options (prefer new enableBillingProgramAndroid over deprecated alternativeBillingModeAndroid)\n const buildConnectionConfig = useCallback(() => {\n return optionsRef.current?.enableBillingProgramAndroid ||\n optionsRef.current?.alternativeBillingModeAndroid\n ? {\n enableBillingProgramAndroid:\n optionsRef.current.enableBillingProgramAndroid,\n alternativeBillingModeAndroid:\n optionsRef.current.alternativeBillingModeAndroid,\n }\n : undefined;\n }, []);\n\n const initIapWithSubscriptions = useCallback(async (): Promise<void> => {\n // CRITICAL: Register listeners BEFORE initConnection to avoid race condition\n // Events might fire immediately after initConnection, so listeners must be ready\n // Register purchase update listener BEFORE initConnection to avoid race conditions.\n subscriptionsRef.current.purchaseUpdate = purchaseUpdatedListener(\n async (purchase: Purchase) => {\n // Refresh subscription status for both iOS and Android subscription purchases.\n // refreshSubscriptionStatus internally checks whether the product is a known\n // subscription, so it is safe to call unconditionally for any purchase event.\n await refreshSubscriptionStatus(purchase.productId);\n\n if (optionsRef.current?.onPurchaseSuccess) {\n optionsRef.current.onPurchaseSuccess(purchase);\n }\n },\n );\n\n // Register purchase error listener EARLY. Ignore init-related errors until connected.\n subscriptionsRef.current.purchaseError = purchaseErrorListener(\n (error: PurchaseError) => {\n if (!connectedRef.current && error.code === ErrorCode.InitConnection) {\n return; // Ignore initialization error before connected\n }\n const friendly = getUserFriendlyErrorMessage(error);\n if (!isUserCancelledError(error) && !isRecoverableError(error)) {\n ExpoIapConsole.warn('[useIAP] Purchase error:', friendly);\n }\n\n if (optionsRef.current?.onPurchaseError) {\n optionsRef.current.onPurchaseError(error);\n }\n },\n );\n\n if (Platform.OS === 'ios') {\n // iOS promoted products listener\n subscriptionsRef.current.promotedProductIOS = promotedProductListenerIOS(\n (product: Product) => {\n setPromotedProductIOS(product);\n\n if (optionsRef.current?.onPromotedProductIOS) {\n optionsRef.current.onPromotedProductIOS(product);\n }\n },\n );\n }\n\n // NOW call initConnection after listeners are ready\n const config = buildConnectionConfig();\n\n try {\n const result = await initConnection(config);\n setConnected(result);\n if (!result) {\n // If connection failed, clean up listeners\n ExpoIapConsole.warn(\n '[useIAP] Connection failed, cleaning up listeners...',\n );\n subscriptionsRef.current.purchaseUpdate?.remove();\n subscriptionsRef.current.promotedProductIOS?.remove();\n subscriptionsRef.current.purchaseUpdate = undefined;\n subscriptionsRef.current.promotedProductIOS = undefined;\n // Keep purchaseError listener registered to capture subsequent retries\n }\n } catch (error) {\n ExpoIapConsole.error('initConnection failed:', error);\n invokeOnError(error);\n // Clean up listeners on error\n subscriptionsRef.current.purchaseUpdate?.remove();\n subscriptionsRef.current.promotedProductIOS?.remove();\n subscriptionsRef.current.purchaseUpdate = undefined;\n subscriptionsRef.current.promotedProductIOS = undefined;\n }\n }, [buildConnectionConfig, refreshSubscriptionStatus, invokeOnError]);\n\n // Manual reconnect method for when the initial auto-connect fails.\n // Re-runs initConnection and updates the connected state.\n // Re-registers event listeners if they were cleaned up during a previous failure.\n const reconnect = useCallback(async (): Promise<boolean> => {\n const config = buildConnectionConfig();\n\n try {\n const result = await initConnection(config);\n setConnected(result);\n\n if (result) {\n // Re-register listeners if they were cleaned up during a previous failure\n if (!subscriptionsRef.current.purchaseUpdate) {\n subscriptionsRef.current.purchaseUpdate = purchaseUpdatedListener(\n async (purchase: Purchase) => {\n await refreshSubscriptionStatus(purchase.productId);\n\n if (optionsRef.current?.onPurchaseSuccess) {\n optionsRef.current.onPurchaseSuccess(purchase);\n }\n },\n );\n }\n\n if (\n Platform.OS === 'ios' &&\n !subscriptionsRef.current.promotedProductIOS\n ) {\n subscriptionsRef.current.promotedProductIOS =\n promotedProductListenerIOS((product: Product) => {\n setPromotedProductIOS(product);\n\n if (optionsRef.current?.onPromotedProductIOS) {\n optionsRef.current.onPromotedProductIOS(product);\n }\n });\n }\n }\n\n return result;\n } catch (error) {\n ExpoIapConsole.error('[useIAP] reconnect failed:', error);\n invokeOnError(error);\n return false;\n }\n }, [buildConnectionConfig, refreshSubscriptionStatus, invokeOnError]);\n\n useEffect(() => {\n initIapWithSubscriptions();\n const currentSubscriptions = subscriptionsRef.current;\n\n return () => {\n currentSubscriptions.purchaseUpdate?.remove();\n currentSubscriptions.purchaseError?.remove();\n currentSubscriptions.promotedProductIOS?.remove();\n endConnection();\n setConnected(false);\n };\n }, [initIapWithSubscriptions]);\n\n return {\n connected,\n products,\n subscriptions,\n finishTransaction,\n availablePurchases,\n promotedProductIOS,\n activeSubscriptions,\n getAvailablePurchases: getAvailablePurchasesInternal,\n fetchProducts: fetchProductsInternal,\n requestPurchase: requestPurchaseWithReset,\n validateReceipt,\n verifyPurchase,\n verifyPurchaseWithProvider,\n restorePurchases: restorePurchasesInternal,\n // internal getters kept for hook state management\n getPromotedProductIOS,\n requestPurchaseOnPromotedProductIOS,\n getActiveSubscriptions: getActiveSubscriptionsInternal,\n hasActiveSubscriptions: hasActiveSubscriptionsInternal,\n // Reconnect method for manual retry\n reconnect,\n // Alternative billing methods (Android only)\n checkAlternativeBillingAvailabilityAndroid,\n showAlternativeBillingDialogAndroid,\n createAlternativeBillingTokenAndroid,\n };\n}\n"]}
@@ -0,0 +1,26 @@
1
+ import { type WebhookEventPayload, type WebhookEventStream, type WebhookListenerError } from './webhook-client';
2
+ export type UseWebhookEventsOptions = {
3
+ apiKey: string | null | undefined;
4
+ baseUrl?: string;
5
+ eventSourceFactory?: (url: string, headers: Record<string, string>) => WebhookEventStream;
6
+ bufferSize?: number;
7
+ onEvent?: (event: WebhookEventPayload) => void;
8
+ onError?: (error: WebhookListenerError) => void;
9
+ };
10
+ export type UseWebhookEventsResult = {
11
+ /** Most recent N events (most-recent-first). Capped at bufferSize. */
12
+ events: WebhookEventPayload[];
13
+ /** Last error reported by the underlying stream. Null when healthy. */
14
+ lastError: WebhookListenerError | null;
15
+ /**
16
+ * True once the first webhook event has been received from the
17
+ * stream. Remains false if the connection is open but idle (the
18
+ * underlying SSE bridge doesn't surface a "stream opened"
19
+ * lifecycle event we can hook into; isConnected is therefore an
20
+ * activity indicator, not a raw socket-state flag). Reset to
21
+ * false on cleanup / apiKey change.
22
+ */
23
+ isConnected: boolean;
24
+ };
25
+ export declare function useWebhookEvents({ apiKey, baseUrl, eventSourceFactory, bufferSize, onEvent, onError, }: UseWebhookEventsOptions): UseWebhookEventsResult;
26
+ //# sourceMappingURL=useWebhookEvents.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWebhookEvents.d.ts","sourceRoot":"","sources":["../src/useWebhookEvents.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EAEvB,KAAK,oBAAoB,EAC1B,MAAM,kBAAkB,CAAC;AAE1B,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,kBAAkB,CAAC,EAAE,CACnB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAC5B,kBAAkB,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC/C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;CACjD,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,sEAAsE;IACtE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,uEAAuE;IACvE,SAAS,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACvC;;;;;;;OAOG;IACH,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAUF,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,OAAO,EACP,kBAAkB,EAClB,UAAe,EACf,OAAO,EACP,OAAO,GACR,EAAE,uBAAuB,GAAG,sBAAsB,CAqGlD"}
@@ -0,0 +1,105 @@
1
+ import { useEffect, useRef, useState } from 'react';
2
+ import { connectWebhookStream, } from './webhook-client';
3
+ // React hook wrapping the kit SSE webhook stream. See
4
+ // `libraries/react-native-iap/src/hooks/useWebhookEvents.ts` for the
5
+ // canonical version — this file mirrors it 1:1 because expo-iap and
6
+ // react-native-iap share the JS/TS SSE wire format. The intentional
7
+ // duplication keeps each library self-contained (no cross-package
8
+ // runtime dep) at the cost of a coordinated edit when the surface
9
+ // changes; that's checked by the SDK Parity Checklist in
10
+ // `knowledge/internal/04-platform-packages.md`.
11
+ export function useWebhookEvents({ apiKey, baseUrl, eventSourceFactory, bufferSize = 50, onEvent, onError, }) {
12
+ const [events, setEvents] = useState([]);
13
+ const [lastError, setLastError] = useState(null);
14
+ const [isConnected, setIsConnected] = useState(false);
15
+ const onEventRef = useRef(onEvent);
16
+ const onErrorRef = useRef(onError);
17
+ // Hold `eventSourceFactory` in a ref too so a caller passing an
18
+ // anonymous function literal (the common React pitfall) doesn't
19
+ // tear down the SSE connection on every render. We still capture
20
+ // the latest factory so a runtime-config swap (e.g. apiKey changes
21
+ // and a new EventSource constructor is needed) is honored on the
22
+ // next connect, but the *identity* of the factory no longer drives
23
+ // useEffect.
24
+ const eventSourceFactoryRef = useRef(eventSourceFactory);
25
+ // Holding bufferSize in a ref so adjusting it from the host
26
+ // component doesn't tear down the SSE connection. Same reasoning
27
+ // as onEvent / onError: a re-render with a new bufferSize would
28
+ // otherwise re-fire useEffect, close the stream, and reconnect
29
+ // (losing in-flight events the SSE handler had already buffered).
30
+ const bufferSizeRef = useRef(bufferSize);
31
+ onEventRef.current = onEvent;
32
+ onErrorRef.current = onError;
33
+ eventSourceFactoryRef.current = eventSourceFactory;
34
+ bufferSizeRef.current = bufferSize;
35
+ // Trim the existing buffer when the host lowers `bufferSize`
36
+ // mid-stream. The ref-based update only takes effect on the next
37
+ // event arrival, which can leave the visible buffer above the new
38
+ // cap until traffic resumes — this effect enforces the cap
39
+ // immediately on the change instead.
40
+ useEffect(() => {
41
+ setEvents((prev) => (bufferSize > 0 ? prev.slice(0, bufferSize) : []));
42
+ }, [bufferSize]);
43
+ useEffect(() => {
44
+ // Reset surfaced state on every (re)connect target so a stale
45
+ // event from the prior stream can't briefly leak into a new
46
+ // apiKey/baseUrl context. Matches the SSE convention of
47
+ // "fresh stream → fresh history."
48
+ setEvents([]);
49
+ setLastError(null);
50
+ if (!apiKey) {
51
+ return;
52
+ }
53
+ let listener = null;
54
+ let mounted = true;
55
+ try {
56
+ listener = connectWebhookStream({
57
+ apiKey,
58
+ baseUrl,
59
+ eventSourceFactory: eventSourceFactoryRef.current,
60
+ onEvent: (event) => {
61
+ if (!mounted) {
62
+ return;
63
+ }
64
+ setIsConnected(true);
65
+ const cap = bufferSizeRef.current;
66
+ if (cap > 0) {
67
+ setEvents((prev) => [event, ...prev].slice(0, cap));
68
+ }
69
+ onEventRef.current?.(event);
70
+ },
71
+ onError: (error) => {
72
+ if (!mounted) {
73
+ return;
74
+ }
75
+ setLastError(error);
76
+ onErrorRef.current?.(error);
77
+ },
78
+ });
79
+ }
80
+ catch (error) {
81
+ const wrapped = {
82
+ code: 'TRANSPORT_ERROR',
83
+ message: error instanceof Error
84
+ ? error.message
85
+ : 'Failed to open webhook stream',
86
+ cause: error,
87
+ };
88
+ setLastError(wrapped);
89
+ onErrorRef.current?.(wrapped);
90
+ }
91
+ return () => {
92
+ mounted = false;
93
+ listener?.close();
94
+ setIsConnected(false);
95
+ };
96
+ // `eventSourceFactory` deliberately omitted from deps — held in a
97
+ // ref above so anonymous-function callers don't trigger reconnects
98
+ // on every render. The connection is only re-opened when apiKey or
99
+ // baseUrl changes; a runtime factory swap is picked up on that
100
+ // next reconnect via the ref.
101
+ // eslint-disable-next-line react-hooks/exhaustive-deps
102
+ }, [apiKey, baseUrl]);
103
+ return { events, lastError, isConnected };
104
+ }
105
+ //# sourceMappingURL=useWebhookEvents.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useWebhookEvents.js","sourceRoot":"","sources":["../src/useWebhookEvents.ts"],"names":[],"mappings":"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","sourcesContent":["import {useEffect, useRef, useState} from 'react';\n\nimport {\n connectWebhookStream,\n type WebhookEventPayload,\n type WebhookEventStream,\n type WebhookListener,\n type WebhookListenerError,\n} from './webhook-client';\n\nexport type UseWebhookEventsOptions = {\n apiKey: string | null | undefined;\n baseUrl?: string;\n eventSourceFactory?: (\n url: string,\n headers: Record<string, string>,\n ) => WebhookEventStream;\n bufferSize?: number;\n onEvent?: (event: WebhookEventPayload) => void;\n onError?: (error: WebhookListenerError) => void;\n};\n\nexport type UseWebhookEventsResult = {\n /** Most recent N events (most-recent-first). Capped at bufferSize. */\n events: WebhookEventPayload[];\n /** Last error reported by the underlying stream. Null when healthy. */\n lastError: WebhookListenerError | null;\n /**\n * True once the first webhook event has been received from the\n * stream. Remains false if the connection is open but idle (the\n * underlying SSE bridge doesn't surface a \"stream opened\"\n * lifecycle event we can hook into; isConnected is therefore an\n * activity indicator, not a raw socket-state flag). Reset to\n * false on cleanup / apiKey change.\n */\n isConnected: boolean;\n};\n\n// React hook wrapping the kit SSE webhook stream. See\n// `libraries/react-native-iap/src/hooks/useWebhookEvents.ts` for the\n// canonical version — this file mirrors it 1:1 because expo-iap and\n// react-native-iap share the JS/TS SSE wire format. The intentional\n// duplication keeps each library self-contained (no cross-package\n// runtime dep) at the cost of a coordinated edit when the surface\n// changes; that's checked by the SDK Parity Checklist in\n// `knowledge/internal/04-platform-packages.md`.\nexport function useWebhookEvents({\n apiKey,\n baseUrl,\n eventSourceFactory,\n bufferSize = 50,\n onEvent,\n onError,\n}: UseWebhookEventsOptions): UseWebhookEventsResult {\n const [events, setEvents] = useState<WebhookEventPayload[]>([]);\n const [lastError, setLastError] = useState<WebhookListenerError | null>(null);\n const [isConnected, setIsConnected] = useState(false);\n\n const onEventRef = useRef(onEvent);\n const onErrorRef = useRef(onError);\n // Hold `eventSourceFactory` in a ref too so a caller passing an\n // anonymous function literal (the common React pitfall) doesn't\n // tear down the SSE connection on every render. We still capture\n // the latest factory so a runtime-config swap (e.g. apiKey changes\n // and a new EventSource constructor is needed) is honored on the\n // next connect, but the *identity* of the factory no longer drives\n // useEffect.\n const eventSourceFactoryRef = useRef(eventSourceFactory);\n // Holding bufferSize in a ref so adjusting it from the host\n // component doesn't tear down the SSE connection. Same reasoning\n // as onEvent / onError: a re-render with a new bufferSize would\n // otherwise re-fire useEffect, close the stream, and reconnect\n // (losing in-flight events the SSE handler had already buffered).\n const bufferSizeRef = useRef(bufferSize);\n onEventRef.current = onEvent;\n onErrorRef.current = onError;\n eventSourceFactoryRef.current = eventSourceFactory;\n bufferSizeRef.current = bufferSize;\n\n // Trim the existing buffer when the host lowers `bufferSize`\n // mid-stream. The ref-based update only takes effect on the next\n // event arrival, which can leave the visible buffer above the new\n // cap until traffic resumes — this effect enforces the cap\n // immediately on the change instead.\n useEffect(() => {\n setEvents((prev) => (bufferSize > 0 ? prev.slice(0, bufferSize) : []));\n }, [bufferSize]);\n\n useEffect(() => {\n // Reset surfaced state on every (re)connect target so a stale\n // event from the prior stream can't briefly leak into a new\n // apiKey/baseUrl context. Matches the SSE convention of\n // \"fresh stream → fresh history.\"\n setEvents([]);\n setLastError(null);\n\n if (!apiKey) {\n return;\n }\n\n let listener: WebhookListener | null = null;\n let mounted = true;\n\n try {\n listener = connectWebhookStream({\n apiKey,\n baseUrl,\n eventSourceFactory: eventSourceFactoryRef.current,\n onEvent: (event) => {\n if (!mounted) {\n return;\n }\n setIsConnected(true);\n const cap = bufferSizeRef.current;\n if (cap > 0) {\n setEvents((prev) => [event, ...prev].slice(0, cap));\n }\n onEventRef.current?.(event);\n },\n onError: (error) => {\n if (!mounted) {\n return;\n }\n setLastError(error);\n onErrorRef.current?.(error);\n },\n });\n } catch (error) {\n const wrapped: WebhookListenerError = {\n code: 'TRANSPORT_ERROR',\n message:\n error instanceof Error\n ? error.message\n : 'Failed to open webhook stream',\n cause: error,\n };\n setLastError(wrapped);\n onErrorRef.current?.(wrapped);\n }\n\n return () => {\n mounted = false;\n listener?.close();\n setIsConnected(false);\n };\n // `eventSourceFactory` deliberately omitted from deps — held in a\n // ref above so anonymous-function callers don't trigger reconnects\n // on every render. The connection is only re-opened when apiKey or\n // baseUrl changes; a runtime factory swap is picked up on that\n // next reconnect via the ref.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [apiKey, baseUrl]);\n\n return {events, lastError, isConnected};\n}\n"]}
@@ -0,0 +1,82 @@
1
+ export type WebhookEventType = 'SubscriptionStarted' | 'SubscriptionRenewed' | 'SubscriptionExpired' | 'SubscriptionInGracePeriod' | 'SubscriptionInBillingRetry' | 'SubscriptionRecovered' | 'SubscriptionCanceled' | 'SubscriptionUncanceled' | 'SubscriptionRevoked' | 'SubscriptionPriceChange' | 'SubscriptionProductChanged' | 'SubscriptionPaused' | 'SubscriptionResumed' | 'PurchaseRefunded' | 'PurchaseConsumptionRequest' | 'TestNotification';
2
+ export declare const WEBHOOK_EVENT_TYPES: readonly ["SubscriptionStarted", "SubscriptionRenewed", "SubscriptionExpired", "SubscriptionInGracePeriod", "SubscriptionInBillingRetry", "SubscriptionRecovered", "SubscriptionCanceled", "SubscriptionUncanceled", "SubscriptionRevoked", "SubscriptionPriceChange", "SubscriptionProductChanged", "SubscriptionPaused", "SubscriptionResumed", "PurchaseRefunded", "PurchaseConsumptionRequest", "TestNotification"];
3
+ export type WebhookEventPayload = {
4
+ id: string;
5
+ type: WebhookEventType;
6
+ source: string;
7
+ platform: 'IOS' | 'Android';
8
+ environment: 'Production' | 'Sandbox' | 'Xcode';
9
+ projectId: string;
10
+ occurredAt: number;
11
+ receivedAt: number;
12
+ purchaseToken?: string;
13
+ productId?: string;
14
+ subscriptionState?: string;
15
+ expiresAt?: number;
16
+ renewsAt?: number;
17
+ cancellationReason?: string;
18
+ currency?: string;
19
+ priceAmountMicros?: number;
20
+ rawSignedPayload?: string;
21
+ };
22
+ export type WebhookListenerOptions = {
23
+ /**
24
+ * Project API key. Embedded in the URL path because Apple ASN
25
+ * registration cannot send custom headers; the same path is reused
26
+ * here for symmetry.
27
+ */
28
+ apiKey: string;
29
+ /**
30
+ * Override the kit base URL. Defaults to https://kit.openiap.dev.
31
+ * In tests, point this at a local server.
32
+ */
33
+ baseUrl?: string;
34
+ /** Called on every successfully-parsed webhook event. */
35
+ onEvent: (event: WebhookEventPayload) => void;
36
+ /**
37
+ * Called on transport errors. The connection auto-reconnects
38
+ * unconditionally; this callback exists for telemetry / surfacing
39
+ * to the host UI.
40
+ */
41
+ onError?: (error: WebhookListenerError) => void;
42
+ /**
43
+ * Optional injection of an EventSource constructor. Lets RN /
44
+ * Expo plug in `react-native-event-source` when running on a JS
45
+ * runtime that lacks the global, or vitest plug in a stub.
46
+ */
47
+ eventSourceFactory?: (url: string, headers: Record<string, string>) => WebhookEventStream;
48
+ };
49
+ export interface WebhookEventStream {
50
+ close(): void;
51
+ onmessage: ((event: {
52
+ data: string;
53
+ lastEventId?: string;
54
+ }) => void) | null;
55
+ onerror: ((error: unknown) => void) | null;
56
+ addEventListener?: (type: string, listener: (event: {
57
+ data: string;
58
+ lastEventId?: string;
59
+ }) => void) => void;
60
+ }
61
+ export type WebhookListener = {
62
+ /** Tear down the connection and stop receiving events. */
63
+ close(): void;
64
+ };
65
+ export type WebhookListenerError = {
66
+ code: 'TRANSPORT_ERROR' | 'PARSE_ERROR' | 'MALFORMED_EVENT' | 'NO_EVENTSOURCE';
67
+ message: string;
68
+ cause?: unknown;
69
+ };
70
+ export declare function connectWebhookStream(options: WebhookListenerOptions): WebhookListener;
71
+ export type ParsedEventResult = {
72
+ kind: 'ok';
73
+ event: WebhookEventPayload;
74
+ } | {
75
+ kind: 'skip';
76
+ reason: 'heartbeat' | 'stream-control';
77
+ } | {
78
+ kind: 'error';
79
+ message: string;
80
+ };
81
+ export declare function parseWebhookEventData(raw: string): ParsedEventResult;
82
+ //# sourceMappingURL=webhook-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook-client.d.ts","sourceRoot":"","sources":["../src/webhook-client.ts"],"names":[],"mappings":"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"}