capacitor-plugin-cdv-purchase 13.15.4 → 13.16.0

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.
package/dist/index.js CHANGED
@@ -661,10 +661,16 @@ var CdvPurchase;
661
661
  const body = yield (adapter === null || adapter === void 0 ? void 0 : adapter.receiptValidationBody(receipt));
662
662
  if (!body)
663
663
  return;
664
- // Add the applicationUsername
665
- body.additionalData = Object.assign(Object.assign({}, (_a = body.additionalData) !== null && _a !== void 0 ? _a : {}), { applicationUsername: this.controller.getApplicationUsername() });
664
+ // Add the applicationUsername and its obfuscated form
665
+ const rawUsername = this.controller.getApplicationUsername();
666
+ body.additionalData = Object.assign(Object.assign({}, (_a = body.additionalData) !== null && _a !== void 0 ? _a : {}), { applicationUsername: rawUsername });
666
667
  if (!body.additionalData.applicationUsername)
667
668
  delete body.additionalData.applicationUsername;
669
+ if (rawUsername) {
670
+ const obfuscated = this.controller.obfuscateUsername(rawUsername, receipt.platform);
671
+ if (obfuscated)
672
+ body.additionalData.obfuscatedUsername = obfuscated;
673
+ }
668
674
  // Add device information
669
675
  body.device = Object.assign(Object.assign({}, (_b = body.device) !== null && _b !== void 0 ? _b : {}), CdvPurchase.Validator.Internal.getDeviceInfo(this.controller));
670
676
  // Add legacy pricing information
@@ -782,13 +788,32 @@ var CdvPurchase;
782
788
  Internal.Validator = Validator;
783
789
  /**
784
790
  * Check if a payload looks like a valid validator response.
791
+ *
792
+ * When `ok` is `true`, validates that `data` exists and contains the
793
+ * fields the rest of the pipeline reads unconditionally: `id` (used to
794
+ * key the verified-receipt cache) and `transaction` (stored as the
795
+ * native transaction). Optional fields like `latest_receipt`,
796
+ * `collection`, `warning`, `date` are not required — a validator that
797
+ * omits them produces a usable VerifiedReceipt all the same.
798
+ *
799
+ * When `ok` is `false`, the `data` field is optional per ErrorPayload.
785
800
  */
786
801
  function isValidatorResponsePayload(payload) {
787
- // TODO: could be made more robust.
788
- return (!!payload)
789
- && (typeof payload === 'object')
790
- && ('ok' in payload)
791
- && (typeof payload.ok === 'boolean');
802
+ if (!payload || typeof payload !== 'object')
803
+ return false;
804
+ const p = payload;
805
+ if (typeof p.ok !== 'boolean')
806
+ return false;
807
+ if (p.ok === true) {
808
+ const data = p.data;
809
+ if (!data || typeof data !== 'object')
810
+ return false;
811
+ if (typeof data.id !== 'string')
812
+ return false;
813
+ if (!data.transaction || typeof data.transaction !== 'object')
814
+ return false;
815
+ }
816
+ return true;
792
817
  }
793
818
  })(CdvPurchase.Internal || (CdvPurchase.Internal = {}));
794
819
  })(CdvPurchase || (CdvPurchase = {}));
@@ -1598,6 +1623,37 @@ var CdvPurchase;
1598
1623
  Internal.ExpiryMonitor = ExpiryMonitor;
1599
1624
  })(CdvPurchase.Internal || (CdvPurchase.Internal = {}));
1600
1625
  })(CdvPurchase || (CdvPurchase = {}));
1626
+ var CdvPurchase;
1627
+ (function (CdvPurchase) {
1628
+ (function (Utils) {
1629
+ /**
1630
+ * Convert a string to a UUIDv3-like format using MD5 hashing.
1631
+ *
1632
+ * Takes an input string, computes its MD5 hash, then formats the 32 hex
1633
+ * characters as a UUID with version nibble set to '3' (MD5) and variant
1634
+ * nibble set to '8' (RFC 4122).
1635
+ *
1636
+ * This produces a deterministic, valid UUID suitable for Apple's SK2
1637
+ * `appAccountToken` and Google Play's `obfuscatedAccountId`.
1638
+ *
1639
+ * @param str - The input string to hash and format
1640
+ * @returns A UUIDv3-like string (36 chars with dashes), or empty string if input is empty
1641
+ */
1642
+ function md5toUUID(str) {
1643
+ if (!str)
1644
+ return '';
1645
+ const hash = Utils.md5(str);
1646
+ // UUID format: xxxxxxxx-xxxx-3xxx-8xxx-xxxxxxxxxxxx
1647
+ // Position 12: version '3' (MD5), Position 16: variant '8' (RFC 4122)
1648
+ return hash.substring(0, 8) + '-'
1649
+ + hash.substring(8, 12) + '-'
1650
+ + '3' + hash.substring(13, 16) + '-'
1651
+ + '8' + hash.substring(17, 20) + '-'
1652
+ + hash.substring(20, 32);
1653
+ }
1654
+ Utils.md5toUUID = md5toUUID;
1655
+ })(CdvPurchase.Utils || (CdvPurchase.Utils = {}));
1656
+ })(CdvPurchase || (CdvPurchase = {}));
1601
1657
  /// <reference path="types.ts" />
1602
1658
  /// <reference path="utils/compatibility.ts" />
1603
1659
  /// <reference path="utils/platform-name.ts" />
@@ -1612,6 +1668,7 @@ var CdvPurchase;
1612
1668
  /// <reference path="internal/transaction-monitor.ts" />
1613
1669
  /// <reference path="internal/receipts-monitor.ts" />
1614
1670
  /// <reference path="internal/expiry-monitor.ts" />
1671
+ /// <reference path="utils/to-uuid.ts" />
1615
1672
  /**
1616
1673
  * Namespace for the cordova-plugin-purchase plugin.
1617
1674
  *
@@ -1645,7 +1702,7 @@ var CdvPurchase;
1645
1702
  /**
1646
1703
  * Current release number of the plugin.
1647
1704
  */
