@choochmeque/tauri-plugin-iap-api 0.4.4 → 0.5.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/LICENSE +2 -2
- package/README.md +24 -7
- package/dist-js/index.cjs +5 -11
- package/dist-js/index.d.ts +26 -5
- package/dist-js/index.js +6 -12
- package/package.json +11 -3
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
3
|
+
Copyright (c) 2025 Vladimir Pankratov
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
[](https://www.npmjs.com/package/@choochmeque/tauri-plugin-iap-api)
|
|
2
2
|
[](https://crates.io/crates/tauri-plugin-iap)
|
|
3
|
+
[](https://github.com/Choochmeque/tauri-plugin-iap/actions/workflows/tests.yml)
|
|
4
|
+
[](https://codecov.io/gh/Choochmeque/tauri-plugin-iap)
|
|
3
5
|
[](LICENSE)
|
|
4
6
|
|
|
5
7
|
# Tauri Plugin IAP
|
|
6
8
|
|
|
7
|
-
A Tauri plugin for In-App Purchases (IAP) with support for subscriptions on iOS (StoreKit 2), Android (Google Play Billing)
|
|
9
|
+
A Tauri plugin for In-App Purchases (IAP) with support for subscriptions on iOS (StoreKit 2), Android (Google Play Billing), Windows (Microsoft Store) and macOS (StoreKit 2).
|
|
8
10
|
|
|
9
11
|
## Features
|
|
10
12
|
|
|
@@ -26,7 +28,7 @@ A Tauri plugin for In-App Purchases (IAP) with support for subscriptions on iOS
|
|
|
26
28
|
- **iOS**: StoreKit 2 (requires iOS 15.0+)
|
|
27
29
|
- **Android**: Google Play Billing Library v8.0.0
|
|
28
30
|
- **Windows**: Microsoft Store API (Windows 10/11)
|
|
29
|
-
- **macOS**:
|
|
31
|
+
- **macOS**: StoreKit 2 (requires macOS 13.0+)
|
|
30
32
|
|
|
31
33
|
## Installation
|
|
32
34
|
|
|
@@ -44,7 +46,7 @@ Add the plugin to your Tauri project's `Cargo.toml`:
|
|
|
44
46
|
|
|
45
47
|
```toml
|
|
46
48
|
[dependencies]
|
|
47
|
-
tauri-plugin-iap = "0.
|
|
49
|
+
tauri-plugin-iap = "0.5"
|
|
48
50
|
```
|
|
49
51
|
|
|
50
52
|
Configure the plugin permissions in your `capabilities/default.json`:
|
|
@@ -82,7 +84,7 @@ import {
|
|
|
82
84
|
getProductStatus,
|
|
83
85
|
onPurchaseUpdated,
|
|
84
86
|
PurchaseState
|
|
85
|
-
} from 'tauri-plugin-iap-api';
|
|
87
|
+
} from '@choochmeque/tauri-plugin-iap-api';
|
|
86
88
|
|
|
87
89
|
// Initialize the billing client
|
|
88
90
|
await initialize();
|
|
@@ -126,12 +128,12 @@ const restored = await restorePurchases('subs');
|
|
|
126
128
|
await acknowledgePurchase(purchaseResult.purchaseToken);
|
|
127
129
|
|
|
128
130
|
// Listen for purchase updates
|
|
129
|
-
const
|
|
131
|
+
const listener = await onPurchaseUpdated((purchase) => {
|
|
130
132
|
console.log('Purchase updated:', purchase);
|
|
131
133
|
});
|
|
132
134
|
|
|
133
135
|
// Stop listening
|
|
134
|
-
|
|
136
|
+
await listener.unregister();
|
|
135
137
|
```
|
|
136
138
|
|
|
137
139
|
## Platform Setup
|
|
@@ -221,9 +223,11 @@ Checks the ownership and subscription status of a specific product.
|
|
|
221
223
|
- `isAcknowledged`: Whether the purchase has been acknowledged
|
|
222
224
|
- `purchaseToken`: Token for the purchase transaction
|
|
223
225
|
|
|
224
|
-
### `onPurchaseUpdated(callback: (purchase: Purchase) => void)
|
|
226
|
+
### `onPurchaseUpdated(callback: (purchase: Purchase) => void): Promise<PluginListener>`
|
|
225
227
|
Listens for purchase state changes.
|
|
226
228
|
|
|
229
|
+
**Returns:** A `PluginListener` object with an `unregister()` method to stop listening.
|
|
230
|
+
|
|
227
231
|
## Differences Between Platforms
|
|
228
232
|
|
|
229
233
|
### iOS (StoreKit 2)
|
|
@@ -244,6 +248,13 @@ Listens for purchase state changes.
|
|
|
244
248
|
- Supports consumables, durables, and subscriptions
|
|
245
249
|
- Uses SKUs for subscription offer variations
|
|
246
250
|
|
|
251
|
+
### macOS (StoreKit 2)
|
|
252
|
+
- Same StoreKit 2 API as iOS
|
|
253
|
+
- Automatic transaction verification
|
|
254
|
+
- No manual acknowledgment needed
|
|
255
|
+
- Requires macOS 13.0+
|
|
256
|
+
- App must be code-signed (StoreKit requires valid signature)
|
|
257
|
+
|
|
247
258
|
## Testing
|
|
248
259
|
|
|
249
260
|
### iOS
|
|
@@ -262,6 +273,12 @@ Listens for purchase state changes.
|
|
|
262
273
|
3. Test with Windows Dev Center test payment methods
|
|
263
274
|
4. Ensure app is associated with Store listing
|
|
264
275
|
|
|
276
|
+
### macOS
|
|
277
|
+
1. Use sandbox test accounts (same as iOS)
|
|
278
|
+
2. Use StoreKit Configuration files for local testing
|
|
279
|
+
3. App must be code-signed to use StoreKit
|
|
280
|
+
4. Clear purchase history in System Settings > App Store > Sandbox Account
|
|
281
|
+
|
|
265
282
|
## License
|
|
266
283
|
|
|
267
284
|
[MIT](LICENSE)
|
package/dist-js/index.cjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var core = require('@tauri-apps/api/core');
|
|
4
|
-
var event = require('@tauri-apps/api/event');
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Purchase state enumeration
|
|
@@ -173,10 +172,10 @@ async function getProductStatus(productId, productType = "subs") {
|
|
|
173
172
|
* This event is triggered when a purchase state changes.
|
|
174
173
|
*
|
|
175
174
|
* @param callback - Function to call when a purchase is updated
|
|
176
|
-
* @returns
|
|
175
|
+
* @returns Promise resolving to a PluginListener that can be used to stop listening
|
|
177
176
|
* @example
|
|
178
177
|
* ```typescript
|
|
179
|
-
* const
|
|
178
|
+
* const listener = await onPurchaseUpdated((purchase) => {
|
|
180
179
|
* console.log(`Purchase updated: ${purchase.productId}`);
|
|
181
180
|
* if (purchase.purchaseState === PurchaseState.PURCHASED) {
|
|
182
181
|
* // Handle successful purchase
|
|
@@ -184,16 +183,11 @@ async function getProductStatus(productId, productType = "subs") {
|
|
|
184
183
|
* });
|
|
185
184
|
*
|
|
186
185
|
* // Later, stop listening
|
|
187
|
-
*
|
|
186
|
+
* await listener.unregister();
|
|
188
187
|
* ```
|
|
189
188
|
*/
|
|
190
|
-
function onPurchaseUpdated(callback) {
|
|
191
|
-
|
|
192
|
-
callback(event.payload);
|
|
193
|
-
});
|
|
194
|
-
return () => {
|
|
195
|
-
unlisten.then((fn) => fn());
|
|
196
|
-
};
|
|
189
|
+
async function onPurchaseUpdated(callback) {
|
|
190
|
+
return await core.addPluginListener("iap", "purchaseUpdated", callback);
|
|
197
191
|
}
|
|
198
192
|
|
|
199
193
|
exports.acknowledgePurchase = acknowledgePurchase;
|
package/dist-js/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PluginListener } from "@tauri-apps/api/core";
|
|
1
2
|
/**
|
|
2
3
|
* Response from IAP initialization
|
|
3
4
|
*/
|
|
@@ -28,13 +29,21 @@ export interface SubscriptionOffer {
|
|
|
28
29
|
* Product information from the app store
|
|
29
30
|
*/
|
|
30
31
|
export interface Product {
|
|
32
|
+
/** Unique product identifier as configured in the app store */
|
|
31
33
|
productId: string;
|
|
34
|
+
/** Localized product title */
|
|
32
35
|
title: string;
|
|
36
|
+
/** Localized product description */
|
|
33
37
|
description: string;
|
|
38
|
+
/** Type of product: "subs" for subscriptions, "inapp" for one-time purchases */
|
|
34
39
|
productType: string;
|
|
40
|
+
/** Localized price string with currency symbol (e.g., "$9.99") */
|
|
35
41
|
formattedPrice?: string;
|
|
42
|
+
/** ISO 4217 currency code (e.g., "USD", "EUR") */
|
|
36
43
|
priceCurrencyCode?: string;
|
|
44
|
+
/** Price in micros (price × 1,000,000). For example, $9.99 = 9990000 */
|
|
37
45
|
priceAmountMicros?: number;
|
|
46
|
+
/** Subscription offer details including pricing phases. (Android only) */
|
|
38
47
|
subscriptionOfferDetails?: SubscriptionOffer[];
|
|
39
48
|
}
|
|
40
49
|
/**
|
|
@@ -47,16 +56,28 @@ export interface GetProductsResponse {
|
|
|
47
56
|
* Purchase transaction information
|
|
48
57
|
*/
|
|
49
58
|
export interface Purchase {
|
|
59
|
+
/** Unique order identifier from the store. May be undefined for pending purchases. */
|
|
50
60
|
orderId?: string;
|
|
61
|
+
/** Application package name (Android) or bundle identifier (iOS/macOS) */
|
|
51
62
|
packageName: string;
|
|
63
|
+
/** Product identifier that was purchased */
|
|
52
64
|
productId: string;
|
|
65
|
+
/** Unix timestamp (milliseconds) when the purchase was made */
|
|
53
66
|
purchaseTime: number;
|
|
67
|
+
/** Token used to identify this purchase for acknowledgment and server-side verification */
|
|
54
68
|
purchaseToken: string;
|
|
55
|
-
|
|
69
|
+
/** Current state of the purchase. */
|
|
70
|
+
purchaseState: PurchaseState;
|
|
71
|
+
/** Whether this subscription is set to auto-renew. Always false for one-time purchases. */
|
|
56
72
|
isAutoRenewing: boolean;
|
|
73
|
+
/** Whether the purchase has been acknowledged. Unacknowledged purchases are refunded after 3 days. (Android only, always true on iOS/macOS) */
|
|
57
74
|
isAcknowledged: boolean;
|
|
75
|
+
/** Raw JSON response from the store for server-side verification. (Android only) */
|
|
58
76
|
originalJson: string;
|
|
77
|
+
/** Cryptographic signature for purchase verification. (Android only) */
|
|
59
78
|
signature: string;
|
|
79
|
+
/** Original transaction ID. Used to link renewals and restores to the original purchase. (iOS/macOS only) */
|
|
80
|
+
originalId?: string;
|
|
60
81
|
}
|
|
61
82
|
/**
|
|
62
83
|
* Response containing restored purchases
|
|
@@ -244,10 +265,10 @@ export declare function getProductStatus(productId: string, productType?: "subs"
|
|
|
244
265
|
* This event is triggered when a purchase state changes.
|
|
245
266
|
*
|
|
246
267
|
* @param callback - Function to call when a purchase is updated
|
|
247
|
-
* @returns
|
|
268
|
+
* @returns Promise resolving to a PluginListener that can be used to stop listening
|
|
248
269
|
* @example
|
|
249
270
|
* ```typescript
|
|
250
|
-
* const
|
|
271
|
+
* const listener = await onPurchaseUpdated((purchase) => {
|
|
251
272
|
* console.log(`Purchase updated: ${purchase.productId}`);
|
|
252
273
|
* if (purchase.purchaseState === PurchaseState.PURCHASED) {
|
|
253
274
|
* // Handle successful purchase
|
|
@@ -255,7 +276,7 @@ export declare function getProductStatus(productId: string, productType?: "subs"
|
|
|
255
276
|
* });
|
|
256
277
|
*
|
|
257
278
|
* // Later, stop listening
|
|
258
|
-
*
|
|
279
|
+
* await listener.unregister();
|
|
259
280
|
* ```
|
|
260
281
|
*/
|
|
261
|
-
export declare function onPurchaseUpdated(callback: (purchase: Purchase) => void):
|
|
282
|
+
export declare function onPurchaseUpdated(callback: (purchase: Purchase) => void): Promise<PluginListener>;
|
package/dist-js/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { invoke } from '@tauri-apps/api/core';
|
|
2
|
-
import { listen } from '@tauri-apps/api/event';
|
|
1
|
+
import { invoke, addPluginListener } from '@tauri-apps/api/core';
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* Purchase state enumeration
|
|
@@ -171,10 +170,10 @@ async function getProductStatus(productId, productType = "subs") {
|
|
|
171
170
|
* This event is triggered when a purchase state changes.
|
|
172
171
|
*
|
|
173
172
|
* @param callback - Function to call when a purchase is updated
|
|
174
|
-
* @returns
|
|
173
|
+
* @returns Promise resolving to a PluginListener that can be used to stop listening
|
|
175
174
|
* @example
|
|
176
175
|
* ```typescript
|
|
177
|
-
* const
|
|
176
|
+
* const listener = await onPurchaseUpdated((purchase) => {
|
|
178
177
|
* console.log(`Purchase updated: ${purchase.productId}`);
|
|
179
178
|
* if (purchase.purchaseState === PurchaseState.PURCHASED) {
|
|
180
179
|
* // Handle successful purchase
|
|
@@ -182,16 +181,11 @@ async function getProductStatus(productId, productType = "subs") {
|
|
|
182
181
|
* });
|
|
183
182
|
*
|
|
184
183
|
* // Later, stop listening
|
|
185
|
-
*
|
|
184
|
+
* await listener.unregister();
|
|
186
185
|
* ```
|
|
187
186
|
*/
|
|
188
|
-
function onPurchaseUpdated(callback) {
|
|
189
|
-
|
|
190
|
-
callback(event.payload);
|
|
191
|
-
});
|
|
192
|
-
return () => {
|
|
193
|
-
unlisten.then((fn) => fn());
|
|
194
|
-
};
|
|
187
|
+
async function onPurchaseUpdated(callback) {
|
|
188
|
+
return await addPluginListener("iap", "purchaseUpdated", callback);
|
|
195
189
|
}
|
|
196
190
|
|
|
197
191
|
export { PurchaseState, acknowledgePurchase, getProductStatus, getProducts, getPurchaseHistory, initialize, onPurchaseUpdated, purchase, restorePurchases };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@choochmeque/tauri-plugin-iap-api",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "You",
|
|
6
6
|
"description": "A Tauri v2 plugin that enables In-App Purchases (IAP)",
|
|
@@ -37,15 +37,23 @@
|
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@rollup/plugin-typescript": "^12.1.4",
|
|
40
|
+
"@vitest/coverage-v8": "^4.0.13",
|
|
41
|
+
"@vitest/ui": "^4.0.13",
|
|
42
|
+
"happy-dom": "^20.0.10",
|
|
43
|
+
"prettier": "3.6.2",
|
|
40
44
|
"rollup": "^4.9.6",
|
|
41
45
|
"tslib": "^2.6.2",
|
|
42
46
|
"typescript": "^5.3.3",
|
|
43
|
-
"
|
|
47
|
+
"vitest": "^4.0.13"
|
|
44
48
|
},
|
|
45
49
|
"scripts": {
|
|
46
50
|
"build": "rollup -c",
|
|
47
51
|
"pretest": "pnpm build",
|
|
52
|
+
"test": "vitest run",
|
|
53
|
+
"test:watch": "vitest",
|
|
54
|
+
"test:ui": "vitest --ui",
|
|
55
|
+
"test:coverage": "vitest run --coverage",
|
|
48
56
|
"format": "prettier --write \"./**/*.{cjs,mjs,js,jsx,mts,ts,tsx,html,css,json}\"",
|
|
49
|
-
"format
|
|
57
|
+
"format:check": "prettier --check \"./**/*.{cjs,mjs,js,jsx,mts,ts,tsx,html,css,json}\""
|
|
50
58
|
}
|
|
51
59
|
}
|