@capgo/native-purchases 7.16.2 → 7.16.3-alpha.2

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.
@@ -42,10 +42,12 @@ import org.json.JSONArray;
42
42
  @CapacitorPlugin(name = "NativePurchases")
43
43
  public class NativePurchasesPlugin extends Plugin {
44
44
 
45
- private final String pluginVersion = "7.16.2";
45
+ private final String pluginVersion = "7.16.3-alpha.2";
46
46
  public static final String TAG = "NativePurchases";
47
47
  private static final Phaser semaphoreReady = new Phaser(1);
48
48
  private BillingClient billingClient;
49
+ private PluginCall pendingCall = null;
50
+ private BillingResult lastBillingError = null;
49
51
 
50
52
  @PluginMethod
51
53
  public void isBillingSupported(PluginCall call) {
@@ -110,6 +112,13 @@ public class NativePurchasesPlugin extends Plugin {
110
112
  } else {
111
113
  Log.d(TAG, "Billing client was already null");
112
114
  }
115
+
116
+ // Clear pending call and error state
117
+ if (pendingCall != null) {
118
+ Log.w(TAG, "Warning: Clearing pending call that was never resolved/rejected");
119
+ pendingCall = null;
120
+ }
121
+ lastBillingError = null;
113
122
  }
114
123
 
115
124
  private void handlePurchase(Purchase purchase, PluginCall purchaseCall) {
@@ -233,6 +242,12 @@ public class NativePurchasesPlugin extends Plugin {
233
242
 
234
243
  private void initBillingClient(PluginCall purchaseCall) {
235
244
  Log.d(TAG, "initBillingClient() called");
245
+ Log.d(TAG, "purchaseCall is null: " + (purchaseCall == null));
246
+
247
+ // Store the pending call so we can reject it if billing setup fails
248
+ this.pendingCall = purchaseCall;
249
+ this.lastBillingError = null;
250
+
236
251
  semaphoreWait();
237
252
  closeBillingClient();
238
253
  semaphoreUp();
@@ -278,9 +293,43 @@ public class NativePurchasesPlugin extends Plugin {
278
293
  if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
279
294
  Log.d(TAG, "Billing setup successful, client is ready");
280
295
  // The BillingClient is ready. You can query purchases here.
296
+ lastBillingError = null;
281
297
  semaphoreReady.countDown();
282
298
  } else {
283
- Log.d(TAG, "Billing setup failed");
299
+ Log.e(TAG, "Billing setup failed with code: " + billingResult.getResponseCode());
300
+ Log.e(TAG, "Error message: " + billingResult.getDebugMessage());
301
+
302
+ // Store the error for later use
303
+ lastBillingError = billingResult;
304
+
305
+ // Release the latch so the waiting thread can continue
306
+ semaphoreReady.countDown();
307
+
308
+ // Reject the pending call if there is one
309
+ if (pendingCall != null) {
310
+ Log.d(TAG, "Rejecting pending call due to billing setup failure");
311
+ String errorMessage = "Billing service unavailable";
312
+ switch (billingResult.getResponseCode()) {
313
+ case BillingClient.BillingResponseCode.SERVICE_UNAVAILABLE:
314
+ errorMessage =
315
+ "Billing service unavailable. Please check your internet connection and Google Play Services.";
316
+ break;
317
+ case BillingClient.BillingResponseCode.BILLING_UNAVAILABLE:
318
+ errorMessage = "Billing is not available on this device.";
319
+ break;
320
+ case BillingClient.BillingResponseCode.FEATURE_NOT_SUPPORTED:
321
+ errorMessage = "This billing feature is not supported.";
322
+ break;
323
+ case BillingClient.BillingResponseCode.SERVICE_DISCONNECTED:
324
+ errorMessage = "Billing service disconnected. Please try again.";
325
+ break;
326
+ default:
327
+ errorMessage = "Billing setup failed: " + billingResult.getDebugMessage();
328
+ break;
329
+ }
330
+ pendingCall.reject("BILLING_SETUP_FAILED", errorMessage);
331
+ pendingCall = null;
332
+ }
284
333
  }
285
334
  }
286
335
 
@@ -295,10 +344,26 @@ public class NativePurchasesPlugin extends Plugin {
295
344
  try {
296
345
  Log.d(TAG, "Waiting for billing client setup to finish");
297
346
  semaphoreReady.await();
298
- Log.d(TAG, "Billing client setup completed");
347
+ Log.d(TAG, "Billing client setup wait completed");
348
+
349
+ // Check if billing setup failed
350
+ if (lastBillingError != null) {
351
+ Log.e(TAG, "Billing setup failed, throwing exception");
352
+ throw new RuntimeException("Billing setup failed: " + lastBillingError.getDebugMessage());
353
+ }
354
+
355
+ Log.d(TAG, "Billing client setup completed successfully");
299
356
  } catch (InterruptedException e) {
300
- Log.d(TAG, "InterruptedException while waiting for billing setup: " + e.getMessage());
357
+ Log.e(TAG, "InterruptedException while waiting for billing setup: " + e.getMessage());
301
358
  e.printStackTrace();
359
+ if (pendingCall != null) {
360
+ pendingCall.reject("BILLING_INTERRUPTED", "Billing setup was interrupted");
361
+ pendingCall = null;
362
+ }
363
+ } catch (RuntimeException e) {
364
+ Log.e(TAG, "RuntimeException during billing setup: " + e.getMessage());
365
+ // Don't reject here - already rejected in onBillingSetupFinished
366
+ throw e;
302
367
  }
303
368
  }
304
369
 
@@ -383,7 +448,14 @@ public class NativePurchasesPlugin extends Plugin {
383
448
  );
384
449
  QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder().setProductList(productList).build();
385
450
  Log.d(TAG, "Initializing billing client for purchase");
386
- this.initBillingClient(call);
451
+ try {
452
+ this.initBillingClient(call);
453
+ } catch (RuntimeException e) {
454
+ Log.e(TAG, "Failed to initialize billing client: " + e.getMessage());
455
+ closeBillingClient();
456
+ // Call already rejected in initBillingClient
457
+ return;
458
+ }
387
459
  try {
388
460
  Log.d(TAG, "Querying product details for purchase");
389
461
  billingClient.queryProductDetailsAsync(
@@ -520,7 +592,14 @@ public class NativePurchasesPlugin extends Plugin {
520
592
  public void restorePurchases(PluginCall call) {
521
593
  Log.d(TAG, "restorePurchases() called");
522
594
  Log.d(NativePurchasesPlugin.TAG, "restorePurchases");
523
- this.initBillingClient(null);
595
+ try {
596
+ this.initBillingClient(call);
597
+ } catch (RuntimeException e) {
598
+ Log.e(TAG, "Failed to initialize billing client: " + e.getMessage());
599
+ closeBillingClient();
600
+ // Call already rejected in initBillingClient
601
+ return;
602
+ }
524
603
  this.processUnfinishedPurchases();
525
604
  call.resolve();
526
605
  Log.d(TAG, "restorePurchases() completed");
@@ -541,7 +620,14 @@ public class NativePurchasesPlugin extends Plugin {
541
620
 
542
621
  QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder().setProductList(productList).build();
543
622
  Log.d(TAG, "Initializing billing client for single product query");
544
- this.initBillingClient(call);
623
+ try {
624
+ this.initBillingClient(call);
625
+ } catch (RuntimeException e) {
626
+ Log.e(TAG, "Failed to initialize billing client: " + e.getMessage());
627
+ closeBillingClient();
628
+ // Call already rejected in initBillingClient
629
+ return;
630
+ }
545
631
  try {
546
632
  Log.d(TAG, "Querying product details");
547
633
  billingClient.queryProductDetailsAsync(
@@ -655,7 +741,14 @@ public class NativePurchasesPlugin extends Plugin {
655
741
  Log.d(TAG, "Total products in query list: " + productList.size());
656
742
  QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder().setProductList(productList).build();
657
743
  Log.d(TAG, "Initializing billing client for product query");
658
- this.initBillingClient(call);
744
+ try {
745
+ this.initBillingClient(call);
746
+ } catch (RuntimeException e) {
747
+ Log.e(TAG, "Failed to initialize billing client: " + e.getMessage());
748
+ closeBillingClient();
749
+ // Call already rejected in initBillingClient
750
+ return;
751
+ }
659
752
  try {
660
753
  Log.d(TAG, "Querying product details");
661
754
  billingClient.queryProductDetailsAsync(
@@ -817,7 +910,14 @@ public class NativePurchasesPlugin extends Plugin {
817
910
  return;
818
911
  }
819
912
 
820
- this.initBillingClient(null);
913
+ try {
914
+ this.initBillingClient(call);
915
+ } catch (RuntimeException e) {
916
+ Log.e(TAG, "Failed to initialize billing client: " + e.getMessage());
917
+ closeBillingClient();
918
+ // Call already rejected in initBillingClient
919
+ return;
920
+ }
821
921
 
822
922
  JSONArray allPurchases = new JSONArray();
823
923
  AtomicInteger pendingQueries = new AtomicInteger((queryInApp ? 1 : 0) + (querySubs ? 1 : 0));
@@ -982,7 +1082,14 @@ public class NativePurchasesPlugin extends Plugin {
982
1082
  }
983
1083
 
984
1084
  Log.d(TAG, "Manually acknowledging purchase with token: " + purchaseToken);
985
- this.initBillingClient(null);
1085
+ try {
1086
+ this.initBillingClient(call);
1087
+ } catch (RuntimeException e) {
1088
+ Log.e(TAG, "Failed to initialize billing client: " + e.getMessage());
1089
+ closeBillingClient();
1090
+ // Call already rejected in initBillingClient
1091
+ return;
1092
+ }
986
1093
 
987
1094
  try {
988
1095
  AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
@@ -24,7 +24,7 @@ public class NativePurchasesPlugin: CAPPlugin, CAPBridgedPlugin {
24
24
  CAPPluginMethod(name: "isEntitledToOldBusinessModel", returnType: CAPPluginReturnPromise)
25
25
  ]
26
26
 
27
- private let pluginVersion: String = "7.16.2"
27
+ private let pluginVersion: String = "7.16.3-alpha.2"
28
28
  private var transactionUpdatesTask: Task<Void, Never>?
29
29
 
30
30
  @objc func getPluginVersion(_ call: CAPPluginCall) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/native-purchases",
3
- "version": "7.16.2",
3
+ "version": "7.16.3-alpha.2",
4
4
  "description": "In-app Subscriptions Made Easy",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",