1648
- CdvPurchase.PLUGIN_VERSION = '13.15.4';
1705
+ CdvPurchase.PLUGIN_VERSION = '13.16.0';
1649
1706
  /**
1650
1707
  * Entry class of the plugin.
1651
1708
  */
@@ -1677,6 +1734,8 @@ var CdvPurchase;
1677
1734
  * @see {@link LogLevel}
1678
1735
  */
1679
1736
  this.verbosity = CdvPurchase.LogLevel.ERROR;
1737
+ /** @internal Tracks whether the info notice for 'legacy' has been emitted */
1738
+ this._legacyObfuscatorNoticeEmitted = false;
1680
1739
  /** List of callbacks for the "ready" events */
1681
1740
  this._readyCallbacks = new CdvPurchase.Internal.ReadyCallbacks(this.log);
1682
1741
  /** Callbacks when a product definition was updated */
@@ -1736,6 +1795,7 @@ var CdvPurchase;
1736
1795
  this._validator = new CdvPurchase.Internal.Validator({
1737
1796
  adapters: this.adapters,
1738
1797
  getApplicationUsername: this.getApplicationUsername.bind(this),
1798
+ obfuscateUsername: this.obfuscateUsername.bind(this),
1739
1799
  get localReceipts() { return store.localReceipts; },
1740
1800
  get validator() { return store.validator; },
1741
1801
  get validator_privacy_policy() { return store.validator_privacy_policy; },
@@ -1793,6 +1853,40 @@ var CdvPurchase;
1793
1853
  return this.applicationUsername();
1794
1854
  return this.applicationUsername;
1795
1855
  }
1856
+ /**
1857
+ * Obfuscate the application username according to the configured obfuscation strategy.
1858
+ *
1859
+ * See {@link Obfuscator} for the per-mode output format.
1860
+ *
1861
+ * @internal
1862
+ */
1863
+ obfuscateUsername(applicationUsername, platform) {
1864
+ var _a;
1865
+ if (!applicationUsername)
1866
+ return undefined;
1867
+ const obfuscator = (_a = this.obfuscator) !== null && _a !== void 0 ? _a : 'legacy';
1868
+ if (typeof obfuscator === 'function') {
1869
+ return obfuscator(applicationUsername, platform);
1870
+ }
1871
+ switch (obfuscator) {
1872
+ case 'disabled':
1873
+ return applicationUsername;
1874
+ case 'uuid':
1875
+ return CdvPurchase.Utils.md5toUUID(applicationUsername);
1876
+ case 'legacy':
1877
+ default:
1878
+ if (!this._legacyObfuscatorNoticeEmitted) {
1879
+ this._legacyObfuscatorNoticeEmitted = true;
1880
+ this.log.info('store.obfuscator defaults to "legacy" for backward compatibility. New integrations should set store.obfuscator = "uuid". See https://github.com/j3k0/cordova-plugin-purchase/issues/1665');
1881
+ }
1882
+ if (platform === CdvPurchase.Platform.GOOGLE_PLAY) {
1883
+ // Backward-compatible: raw MD5 hash (32 hex chars, no dashes)
1884
+ return CdvPurchase.Utils.md5(applicationUsername);
1885
+ }
1886
+ // UUIDv3 format — valid for Apple appAccountToken (SK1 + SK2) and any other platform
1887
+ return CdvPurchase.Utils.md5toUUID(applicationUsername);
1888
+ }
1889
+ }
1796
1890
  /**
1797
1891
  * Register a product.
1798
1892
  *
@@ -1851,6 +1945,8 @@ var CdvPurchase;
1851
1945
  error: this.triggerError.bind(this),
1852
1946
  get verbosity() { return store.verbosity; },
1853
1947
  getApplicationUsername() { return store.getApplicationUsername(); },
1948
+ obfuscateUsername: (username, platform) => store.obfuscateUsername(username, platform),
1949
+ get obfuscator() { return store.obfuscator; },
1854
1950
  get listener() { return store.listener; },
1855
1951
  get log() { return store.log; },
1856
1952
  get registeredProducts() { return store.registeredProducts; },
@@ -3070,6 +3166,24 @@ var CdvPurchase;
3070
3166
  }, 300);
3071
3167
  }
3072
3168
  get products() { return this._products; }
3169
+ /**
3170
+ * Resolve the username string passed to the native bridge for a
3171
+ * purchase. SK1 + 'legacy' keeps the raw username for backward
3172
+ * compatibility; every other mode obfuscates through the
3173
+ * configured strategy. 'disabled' always returns the raw value.
3174
+ */
3175
+ resolveBridgeUsername() {
3176
+ var _a;
3177
+ const raw = this.context.getApplicationUsername();
3178
+ if (!raw)
3179
+ return undefined;
3180
+ const obfuscator = (_a = this.context.obfuscator) !== null && _a !== void 0 ? _a : 'legacy';
3181
+ if (obfuscator === 'disabled')
3182
+ return raw;
3183
+ if (obfuscator === 'legacy' && !this.useSK2)
3184
+ return raw;
3185
+ return this.context.obfuscateUsername(raw, CdvPurchase.Platform.APPLE_APPSTORE);
3186
+ }
3073
3187
  /** Find a given product from ID */
3074
3188
  getProduct(id) { return this._products.find(p => p.id === id); }
3075
3189
  get receipts() {
@@ -3565,7 +3679,9 @@ var CdvPurchase;
3565
3679
  // When we switch AppStore user, the cached receipt isn't from the new user.
3566
3680
  // so after a purchase, we want to make sure we're using the receipt from the logged in user.
3567
3681
  this.forceReceiptReload = true;
3568
- this.bridge.purchase(offer.productId, quantity, this.context.getApplicationUsername(), discount, success, error);
3682
+ warnIfDeprecatedAdditionalUsername(this.log, additionalData);
3683
+ const username = this.resolveBridgeUsername();
3684
+ this.bridge.purchase(offer.productId, quantity, username, discount, success, error);
3569
3685
  });
3570
3686
  });
3571
3687
  }
@@ -3822,6 +3938,16 @@ var CdvPurchase;
3822
3938
  function appStoreError(code, message, productId) {
3823
3939
  return CdvPurchase.storeError(code, message, CdvPurchase.Platform.APPLE_APPSTORE, productId);
3824
3940
  }
