expo-iap 6.0.1 → 6.0.3

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 (45) hide show
  1. package/AGENTS.md +3 -5
  2. package/CONTRIBUTING.md +2 -30
  3. package/android/src/main/java/expo/modules/iap/ExpoIapHelper.kt +10 -5
  4. package/android/src/main/java/expo/modules/iap/ExpoIapModule.kt +5 -4
  5. package/build/index.d.ts.map +1 -1
  6. package/build/index.js +24 -46
  7. package/build/index.js.map +1 -1
  8. package/build/modules/android.d.ts.map +1 -1
  9. package/build/modules/android.js +3 -2
  10. package/build/modules/android.js.map +1 -1
  11. package/build/modules/ios.d.ts +2 -1
  12. package/build/modules/ios.d.ts.map +1 -1
  13. package/build/modules/ios.js +36 -26
  14. package/build/modules/ios.js.map +1 -1
  15. package/build/types.d.ts +6 -0
  16. package/build/types.d.ts.map +1 -1
  17. package/build/types.js.map +1 -1
  18. package/build/useIAP.d.ts +5 -4
  19. package/build/useIAP.d.ts.map +1 -1
  20. package/build/useIAP.js +128 -170
  21. package/build/useIAP.js.map +1 -1
  22. package/build/utils/errorMapping.d.ts +12 -15
  23. package/build/utils/errorMapping.d.ts.map +1 -1
  24. package/build/utils/errorMapping.js +113 -298
  25. package/build/utils/errorMapping.js.map +1 -1
  26. package/build/utils/nativeError.d.ts +20 -0
  27. package/build/utils/nativeError.d.ts.map +1 -0
  28. package/build/utils/nativeError.js +138 -0
  29. package/build/utils/nativeError.js.map +1 -0
  30. package/build/utils/packageName.d.ts +3 -0
  31. package/build/utils/packageName.d.ts.map +1 -0
  32. package/build/utils/packageName.js +3 -0
  33. package/build/utils/packageName.js.map +1 -0
  34. package/ios/ExpoIapHelper.swift +26 -0
  35. package/ios/ExpoIapModule.swift +252 -273
  36. package/openiap-versions.json +3 -3
  37. package/package.json +1 -1
  38. package/src/index.ts +61 -60
  39. package/src/modules/android.ts +9 -2
  40. package/src/modules/ios.ts +70 -29
  41. package/src/types.ts +7 -0
  42. package/src/useIAP.ts +158 -210
  43. package/src/utils/errorMapping.ts +136 -370
  44. package/src/utils/nativeError.ts +187 -0
  45. package/src/utils/packageName.ts +2 -0
package/AGENTS.md CHANGED
@@ -2,11 +2,9 @@
2
2
 
3
3
  ## Commit Message Convention
4
4
 
