capacitor-plugin-cdv-purchase 13.15.2 → 13.15.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.
@@ -499,6 +499,7 @@ public class PurchasePlugin extends Plugin implements
499
499
  .enableOneTimeProducts()
500
500
  .enablePrepaidPlans()
501
501
  .build())
502
+ .enableAutoServiceReconnection()
502
503
  .setListener(this)
503
504
  .build();
504
505
 
@@ -795,8 +796,8 @@ public class PurchasePlugin extends Plugin implements
795
796
  mPendingBuyCall = null;
796
797
  }
797
798
  }
798
- } catch (JSONException e) {
799
- Log.w(TAG, "onPurchasesUpdated() -> JSONException "
799
+ } catch (Exception e) {
800
+ Log.w(TAG, "onPurchasesUpdated() -> Exception "
800
801
  + e.getMessage());
801
802
  }
802
803
  }
package/dist/index.js CHANGED
@@ -1645,7 +1645,7 @@ var CdvPurchase;
1645
1645
  /**
1646
1646
  * Current release number of the plugin.
1647
1647
  */
1648
- CdvPurchase.PLUGIN_VERSION = '13.15.2';
1648
+ CdvPurchase.PLUGIN_VERSION = '13.15.4';
1649
1649
  /**
1650
1650
  * Entry class of the plugin.
1651
1651
  */
@@ -3121,9 +3121,14 @@ var CdvPurchase;
3121
3121
  this.initializeAppReceipt(() => {
3122
3122
  var _a;
3123
3123
  if (!this._receipt) {
3124
- // this should not happen
3125
- this.log.warn('Failed to load the application receipt, cannot proceed with handling the purchase');
3126
- return;
3124
+ // Receipt failed to load — create a minimal receipt so the
3125
+ // transaction can still be tracked and finished. Without this
3126
+ // fallback the Promise would never resolve, leaving the native
3127
+ // transaction unfinished (causing the purchase dialog to loop on
3128
+ // iOS — see #1568).
3129
+ this.log.warn('Application receipt unavailable, creating a fallback receipt to avoid blocking transactions');
3130
+ this._receipt = new AppleAppStore.SKApplicationReceipt({ appStoreReceipt: '', bundleIdentifier: '',
3131
+ bundleShortVersion: '', bundleNumericVersion: 0, bundleSignature: '' }, this.needAppReceipt, this.context.apiDecorators);
3127
3132
  }
3128
3133
  const existing = (_a = this._receipt) === null || _a === void 0 ? void 0 : _a.transactions.find(t => t.transactionId === transactionId);
3129
3134
  if (existing) {
@@ -3285,8 +3290,22 @@ var CdvPurchase;
3285
3290
  });
3286
3291
  }
3287
3292
  loadReceipts() {
3288
- return new Promise((resolve) => {
3289
- setTimeout(() => {
3293
+ return __awaiter(this, void 0, void 0, function* () {
3294
+ // Wait for native pending transactions to be processed before
3295
+ // initializing the receipt. Previously used a fixed 300ms delay
3296
+ // which was unreliable and could miss transactions that arrived
3297
+ // from the native queue (see #1529).
3298
+ //
3299
+ // The pendingTransactionsReady Promise resolves when the native
3300
+ // `processPendingTransactions` call returns, but the per-transaction
3301
+ // callbacks it triggers via evalJs land asynchronously. Yield one
3302
+ // task so those purchased/restored callbacks (and their async
3303
+ // upsertTransaction chain) settle before we snapshot _receipt.
3304
+ if (this.bridge.pendingTransactionsReady) {
3305
+ yield this.bridge.pendingTransactionsReady;
3306
+ yield new Promise(r => setTimeout(r, 0));
3307
+ }
3308
+ return new Promise((resolve) => {
3290
3309
  this.initializeAppReceipt(() => {
3291
3310
  this.receiptsUpdated.call();
3292
3311
  if (this._receipt) {
@@ -3296,7 +3315,7 @@ var CdvPurchase;
3296
3315
  resolve([this.pseudoReceipt]);
3297
3316
  }
3298
3317
  });
3299
- }, 300);
3318
+ });
3300
3319
  });
3301
3320
  }
3302
3321
  canMakePayments() {
@@ -3352,6 +3371,7 @@ var CdvPurchase;
3352
3371
  return;
3353
3372
  }
3354
3373
  this._receipt = new AppleAppStore.SKApplicationReceipt(nativeData, this.needAppReceipt, this.context.apiDecorators);
3374
+ this._appStoreReceiptLoading = false;
3355
3375
  callCallbacks(undefined);
3356
3376
  });
3357
3377
  }