3941
+ let deprecatedAdditionalUsernameNoticed = false;
3942
+ function warnIfDeprecatedAdditionalUsername(log, additionalData) {
3943
+ // Bracket access avoids the @deprecated read warning on the field.
3944
+ if (!additionalData || !additionalData['applicationUsername'])
3945
+ return;
3946
+ if (deprecatedAdditionalUsernameNoticed)
3947
+ return;
3948
+ deprecatedAdditionalUsernameNoticed = true;
3949
+ log.warn('additionalData.applicationUsername is deprecated and ignored. Set store.applicationUsername instead.');
3950
+ }
3825
3951
  })(CdvPurchase.AppleAppStore || (CdvPurchase.AppleAppStore = {}));
3826
3952
  })(CdvPurchase || (CdvPurchase = {}));
3827
3953
  var CdvPurchase;
@@ -6218,6 +6344,8 @@ var CdvPurchase;
6218
6344
  /** @inheritDoc */
6219
6345
  order(offer, additionalData) {
6220
6346
  return __awaiter(this, void 0, void 0, function* () {
6347
+ warnIfDeprecatedAdditionalUsername(this.log, additionalData);
6348
+ additionalData = withObfuscatedAccountId(additionalData, this.context);
6221
6349
  return new Promise(resolve => {
6222
6350
  this.log.info("Order - " + JSON.stringify(offer));
6223
6351
  const buySuccess = () => resolve(undefined);
@@ -6365,6 +6493,33 @@ var CdvPurchase;
6365
6493
  PRODUCTION: 7 * 24 * 60 * 60 * 1000 + 10 * 60 * 1000, // 7 days + 10 minutes for production
6366
6494
  };
6367
6495
  GooglePlay.Adapter = Adapter;
6496
+ let deprecatedAdditionalUsernameNoticed = false;
6497
+ function warnIfDeprecatedAdditionalUsername(log, additionalData) {
6498
+ // Bracket access avoids the @deprecated read warning on the field.
6499
+ if (!additionalData || !additionalData['applicationUsername'])
6500
+ return;
6501
+ if (deprecatedAdditionalUsernameNoticed)
6502
+ return;
6503
+ deprecatedAdditionalUsernameNoticed = true;
6504
+ log.warn('additionalData.applicationUsername is deprecated and ignored. Set store.applicationUsername instead.');
6505
+ }
6506
+ /**
6507
+ * Return a copy of `additionalData` with `googlePlay.accountId` populated
6508
+ * from `store.applicationUsername` (via the configured obfuscator) when
6509
+ * not already provided by the caller. Never mutates the input.
6510
+ */
6511
+ function withObfuscatedAccountId(additionalData, context) {
6512
+ var _a;
6513
+ const next = Object.assign({}, (additionalData !== null && additionalData !== void 0 ? additionalData : {}));
6514
+ next.googlePlay = Object.assign({}, ((_a = additionalData === null || additionalData === void 0 ? void 0 : additionalData.googlePlay) !== null && _a !== void 0 ? _a : {}));
6515
+ if (!next.googlePlay.accountId) {
6516
+ const username = context.getApplicationUsername();
6517
+ if (username) {
6518
+ next.googlePlay.accountId = context.obfuscateUsername(username, CdvPurchase.Platform.GOOGLE_PLAY);
6519
+ }
6520
+ }
6521
+ return next;
6522
+ }
6368
6523
  function playStoreError(code, message, productId) {
6369
6524
  return CdvPurchase.storeError(code, message, CdvPurchase.Platform.GOOGLE_PLAY, productId);
6370
6525
  }
@@ -6528,11 +6683,7 @@ var CdvPurchase;
6528
6683
  return !!obj && obj.constructor === Object ? obj : {};
6529
6684
  }
6530
6685
  function extendAdditionalData(ad) {
6531
- const additionalData = ensureObject(ad === null || ad === void 0 ? void 0 : ad.googlePlay);
6532
- if (!additionalData.accountId && (ad === null || ad === void 0 ? void 0 : ad.applicationUsername)) {
6533
- additionalData.accountId = CdvPurchase.Utils.md5(ad.applicationUsername);
6534
- }
6535
- return additionalData;
6686
+ return ensureObject(ad === null || ad === void 0 ? void 0 : ad.googlePlay);
6536
6687
  }
6537
6688
  })(GooglePlay.Bridge || (GooglePlay.Bridge = {}));
6538
6689
  })(CdvPurchase.GooglePlay || (CdvPurchase.GooglePlay = {}));
@@ -6751,11 +6902,7 @@ var CdvPurchase;
6751
6902
  return !!obj && obj.constructor === Object ? obj : {};
6752
6903
  }
6753
6904
  function extendAdditionalData(ad) {
6754
- const additionalData = ensureObject(ad === null || ad === void 0 ? void 0 : ad.googlePlay);
6755
- if (!additionalData.accountId && (ad === null || ad === void 0 ? void 0 : ad.applicationUsername)) {
6756
- additionalData.accountId = CdvPurchase.Utils.md5(ad.applicationUsername);
6757
- }
6758
- return additionalData;
6905
+ return ensureObject(ad === null || ad === void 0 ? void 0 : ad.googlePlay);
6759
6906
  }
6760
6907
  })(GooglePlay.Bridge || (GooglePlay.Bridge = {}));
6761
6908
  })(CdvPurchase.GooglePlay || (CdvPurchase.GooglePlay = {}));
@@ -7600,11 +7747,12 @@ var CdvPurchase;
7600
7747
  });
7601
7748
  }