5
- - Follow the Angular Conventional Commits format: `<type>(<scope>): <subject>`
6
- - Allowed types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`
7
- - Scope is optional but recommended (for example: `auth`, `api`, `ui`)
8
- - Subject must be imperative, lowercase, without a trailing period, and roughly 50 characters
9
- - Wrap commit body lines near 72 characters and include footers such as `BREAKING CHANGE:` or `Closes #123` when needed
5
+ Follow the monorepo
6
+ [Git Commit Message Format](../../knowledge/internal/06-git-deployment.md#git-commit-message-format)
7
+ with the `expo` scope, e.g. `fix(expo): resolve purchase crash`.
10
8
 
11
9
  ## Tooling & Package Management
12
10
 
package/CONTRIBUTING.md CHANGED
@@ -363,36 +363,8 @@ bun run lint:prettier
363
363
 
364
364
  ### Commit Messages
365
365
 
366
- Follow conventional commit format:
367
-
368
- ```text
369
- type(scope): subject
370
-
371
- body
372
-
373
- footer
374
- ```
375
-
376
- Types:
377
-
378
- - `feat`: new feature
379
- - `fix`: bug fix
380
- - `docs`: documentation changes
381
- - `style`: code style changes (formatting, etc.)
382
- - `refactor`: code refactoring
383
- - `test`: test additions or modifications
384
- - `chore`: maintenance tasks
385
-
386
- Example:
387
-
388
- ```text
389
- feat(ios): add getStorefrontIos function
390
-
391
- Implements iOS-specific storefront retrieval using StoreKit.
392
- Follows platform-specific naming convention.
393
-
394
- Closes #123
395
- ```
366
+ Follow the monorepo's [Git Commit Message Format](https://github.com/hyodotdev/openiap/blob/main/knowledge/internal/06-git-deployment.md#git-commit-message-format),
367
+ for example `feat(expo): add getAppTransactionIOS`.
396
368
 
397
369
  ### Pull Request Process
398
370
 
@@ -45,6 +45,15 @@ object ExpoIapHelper {
45
45
 
46
46
  internal fun serializeErrorEnvelope(payload: Map<String, Any?>): String = ERROR_ENVELOPE_PREFIX + JSONObject(payload).toString()
47
47
 
48
+ /** Rejects with the canonical error envelope that the JS bridge parses. */
49
+ internal fun rejectWithErrorEnvelope(
50
+ promise: Promise,
51
+ error: Exception,
52
+ ) {
53
+ val openIapError = error as? OpenIapError ?: OpenIapError.ServiceUnavailable(error.message)
54
+ promise.reject(openIapError.code, serializeErrorEnvelope(serializeOpenIapError(openIapError)), null)
55
+ }
56
+
48
57
  fun emitOrQueue(
49
58
  module: Module,
50
59
  scope: CoroutineScope,
@@ -282,7 +291,6 @@ object ExpoIapHelper {
282
291
  eventName: String,
283
292
  payload: Map<String, Any?>,
284
293
  eventPurchaseError: String,
285
- fallbackErrorCode: String,
286
294
  fallbackErrorPrefix: String,
287
295
  logTag: String,
288
296
  ) {
@@ -292,7 +300,7 @@ object ExpoIapHelper {
292
300
  ExpoIapLog.failure("buffer/send $logTag", error)
293
301
  val errorPayload =
294
302
  mapOf(
295
- "code" to fallbackErrorCode,
303
+ "code" to OpenIapError.UnknownError.CODE,
296
304
  "message" to "$fallbackErrorPrefix: ${error.message}",
297
305
  )
298
306
  runCatching {
@@ -397,7 +405,6 @@ object ExpoIapHelper {
397
405
  eventUserChoiceBilling,
398
406
  details.toJson(),
399
407
  eventPurchaseError,
400
- "alternative-billing-not-available",
401
408
  "Failed to process user choice billing",
402
409
  "USER_CHOICE_BILLING",
403
410
  )
@@ -415,7 +422,6 @@ object ExpoIapHelper {
415
422
  eventDeveloperProvidedBilling,
416
423
  details.toJson(),
417
424
  eventPurchaseError,
418
- "developer-billing-error",
419
425
  "Failed to process developer provided billing",
420
426
  "DEVELOPER_PROVIDED_BILLING",
421
427
  )
@@ -433,7 +439,6 @@ object ExpoIapHelper {
433
439
  eventSubscriptionBillingIssue,
434
440
  purchase.toJson(),
435
441
  eventPurchaseError,
436
- "subscription-billing-issue-error",
437
442
  "Failed to process subscription billing issue",
438
443
  "SUBSCRIPTION_BILLING_ISSUE",
439
444
  )
@@ -25,6 +25,7 @@ import dev.hyo.openiap.VerifyPurchaseHorizonOptions
25
25
  import dev.hyo.openiap.VerifyPurchaseProps
26
26
  import dev.hyo.openiap.VerifyPurchaseWithProviderProps
27
27
  import dev.hyo.openiap.helpers.OpenIapFirstPurchaseNotice
28
+ import dev.hyo.openiap.helpers.finishPurchaseToken
28
29
  import dev.hyo.openiap.store.OpenIapStore
29
30
  import expo.modules.kotlin.Promise
30
31
  import expo.modules.kotlin.exception.Exceptions
@@ -529,13 +530,13 @@ class ExpoIapModule : Module() {
529
530
  ExpoIapLog.payload("acknowledgePurchaseAndroid", mapOf("token" to token))
530
531
  scope.launch {
531
532
  try {
532
- openIap.acknowledgePurchaseAndroid(token)
533
+ openIap.finishPurchaseToken(token, isConsumable = false)
533
534
  val response = mapOf("responseCode" to 0)
534
535
  ExpoIapLog.result("acknowledgePurchaseAndroid", response)
535
536
  promise.resolve(response)
536
537
  } catch (e: Exception) {
537
538
  ExpoIapLog.failure("acknowledgePurchaseAndroid", e)
538
- promise.reject((e as? OpenIapError)?.code ?: OpenIapError.ServiceUnavailable.CODE, e.message, null)
539
+ ExpoIapHelper.rejectWithErrorEnvelope(promise, e)
539
540
  }
540
541
  }
541
542
  }
@@ -544,7 +545,7 @@ class ExpoIapModule : Module() {
544
545
  ExpoIapLog.payload("consumePurchaseAndroid", mapOf("token" to token))
545
546
  scope.launch {
546
547
  try {
547
- openIap.consumePurchaseAndroid(token)
548
+ openIap.finishPurchaseToken(token, isConsumable = true)
548
549
  val response = mapOf("responseCode" to 0, "purchaseToken" to token)
549
550
  ExpoIapLog.result(
550
551
  "consumePurchaseAndroid",
@@ -553,7 +554,7 @@ class ExpoIapModule : Module() {
553
554
  promise.resolve(response)
554
555
  } catch (e: Exception) {
555
556
  ExpoIapLog.failure("consumePurchaseAndroid", e)
556
- promise.reject((e as? OpenIapError)?.code ?: OpenIapError.ServiceUnavailable.CODE, e.message, null)
557
+ ExpoIapHelper.rejectWithErrorEnvelope(promise, e)
557
558
  }
558
559
  }
559
560
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/build/index.js CHANGED
@@ -10,7 +10,8 @@ import { showFirstPurchaseNotice } from './utils/firstPurchaseNotice';
10
10
  import { restorePurchasesNative } from './utils/restorePurchases';
11
11
  import { decodeAndroidPurchases, decodeApplePurchases, } from './utils/availablePurchases';
12
12
  import { ErrorCode, resolveStoreId } from './types';
13
- import { createPurchaseError, createPurchaseErrorFromNativeException, OPENIAP_ERROR_ENVELOPE_PREFIX, } from './utils/errorMapping';
13
+ import { createPurchaseError, normalizeErrorCodeFromNative, } from './utils/errorMapping';
14
+ import { createPurchaseErrorFromNativeException, invokeNativeWithPurchaseError, } from './utils/nativeError';
14
15
  export * from './types';
15
16
  export * from './modules/android';
16
17
  export * from './modules/ios';
@@ -33,6 +34,8 @@ export var OpenIapEvent;
33
34
  const isStorePlatform = () => Platform.OS === 'ios' || Platform.OS === 'android';
34
35
  const isStoreRuntime = () => Platform.OS === 'ios' || isAndroidStoreRuntime();
35
36
  const unsupportedPlatformError = () => new Error(`Unsupported platform: ${Platform.OS}`);
37
+ // Platform tag for PurchaseErrors built from native rejections.
38
+ const nativePlatform = () => Platform.OS === 'ios' ? 'ios' : 'android';
36
39
  // Listener calls go to the raw native module (see getNativeModule), resolved
37
40
  // lazily so importing this module doesn't throw on unsupported platforms.
38
41
  export const emitter = {
@@ -185,8 +188,9 @@ export const purchaseUpdatedListener = (listener, options) => {
185
188
  };
186
189
  };
187
190
  export const purchaseErrorListener = (listener) => {
191
+ // Native events may carry codes outside ErrorCode; deliver canonical codes.
188
192
  const wrappedListener = (error) => {
189
- listener(error);
193
+ listener({ ...error, code: normalizeErrorCodeFromNative(error.code) });
190
194
  };
191
195
  const emitterSubscription = emitter.addListener(OpenIapEvent.PurchaseError, wrappedListener);
192
196
  return emitterSubscription;
@@ -371,7 +375,7 @@ export const subscriptionBillingIssueListener = (listener) => {
371
375
  * @see {@link https://openiap.dev/docs/apis/init-connection}
372
376
  */
373
377
  export const initConnection = async (config) => {
374
- const result = await ExpoIapModule.initConnection(config ?? null);
378
+ const result = await invokeNativeWithPurchaseError(() => ExpoIapModule.initConnection(config ?? null), nativePlatform());
375
379
  if (result === true &&
376
380
  Platform.OS === 'ios' &&
377
381
  nonDedupingPurchaseUpdatedListenerCountIOS > 0) {
@@ -385,38 +389,12 @@ export const initConnection = async (config) => {
385
389
  * @see {@link https://openiap.dev/docs/apis/end-connection}
386
390
  */
387
391
  export const endConnection = async () => {
388
- const result = await ExpoIapModule.endConnection();
392
+ const result = await invokeNativeWithPurchaseError(() => ExpoIapModule.endConnection(), nativePlatform());
389
393
  if (result === true && Platform.OS === 'ios') {
390
394
  resetPurchaseUpdatedDedupeHistoryIOS();
391
395
  }
392
396
  return result;
393
397
  };
394
- const invokeNativeWithPurchaseError = async (operation, platform, fallback) => {
395
- try {
396
- return await operation();
397
- }
398
- catch (error) {
399
- const nativeError = typeof error === 'object' && error !== null
400
- ? error
401
- : undefined;
402
- const nativeMessage = typeof nativeError?.message === 'string'
403
- ? nativeError.message
404
- : typeof error === 'string'
405
- ? error
406
- : '';
407
- const hasCanonicalFields = nativeMessage.includes(OPENIAP_ERROR_ENVELOPE_PREFIX) ||
408
- nativeError?.code !== undefined ||
409
- nativeError?.responseCode !== undefined ||
410
- nativeError?.debugMessage !== undefined ||
411
- nativeError?.productId !== undefined ||
412
- nativeError?.productIds !== undefined;
413
- // Preserve the identity of unrelated JavaScript errors (including adapter
414
- // or test errors) while normalizing native OpenIAP rejections.
415
- if (!hasCanonicalFields)
416
- throw error;
417
- throw createPurchaseErrorFromNativeException(error, platform, fallback);
418
- }
419
- };
420
398
  /**
421
399
  * Retrieve products or subscriptions from the store by SKU.
422
400
  *
@@ -525,10 +503,10 @@ export const getAvailablePurchases = async (options) => {
525
503
  }
526
504
  let purchases;
527
505
  if (Platform.OS === 'ios') {
528
- purchases = (await ExpoIapModule.getAvailableItems(normalizedOptions.alsoPublishToEventListenerIOS, normalizedOptions.onlyIncludeActiveItemsIOS));
506
+ purchases = (await invokeNativeWithPurchaseError(() => ExpoIapModule.getAvailableItems(normalizedOptions.alsoPublishToEventListenerIOS, normalizedOptions.onlyIncludeActiveItemsIOS), 'ios'));
529
507
  }
530
508
  else if (Platform.OS === 'android') {
531
- purchases = (await ExpoIapModule.getAvailableItems(normalizedOptions));
509
+ purchases = (await invokeNativeWithPurchaseError(() => ExpoIapModule.getAvailableItems(normalizedOptions), 'android'));
532
510
  }
533
511
  else {
534
512
  throw unsupportedPlatformError();
@@ -567,7 +545,7 @@ export const getActiveSubscriptions = async (subscriptionIds) => {
567
545
  if (!isStoreRuntime()) {
568
546
  throw unsupportedPlatformError();
569
547
  }
570
- const result = await ExpoIapModule.getActiveSubscriptions(subscriptionIds ?? null);
548
+ const result = await invokeNativeWithPurchaseError(() => ExpoIapModule.getActiveSubscriptions(subscriptionIds ?? null), nativePlatform());
571
549
  return (result ?? []);
572
550
  };
573
551
  /**
@@ -591,7 +569,7 @@ export const hasActiveSubscriptions = async (subscriptionIds) => {
591
569
  if (!isStoreRuntime()) {
592
570
  throw unsupportedPlatformError();
593
571
  }
594
- return !!(await ExpoIapModule.hasActiveSubscriptions(subscriptionIds ?? null));
572
+ return !!(await invokeNativeWithPurchaseError(() => ExpoIapModule.hasActiveSubscriptions(subscriptionIds ?? null), nativePlatform()));
595
573
  };
596
574
  /**
597
575
  * Return the user's storefront country code.
@@ -605,7 +583,7 @@ export const getStorefront = async () => {
605
583
  message: `Storefront lookup is not supported on ${Platform.OS}.`,
606
584
  });
607
585
  }
608
- const platform = Platform.OS === 'ios' ? 'ios' : 'android';
586
+ const platform = nativePlatform();
609
587
  if (typeof ExpoIapModule.getStorefront !== 'function') {
610
588
  throw createPurchaseError({
611
589
  code: ErrorCode.FeatureNotSupported,
@@ -673,7 +651,7 @@ export const verifyAppOwnership = async (options) => {
673
651
  : 'unknown',
674
652
  };
675
653
  }
676
- return invokeNativeWithPurchaseError(() => ExpoIapModule.verifyAppOwnership(options ?? {}), Platform.OS === 'ios' ? 'ios' : 'android', {
654
+ return invokeNativeWithPurchaseError(() => ExpoIapModule.verifyAppOwnership(options ?? {}), nativePlatform(), {
677
655
  code: ErrorCode.ServiceError,
678
656
  });
679
657
  };
@@ -858,9 +836,10 @@ export const requestPurchase = async (args) => {
858
836
  export const finishTransaction = async ({ purchase, isConsumable, }) => {
859
837
  // The schema allows explicit null; the native boolean cannot take it.
860
838
  const consumable = isConsumable ?? false;
839
+ const platform = nativePlatform();
861
840
  if (Platform.OS === 'ios' ||
862
841
  (isAndroidStoreRuntime() && purchase.store === 'unknown')) {
863
- await ExpoIapModule.finishTransaction(purchase, consumable);
842
+ await invokeNativeWithPurchaseError(() => ExpoIapModule.finishTransaction(purchase, consumable), platform, { productId: purchase.productId });
864
843
  }
865
844
  else if (isAndroidStoreRuntime()) {
866
845
  const token = purchase.purchaseToken ?? undefined;
@@ -872,12 +851,10 @@ export const finishTransaction = async ({ purchase, isConsumable, }) => {
872
851
  platform: 'android',
873
852
  });
874
853
  }
875
- if (consumable) {
876
- await ExpoIapModule.consumePurchaseAndroid(token);
877
- }
878
- else {
879
- await ExpoIapModule.acknowledgePurchaseAndroid(token);
880
- }
854
+ // Native rejects when the store refuses the token, so a failure cannot pass as finished.
855
+ await invokeNativeWithPurchaseError(() => consumable
856
+ ? ExpoIapModule.consumePurchaseAndroid(token)
857
+ : ExpoIapModule.acknowledgePurchaseAndroid(token), 'android', { productId: purchase.productId });
881
858
  }
882
859
  else {
883
860
  throw unsupportedPlatformError();
@@ -949,7 +926,7 @@ export const openRedeemOfferCode = async () => {
949
926
  if (Platform.OS !== 'ios' && !isAndroidStoreRuntime()) {
950
927
  throw unsupportedPlatformError();
951
928
  }
952
- return invokeNativeWithPurchaseError(() => ExpoIapModule.openRedeemOfferCode(), Platform.OS === 'ios' ? 'ios' : 'android', { code: ErrorCode.PurchaseError, message: 'Failed to redeem offer code.' });
929
+ return invokeNativeWithPurchaseError(() => ExpoIapModule.openRedeemOfferCode(), nativePlatform(), { code: ErrorCode.PurchaseError, message: 'Failed to redeem offer code.' });
953
930
  };
954
931
  /**
955
932
  * Verify purchase with the configured providers.
@@ -963,7 +940,8 @@ export const verifyPurchase = async (options) => {
963
940
  if (!isStorePlatform()) {
964
941
  throw unsupportedPlatformError();
965
942
  }
966
- return ExpoIapModule.verifyPurchase(options);
943
+ // The native result is already the flat union member, with `__typename`.
944
+ return invokeNativeWithPurchaseError(() => ExpoIapModule.verifyPurchase(options), nativePlatform());
967
945
  };
968
946
  /**
969
947
  * Verify purchase with a specific provider (e.g., IAPKit).
@@ -1021,7 +999,7 @@ export const verifyPurchaseWithProvider = async (options) => {
1021
999
  'Or provide apiKey directly in verifyPurchaseWithProvider options.');
1022
1000
  }
1023
1001
  }
1024
- const result = await ExpoIapModule.verifyPurchaseWithProvider(resolvedOptions);
1002
+ const result = await invokeNativeWithPurchaseError(() => ExpoIapModule.verifyPurchaseWithProvider(resolvedOptions), nativePlatform());
1025
1003
  if (result.iapkit == null) {
1026
1004
  return result;
1027
1005
  }