@@ -3407,46 +3427,39 @@ var CdvPurchase;
3407
3427
  loadEligibility(validProducts) {
3408
3428
  return __awaiter(this, void 0, void 0, function* () {
3409
3429
  this.log.debug('load eligibility: ' + JSON.stringify(validProducts));
3410
- if (!this.discountEligibilityDeterminer) {
3411
- this.log.debug('No discount eligibility determiner, skipping...');
3430
+ // Collect eligibility requests alongside native-provided answers (from
3431
+ // StoreKit 2's isEligibleForIntroOffer, when available).
3432
+ const { requests, nativeAnswers } = AppleAppStore.Internal.collectEligibilityRequests(validProducts);
3433
+ if (requests.length === 0) {
3412
3434
  return new AppleAppStore.Internal.DiscountEligibilities([], []);
3413
3435
  }
3414
- const eligibilityRequests = [];
3415
- validProducts.forEach(valid => {
3416
- var _a, _b, _c;
3417
- (_a = valid.discounts) === null || _a === void 0 ? void 0 : _a.forEach(discount => {
3418
- eligibilityRequests.push({
3419
- productId: valid.id,
3420
- discountId: discount.id,
3421
- discountType: discount.type,
3422
- });
3423
- });
3424
- if (((_c = (_b = valid.discounts) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0) === 0 && valid.introPrice) {
3425
- // sometime apple returns the discounts in the deprecated "introductory" info
3426
- // we create a special "discount" with the id "intro" to check for eligibility.
3427
- eligibilityRequests.push({
3428
- productId: valid.id,
3429
- discountId: 'intro',
3430
- discountType: 'Introductory',
3431
- });
3432
- }
3433
- });
3434
- if (eligibilityRequests.length > 0) {
3435
- const applicationReceipt = yield this.loadAppStoreReceipt();
3436
- if (!applicationReceipt || !applicationReceipt.appStoreReceipt) {
3437
- this.log.debug('no receipt, assuming introductory price are available.');
3438
- return new AppleAppStore.Internal.DiscountEligibilities(eligibilityRequests, eligibilityRequests.map(r => r.discountType === "Introductory"));
3439
- }
3440
- else {
3441
- this.log.debug('calling discount eligibility determiner.');
3442
- const response = yield this.callDiscountEligibilityDeterminer(applicationReceipt, eligibilityRequests);
3443
- this.log.debug('response: ' + JSON.stringify(response));
3444
- return new AppleAppStore.Internal.DiscountEligibilities(eligibilityRequests, response);
3445
- }
3436
+ // Fast path — if every eligibility answer came from native, we can skip
3437
+ // the receipt fetch and the determiner entirely. This is the common case
3438
+ // for StoreKit 2 where the app store receipt is always empty.
3439
+ const allNative = nativeAnswers.every(a => a !== undefined);
3440
+ if (allNative) {
3441
+ this.log.debug('native eligibility answers cover all requests, skipping determiner.');
3442
+ return new AppleAppStore.Internal.DiscountEligibilities(requests, nativeAnswers);
3443
+ }
3444
+ // Otherwise fall back to the receipt + determiner path, then overlay any
3445
+ // native answers we do have (native wins on conflict — it's authoritative).
3446
+ if (!this.discountEligibilityDeterminer) {
3447
+ this.log.debug('No discount eligibility determiner; using native answers only where available.');
3448
+ const defaultForMissing = requests.map(r => r.discountType === 'Introductory');
3449
+ return new AppleAppStore.Internal.DiscountEligibilities(requests, AppleAppStore.Internal.mergeNativeEligibility(defaultForMissing, nativeAnswers));
3450
+ }
3451
+ const applicationReceipt = yield this.loadAppStoreReceipt();
3452
+ let response;
3453
+ if (!applicationReceipt || !applicationReceipt.appStoreReceipt) {
3454
+ this.log.debug('no receipt, assuming introductory price are available.');
3455
+ response = requests.map(r => r.discountType === 'Introductory');
3446
3456
  }
3447
3457
  else {
3448
- return new AppleAppStore.Internal.DiscountEligibilities([], []);
3458
+ this.log.debug('calling discount eligibility determiner.');
3459
+ response = yield this.callDiscountEligibilityDeterminer(applicationReceipt, requests);
3460
+ this.log.debug('response: ' + JSON.stringify(response));
3449
3461
  }
3462
+ return new AppleAppStore.Internal.DiscountEligibilities(requests, AppleAppStore.Internal.mergeNativeEligibility(response, nativeAnswers));
3450
3463
  });
3451
3464
  }
3452
3465
  callDiscountEligibilityDeterminer(applicationReceipt, eligibilityRequests) {
@@ -4140,6 +4153,9 @@ var CdvPurchase;
4140
4153
  protectCall(this.options.ready, 'options.ready');
4141
4154
  protectCall(success, 'init.success');
4142
4155
  this.initialized = true;
4156
+ this.pendingTransactionsReady = new Promise(resolve => {
4157
+ this._pendingTransactionsResolve = resolve;
4158
+ });
4143
4159
  setTimeout(() => this.processPendingTransactions(), 50);
4144
4160
  };
4145
4161
  const setupFailed = (err) => {
@@ -4152,6 +4168,10 @@ var CdvPurchase;
4152
4168
  log('processing pending transactions');
4153
4169
  exec('processPendingTransactions', [], () => {
4154
4170
  this.finalizeTransactionUpdates();
4171
+ if (this._pendingTransactionsResolve) {
4172
+ this._pendingTransactionsResolve();
4173
+ this._pendingTransactionsResolve = undefined;
4174
+ }
4155
4175
  }, undefined);
4156
4176
  }
4157
4177
  purchase(productId, quantity, applicationUsername, discount, success, error) {
@@ -4459,6 +4479,9 @@ var CdvPurchase;
4459
4479
  protectCall(this.options.ready, 'options.ready');
4460
4480
  protectCall(success, 'init.success');
4461
4481
  this.initialized = true;
4482
+ this.pendingTransactionsReady = new Promise(resolve => {
4483
+ this._pendingTransactionsResolve = resolve;
4484
+ });
4462
4485
  setTimeout(() => this.processPendingTransactions(), 50);
4463
4486
  };
4464
4487
  const setupFailed = (err) => {
@@ -4472,6 +4495,10 @@ var CdvPurchase;
4472
4495
  log('processing pending transactions');
4473
4496
  exec('processPendingTransactions', [], () => {
4474
4497
  this.finalizeTransactionUpdates();
4498
+ if (this._pendingTransactionsResolve) {
4499
+ this._pendingTransactionsResolve();
4500
+ this._pendingTransactionsResolve = undefined;
4501
+ }
4475
4502
  }, undefined);
4476
4503
  }
4477
4504
  /**
@@ -4761,6 +4788,52 @@ var CdvPurchase;
4761
4788
  }
4762
4789
  }
4763
4790
  Internal.DiscountEligibilities = DiscountEligibilities;
4791
+ /**
4792
+ * Build the pair of (requests, native-provided answers) for every valid product.
4793
+ *
4794
+ * The two arrays are parallel: for each request, the matching `nativeAnswers` entry
4795
+ * is either the native eligibility (from StoreKit 2's `isEligibleForIntroOffer`)
4796
+ * or `undefined` if native did not provide one (SK1 / older native plugin).
4797
+ *
4798
+ * Only Introductory requests can carry a native answer — SK2 does not answer
4799
+ * promotional offer eligibility at the adapter level.
4800
+ */
4801
+ function collectEligibilityRequests(validProducts) {
4802
+ const requests = [];
4803
+ const nativeAnswers = [];
4804
+ validProducts.forEach(valid => {
4805
+ var _a, _b, _c;
4806
+ (_a = valid.discounts) === null || _a === void 0 ? void 0 : _a.forEach(discount => {
4807
+ requests.push({
4808
+ productId: valid.id,
4809
+ discountId: discount.id,
4810
+ discountType: discount.type,
4811
+ });
4812
+ nativeAnswers.push(discount.type === 'Introductory' ? valid.introPriceEligible : undefined);
4813
+ });
4814
+ if (((_c = (_b = valid.discounts) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0) === 0 && valid.introPrice) {
4815
+ requests.push({
4816
+ productId: valid.id,
4817
+ discountId: 'intro',
4818
+ discountType: 'Introductory',
4819
+ });
4820
+ nativeAnswers.push(valid.introPriceEligible);
4821
+ }
4822
+ });
4823
+ return { requests, nativeAnswers };
4824
+ }
4825
+ Internal.collectEligibilityRequests = collectEligibilityRequests;
4826
+ /**
4827
+ * Overlay native-provided eligibility answers on top of a determiner response.
4828
+ *
4829
+ * Native wins on conflict — it's the authoritative source for StoreKit 2.
4830
+ * Determiner response is used where native did not provide an answer (SK1
4831
+ * or older native builds).
4832
+ */
4833
+ function mergeNativeEligibility(determinerResponse, nativeAnswers) {
4834
+ return determinerResponse.map((r, i) => nativeAnswers[i] !== undefined ? nativeAnswers[i] : r);
4835
+ }
4836
+ Internal.mergeNativeEligibility = mergeNativeEligibility;
4764
4837
  })(AppleAppStore.Internal || (AppleAppStore.Internal = {}));
4765
4838
  })(CdvPurchase.AppleAppStore || (CdvPurchase.AppleAppStore = {}));