7602
7749
  handleReceiptValidationResponse(receipt, response) {
7750
+ var _a, _b;
7603
7751
  return __awaiter(this, void 0, void 0, function* () {
7604
7752
  this.log.info('handleReceiptValidationResponse for IapticJS');
7605
7753
  if (response.ok) {
7606
- response.data.transaction;
7607
- const collection = response.data.collection;
7754
+ (_a = response.data) === null || _a === void 0 ? void 0 : _a.transaction;
7755
+ const collection = (_b = response.data) === null || _b === void 0 ? void 0 : _b.collection;
7608
7756
  // Update receipt based on validated collection
7609
7757
  if (collection) {
7610
7758
  const purchases = collection.map((vp) => {
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;;;;"}
@@ -186,9 +186,12 @@ public class PurchasePlugin: CAPPlugin, CAPBridgedPlugin {
186
186
  Task {
187
187
  do {
188
188
  var options: Set<Product.PurchaseOption> = []
189
- if let username = call.getString("applicationUsername") {
190
- options.insert(.appAccountToken(
191
- UUID(uuidString: username) ?? UUID()))
189
+ if let username = call.getString("applicationUsername"), !username.isEmpty {
190
+ if let uuid = UUID(uuidString: username) {
191
+ options.insert(.appAccountToken(uuid))
192
+ } else {
193
+ debugLog("applicationUsername is not a valid UUID, appAccountToken will not be set: \(username)")
194
+ }
192
195
  }
193
196
  if quantity > 1 {
194
197
  options.insert(.quantity(quantity))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "capacitor-plugin-cdv-purchase",
3
- "version": "13.15.4",
3
+ "version": "13.16.0",
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",
package/www/store.d.ts CHANGED
@@ -348,6 +348,7 @@ declare namespace CdvPurchase {
348
348
  adapters: Adapters;
349
349
  validator_privacy_policy: PrivacyPolicyItem | PrivacyPolicyItem[] | undefined;
350
350
  getApplicationUsername(): string | undefined;
351
+ obfuscateUsername: (applicationUsername: string, platform: CdvPurchase.Platform) => string | undefined;
351
352
  verifiedCallbacks: Callbacks<VerifiedReceipt>;
352
353
  unverifiedCallbacks: Callbacks<UnverifiedReceipt>;
353
354
  finish(receipt: VerifiedReceipt): Promise<void>;
@@ -443,6 +444,10 @@ declare namespace CdvPurchase {
443
444
  listener: AdapterListener;
444
445
  /** Retrieves the application username */
445
446
  getApplicationUsername: () => string | undefined;
447
+ /** Obfuscate the application username for the given platform */
448
+ obfuscateUsername: (applicationUsername: string, platform: CdvPurchase.Platform) => string | undefined;
449
+ /** The obfuscation strategy */
450
+ obfuscator?: CdvPurchase.Obfuscator;
446
451
  /** Functions used to decorate the API */
447
452
  apiDecorators: ProductDecorator & TransactionDecorator & OfferDecorator & ReceiptDecorator;
448
453
  /** Collection of per-platform storefront values. */
@@ -854,6 +859,24 @@ declare namespace CdvPurchase {
854
859
  }
855
860
  }
856
861
  }
862
+ declare namespace CdvPurchase {
863
+ namespace Utils {
864
+ /**
865
+ * Convert a string to a UUIDv3-like format using MD5 hashing.
866
+ *
867
+ * Takes an input string, computes its MD5 hash, then formats the 32 hex
868
+ * characters as a UUID with version nibble set to '3' (MD5) and variant
869
+ * nibble set to '8' (RFC 4122).
870
+ *
871
+ * This produces a deterministic, valid UUID suitable for Apple's SK2
872
+ * `appAccountToken` and Google Play's `obfuscatedAccountId`.
873
+ *
874
+ * @param str - The input string to hash and format
875
+ * @returns A UUIDv3-like string (36 chars with dashes), or empty string if input is empty
876
+ */
877
+ function md5toUUID(str: string): string;
878
+ }
879
+ }
857
880
  /**
858
881
  * Namespace for the cordova-plugin-purchase plugin.
859
882
  *
@@ -886,7 +909,7 @@ declare namespace CdvPurchase {
886
909
  /**
887
910
  * Current release number of the plugin.
888
911
  */
889
- const PLUGIN_VERSION = "13.15.4";
912
+ const PLUGIN_VERSION = "13.16.0";
890
913
  /**
891
914
  * Entry class of the plugin.
892
915
  */
@@ -928,14 +951,44 @@ declare namespace CdvPurchase {
928
951
  /**
929
952
  * Return the identifier of the user for your application.
930
953
  *
931
- * **Note:** Apple AppStore requires an UUIDv4 if you want it to appear as the "appAccountToken" in
932
- * the transaction data.
954
+ * This value is obfuscated according to {@link Store.obfuscator} before being
955
+ * sent to the native platform API. The default obfuscator (`'legacy'`) hashes
956
+ * or formats the value so the original username is never transmitted in cleartext.
957
+ *
958
+ * For Apple's App Store, the obfuscated value is used as `appAccountToken`
959
+ * (which must be a valid UUID when using StoreKit 2).
960
+ *
961
+ * You can also pass it per-transaction via `additionalData.applicationUsername`
962
+ * in `store.order()` or `store.requestPayment()`, which takes priority.
933
963
  */
934
964
  applicationUsername?: string | (() => string | undefined);
935
965
  /**
936
966
  * Get the application username as a string by either calling or returning {@link Store.applicationUsername}
937
967
  */
938
968
  getApplicationUsername(): string | undefined;
969
+ /**
970
+ * Obfuscation strategy for the application username.
971
+ *
972
+ * Controls how `applicationUsername` is transformed before being sent
973
+ * to each platform's native API. `'uuid'` is the recommended setting
974
+ * for new integrations; the default `'legacy'` exists only for
975
+ * backward compatibility with server-side modules that already
976
+ * correlate against the raw 32-hex MD5 value.
977
+ *
978
+ * @default 'legacy'
979
+ * @see {@link Obfuscator}
980
+ */
981
+ obfuscator?: CdvPurchase.Obfuscator;
982
+ /** @internal Tracks whether the info notice for 'legacy' has been emitted */
983
+ private _legacyObfuscatorNoticeEmitted;
984
+ /**
985
+ * Obfuscate the application username according to the configured obfuscation strategy.
986
+ *
987
+ * See {@link Obfuscator} for the per-mode output format.
988
+ *
989
+ * @internal
990
+ */
991
+ obfuscateUsername(applicationUsername: string, platform: CdvPurchase.Platform): string | undefined;
939
992
  /**
940
993
  * URL or implementation of the receipt validation service
941
994
  *
@@ -1512,7 +1565,16 @@ declare namespace CdvPurchase {
1512
1565
  * @see {@link Store.requestPayment}
1513
1566
  */
1514
1567
  interface AdditionalData {
1515
- /** The application's user identifier, will be obfuscated with md5 to fill `accountId` if necessary */
1568
+ /**
1569
+ * The application's user identifier.
1570
+ *
1571
+ * @deprecated Set {@link Store.applicationUsername} instead. The
1572
+ * per-transaction value is ignored — adapters always read the
1573
+ * store-level username so receipt validation later (which doesn't
1574
+ * have access to the original additionalData) sees the same value
1575
+ * that was sent to the native API at purchase time. Passing this
1576
+ * field logs a one-shot notice.
1577
+ */
1516
1578
  applicationUsername?: string;
1517
1579
  /**
1518
1580
  * Quantity of items to purchase.
@@ -1530,6 +1592,38 @@ declare namespace CdvPurchase {
1530
1592
  /** Apple AppStore specific additional data */
1531
1593
  appStore?: AppleAppStore.AdditionalData;
1532
1594
  }
1595
+ /**
1596
+ * Obfuscation strategy for the application username.
1597
+ *
1598
+ * Controls how `applicationUsername` is transformed before being sent to
1599
+ * each platform's native API.
1600
+ *
1601
+ * - `'uuid'` — **Recommended.** MD5 hash formatted as UUIDv3 on all
1602
+ * platforms. Deterministic, valid UUID, works as Apple's
1603
+ * `appAccountToken` (SK1 + SK2) and Google Play's
1604
+ * `obfuscatedAccountId`.
1605
+ *
1606
+ * - `'legacy'` (default) — Only use this when an existing server-side
1607
+ * integration already correlates against the original 32-hex MD5 value
1608
+ * sent on Google Play. New integrations should pick `'uuid'`.
1609
+ * - Google Play: raw MD5 hash (32 hex chars)
1610
+ * - Apple AppStore (SK2): MD5 hash formatted as UUIDv3
1611
+ * - Apple AppStore (SK1, deprecated): raw username, unchanged
1612
+ * - Other platforms: MD5 hash formatted as UUIDv3
1613
+ *
1614
+ * - `'disabled'` — No obfuscation. The raw `applicationUsername` is
1615
+ * passed through to all platforms. For Apple SK2, the value must be a
1616
+ * valid UUID string or `appAccountToken` will not be set.
1617
+ *
1618
+ * - Custom function — `(username: string, platform: Platform) => string`.
1619
+ * Receives the raw username and platform, returns the obfuscated value.
1620
+ * For Apple (both SK1 and SK2), the function must return a valid UUID
1621
+ * string.
1622
+ *
1623
+ * @see {@link Store.obfuscator}
1624
+ * @see {@link https://github.com/j3k0/cordova-plugin-purchase/issues/1665}
1625
+ */
1626
+ type Obfuscator = 'legacy' | 'uuid' | 'disabled' | ((applicationUsername: string, platform: Platform) => string);
1533
1627
  /**
1534
1628
  * Purchase platforms supported by the plugin
1535
1629
  */
@@ -2700,6 +2794,13 @@ declare namespace CdvPurchase {
2700
2794
  /** List of products loaded from AppStore */
2701
2795
  _products: SKProduct[];
2702
2796
  get products(): Product[];
2797
+ /**
2798
+ * Resolve the username string passed to the native bridge for a
2799
+ * purchase. SK1 + 'legacy' keeps the raw username for backward
2800
+ * compatibility; every other mode obfuscates through the
2801
+ * configured strategy. 'disabled' always returns the raw value.
2802
+ */
2803
+ private resolveBridgeUsername;
2703
2804
  /** Find a given product from ID */
2704
2805
  getProduct(id: string): SKProduct | undefined;
2705
2806
  /** The application receipt, contains all transactions */
@@ -4879,7 +4980,9 @@ declare namespace CdvPurchase {
4879
4980
  /**
4880
4981
  * Obfuscated user account identifier
4881
4982
  *
4882
- * Default to md5(store.applicationUsername)
4983
+ * Populated by the adapter using `store.obfuscateUsername()`.
4984
+ * Format depends on `store.obfuscator` setting.
4985
+ * @see {@link CdvPurchase.Store.obfuscator}
4883
4986
  */
4884
4987
  accountId?: string;
4885
4988
  /**
@@ -4951,7 +5054,7 @@ declare namespace CdvPurchase {
4951
5054
  signature: string;
4952
5055
  /** String in JSON format that contains details about the purchase order. */
4953
5056
  receipt: string;
4954
- /** Obfuscated account id specified at purchase - by default md5(applicationUsername) */
5057
+ /** Obfuscated account id specified at purchase. Format depends on `store.obfuscator`. */
4955
5058
  accountId: string;
4956
5059
  /** Obfuscated profile id specified at purchase - used when a single user can have multiple profiles */
4957
5060
  profileId: string;
@@ -6188,6 +6291,14 @@ declare namespace CdvPurchase {
6188
6291
  *
6189
6292
  * @optional */
6190
6293
  applicationUsername?: string | number;
6294
+ /**
6295
+ * The obfuscated form of `applicationUsername`, derived by applying
6296
+ * `store.obfuscator`. The server can use this to correlate obfuscated
6297
+ * IDs from Apple/Google server notifications (e.g. `appAccountToken`,
6298
+ * `obfuscatedExternalAccountId`) with the original user.
6299
+ *
6300
+ * @optional */
6301
+ obfuscatedUsername?: string;
6191
6302
  };
6192
6303
  /** Microsoft license information */
6193
6304
  license?: {
package/www/store.js CHANGED
@@ -666,10 +666,16 @@ var CdvPurchase;
666
666
  const body = yield (adapter === null || adapter === void 0 ? void 0 : adapter.receiptValidationBody(receipt));
667
667
  if (!body)
668
668
  return;
669
- // Add the applicationUsername
670
- body.additionalData = Object.assign(Object.assign({}, (_a = body.additionalData) !== null && _a !== void 0 ? _a : {}), { applicationUsername: this.controller.getApplicationUsername() });
669
+ // Add the applicationUsername and its obfuscated form
670
+ const rawUsername = this.controller.getApplicationUsername();
671
+ body.additionalData = Object.assign(Object.assign({}, (_a = body.additionalData) !== null && _a !== void 0 ? _a : {}), { applicationUsername: rawUsername });
671
672
  if (!body.additionalData.applicationUsername)
672
673
  delete body.additionalData.applicationUsername;
674
+ if (rawUsername) {
675
+ const obfuscated = this.controller.obfuscateUsername(rawUsername, receipt.platform);
676
+ if (obfuscated)
677
+ body.additionalData.obfuscatedUsername = obfuscated;
678
+ }
673
679
  // Add device information
674
680
  body.device = Object.assign(Object.assign({}, (_b = body.device) !== null && _b !== void 0 ? _b : {}), CdvPurchase.Validator.Internal.getDeviceInfo(this.controller));
675
681
  // Add legacy pricing information
@@ -787,13 +793,32 @@ var CdvPurchase;
787
793
  Internal.Validator = Validator;
788
794
  /**
789
795
  * Check if a payload looks like a valid validator response.
796
+ *
797
+ * When `ok` is `true`, validates that `data` exists and contains the
798
+ * fields the rest of the pipeline reads unconditionally: `id` (used to
799
+ * key the verified-receipt cache) and `transaction` (stored as the
800
+ * native transaction). Optional fields like `latest_receipt`,
801
+ * `collection`, `warning`, `date` are not required — a validator that
802
+ * omits them produces a usable VerifiedReceipt all the same.
803
+ *
804
+ * When `ok` is `false`, the `data` field is optional per ErrorPayload.
790
805
  */
791
806
  function isValidatorResponsePayload(payload) {
792
- // TODO: could be made more robust.
793
- return (!!payload)
794
- && (typeof payload === 'object')
795
- && ('ok' in payload)
796
- && (typeof payload.ok === 'boolean');
807
+ if (!payload || typeof payload !== 'object')
808
+ return false;
809
+ const p = payload;
810
+ if (typeof p.ok !== 'boolean')
811
+ return false;
812
+ if (p.ok === true) {
813
+ const data = p.data;
814
+ if (!data || typeof data !== 'object')
815
+ return false;
816
+ if (typeof data.id !== 'string')
817
+ return false;
818
+ if (!data.transaction || typeof data.transaction !== 'object')
819
+ return false;
820
+ }
821
+ return true;
797
822
  }
798
823
  })(Internal = CdvPurchase.Internal || (CdvPurchase.Internal = {}));
799
824
  })(CdvPurchase || (CdvPurchase = {}));
@@ -1615,6 +1640,38 @@ var CdvPurchase;
1615
1640
  Internal.ExpiryMonitor = ExpiryMonitor;
1616
1641
  })(Internal = CdvPurchase.Internal || (CdvPurchase.Internal = {}));
1617
1642
  })(CdvPurchase || (CdvPurchase = {}));
1643
+ var CdvPurchase;
1644
+ (function (CdvPurchase) {
1645
+ let Utils;
1646
+ (function (Utils) {
1647
+ /**
1648
+ * Convert a string to a UUIDv3-like format using MD5 hashing.
1649
+ *
1650
+ * Takes an input string, computes its MD5 hash, then formats the 32 hex
1651
+ * characters as a UUID with version nibble set to '3' (MD5) and variant
1652
+ * nibble set to '8' (RFC 4122).
1653
+ *
1654
+ * This produces a deterministic, valid UUID suitable for Apple's SK2
1655
+ * `appAccountToken` and Google Play's `obfuscatedAccountId`.
1656
+ *
1657
+ * @param str - The input string to hash and format
1658
+ * @returns A UUIDv3-like string (36 chars with dashes), or empty string if input is empty
1659
+ */
1660
+ function md5toUUID(str) {
1661
+ if (!str)
1662
+ return '';
1663
+ const hash = Utils.md5(str);
1664
+ // UUID format: xxxxxxxx-xxxx-3xxx-8xxx-xxxxxxxxxxxx
1665
+ // Position 12: version '3' (MD5), Position 16: variant '8' (RFC 4122)
1666
+ return hash.substring(0, 8) + '-'
1667
+ + hash.substring(8, 12) + '-'
1668
+ + '3' + hash.substring(13, 16) + '-'
1669
+ + '8' + hash.substring(17, 20) + '-'
1670
+ + hash.substring(20, 32);
1671
+ }
1672
+ Utils.md5toUUID = md5toUUID;
1673
+ })(Utils = CdvPurchase.Utils || (CdvPurchase.Utils = {}));
1674
+ })(CdvPurchase || (CdvPurchase = {}));
1618
1675
  /// <reference path="types.ts" />
1619
1676
  /// <reference path="utils/compatibility.ts" />
1620
1677
  /// <reference path="utils/platform-name.ts" />
@@ -1629,6 +1686,7 @@ var CdvPurchase;
1629
1686
  /// <reference path="internal/transaction-monitor.ts" />
1630
1687
  /// <reference path="internal/receipts-monitor.ts" />
1631
1688
  /// <reference path="internal/expiry-monitor.ts" />
1689
+ /// <reference path="utils/to-uuid.ts" />
1632
1690
  /**
1633
1691
  * Namespace for the cordova-plugin-purchase plugin.
1634
1692
  *
@@ -1662,7 +1720,7 @@ var CdvPurchase;
1662
1720
  /**
1663
1721
  * Current release number of the plugin.
1664
1722
  */
1665
- CdvPurchase.PLUGIN_VERSION = '13.15.4';
1723
+ CdvPurchase.PLUGIN_VERSION = '13.16.0';
1666
1724
  /**
1667
1725
  * Entry class of the plugin.
1668
1726
  */
@@ -1694,6 +1752,8 @@ var CdvPurchase;
1694
1752
  * @see {@link LogLevel}
1695
1753
  */
1696
1754
  this.verbosity = CdvPurchase.LogLevel.ERROR;
1755
+ /** @internal Tracks whether the info notice for 'legacy' has been emitted */
1756
+ this._legacyObfuscatorNoticeEmitted = false;
1697
1757
  /** List of callbacks for the "ready" events */
1698
1758
  this._readyCallbacks = new CdvPurchase.Internal.ReadyCallbacks(this.log);
1699
1759
  /** Callbacks when a product definition was updated */
@@ -1753,6 +1813,7 @@ var CdvPurchase;
1753
1813
  this._validator = new CdvPurchase.Internal.Validator({
1754
1814
  adapters: this.adapters,
1755
1815
  getApplicationUsername: this.getApplicationUsername.bind(this),
1816
+ obfuscateUsername: this.obfuscateUsername.bind(this),
1756
1817
  get localReceipts() { return store.localReceipts; },
1757
1818
  get validator() { return store.validator; },
1758
1819
  get validator_privacy_policy() { return store.validator_privacy_policy; },
@@ -1810,6 +1871,40 @@ var CdvPurchase;
1810
1871
  return this.applicationUsername();
1811
1872
  return this.applicationUsername;
1812
1873
  }
1874
+ /**
1875
+ * Obfuscate the application username according to the configured obfuscation strategy.
1876
+ *
1877
+ * See {@link Obfuscator} for the per-mode output format.
1878
+ *
1879
+ * @internal
1880
+ */
1881
+ obfuscateUsername(applicationUsername, platform) {
1882
+ var _a;
1883
+ if (!applicationUsername)
1884
+ return undefined;
1885
+ const obfuscator = (_a = this.obfuscator) !== null && _a !== void 0 ? _a : 'legacy';
1886
+ if (typeof obfuscator === 'function') {
1887
+ return obfuscator(applicationUsername, platform);
1888
+ }
1889
+ switch (obfuscator) {
1890
+ case 'disabled':
1891
+ return applicationUsername;
1892
+ case 'uuid':
1893
+ return CdvPurchase.Utils.md5toUUID(applicationUsername);
1894
+ case 'legacy':
1895
+ default:
1896
+ if (!this._legacyObfuscatorNoticeEmitted) {
1897
+ this._legacyObfuscatorNoticeEmitted = true;
1898
+ this.log.info('store.obfuscator defaults to "legacy" for backward compatibility. New integrations should set store.obfuscator = "uuid". See https://github.com/j3k0/cordova-plugin-purchase/issues/1665');
1899
+ }
1900
+ if (platform === CdvPurchase.Platform.GOOGLE_PLAY) {
1901
+ // Backward-compatible: raw MD5 hash (32 hex chars, no dashes)
1902
+ return CdvPurchase.Utils.md5(applicationUsername);
1903
+ }
1904
+ // UUIDv3 format — valid for Apple appAccountToken (SK1 + SK2) and any other platform
1905
+ return CdvPurchase.Utils.md5toUUID(applicationUsername);
1906
+ }
1907
+ }
1813
1908
  /**
1814
1909
  * Register a product.
1815
1910
  *
@@ -1868,6 +1963,8 @@ var CdvPurchase;
1868
1963
  error: this.triggerError.bind(this),
1869
1964
  get verbosity() { return store.verbosity; },
1870
1965
  getApplicationUsername() { return store.getApplicationUsername(); },
1966
+ obfuscateUsername: (username, platform) => store.obfuscateUsername(username, platform),
1967
+ get obfuscator() { return store.obfuscator; },
1871
1968
  get listener() { return store.listener; },
1872
1969
  get log() { return store.log; },
1873
1970
  get registeredProducts() { return store.registeredProducts; },
@@ -3143,6 +3240,24 @@ var CdvPurchase;
3143
3240
  }, 300);
3144
3241
  }
3145
3242
  get products() { return this._products; }
3243
+ /**
3244
+ * Resolve the username string passed to the native bridge for a
3245
+ * purchase. SK1 + 'legacy' keeps the raw username for backward
3246
+ * compatibility; every other mode obfuscates through the
3247
+ * configured strategy. 'disabled' always returns the raw value.
3248
+ */
3249
+ resolveBridgeUsername() {
3250
+ var _a;
3251
+ const raw = this.context.getApplicationUsername();
3252
+ if (!raw)
3253
+ return undefined;
3254
+ const obfuscator = (_a = this.context.obfuscator) !== null && _a !== void 0 ? _a : 'legacy';
3255
+ if (obfuscator === 'disabled')
3256
+ return raw;
3257
+ if (obfuscator === 'legacy' && !this.useSK2)
3258
+ return raw;
3259
+ return this.context.obfuscateUsername(raw, CdvPurchase.Platform.APPLE_APPSTORE);
3260
+ }
3146
3261
  /** Find a given product from ID */
3147
3262
  getProduct(id) { return this._products.find(p => p.id === id); }
3148
3263
  get receipts() {
@@ -3638,7 +3753,9 @@ var CdvPurchase;
3638
3753
  // When we switch AppStore user, the cached receipt isn't from the new user.
3639
3754
  // so after a purchase, we want to make sure we're using the receipt from the logged in user.
3640
3755
  this.forceReceiptReload = true;
3641
- this.bridge.purchase(offer.productId, quantity, this.context.getApplicationUsername(), discount, success, error);
3756
+ warnIfDeprecatedAdditionalUsername(this.log, additionalData);
3757
+ const username = this.resolveBridgeUsername();
3758
+ this.bridge.purchase(offer.productId, quantity, username, discount, success, error);
3642
3759
  });
3643
3760
  });
3644
3761
  }
@@ -3895,6 +4012,16 @@ var CdvPurchase;
3895
4012
  function appStoreError(code, message, productId) {
3896
4013
  return CdvPurchase.storeError(code, message, CdvPurchase.Platform.APPLE_APPSTORE, productId);
3897
4014
  }
4015
+ let deprecatedAdditionalUsernameNoticed = false;
4016
+ function warnIfDeprecatedAdditionalUsername(log, additionalData) {
4017
+ // Bracket access avoids the @deprecated read warning on the field.
4018
+ if (!additionalData || !additionalData['applicationUsername'])
4019
+ return;
4020
+ if (deprecatedAdditionalUsernameNoticed)
4021
+ return;
4022
+ deprecatedAdditionalUsernameNoticed = true;
4023
+ log.warn('additionalData.applicationUsername is deprecated and ignored. Set store.applicationUsername instead.');
4024
+ }
3898
4025
  })(AppleAppStore = CdvPurchase.AppleAppStore || (CdvPurchase.AppleAppStore = {}));
3899
4026
  })(CdvPurchase || (CdvPurchase = {}));
3900
4027
  var CdvPurchase;
@@ -6359,6 +6486,8 @@ var CdvPurchase;
6359
6486
  /** @inheritDoc */
6360
6487
  order(offer, additionalData) {
6361
6488
  return __awaiter(this, void 0, void 0, function* () {
6489
+ warnIfDeprecatedAdditionalUsername(this.log, additionalData);
6490
+ additionalData = withObfuscatedAccountId(additionalData, this.context);
6362
6491
  return new Promise(resolve => {
6363
6492
  this.log.info("Order - " + JSON.stringify(offer));
6364
6493
  const buySuccess = () => resolve(undefined);
@@ -6516,6 +6645,33 @@ var CdvPurchase;
6516
6645
  PRODUCTION: 7 * 24 * 60 * 60 * 1000 + 10 * 60 * 1000, // 7 days + 10 minutes for production
6517
6646
  };
6518
6647
  GooglePlay.Adapter = Adapter;
6648
+ let deprecatedAdditionalUsernameNoticed = false;
6649
+ function warnIfDeprecatedAdditionalUsername(log, additionalData) {
6650
+ // Bracket access avoids the @deprecated read warning on the field.
6651
+ if (!additionalData || !additionalData['applicationUsername'])
6652
+ return;
6653
+ if (deprecatedAdditionalUsernameNoticed)
6654
+ return;
6655
+ deprecatedAdditionalUsernameNoticed = true;
6656
+ log.warn('additionalData.applicationUsername is deprecated and ignored. Set store.applicationUsername instead.');
6657
+ }
6658
+ /**
6659
+ * Return a copy of `additionalData` with `googlePlay.accountId` populated
6660
+ * from `store.applicationUsername` (via the configured obfuscator) when
6661
+ * not already provided by the caller. Never mutates the input.
6662
+ */
6663
+ function withObfuscatedAccountId(additionalData, context) {
6664
+ var _a;
6665
+ const next = Object.assign({}, (additionalData !== null && additionalData !== void 0 ? additionalData : {}));
6666
+ next.googlePlay = Object.assign({}, ((_a = additionalData === null || additionalData === void 0 ? void 0 : additionalData.googlePlay) !== null && _a !== void 0 ? _a : {}));
6667
+ if (!next.googlePlay.accountId) {
6668
+ const username = context.getApplicationUsername();
6669
+ if (username) {
6670
+ next.googlePlay.accountId = context.obfuscateUsername(username, CdvPurchase.Platform.GOOGLE_PLAY);
6671
+ }
6672
+ }
6673
+ return next;
6674
+ }
6519
6675
  function playStoreError(code, message, productId) {
6520
6676
  return CdvPurchase.storeError(code, message, CdvPurchase.Platform.GOOGLE_PLAY, productId);
6521
6677
  }
@@ -6681,11 +6837,7 @@ var CdvPurchase;
6681
6837
  return !!obj && obj.constructor === Object ? obj : {};
6682
6838
  }
6683
6839
  function extendAdditionalData(ad) {
6684
- const additionalData = ensureObject(ad === null || ad === void 0 ? void 0 : ad.googlePlay);
6685
- if (!additionalData.accountId && (ad === null || ad === void 0 ? void 0 : ad.applicationUsername)) {
6686
- additionalData.accountId = CdvPurchase.Utils.md5(ad.applicationUsername);
6687
- }
6688
- return additionalData;
6840
+ return ensureObject(ad === null || ad === void 0 ? void 0 : ad.googlePlay);
6689
6841
  }
6690
6842
  })(Bridge = GooglePlay.Bridge || (GooglePlay.Bridge = {}));
6691
6843
  })(GooglePlay = CdvPurchase.GooglePlay || (CdvPurchase.GooglePlay = {}));
