@capgo/native-purchases 7.13.5 → 7.14.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/README.md +95 -26
- package/android/src/main/java/ee/forgr/nativepurchases/NativePurchasesPlugin.java +59 -3
- package/dist/docs.json +246 -4
- package/dist/esm/definitions.d.ts +156 -2
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +3 -0
- package/dist/esm/web.js +3 -0
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +3 -0
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +3 -0
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/NativePurchasesPlugin/NativePurchasesPlugin.swift +72 -57
- package/ios/Sources/NativePurchasesPlugin/TransactionHelpers.swift +84 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1428,7 +1428,9 @@ This approach balances immediate user gratification with proper server-side vali
|
|
|
1428
1428
|
* [`getPluginVersion()`](#getpluginversion)
|
|
1429
1429
|
* [`getPurchases(...)`](#getpurchases)
|
|
1430
1430
|
* [`manageSubscriptions()`](#managesubscriptions)
|
|
1431
|
+
* [`acknowledgePurchase(...)`](#acknowledgepurchase)
|
|
1431
1432
|
* [`addListener('transactionUpdated', ...)`](#addlistenertransactionupdated-)
|
|
1433
|
+
* [`addListener('transactionVerificationFailed', ...)`](#addlistenertransactionverificationfailed-)
|
|
1432
1434
|
* [`removeAllListeners()`](#removealllisteners)
|
|
1433
1435
|
* [Interfaces](#interfaces)
|
|
1434
1436
|
* [Enums](#enums)
|
|
@@ -1452,14 +1454,14 @@ Restores a user's previous and links their appUserIDs to any user's also using
|
|
|
1452
1454
|
### purchaseProduct(...)
|
|
1453
1455
|
|
|
1454
1456
|
```typescript
|
|
1455
|
-
purchaseProduct(options: { productIdentifier: string; planIdentifier?: string; productType?: PURCHASE_TYPE; quantity?: number; appAccountToken?: string; isConsumable?: boolean; }) => Promise<Transaction>
|
|
1457
|
+
purchaseProduct(options: { productIdentifier: string; planIdentifier?: string; productType?: PURCHASE_TYPE; quantity?: number; appAccountToken?: string; isConsumable?: boolean; autoAcknowledgePurchases?: boolean; }) => Promise<Transaction>
|
|
1456
1458
|
```
|
|
1457
1459
|
|
|
1458
1460
|
Started purchase process for the given product.
|
|
1459
1461
|
|
|
1460
|
-
| Param | Type
|
|
1461
|
-
| ------------- |
|
|
1462
|
-
| **`options`** | <code>{ productIdentifier: string; planIdentifier?: string; productType?: <a href="#purchase_type">PURCHASE_TYPE</a>; quantity?: number; appAccountToken?: string; isConsumable?: boolean; }</code> | - The product to purchase |
|
|
1462
|
+
| Param | Type | Description |
|
|
1463
|
+
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
|
|
1464
|
+
| **`options`** | <code>{ productIdentifier: string; planIdentifier?: string; productType?: <a href="#purchase_type">PURCHASE_TYPE</a>; quantity?: number; appAccountToken?: string; isConsumable?: boolean; autoAcknowledgePurchases?: boolean; }</code> | - The product to purchase |
|
|
1463
1465
|
|
|
1464
1466
|
**Returns:** <code>Promise<<a href="#transaction">Transaction</a>></code>
|
|
1465
1467
|
|
|
@@ -1563,6 +1565,39 @@ This allows users to view, modify, or cancel their subscriptions.
|
|
|
1563
1565
|
--------------------
|
|
1564
1566
|
|
|
1565
1567
|
|
|
1568
|
+
### acknowledgePurchase(...)
|
|
1569
|
+
|
|
1570
|
+
```typescript
|
|
1571
|
+
acknowledgePurchase(options: { purchaseToken: string; }) => Promise<void>
|
|
1572
|
+
```
|
|
1573
|
+
|
|
1574
|
+
Manually acknowledge a purchase on Android.
|
|
1575
|
+
|
|
1576
|
+
This method is only needed when you set `autoAcknowledgePurchases: false` in purchaseProduct().
|
|
1577
|
+
Purchases MUST be acknowledged within 3 days or they will be automatically refunded by Google Play.
|
|
1578
|
+
|
|
1579
|
+
**Acknowledgment Options:**
|
|
1580
|
+
1. **Client-side (this method)**: Call from your app after validation
|
|
1581
|
+
2. **Server-side (recommended for security)**: Use Google Play Developer API v3
|
|
1582
|
+
- Endpoint: POST https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/products/{productId}/tokens/{token}:acknowledge
|
|
1583
|
+
- Requires OAuth 2.0 authentication with appropriate scopes
|
|
1584
|
+
- See: https://developers.google.com/android-publisher/api-ref/rest/v3/purchases.products/acknowledge
|
|
1585
|
+
|
|
1586
|
+
When to use manual acknowledgment:
|
|
1587
|
+
- Server-side validation: Verify the purchase with your backend before acknowledging
|
|
1588
|
+
- Entitlement delivery: Ensure user receives content/features before acknowledging
|
|
1589
|
+
- Multi-step workflows: Complete all steps before final acknowledgment
|
|
1590
|
+
- Security: Prevent client-side manipulation by handling acknowledgment server-side
|
|
1591
|
+
|
|
1592
|
+
| Param | Type | Description |
|
|
1593
|
+
| ------------- | --------------------------------------- | ----------------------------- |
|
|
1594
|
+
| **`options`** | <code>{ purchaseToken: string; }</code> | - The purchase to acknowledge |
|
|
1595
|
+
|
|
1596
|
+
**Since:** 7.14.0
|
|
1597
|
+
|
|
1598
|
+
--------------------
|
|
1599
|
+
|
|
1600
|
+
|
|
1566
1601
|
### addListener('transactionUpdated', ...)
|
|
1567
1602
|
|
|
1568
1603
|
```typescript
|
|
@@ -1583,6 +1618,26 @@ iOS only.
|
|
|
1583
1618
|
--------------------
|
|
1584
1619
|
|
|
1585
1620
|
|
|
1621
|
+
### addListener('transactionVerificationFailed', ...)
|
|
1622
|
+
|
|
1623
|
+
```typescript
|
|
1624
|
+
addListener(eventName: 'transactionVerificationFailed', listenerFunc: (payload: TransactionVerificationFailedEvent) => void) => Promise<PluginListenerHandle>
|
|
1625
|
+
```
|
|
1626
|
+
|
|
1627
|
+
Listen for StoreKit transaction verification failures delivered by Apple's <a href="#transaction">Transaction</a>.updates.
|
|
1628
|
+
Fires when the verification result is unverified.
|
|
1629
|
+
iOS only.
|
|
1630
|
+
|
|
1631
|
+
| Param | Type |
|
|
1632
|
+
| ------------------ | ----------------------------------------------------------------------------------------------------------------------- |
|
|
1633
|
+
| **`eventName`** | <code>'transactionVerificationFailed'</code> |
|
|
1634
|
+
| **`listenerFunc`** | <code>(payload: <a href="#transactionverificationfailedevent">TransactionVerificationFailedEvent</a>) => void</code> |
|
|
1635
|
+
|
|
1636
|
+
**Returns:** <code>Promise<<a href="#pluginlistenerhandle">PluginListenerHandle</a>></code>
|
|
1637
|
+
|
|
1638
|
+
--------------------
|
|
1639
|
+
|
|
1640
|
+
|
|
1586
1641
|
### removeAllListeners()
|
|
1587
1642
|
|
|
1588
1643
|
```typescript
|
|
@@ -1599,28 +1654,34 @@ Remove all registered listeners
|
|
|
1599
1654
|
|
|
1600
1655
|
#### Transaction
|
|
1601
1656
|
|
|
1602
|
-
| Prop | Type
|
|
1603
|
-
| -------------------------- |
|
|
1604
|
-
| **`transactionId`** | <code>string</code>
|
|
1605
|
-
| **`receipt`** | <code>string</code>
|
|
1606
|
-
| **`
|
|
1607
|
-
| **`
|
|
1608
|
-
| **`
|
|
1609
|
-
| **`
|
|
1610
|
-
| **`
|
|
1611
|
-
| **`
|
|
1612
|
-
| **`
|
|
1613
|
-
| **`
|
|
1614
|
-
| **`
|
|
1615
|
-
| **`
|
|
1616
|
-
| **`
|
|
1617
|
-
| **`
|
|
1618
|
-
| **`
|
|
1619
|
-
| **`
|
|
1620
|
-
| **`
|
|
1621
|
-
| **`
|
|
1622
|
-
| **`
|
|
1623
|
-
| **`
|
|
1657
|
+
| Prop | Type | Description | Default | Since |
|
|
1658
|
+
| -------------------------- | ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | ------ |
|
|
1659
|
+
| **`transactionId`** | <code>string</code> | Unique identifier for the transaction. | | 1.0.0 |
|
|
1660
|
+
| **`receipt`** | <code>string</code> | Receipt data for validation (base64 encoded StoreKit receipt). Send this to your backend for server-side validation with Apple's receipt verification API. The receipt remains available even after refund - server validation is required to detect refunded transactions. | | 1.0.0 |
|
|
1661
|
+
| **`jwsRepresentation`** | <code>string</code> | StoreKit 2 JSON Web Signature (JWS) payload describing the verified transaction. Send this to your backend when using Apple's App Store Server API v2 instead of raw receipts. Only available when the transaction originated from StoreKit 2 APIs (e.g. <a href="#transaction">Transaction</a>.updates). | | 7.13.2 |
|
|
1662
|
+
| **`appAccountToken`** | <code>string \| null</code> | An optional obfuscated identifier that uniquely associates the transaction with a user account in your app. PURPOSE: - Fraud detection: Helps platforms detect irregular activity (e.g., many devices purchasing on the same account) - User linking: Links purchases to in-game characters, avatars, or in-app profiles PLATFORM DIFFERENCES: - iOS: Must be a valid UUID format (e.g., "550e8400-e29b-41d4-a716-446655440000") Apple's StoreKit 2 requires UUID format for the appAccountToken parameter - Android: Can be any obfuscated string (max 64 chars), maps to Google Play's ObfuscatedAccountId Google recommends using encryption or one-way hash SECURITY REQUIREMENTS (especially for Android): - DO NOT store Personally Identifiable Information (PII) like emails in cleartext - Use encryption or a one-way hash to generate an obfuscated identifier - Maximum length: 64 characters (both platforms) - Storing PII in cleartext will result in purchases being blocked by Google Play IMPLEMENTATION EXAMPLE: ```typescript // For iOS: Generate a deterministic UUID from user ID import { v5 as uuidv5 } from 'uuid'; const NAMESPACE = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; // Your app's namespace UUID const appAccountToken = uuidv5(userId, NAMESPACE); // For Android: Can also use UUID or any hashed value // The same UUID approach works for both platforms ``` | | |
|
|
1663
|
+
| **`productIdentifier`** | <code>string</code> | <a href="#product">Product</a> identifier associated with the transaction. | | 1.0.0 |
|
|
1664
|
+
| **`purchaseDate`** | <code>string</code> | Purchase date of the transaction in ISO 8601 format. | | 1.0.0 |
|
|
1665
|
+
| **`isUpgraded`** | <code>boolean</code> | Indicates whether this transaction is the result of a subscription upgrade. Useful for understanding when StoreKit generated the transaction because the customer moved from a lower tier to a higher tier plan. | | 7.13.2 |
|
|
1666
|
+
| **`originalPurchaseDate`** | <code>string</code> | Original purchase date of the transaction in ISO 8601 format. For subscription renewals, this shows the date of the original subscription purchase, while purchaseDate shows the date of the current renewal. | | 1.0.0 |
|
|
1667
|
+
| **`expirationDate`** | <code>string</code> | Expiration date of the transaction in ISO 8601 format. Check this date to determine if a subscription is still valid. Compare with current date: if expirationDate > now, subscription is active. | | 1.0.0 |
|
|
1668
|
+
| **`isActive`** | <code>boolean</code> | Whether the subscription is still active/valid. For iOS subscriptions, check if isActive === true to verify an active subscription. For expired or refunded iOS subscriptions, this will be false. | | 1.0.0 |
|
|
1669
|
+
| **`revocationDate`** | <code>string</code> | Date the transaction was revoked/refunded, in ISO 8601 format. Present when Apple revokes access due to an issue (e.g., refund or developer issue). | | 7.13.2 |
|
|
1670
|
+
| **`revocationReason`** | <code>'developerIssue' \| 'other' \| 'unknown'</code> | Reason why Apple revoked the transaction. Possible values: - `"developerIssue"`: Developer-initiated refund or issue - `"other"`: Apple-initiated (customer refund, billing problem, etc.) - `"unknown"`: StoreKit didn't report a specific reason | | 7.13.2 |
|
|
1671
|
+
| **`willCancel`** | <code>boolean \| null</code> | Whether the subscription will be cancelled at the end of the billing cycle. - `true`: User has cancelled but subscription remains active until expiration - `false`: Subscription will auto-renew - `null`: Status unknown or not available | <code>null</code> | 1.0.0 |
|
|
1672
|
+
| **`subscriptionState`** | <code>'unknown' \| 'subscribed' \| 'expired' \| 'revoked' \| 'inGracePeriod' \| 'inBillingRetryPeriod'</code> | Current subscription state reported by StoreKit. Possible values: - `"subscribed"`: Auto-renewing and in good standing - `"expired"`: Lapsed with no access - `"revoked"`: Access removed due to refund or issue - `"inGracePeriod"`: Payment issue but still in grace access window - `"inBillingRetryPeriod"`: StoreKit retrying failed billing - `"unknown"`: StoreKit did not report a state | | 7.13.2 |
|
|
1673
|
+
| **`purchaseState`** | <code>string</code> | Purchase state of the transaction (numeric string value). **Android Values:** - `"1"`: Purchase completed and valid (PURCHASED state) - `"0"`: Payment pending (PENDING state, e.g., cash payment processing) - Other numeric values: Various other states Always check `purchaseState === "1"` on Android to verify a valid purchase. Refunded purchases typically disappear from getPurchases() rather than showing a different state. | | 1.0.0 |
|
|
1674
|
+
| **`orderId`** | <code>string</code> | Order ID associated with the transaction. Use this for server-side verification on Android. This is the Google Play order ID. | | 1.0.0 |
|
|
1675
|
+
| **`purchaseToken`** | <code>string</code> | Purchase token associated with the transaction. Send this to your backend for server-side validation with Google Play Developer API. This is the Android equivalent of iOS's receipt field. | | 1.0.0 |
|
|
1676
|
+
| **`isAcknowledged`** | <code>boolean</code> | Whether the purchase has been acknowledged. Purchases must be acknowledged within 3 days or they will be refunded. By default, this plugin automatically acknowledges purchases unless you set `autoAcknowledgePurchases: false` in purchaseProduct(). | | 1.0.0 |
|
|
1677
|
+
| **`quantity`** | <code>number</code> | Quantity purchased. | <code>1</code> | 1.0.0 |
|
|
1678
|
+
| **`productType`** | <code>string</code> | <a href="#product">Product</a> type. - `"inapp"`: One-time in-app purchase - `"subs"`: Subscription | | 1.0.0 |
|
|
1679
|
+
| **`ownershipType`** | <code>'purchased' \| 'familyShared'</code> | Indicates how the user obtained access to the product. - `"purchased"`: The user purchased the product directly - `"familyShared"`: The user has access through Family Sharing (another family member purchased it) This property is useful for: - Detecting family sharing usage for analytics - Implementing different features/limits for family-shared vs. directly purchased products - Understanding your user acquisition channels | | 7.12.8 |
|
|
1680
|
+
| **`environment`** | <code>'Sandbox' \| 'Production' \| 'Xcode'</code> | Indicates the server environment where the transaction was processed. - `"Sandbox"`: <a href="#transaction">Transaction</a> belongs to testing in the sandbox environment - `"Production"`: <a href="#transaction">Transaction</a> belongs to a customer in the production environment - `"Xcode"`: <a href="#transaction">Transaction</a> from StoreKit Testing in Xcode This property is useful for: - Debugging and identifying test vs. production purchases - Analytics and reporting (filtering out sandbox transactions) - Server-side validation (knowing which Apple endpoint to use) - Preventing test purchases from affecting production metrics | | 7.12.8 |
|
|
1681
|
+
| **`transactionReason`** | <code>'unknown' \| 'purchase' \| 'renewal'</code> | Reason StoreKit generated the transaction. - `"purchase"`: Initial purchase that user made manually - `"renewal"`: Automatically generated renewal for an auto-renewable subscription - `"unknown"`: StoreKit did not return a reason | | 7.13.2 |
|
|
1682
|
+
| **`isTrialPeriod`** | <code>boolean</code> | Whether the transaction is in a trial period. - `true`: Currently in free trial period - `false`: Not in trial period | | 1.0.0 |
|
|
1683
|
+
| **`isInIntroPricePeriod`** | <code>boolean</code> | Whether the transaction is in an introductory price period. Introductory pricing is a discounted rate, different from a free trial. - `true`: Currently using introductory pricing - `false`: Not in intro period | | 1.0.0 |
|
|
1684
|
+
| **`isInGracePeriod`** | <code>boolean</code> | Whether the transaction is in a grace period. Grace period allows users to fix payment issues while maintaining access. You typically want to continue providing access during this time. - `true`: Subscription payment failed but user still has access - `false`: Not in grace period | | 1.0.0 |
|
|
1624
1685
|
|
|
1625
1686
|
|
|
1626
1687
|
#### Product
|
|
@@ -1671,6 +1732,14 @@ Remove all registered listeners
|
|
|
1671
1732
|
| **`remove`** | <code>() => Promise<void></code> |
|
|
1672
1733
|
|
|
1673
1734
|
|
|
1735
|
+
#### TransactionVerificationFailedEvent
|
|
1736
|
+
|
|
1737
|
+
| Prop | Type | Description | Since |
|
|
1738
|
+
| ------------------- | ------------------- | ----------------------------------------------------------- | ------ |
|
|
1739
|
+
| **`transactionId`** | <code>string</code> | Identifier of the transaction that failed verification. | 7.13.2 |
|
|
1740
|
+
| **`error`** | <code>string</code> | Localized error message describing why verification failed. | 7.13.2 |
|
|
1741
|
+
|
|
1742
|
+
|
|
1674
1743
|
### Enums
|
|
1675
1744
|
|
|
1676
1745
|
|
|
@@ -39,7 +39,7 @@ import org.json.JSONArray;
|
|
|
39
39
|
@CapacitorPlugin(name = "NativePurchases")
|
|
40
40
|
public class NativePurchasesPlugin extends Plugin {
|
|
41
41
|
|
|
42
|
-
private final String pluginVersion = "7.
|
|
42
|
+
private final String pluginVersion = "7.14.0";
|
|
43
43
|
public static final String TAG = "NativePurchases";
|
|
44
44
|
private static final Phaser semaphoreReady = new Phaser(1);
|
|
45
45
|
private BillingClient billingClient;
|
|
@@ -121,6 +121,9 @@ public class NativePurchasesPlugin extends Plugin {
|
|
|
121
121
|
if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
|
|
122
122
|
Log.d(TAG, "Purchase state is PURCHASED");
|
|
123
123
|
boolean isConsumable = purchaseCall != null && purchaseCall.getBoolean("isConsumable", false);
|
|
124
|
+
boolean autoAcknowledge = purchaseCall != null ? purchaseCall.getBoolean("autoAcknowledgePurchases", true) : true;
|
|
125
|
+
Log.d(TAG, "Auto-acknowledge enabled: " + autoAcknowledge);
|
|
126
|
+
|
|
124
127
|
PurchaseAction action = PurchaseActionDecider.decide(isConsumable, purchase);
|
|
125
128
|
|
|
126
129
|
AccountIdentifiers accountIdentifiers = purchase.getAccountIdentifiers();
|
|
@@ -134,8 +137,12 @@ public class NativePurchasesPlugin extends Plugin {
|
|
|
134
137
|
billingClient.consumeAsync(consumeParams, this::onConsumeResponse);
|
|
135
138
|
break;
|
|
136
139
|
case ACKNOWLEDGE:
|
|
137
|
-
|
|
138
|
-
|
|
140
|
+
if (autoAcknowledge) {
|
|
141
|
+
Log.d(TAG, "Purchase not acknowledged, auto-acknowledging...");
|
|
142
|
+
acknowledgePurchase(purchase.getPurchaseToken());
|
|
143
|
+
} else {
|
|
144
|
+
Log.d(TAG, "Purchase not acknowledged, but auto-acknowledge is disabled. Developer must manually acknowledge.");
|
|
145
|
+
}
|
|
139
146
|
break;
|
|
140
147
|
case NONE:
|
|
141
148
|
default:
|
|
@@ -316,6 +323,7 @@ public class NativePurchasesPlugin extends Plugin {
|
|
|
316
323
|
String appAccountToken = call.getString("appAccountToken");
|
|
317
324
|
final String accountIdentifier = appAccountToken != null && !appAccountToken.isEmpty() ? appAccountToken : null;
|
|
318
325
|
boolean isConsumable = call.getBoolean("isConsumable", false);
|
|
326
|
+
boolean autoAcknowledgePurchases = call.getBoolean("autoAcknowledgePurchases", true);
|
|
319
327
|
|
|
320
328
|
Log.d(TAG, "Product identifier: " + productIdentifier);
|
|
321
329
|
Log.d(TAG, "Plan identifier: " + planIdentifier);
|
|
@@ -323,6 +331,7 @@ public class NativePurchasesPlugin extends Plugin {
|
|
|
323
331
|
Log.d(TAG, "Quantity: " + quantity);
|
|
324
332
|
Log.d(TAG, "Account identifier provided: " + (accountIdentifier != null ? "[REDACTED]" : "none"));
|
|
325
333
|
Log.d(TAG, "Is consumable: " + isConsumable);
|
|
334
|
+
Log.d(TAG, "Auto-acknowledge purchases: " + autoAcknowledgePurchases);
|
|
326
335
|
|
|
327
336
|
// cannot use quantity, because it's done in native modal
|
|
328
337
|
Log.d("CapacitorPurchases", "purchaseProduct: " + productIdentifier);
|
|
@@ -357,6 +366,7 @@ public class NativePurchasesPlugin extends Plugin {
|
|
|
357
366
|
}
|
|
358
367
|
|
|
359
368
|
call.getData().put("isConsumable", isConsumable);
|
|
369
|
+
call.getData().put("autoAcknowledgePurchases", autoAcknowledgePurchases);
|
|
360
370
|
|
|
361
371
|
// For subscriptions, always use the productIdentifier (subscription ID) to query
|
|
362
372
|
// The planIdentifier is used later when setting the offer token
|
|
@@ -956,4 +966,50 @@ public class NativePurchasesPlugin extends Plugin {
|
|
|
956
966
|
call.reject("Failed to open subscription management page", e);
|
|
957
967
|
}
|
|
958
968
|
}
|
|
969
|
+
|
|
970
|
+
@PluginMethod
|
|
971
|
+
public void acknowledgePurchase(PluginCall call) {
|
|
972
|
+
Log.d(TAG, "acknowledgePurchase() called");
|
|
973
|
+
String purchaseToken = call.getString("purchaseToken");
|
|
974
|
+
|
|
975
|
+
if (purchaseToken == null || purchaseToken.isEmpty()) {
|
|
976
|
+
Log.d(TAG, "Error: purchaseToken is empty");
|
|
977
|
+
call.reject("purchaseToken is required");
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
Log.d(TAG, "Manually acknowledging purchase with token: " + purchaseToken);
|
|
982
|
+
this.initBillingClient(null);
|
|
983
|
+
|
|
984
|
+
try {
|
|
985
|
+
AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
|
|
986
|
+
.setPurchaseToken(purchaseToken)
|
|
987
|
+
.build();
|
|
988
|
+
|
|
989
|
+
billingClient.acknowledgePurchase(
|
|
990
|
+
acknowledgePurchaseParams,
|
|
991
|
+
new AcknowledgePurchaseResponseListener() {
|
|
992
|
+
@Override
|
|
993
|
+
public void onAcknowledgePurchaseResponse(@NonNull BillingResult billingResult) {
|
|
994
|
+
Log.d(TAG, "onAcknowledgePurchaseResponse() called");
|
|
995
|
+
Log.d(TAG, "Acknowledge result: " + billingResult.getResponseCode() + " - " + billingResult.getDebugMessage());
|
|
996
|
+
|
|
997
|
+
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
|
|
998
|
+
Log.d(TAG, "Purchase acknowledged successfully");
|
|
999
|
+
closeBillingClient();
|
|
1000
|
+
call.resolve();
|
|
1001
|
+
} else {
|
|
1002
|
+
Log.d(TAG, "Purchase acknowledgment failed");
|
|
1003
|
+
closeBillingClient();
|
|
1004
|
+
call.reject("Failed to acknowledge purchase: " + billingResult.getDebugMessage());
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
);
|
|
1009
|
+
} catch (Exception e) {
|
|
1010
|
+
Log.d(TAG, "Exception during acknowledgePurchase: " + e.getMessage());
|
|
1011
|
+
closeBillingClient();
|
|
1012
|
+
call.reject(e.getMessage());
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
959
1015
|
}
|