4766
4839
  })(CdvPurchase || (CdvPurchase = {}));
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["esm/index.js","../build/entry.mjs"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\n// Set the marker so the shared store.js knows Capacitor native bridges are available\nif (typeof window !== 'undefined') {\n window.CdvPurchaseCapacitor = { installed: true };\n}\nconst PurchasePlugin = registerPlugin('PurchasePlugin');\nexport { PurchasePlugin };\n","// Capacitor bridge — sets CdvPurchaseCapacitor marker and registers native plugin\nexport { PurchasePlugin } from '../dist/esm/index.js';\n\n// Store runtime — executes the IIFE, creates window.CdvPurchase\nimport { CdvPurchase } from 'virtual:store-js';\n\n// Re-export the full namespace\nexport { CdvPurchase };\n\n// Convenience named exports\nexport const store = CdvPurchase.store;\nexport const Store = CdvPurchase.Store;\nexport const ProductType = CdvPurchase.ProductType;\nexport const Platform = CdvPurchase.Platform;\nexport const LogLevel = CdvPurchase.LogLevel;\nexport const ErrorCode = CdvPurchase.ErrorCode;\nexport const Logger = CdvPurchase.Logger;\nexport const Iaptic = CdvPurchase.Iaptic;\n"],"names":[],"mappings":";;AACA;AACA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AACnC,IAAI,MAAM,CAAC,oBAAoB,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE;AACrD;AACK,MAAC,cAAc,GAAG,cAAc,CAAC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACLtD;;AASA;AACY,MAAC,KAAK,GAAG,WAAW,CAAC;AACrB,MAAC,KAAK,GAAG,WAAW,CAAC;AACrB,MAAC,WAAW,GAAG,WAAW,CAAC;AAC3B,MAAC,QAAQ,GAAG,WAAW,CAAC;AACxB,MAAC,QAAQ,GAAG,WAAW,CAAC;AACxB,MAAC,SAAS,GAAG,WAAW,CAAC;AACzB,MAAC,MAAM,GAAG,WAAW,CAAC;AACtB,MAAC,MAAM,GAAG,WAAW,CAAC;;;;"}
1
+ {"version":3,"file":"index.js","sources":["esm/index.js","../build/entry.mjs"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\n// Set the marker so the shared store.js knows Capacitor native bridges are available\nif (typeof window !== 'undefined') {\n window.CdvPurchaseCapacitor = { installed: true };\n}\nconst PurchasePlugin = registerPlugin('PurchasePlugin');\nexport { PurchasePlugin };\n","// Capacitor bridge — sets CdvPurchaseCapacitor marker and registers native plugin\nexport { PurchasePlugin } from '../dist/esm/index.js';\n\n// Store runtime — executes the IIFE, creates window.CdvPurchase\nimport { CdvPurchase } from 'virtual:store-js';\n\n// Re-export the full namespace\nexport { CdvPurchase };\n\n// Convenience named exports\nexport const store = CdvPurchase.store;\nexport const Store = CdvPurchase.Store;\nexport const ProductType = CdvPurchase.ProductType;\nexport const Platform = CdvPurchase.Platform;\nexport const LogLevel = CdvPurchase.LogLevel;\nexport const ErrorCode = CdvPurchase.ErrorCode;\nexport const Logger = CdvPurchase.Logger;\nexport const Iaptic = CdvPurchase.Iaptic;\n"],"names":[],"mappings":";;AACA;AACA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AACnC,IAAI,MAAM,CAAC,oBAAoB,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE;AACrD;AACK,MAAC,cAAc,GAAG,cAAc,CAAC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACLtD;;AASA;AACY,MAAC,KAAK,GAAG,WAAW,CAAC;AACrB,MAAC,KAAK,GAAG,WAAW,CAAC;AACrB,MAAC,WAAW,GAAG,WAAW,CAAC;AAC3B,MAAC,QAAQ,GAAG,WAAW,CAAC;AACxB,MAAC,QAAQ,GAAG,WAAW,CAAC;AACxB,MAAC,SAAS,GAAG,WAAW,CAAC;AACzB,MAAC,MAAM,GAAG,WAAW,CAAC;AACtB,MAAC,MAAM,GAAG,WAAW,CAAC;;;;"}
@@ -150,7 +150,7 @@ public class PurchasePlugin: CAPPlugin, CAPBridgedPlugin {
150
150
 
151
151
  for product in storeProducts {
152
152
  sk2.products[product.id] = product
153
- validProducts.append(productToDict(product))
153
+ validProducts.append(await productToDict(product))
154
154
  validIds.insert(product.id)
155
155
  }
156
156
 
@@ -445,7 +445,7 @@ public class PurchasePlugin: CAPPlugin, CAPBridgedPlugin {
445
445
  }
446
446
 
447
447
  @available(iOS 15.0, *)
448
- private func productToDict(_ product: Product) -> [String: Any] {
448
+ private func productToDict(_ product: Product) async -> [String: Any] {
449
449
  var dict: [String: Any] = [
450
450
  "id": product.id,
451
451
  "title": product.displayName,
@@ -478,6 +478,10 @@ public class PurchasePlugin: CAPPlugin, CAPBridgedPlugin {
478
478
  dict["introPricePeriod"] = intro.period.value
479
479
  dict["introPricePeriodUnit"] = periodUnitToString(intro.period.unit)
480
480
  dict["introPricePaymentMode"] = paymentModeToString(intro.paymentMode)
481
+ // StoreKit 2 eligibility — honors the user's prior subscription/trial history.
482
+ // Only meaningful when an intro offer exists; omitted otherwise so older TS
483
+ // builds that don't know about this field keep their SK1-era behavior.
484
+ dict["introPriceEligible"] = await subscription.isEligibleForIntroOffer
481
485
  }
482
486
 
483
487
  // Promotional offers (discounts)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-plugin-cdv-purchase",
3
- "version": "13.15.2",
3
+ "version": "13.15.4",
4
4
  "description": "In-App Purchases for Capacitor — iOS (StoreKit 2) and Android (Google Play Billing)",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -10,7 +10,8 @@
10
10
  "types": "./types/index.d.ts",
11
11
  "import": "./dist/index.js",
12
12
  "default": "./dist/index.js"
13
- }
13
+ },
14
+ "./package.json": "./package.json"
14
15
  },
15
16
  "capacitor": {
16
17
  "ios": { "src": "ios" },
package/www/store.d.ts CHANGED
@@ -716,7 +716,9 @@ declare namespace CdvPurchase {
716
716
  /**
717
717
  * Name of the group your subscription product is a member of.
718
718
  *
719
- * If you don't set anything, all subscription will be members of the same group.
719
+ * When set, purchasing a subscription in a group will replace the currently
720
+ * owned one (on Google Play, this triggers the subscription replacement flow).
721
+ * When not set, subscriptions are independent — no automatic replacement.
720
722
  */
721
723
  group?: string;
722
724
  }
@@ -884,7 +886,7 @@ declare namespace CdvPurchase {
884
886
  /**
885
887
  * Current release number of the plugin.
886
888
  */
887
- const PLUGIN_VERSION = "13.15.2";
889
+ const PLUGIN_VERSION = "13.15.4";
888
890
  /**
889
891
  * Entry class of the plugin.
890
892
  */
@@ -2832,6 +2834,8 @@ declare namespace CdvPurchase {
2832
2834
  };
2833
2835
  /** Whether this bridge uses StoreKit 2 */
2834
2836
  readonly isSK2?: boolean;
2837
+ /** Resolves when pending transactions from the native queue have been processed */
2838
+ pendingTransactionsReady?: Promise<void>;
2835
2839
  init(options: Partial<BridgeOptions>, success: () => void, error: (code: ErrorCode, message: string) => void): void;
2836
2840
  load(productIds: string[], success: (validProducts: ValidProduct[], invalidProductIds: string[]) => void, error: (code: ErrorCode, message: string) => void): void;
2837
2841
  purchase(productId: string, quantity: number, applicationUsername: string | undefined, discount: PaymentDiscount | undefined, success: () => void, error: () => void): void;
@@ -2866,6 +2870,8 @@ declare namespace CdvPurchase {
2866
2870
  appStoreReceipt?: AppleAppStore.ApplicationReceipt | null;
2867
2871
  private registeredProducts;
2868
2872
  private needRestoreNotification;
2873
+ pendingTransactionsReady?: Promise<void>;
2874
+ private _pendingTransactionsResolve?;
2869
2875
  private pendingUpdates;
2870
2876
  /** True when this bridge is active (SK2 extension installed + iOS 15+) */
2871
2877
  readonly isSK2 = true;
@@ -2964,6 +2970,15 @@ declare namespace CdvPurchase {
2964
2970
  introPricePeriodUnit?: IPeriodUnit;
2965
2971
  /** Payment mode for introductory price */
2966
2972
  introPricePaymentMode?: PaymentMode;
2973
+ /**
2974
+ * Whether the user is eligible for the introductory price.
2975
+ *
2976
+ * Populated from StoreKit 2's `Product.SubscriptionInfo.isEligibleForIntroOffer`
2977
+ * when running on SK2 (iOS 15+). Absent on SK1 and on older native builds that
2978
+ * don't surface it — in which case the discount eligibility determiner is used
2979
+ * as before.
2980
+ */
2981
+ introPriceEligible?: boolean;
2967
2982
  /** Available discount offers */
2968
2983
  discounts?: Discount[];
2969
2984
  /** Group this product is member of */
@@ -3058,6 +3073,9 @@ declare namespace CdvPurchase {
3058
3073
  private registeredProducts;
3059
3074
  /** True if "restoreCompleted" or "restoreFailed" should be called when restore is done */
3060
3075
  private needRestoreNotification;
3076
+ /** Resolves when pending transactions from the native queue have been processed */
3077
+ pendingTransactionsReady?: Promise<void>;
3078
+ private _pendingTransactionsResolve?;
3061
3079
  /** List of transaction updates to process */
3062
3080
  private pendingUpdates;
3063
3081
  constructor();
@@ -3161,6 +3179,28 @@ declare namespace CdvPurchase {
3161
3179
  constructor(request: DiscountEligibilityRequest[], response: boolean[]);
3162
3180
  isEligible(productId: string, discountType: DiscountType, discountId: string): boolean;
3163
3181
  }
3182
+ /**
3183
+ * Build the pair of (requests, native-provided answers) for every valid product.
3184
+ *
3185
+ * The two arrays are parallel: for each request, the matching `nativeAnswers` entry
3186
+ * is either the native eligibility (from StoreKit 2's `isEligibleForIntroOffer`)
3187
+ * or `undefined` if native did not provide one (SK1 / older native plugin).
3188
+ *
3189
+ * Only Introductory requests can carry a native answer — SK2 does not answer
3190
+ * promotional offer eligibility at the adapter level.
3191
+ */
3192
+ function collectEligibilityRequests(validProducts: Bridge.ValidProduct[]): {
3193
+ requests: DiscountEligibilityRequest[];
3194
+ nativeAnswers: (boolean | undefined)[];
3195
+ };
3196
+ /**
3197
+ * Overlay native-provided eligibility answers on top of a determiner response.
3198
+ *
3199
+ * Native wins on conflict — it's the authoritative source for StoreKit 2.
3200
+ * Determiner response is used where native did not provide an answer (SK1
3201
+ * or older native builds).
3202
+ */
3203
+ function mergeNativeEligibility(determinerResponse: boolean[], nativeAnswers: (boolean | undefined)[]): boolean[];
3164
3204
  }
3165
3205
  }
3166
3206
  }
package/www/store.js CHANGED
@@ -1662,7 +1662,7 @@ var CdvPurchase;
1662
1662
  /**
1663
1663
  * Current release number of the plugin.
1664
1664
  */
1665
- CdvPurchase.PLUGIN_VERSION = '13.15.2';
1665
+ CdvPurchase.PLUGIN_VERSION = '13.15.4';
1666
1666
  /**
1667
1667
  * Entry class of the plugin.
1668
1668
  */
@@ -3194,9 +3194,14 @@ var CdvPurchase;
3194
3194
  this.initializeAppReceipt(() => {
3195
3195
  var _a;
3196
3196
  if (!this._receipt) {
3197
- // this should not happen
3198
- this.log.warn('Failed to load the application receipt, cannot proceed with handling the purchase');
3199
- return;
3197
+ // Receipt failed to load — create a minimal receipt so the
3198
+ // transaction can still be tracked and finished. Without this
3199
+ // fallback the Promise would never resolve, leaving the native
3200
+ // transaction unfinished (causing the purchase dialog to loop on
3201
+ // iOS — see #1568).
3202
+ this.log.warn('Application receipt unavailable, creating a fallback receipt to avoid blocking transactions');
3203
+ this._receipt = new AppleAppStore.SKApplicationReceipt({ appStoreReceipt: '', bundleIdentifier: '',
3204
+ bundleShortVersion: '', bundleNumericVersion: 0, bundleSignature: '' }, this.needAppReceipt, this.context.apiDecorators);
3200
3205
  }
3201
3206
  const existing = (_a = this._receipt) === null || _a === void 0 ? void 0 : _a.transactions.find(t => t.transactionId === transactionId);
3202
3207
  if (existing) {
@@ -3358,8 +3363,22 @@ var CdvPurchase;
3358
3363
  });
3359
3364
  }
3360
3365
  loadReceipts() {
3361
- return new Promise((resolve) => {
3362
- setTimeout(() => {
3366
+ return __awaiter(this, void 0, void 0, function* () {
3367
+ // Wait for native pending transactions to be processed before
3368
+ // initializing the receipt. Previously used a fixed 300ms delay
3369
+ // which was unreliable and could miss transactions that arrived
3370
+ // from the native queue (see #1529).
3371
+ //
3372
+ // The pendingTransactionsReady Promise resolves when the native
3373
+ // `processPendingTransactions` call returns, but the per-transaction
3374
+ // callbacks it triggers via evalJs land asynchronously. Yield one
3375
+ // task so those purchased/restored callbacks (and their async
3376
+ // upsertTransaction chain) settle before we snapshot _receipt.
3377
+ if (this.bridge.pendingTransactionsReady) {
3378
+ yield this.bridge.pendingTransactionsReady;
3379
+ yield new Promise(r => setTimeout(r, 0));
3380
+ }
3381
+ return new Promise((resolve) => {
3363
3382
  this.initializeAppReceipt(() => {
3364
3383
  this.receiptsUpdated.call();
3365
3384
  if (this._receipt) {
@@ -3369,7 +3388,7 @@ var CdvPurchase;
3369
3388
  resolve([this.pseudoReceipt]);
3370
3389
  }
3371
3390
  });
3372
- }, 300);
3391
+ });
3373
3392
  });
3374
3393
  }
3375
3394
  canMakePayments() {
@@ -3425,6 +3444,7 @@ var CdvPurchase;
3425
3444
  return;
3426
3445
  }
3427
3446
  this._receipt = new AppleAppStore.SKApplicationReceipt(nativeData, this.needAppReceipt, this.context.apiDecorators);
3447
+ this._appStoreReceiptLoading = false;
3428
3448
  callCallbacks(undefined);
3429
3449
  });
3430
3450
  }
@@ -3480,46 +3500,39 @@ var CdvPurchase;
3480
3500
  loadEligibility(validProducts) {
3481
3501
  return __awaiter(this, void 0, void 0, function* () {
3482
3502
  this.log.debug('load eligibility: ' + JSON.stringify(validProducts));
3483
- if (!this.discountEligibilityDeterminer) {
3484
- this.log.debug('No discount eligibility determiner, skipping...');
3503
+ // Collect eligibility requests alongside native-provided answers (from
3504
+ // StoreKit 2's isEligibleForIntroOffer, when available).
3505
+ const { requests, nativeAnswers } = AppleAppStore.Internal.collectEligibilityRequests(validProducts);
3506
+ if (requests.length === 0) {
3485
3507
  return new AppleAppStore.Internal.DiscountEligibilities([], []);
3486
3508
  }
3487
- const eligibilityRequests = [];
3488
- validProducts.forEach(valid => {
3489
- var _a, _b, _c;
3490
- (_a = valid.discounts) === null || _a === void 0 ? void 0 : _a.forEach(discount => {
3491
- eligibilityRequests.push({
3492
- productId: valid.id,
3493
- discountId: discount.id,
3494
- discountType: discount.type,
3495
- });
3496
- });
3497
- if (((_c = (_b = valid.discounts) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0) === 0 && valid.introPrice) {
3498
- // sometime apple returns the discounts in the deprecated "introductory" info
3499
- // we create a special "discount" with the id "intro" to check for eligibility.
3500
- eligibilityRequests.push({
3501
- productId: valid.id,
3502
- discountId: 'intro',
3503
- discountType: 'Introductory',
3504
- });
3505
- }
3506
- });
3507
- if (eligibilityRequests.length > 0) {
3508
- const applicationReceipt = yield this.loadAppStoreReceipt();
3509
- if (!applicationReceipt || !applicationReceipt.appStoreReceipt) {
3510
- this.log.debug('no receipt, assuming introductory price are available.');
3511
- return new AppleAppStore.Internal.DiscountEligibilities(eligibilityRequests, eligibilityRequests.map(r => r.discountType === "Introductory"));
3512
- }
3513
- else {
3514
- this.log.debug('calling discount eligibility determiner.');
3515
- const response = yield this.callDiscountEligibilityDeterminer(applicationReceipt, eligibilityRequests);
3516
- this.log.debug('response: ' + JSON.stringify(response));
3517
- return new AppleAppStore.Internal.DiscountEligibilities(eligibilityRequests, response);
3518
- }
3509
+ // Fast path — if every eligibility answer came from native, we can skip
3510
+ // the receipt fetch and the determiner entirely. This is the common case
3511
+ // for StoreKit 2 where the app store receipt is always empty.
3512
+ const allNative = nativeAnswers.every(a => a !== undefined);
3513
+ if (allNative) {
3514
+ this.log.debug('native eligibility answers cover all requests, skipping determiner.');
3515
+ return new AppleAppStore.Internal.DiscountEligibilities(requests, nativeAnswers);
3516
+ }
3517
+ // Otherwise fall back to the receipt + determiner path, then overlay any
3518
+ // native answers we do have (native wins on conflict — it's authoritative).
3519
+ if (!this.discountEligibilityDeterminer) {
3520
+ this.log.debug('No discount eligibility determiner; using native answers only where available.');
3521
+ const defaultForMissing = requests.map(r => r.discountType === 'Introductory');
3522
+ return new AppleAppStore.Internal.DiscountEligibilities(requests, AppleAppStore.Internal.mergeNativeEligibility(defaultForMissing, nativeAnswers));
3523
+ }
3524
+ const applicationReceipt = yield this.loadAppStoreReceipt();
3525
+ let response;
3526
+ if (!applicationReceipt || !applicationReceipt.appStoreReceipt) {
3527
+ this.log.debug('no receipt, assuming introductory price are available.');
3528
+ response = requests.map(r => r.discountType === 'Introductory');
3519
3529
  }
3520
3530
  else {
3521
- return new AppleAppStore.Internal.DiscountEligibilities([], []);
3531
+ this.log.debug('calling discount eligibility determiner.');
3532
+ response = yield this.callDiscountEligibilityDeterminer(applicationReceipt, requests);
3533
+ this.log.debug('response: ' + JSON.stringify(response));
3522
3534
  }
3535
+ return new AppleAppStore.Internal.DiscountEligibilities(requests, AppleAppStore.Internal.mergeNativeEligibility(response, nativeAnswers));
3523
3536
  });
3524
3537
  }
3525
3538
  callDiscountEligibilityDeterminer(applicationReceipt, eligibilityRequests) {
@@ -4217,6 +4230,9 @@ var CdvPurchase;
4217
4230
  protectCall(this.options.ready, 'options.ready');
4218
4231
  protectCall(success, 'init.success');
4219
4232
  this.initialized = true;
4233
+ this.pendingTransactionsReady = new Promise(resolve => {
4234
+ this._pendingTransactionsResolve = resolve;
4235
+ });
4220
4236
  setTimeout(() => this.processPendingTransactions(), 50);
4221
4237
  };
4222
4238
  const setupFailed = (err) => {
@@ -4229,6 +4245,10 @@ var CdvPurchase;
4229
4245
  log('processing pending transactions');
4230
4246
  exec('processPendingTransactions', [], () => {
4231
4247
  this.finalizeTransactionUpdates();
4248
+ if (this._pendingTransactionsResolve) {
4249
+ this._pendingTransactionsResolve();
4250
+ this._pendingTransactionsResolve = undefined;
4251
+ }
4232
4252
  }, undefined);
4233
4253
  }
4234
4254
  purchase(productId, quantity, applicationUsername, discount, success, error) {
@@ -4540,6 +4560,9 @@ var CdvPurchase;
4540
4560
  protectCall(this.options.ready, 'options.ready');
4541
4561
  protectCall(success, 'init.success');
4542
4562
  this.initialized = true;
4563
+ this.pendingTransactionsReady = new Promise(resolve => {
4564
+ this._pendingTransactionsResolve = resolve;
4565
+ });
4543
4566
  setTimeout(() => this.processPendingTransactions(), 50);
4544
4567
  };
4545
4568
  const setupFailed = (err) => {
@@ -4553,6 +4576,10 @@ var CdvPurchase;
4553
4576
  log('processing pending transactions');
4554
4577
  exec('processPendingTransactions', [], () => {
4555
4578
  this.finalizeTransactionUpdates();
4579
+ if (this._pendingTransactionsResolve) {
4580
+ this._pendingTransactionsResolve();
4581
+ this._pendingTransactionsResolve = undefined;
4582
+ }
4556
4583
  }, undefined);
4557
4584
  }
4558
4585
  /**
@@ -4848,6 +4875,52 @@ var CdvPurchase;
4848
4875
  }
4849
4876
  }
4850
4877
  Internal.DiscountEligibilities = DiscountEligibilities;
4878
+ /**
4879
+ * Build the pair of (requests, native-provided answers) for every valid product.
4880
+ *
4881
+ * The two arrays are parallel: for each request, the matching `nativeAnswers` entry
4882
+ * is either the native eligibility (from StoreKit 2's `isEligibleForIntroOffer`)
4883
+ * or `undefined` if native did not provide one (SK1 / older native plugin).
4884
+ *
4885
+ * Only Introductory requests can carry a native answer — SK2 does not answer
4886
+ * promotional offer eligibility at the adapter level.
4887
+ */
4888
+ function collectEligibilityRequests(validProducts) {
4889
+ const requests = [];
4890
+ const nativeAnswers = [];
4891
+ validProducts.forEach(valid => {
4892
+ var _a, _b, _c;
4893
+ (_a = valid.discounts) === null || _a === void 0 ? void 0 : _a.forEach(discount => {
4894
+ requests.push({
4895
+ productId: valid.id,
4896
+ discountId: discount.id,
4897
+ discountType: discount.type,
4898
+ });
4899
+ nativeAnswers.push(discount.type === 'Introductory' ? valid.introPriceEligible : undefined);
4900
+ });
4901
+ if (((_c = (_b = valid.discounts) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0) === 0 && valid.introPrice) {
4902
+ requests.push({
4903
+ productId: valid.id,
4904
+ discountId: 'intro',
4905
+ discountType: 'Introductory',
4906
+ });
4907
+ nativeAnswers.push(valid.introPriceEligible);
4908
+ }
4909
+ });
4910
+ return { requests, nativeAnswers };
4911
+ }
4912
+ Internal.collectEligibilityRequests = collectEligibilityRequests;
4913
+ /**
4914
+ * Overlay native-provided eligibility answers on top of a determiner response.
4915
+ *
4916
+ * Native wins on conflict — it's the authoritative source for StoreKit 2.
4917
+ * Determiner response is used where native did not provide an answer (SK1
4918
+ * or older native builds).
4919
+ */
4920
+ function mergeNativeEligibility(determinerResponse, nativeAnswers) {
4921
+ return determinerResponse.map((r, i) => nativeAnswers[i] !== undefined ? nativeAnswers[i] : r);
4922
+ }
4923
+ Internal.mergeNativeEligibility = mergeNativeEligibility;
4851
4924
  })(Internal = AppleAppStore.Internal || (AppleAppStore.Internal = {}));
4852
4925
  })(AppleAppStore = CdvPurchase.AppleAppStore || (CdvPurchase.AppleAppStore = {}));
4853
4926
  })(CdvPurchase || (CdvPurchase = {}));