@@ -6949,11 +7101,7 @@ var CdvPurchase;
6949
7101
  return !!obj && obj.constructor === Object ? obj : {};
6950
7102
  }
6951
7103
  function extendAdditionalData(ad) {
6952
- const additionalData = ensureObject(ad === null || ad === void 0 ? void 0 : ad.googlePlay);
6953
- if (!additionalData.accountId && (ad === null || ad === void 0 ? void 0 : ad.applicationUsername)) {
6954
- additionalData.accountId = CdvPurchase.Utils.md5(ad.applicationUsername);
6955
- }
6956
- return additionalData;
7104
+ return ensureObject(ad === null || ad === void 0 ? void 0 : ad.googlePlay);
6957
7105
  }
6958
7106
  })(Bridge = GooglePlay.Bridge || (GooglePlay.Bridge = {}));
6959
7107
  })(GooglePlay = CdvPurchase.GooglePlay || (CdvPurchase.GooglePlay = {}));
@@ -7813,11 +7961,12 @@ var CdvPurchase;
7813
7961
  });
7814
7962
  }
7815
7963
  handleReceiptValidationResponse(receipt, response) {
7964
+ var _a, _b;
7816
7965
  return __awaiter(this, void 0, void 0, function* () {
7817
7966
  this.log.info('handleReceiptValidationResponse for IapticJS');
7818
7967
  if (response.ok) {
7819
- const validatedData = response.data.transaction;
7820
- const collection = response.data.collection;
7968
+ const validatedData = (_a = response.data) === null || _a === void 0 ? void 0 : _a.transaction;
7969
+ const collection = (_b = response.data) === null || _b === void 0 ? void 0 : _b.collection;
7821
7970
  // Update receipt based on validated collection
7822
7971
  if (collection) {
7823
7972
  const purchases = collection.map((vp) => {