@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.
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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) {
|