rampkit-expo-dev 0.0.72 → 0.0.74

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/build/RampKit.js CHANGED
@@ -308,6 +308,8 @@ class RampKitCore {
308
308
  // Track onboarding completed - trigger: paywall_shown
309
309
  EventManager_1.eventManager.trackOnboardingCompleted("paywall_shown", screens.length, // We don't know exact step, use total
310
310
  screens.length, onboardingId);
311
+ // Auto-recheck transactions after paywall shown (catches purchases made during onboarding)
312
+ RampKitNative_1.TransactionObserver.recheck().catch(() => { });
311
313
  // Call the original callback
312
314
  const paywallCallback = (opts === null || opts === void 0 ? void 0 : opts.onShowPaywall) || (opts === null || opts === void 0 ? void 0 : opts.showPaywall) || this.onShowPaywall;
313
315
  try {
@@ -483,18 +483,23 @@ public class RampKitModule: Module {
483
483
  return result
484
484
  }
485
485
 
486
- /// Check all current entitlements and track any we haven't seen before
487
- /// This catches purchases made by Superwall/RevenueCat before our observer started
486
+ /// Check ALL transactions (not just current entitlements) and track any we haven't seen before
487
+ /// This catches ALL purchases including expired/superseded ones made by Superwall/RevenueCat
488
488
  /// Returns a dictionary with the results for JavaScript logging
489
489
  ///
490
490
  /// IMPORTANT: "Already sent" means we previously sent this transaction to the backend
491
- /// and received a successful HTTP 2xx response. The originalTransactionId is stored
491
+ /// and received a successful HTTP 2xx response. The transactionId is stored
492
492
  /// in UserDefaults ONLY after a successful send.
493
+ ///
494
+ /// NOTE: We use Transaction.all instead of Transaction.currentEntitlements because
495
+ /// currentEntitlements only returns ACTIVE entitlements. If a user purchases a subscription
496
+ /// and it expires, or if they upgrade (superseding the old transaction), currentEntitlements
497
+ /// will NOT include the original purchase. Transaction.all returns the complete history.
493
498
  @available(iOS 15.0, *)
494
499
  private func checkAndTrackCurrentEntitlements() async -> [String: Any] {
495
500
  print("[RampKit] ")
496
501
  print("[RampKit] ════════════════════════════════════════════════════════════")
497
- print("[RampKit] 🔍 CHECKING ENTITLEMENTS FOR UNSENT PURCHASES")
502
+ print("[RampKit] 🔍 CHECKING ALL TRANSACTIONS FOR UNSENT PURCHASES")
498
503
  print("[RampKit] ════════════════════════════════════════════════════════════")
499
504
  print("[RampKit] ")
500
505
  print("[RampKit] 📚 Tracked transaction IDs in storage: \(trackedTransactionIds.count)")
@@ -518,11 +523,11 @@ public class RampKitModule: Module {
518
523
  var skippedReasons: [[String: Any]] = []
519
524
  var alreadyTrackedDetails: [[String: Any]] = [] // NEW: Details of already-tracked transactions
520
525
 
521
- for await result in Transaction.currentEntitlements {
526
+ for await result in Transaction.all {
522
527
  foundCount += 1
523
528
 
524
529
  guard case .verified(let transaction) = result else {
525
- print("[RampKit] ⚠️ Unverified entitlement skipped")
530
+ print("[RampKit] ⚠️ Unverified transaction skipped")
526
531
  skippedReasons.append(["productId": "unknown", "reason": "unverified"])
527
532
  continue
528
533
  }
@@ -545,7 +550,7 @@ public class RampKitModule: Module {
545
550
  txDetails["environment"] = transaction.environment.rawValue
546
551
  }
547
552
 
548
- print("[RampKit] 📦 Found entitlement:")
553
+ print("[RampKit] 📦 Found transaction:")
549
554
  print("[RampKit] - productId: \(transaction.productID)")
550
555
  print("[RampKit] - transactionId: \(transactionId)")
551
556
  print("[RampKit] - originalTransactionId: \(originalId)")
@@ -553,30 +558,34 @@ public class RampKitModule: Module {
553
558
 
554
559
  // Check if we've already tracked this transaction
555
560
  // "Tracked" means we successfully sent a purchase_completed event to the backend
556
- // and received an HTTP 2xx response. We store the originalTransactionId after success.
557
- if trackedTransactionIds.contains(originalId) {
561
+ // and received an HTTP 2xx response. We store the transactionId after success.
562
+ // NOTE: We track by transactionId (not originalTransactionId) so renewals are also sent.
563
+ if trackedTransactionIds.contains(transactionId) {
558
564
  trackedCount += 1
559
565
  txDetails["status"] = "already_sent"
560
566
  alreadyTrackedDetails.append(txDetails)
561
567
  print("[RampKit] ✅ STATUS: ALREADY SENT TO BACKEND")
562
- print("[RampKit] (originalTransactionId \(originalId) is in our sent-transactions storage)")
568
+ print("[RampKit] (transactionId \(transactionId) is in our sent-transactions storage)")
563
569
  print("[RampKit] This means we previously sent a purchase_completed event")
564
570
  print("[RampKit] and received a successful HTTP 2xx response.")
565
571
  print("[RampKit] ")
566
572
  continue
567
573
  }
568
574
 
569
- // Skip renewals and revocations
570
- guard transaction.originalID == transaction.id,
571
- transaction.revocationDate == nil else {
572
- let reason = transaction.revocationDate != nil ? "revoked" : "renewal"
575
+ // Skip revocations only (NOT renewals - we want to track renewals too!)
576
+ if transaction.revocationDate != nil {
573
577
  txDetails["status"] = "skipped"
574
- txDetails["reason"] = reason
578
+ txDetails["reason"] = "revoked"
575
579
  skippedReasons.append(txDetails)
576
- print("[RampKit] ⏭️ STATUS: Skipped (\(reason))")
580
+ print("[RampKit] ⏭️ STATUS: Skipped (revoked)")
577
581
  continue
578
582
  }
579
583
 
584
+ // Log if this is a renewal
585
+ if transaction.originalID != transaction.id {
586
+ print("[RampKit] ℹ️ This is a RENEWAL (originalID != transactionID)")
587
+ }
588
+
580
589
  // NEW transaction we haven't seen!
581
590
  newCount += 1
582
591
  newProductIds.append(transaction.productID)
@@ -588,10 +597,10 @@ public class RampKitModule: Module {
588
597
 
589
598
  // Only mark as tracked if send succeeded
590
599
  if let status = sendResult["status"] as? String, status == "sent" {
591
- trackedTransactionIds.insert(originalId)
600
+ trackedTransactionIds.insert(transactionId)
592
601
  saveTrackedTransactions()
593
602
  print("[RampKit] ✅ Event sent successfully! HTTP status: \(sendResult["httpStatus"] ?? "unknown")")
594
- print("[RampKit] ✅ Marked originalTransactionId \(originalId) as tracked")
603
+ print("[RampKit] ✅ Marked transactionId \(transactionId) as tracked")
595
604
  } else {
596
605
  print("[RampKit] ❌ Send failed: \(sendResult["error"] ?? "unknown error")")
597
606
  print("[RampKit] ⚠️ Will retry on next app launch")
@@ -600,9 +609,9 @@ public class RampKitModule: Module {
600
609
 
601
610
  print("[RampKit] ")
602
611
  print("[RampKit] ════════════════════════════════════════════════════════════")
603
- print("[RampKit] 📊 ENTITLEMENT CHECK SUMMARY")
612
+ print("[RampKit] 📊 TRANSACTION CHECK SUMMARY")
604
613
  print("[RampKit] ════════════════════════════════════════════════════════════")
605
- print("[RampKit] Total entitlements found: \(foundCount)")
614
+ print("[RampKit] Total transactions found: \(foundCount)")
606
615
  print("[RampKit] Already sent (HTTP 2xx): \(trackedCount) (no action needed)")
607
616
  print("[RampKit] Skipped (renewal/revoked): \(skippedReasons.count) (backend gets via S2S)")
608
617
  print("[RampKit] NEW events sent this session: \(newCount)")
@@ -645,39 +654,38 @@ public class RampKitModule: Module {
645
654
  continue
646
655
  }
647
656
 
657
+ let transactionId = String(transaction.id)
648
658
  let originalId = String(transaction.originalID)
649
659
 
650
- // Skip if already tracked
651
- if self.trackedTransactionIds.contains(originalId) {
652
- print("[RampKit] ✓ Transaction.updates: Already tracked \(transaction.productID)")
660
+ // Skip if already tracked (by transactionId, not originalId - so renewals are tracked)
661
+ if self.trackedTransactionIds.contains(transactionId) {
662
+ print("[RampKit] ✓ Transaction.updates: Already tracked \(transaction.productID) (txId: \(transactionId))")
653
663
  await transaction.finish()
654
664
  continue
655
665
  }
656
666
 
657
- // Skip renewals - backend gets these from App Store S2S notifications
658
- if transaction.originalID != transaction.id {
659
- print("[RampKit] ⏭️ Transaction.updates: skipped (renewal) \(transaction.productID)")
660
- await transaction.finish()
661
- continue
662
- }
663
-
664
- // Skip revocations - backend gets these from S2S notifications
667
+ // Skip revocations only (NOT renewals - we want to track renewals!)
665
668
  if transaction.revocationDate != nil {
666
669
  print("[RampKit] ⏭️ Transaction.updates: skipped (revoked) \(transaction.productID)")
667
670
  await transaction.finish()
668
671
  continue
669
672
  }
670
673
 
671
- print("[RampKit] 🆕 Transaction.updates: NEW purchase \(transaction.productID)")
674
+ // Log if this is a renewal
675
+ if transaction.originalID != transaction.id {
676
+ print("[RampKit] 🔄 Transaction.updates: RENEWAL detected for \(transaction.productID)")
677
+ }
678
+
679
+ print("[RampKit] 🆕 Transaction.updates: NEW transaction \(transaction.productID) (txId: \(transactionId))")
672
680
 
673
681
  // Track it and check result
674
682
  let sendResult = await self.handleTransactionWithResult(transaction)
675
683
 
676
- // Only mark as tracked if send succeeded
684
+ // Only mark as tracked if send succeeded (use transactionId for renewals support)
677
685
  if let status = sendResult["status"] as? String, status == "sent" {
678
- self.trackedTransactionIds.insert(originalId)
686
+ self.trackedTransactionIds.insert(transactionId)
679
687
  self.saveTrackedTransactions()
680
- print("[RampKit] ✅ Transaction.updates: Sent and tracked \(transaction.productID)")
688
+ print("[RampKit] ✅ Transaction.updates: Sent and tracked \(transaction.productID) (txId: \(transactionId))")
681
689
  } else {
682
690
  print("[RampKit] ⚠️ Transaction.updates: Send failed, will retry \(transaction.productID)")
683
691
  }
@@ -1137,10 +1145,10 @@ public class RampKitModule: Module {
1137
1145
  private func trackPurchaseFromProductId(productId: String) async {
1138
1146
  print("[RampKit] 🔍 Looking up transaction for product: \(productId)")
1139
1147
 
1140
- // Try to find the latest transaction for this product
1148
+ // Try to find the latest transaction for this product (check all transactions, not just current entitlements)
1141
1149
  var latestTransaction: Transaction?
1142
1150
 
1143
- for await result in Transaction.currentEntitlements {
1151
+ for await result in Transaction.all {
1144
1152
  if case .verified(let transaction) = result {
1145
1153
  if transaction.productID == productId {
1146
1154
  if latestTransaction == nil || transaction.purchaseDate > latestTransaction!.purchaseDate {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rampkit-expo-dev",
3
- "version": "0.0.72",
3
+ "version": "0.0.74",
4
4
  "description": "The Expo SDK for RampKit. Build, test, and personalize app onboardings with instant updates.",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",