@choochmeque/tauri-plugin-iap-api 0.8.2 → 0.9.1
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 +77 -3
- package/dist-js/index.cjs +42 -9
- package/dist-js/index.d.ts +35 -15
- package/dist-js/index.js +42 -10
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -46,7 +46,7 @@ Add the plugin to your Tauri project's `Cargo.toml`:
|
|
|
46
46
|
|
|
47
47
|
```toml
|
|
48
48
|
[dependencies]
|
|
49
|
-
tauri-plugin-iap = "0.
|
|
49
|
+
tauri-plugin-iap = "0.9"
|
|
50
50
|
```
|
|
51
51
|
|
|
52
52
|
Configure the plugin permissions in your `capabilities/default.json`:
|
|
@@ -112,6 +112,7 @@ import {
|
|
|
112
112
|
purchase,
|
|
113
113
|
restorePurchases,
|
|
114
114
|
acknowledgePurchase,
|
|
115
|
+
consumePurchase,
|
|
115
116
|
getProductStatus,
|
|
116
117
|
onPurchaseUpdated,
|
|
117
118
|
PurchaseState
|
|
@@ -161,9 +162,14 @@ const upgraded = await purchase('premium_subscription', 'subs', {
|
|
|
161
162
|
// Restore purchases (specify product type)
|
|
162
163
|
const restored = await restorePurchases('subs');
|
|
163
164
|
|
|
164
|
-
// Acknowledge a purchase (
|
|
165
|
+
// Acknowledge a non-consumable purchase (subscriptions, durables).
|
|
166
|
+
// No-op on iOS/macOS — StoreKit auto-finishes transactions.
|
|
165
167
|
await acknowledgePurchase(purchaseResult.purchaseToken);
|
|
166
168
|
|
|
169
|
+
// Consume a consumable purchase (credits, coins) so it can be re-bought.
|
|
170
|
+
// No-op on iOS/macOS — StoreKit auto-allows re-purchase.
|
|
171
|
+
await consumePurchase(purchaseResult.purchaseToken);
|
|
172
|
+
|
|
167
173
|
// Listen for purchase updates
|
|
168
174
|
const listener = await onPurchaseUpdated((purchase) => {
|
|
169
175
|
console.log('Purchase updated:', purchase);
|
|
@@ -173,6 +179,49 @@ const listener = await onPurchaseUpdated((purchase) => {
|
|
|
173
179
|
await listener.unregister();
|
|
174
180
|
```
|
|
175
181
|
|
|
182
|
+
### Rust
|
|
183
|
+
|
|
184
|
+
```rust
|
|
185
|
+
use tauri_plugin_iap::{IapExt, PurchaseRequest, PurchaseStateValue, Result};
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
// Get available products
|
|
189
|
+
let products = app.iap()
|
|
190
|
+
.get_products(
|
|
191
|
+
vec!["subscription_id_1".into(), "subscription_id_2".into()],
|
|
192
|
+
"subs".into(),
|
|
193
|
+
)
|
|
194
|
+
.await?;
|
|
195
|
+
|
|
196
|
+
// Check if user owns a specific product
|
|
197
|
+
let status = app.iap()
|
|
198
|
+
.get_product_status("subscription_id_1".into(), "subs".into())
|
|
199
|
+
.await?;
|
|
200
|
+
if status.is_owned && status.purchase_state == Some(PurchaseStateValue::Purchased) {
|
|
201
|
+
println!("User has active subscription");
|
|
202
|
+
if status.is_auto_renewing == Some(true) {
|
|
203
|
+
println!("Subscription will auto-renew");
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Purchase a subscription or in-app product
|
|
208
|
+
// Simple purchase (will use first available offer on Android if not specified)
|
|
209
|
+
let purchase_result = app.iap()
|
|
210
|
+
.purchase(PurchaseRequest {
|
|
211
|
+
product_id: "subscription_id_1".into(),
|
|
212
|
+
product_type: "subs".into(),
|
|
213
|
+
options: None,
|
|
214
|
+
})
|
|
215
|
+
.await?;
|
|
216
|
+
|
|
217
|
+
// Restore purchases (specify product type)
|
|
218
|
+
let restored = app.iap().restore_purchases("subs".into()).await?;
|
|
219
|
+
|
|
220
|
+
// Acknowledge a non-consumable purchase (subscriptions, durables).
|
|
221
|
+
// No-op on iOS/macOS — StoreKit auto-finishes transactions.
|
|
222
|
+
app.iap().acknowledge_purchase(purchase_result.purchase_token).await?;
|
|
223
|
+
```
|
|
224
|
+
|
|
176
225
|
## Platform Setup
|
|
177
226
|
|
|
178
227
|
### iOS Setup
|
|
@@ -276,7 +325,10 @@ Queries and returns all active purchases.
|
|
|
276
325
|
Returns the complete purchase history.
|
|
277
326
|
|
|
278
327
|
### `acknowledgePurchase(purchaseToken: string)`
|
|
279
|
-
Acknowledges a purchase (
|
|
328
|
+
Acknowledges a non-consumable purchase (subscriptions, durables). On Android this is required within 3 days or Google auto-refunds the purchase. No-op on iOS, macOS, and Windows. Use `consumePurchase` instead for consumables.
|
|
329
|
+
|
|
330
|
+
### `consumePurchase(purchaseToken: string)`
|
|
331
|
+
Consumes a consumable purchase (credits, coins, gems) so it can be purchased again. On Android calls `BillingClient.consumeAsync()`; on Windows calls `StoreContext.ReportConsumableFulfillmentAsync` with quantity 1. No-op on iOS and macOS — StoreKit auto-allows re-purchase. Never call both `acknowledgePurchase` and `consumePurchase` for the same purchase token.
|
|
280
332
|
|
|
281
333
|
### `getProductStatus(productId: string, productType: 'subs' | 'inapp' = 'subs')`
|
|
282
334
|
Checks the ownership and subscription status of a specific product.
|
|
@@ -351,6 +403,28 @@ Listens for purchase state changes.
|
|
|
351
403
|
3. App must be code-signed to use StoreKit
|
|
352
404
|
4. Clear purchase history in System Settings > App Store > Sandbox Account
|
|
353
405
|
|
|
406
|
+
## Troubleshooting
|
|
407
|
+
|
|
408
|
+
<details>
|
|
409
|
+
<summary><code>dyld: Library not loaded: @rpath/libswift_Concurrency.dylib</code></summary>
|
|
410
|
+
|
|
411
|
+
This error occurs when `MACOSX_DEPLOYMENT_TARGET` is below 13.0. Tauri defaults to 11.0 in debug mode.
|
|
412
|
+
|
|
413
|
+
**Option 1:** Add `.cargo/config.toml` to your project:
|
|
414
|
+
|
|
415
|
+
```toml
|
|
416
|
+
[env]
|
|
417
|
+
MACOSX_DEPLOYMENT_TARGET = "13.0"
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
**Option 2:** Set the environment variable when running:
|
|
421
|
+
|
|
422
|
+
```bash
|
|
423
|
+
MACOSX_DEPLOYMENT_TARGET="13.0" pnpm tauri dev
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
</details>
|
|
427
|
+
|
|
354
428
|
## License
|
|
355
429
|
|
|
356
430
|
[MIT](LICENSE)
|
package/dist-js/index.cjs
CHANGED
|
@@ -138,22 +138,54 @@ async function getPurchaseHistory() {
|
|
|
138
138
|
return await core.invoke("plugin:iap|get_purchase_history");
|
|
139
139
|
}
|
|
140
140
|
/**
|
|
141
|
-
* Acknowledge a purchase (
|
|
142
|
-
*
|
|
143
|
-
*
|
|
141
|
+
* Acknowledge a non-consumable purchase (subscriptions, durable products).
|
|
142
|
+
*
|
|
143
|
+
* On Android this calls `BillingClient.acknowledgePurchase()` and is required
|
|
144
|
+
* within 3 days of purchase or Google will auto-refund. On iOS, macOS, and
|
|
145
|
+
* Windows this is a no-op — those stores handle acknowledgment automatically.
|
|
146
|
+
*
|
|
147
|
+
* For consumable products (credits, coins, gems) call {@link consumePurchase}
|
|
148
|
+
* instead. Never call both for the same purchase token.
|
|
144
149
|
*
|
|
145
150
|
* @param purchaseToken - Purchase token from the transaction
|
|
146
|
-
* @
|
|
151
|
+
* @throws Rejects if acknowledgment fails (e.g., Android billing client error)
|
|
147
152
|
* @example
|
|
148
153
|
* ```typescript
|
|
149
|
-
*
|
|
150
|
-
* if (result.success) {
|
|
151
|
-
* console.log('Purchase acknowledged');
|
|
152
|
-
* }
|
|
154
|
+
* await acknowledgePurchase(purchase.purchaseToken);
|
|
153
155
|
* ```
|
|
154
156
|
*/
|
|
155
157
|
async function acknowledgePurchase(purchaseToken) {
|
|
156
|
-
|
|
158
|
+
await core.invoke("plugin:iap|acknowledge_purchase", {
|
|
159
|
+
payload: {
|
|
160
|
+
purchaseToken,
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Consume a purchased consumable product so it can be purchased again.
|
|
166
|
+
*
|
|
167
|
+
* On Android this calls `BillingClient.consumeAsync()`, which acknowledges the
|
|
168
|
+
* purchase and removes ownership from the user's account. On Windows this calls
|
|
169
|
+
* `StoreContext.ReportConsumableFulfillmentAsync` with quantity 1. On iOS and
|
|
170
|
+
* macOS this is a no-op — StoreKit auto-allows re-purchase once `purchase()`
|
|
171
|
+
* has finished the transaction.
|
|
172
|
+
*
|
|
173
|
+
* Use this for consumables (credits, coins, gems). For non-consumables and
|
|
174
|
+
* subscriptions call {@link acknowledgePurchase} instead. Never call both for
|
|
175
|
+
* the same purchase token.
|
|
176
|
+
*
|
|
177
|
+
* @param purchaseToken - Purchase token from the transaction
|
|
178
|
+
* @throws Rejects if consumption fails (e.g., Android billing client error,
|
|
179
|
+
* Windows network/server error, or invalid token on Windows)
|
|
180
|
+
* @example
|
|
181
|
+
* ```typescript
|
|
182
|
+
* const result = await purchase('credits_100', 'inapp');
|
|
183
|
+
* await consumePurchase(result.purchaseToken);
|
|
184
|
+
* // user can now buy credits_100 again
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
async function consumePurchase(purchaseToken) {
|
|
188
|
+
await core.invoke("plugin:iap|consume_purchase", {
|
|
157
189
|
payload: {
|
|
158
190
|
purchaseToken,
|
|
159
191
|
},
|
|
@@ -209,6 +241,7 @@ async function onPurchaseUpdated(callback) {
|
|
|
209
241
|
}
|
|
210
242
|
|
|
211
243
|
exports.acknowledgePurchase = acknowledgePurchase;
|
|
244
|
+
exports.consumePurchase = consumePurchase;
|
|
212
245
|
exports.getProductStatus = getProductStatus;
|
|
213
246
|
exports.getProducts = getProducts;
|
|
214
247
|
exports.getPurchaseHistory = getPurchaseHistory;
|
package/dist-js/index.d.ts
CHANGED
|
@@ -104,12 +104,6 @@ export interface PurchaseHistoryRecord {
|
|
|
104
104
|
export interface GetPurchaseHistoryResponse {
|
|
105
105
|
history: PurchaseHistoryRecord[];
|
|
106
106
|
}
|
|
107
|
-
/**
|
|
108
|
-
* Response from acknowledging a purchase
|
|
109
|
-
*/
|
|
110
|
-
export interface AcknowledgePurchaseResponse {
|
|
111
|
-
success: boolean;
|
|
112
|
-
}
|
|
113
107
|
/**
|
|
114
108
|
* Purchase state enumeration
|
|
115
109
|
*/
|
|
@@ -259,21 +253,47 @@ export declare function restorePurchases(productType?: "subs" | "inapp"): Promis
|
|
|
259
253
|
*/
|
|
260
254
|
export declare function getPurchaseHistory(): Promise<GetPurchaseHistoryResponse>;
|
|
261
255
|
/**
|
|
262
|
-
* Acknowledge a purchase (
|
|
263
|
-
*
|
|
264
|
-
*
|
|
256
|
+
* Acknowledge a non-consumable purchase (subscriptions, durable products).
|
|
257
|
+
*
|
|
258
|
+
* On Android this calls `BillingClient.acknowledgePurchase()` and is required
|
|
259
|
+
* within 3 days of purchase or Google will auto-refund. On iOS, macOS, and
|
|
260
|
+
* Windows this is a no-op — those stores handle acknowledgment automatically.
|
|
261
|
+
*
|
|
262
|
+
* For consumable products (credits, coins, gems) call {@link consumePurchase}
|
|
263
|
+
* instead. Never call both for the same purchase token.
|
|
265
264
|
*
|
|
266
265
|
* @param purchaseToken - Purchase token from the transaction
|
|
267
|
-
* @
|
|
266
|
+
* @throws Rejects if acknowledgment fails (e.g., Android billing client error)
|
|
268
267
|
* @example
|
|
269
268
|
* ```typescript
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
|
|
273
|
-
|
|
269
|
+
* await acknowledgePurchase(purchase.purchaseToken);
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
export declare function acknowledgePurchase(purchaseToken: string): Promise<void>;
|
|
273
|
+
/**
|
|
274
|
+
* Consume a purchased consumable product so it can be purchased again.
|
|
275
|
+
*
|
|
276
|
+
* On Android this calls `BillingClient.consumeAsync()`, which acknowledges the
|
|
277
|
+
* purchase and removes ownership from the user's account. On Windows this calls
|
|
278
|
+
* `StoreContext.ReportConsumableFulfillmentAsync` with quantity 1. On iOS and
|
|
279
|
+
* macOS this is a no-op — StoreKit auto-allows re-purchase once `purchase()`
|
|
280
|
+
* has finished the transaction.
|
|
281
|
+
*
|
|
282
|
+
* Use this for consumables (credits, coins, gems). For non-consumables and
|
|
283
|
+
* subscriptions call {@link acknowledgePurchase} instead. Never call both for
|
|
284
|
+
* the same purchase token.
|
|
285
|
+
*
|
|
286
|
+
* @param purchaseToken - Purchase token from the transaction
|
|
287
|
+
* @throws Rejects if consumption fails (e.g., Android billing client error,
|
|
288
|
+
* Windows network/server error, or invalid token on Windows)
|
|
289
|
+
* @example
|
|
290
|
+
* ```typescript
|
|
291
|
+
* const result = await purchase('credits_100', 'inapp');
|
|
292
|
+
* await consumePurchase(result.purchaseToken);
|
|
293
|
+
* // user can now buy credits_100 again
|
|
274
294
|
* ```
|
|
275
295
|
*/
|
|
276
|
-
export declare function
|
|
296
|
+
export declare function consumePurchase(purchaseToken: string): Promise<void>;
|
|
277
297
|
/**
|
|
278
298
|
* Get the current status of a product for the user.
|
|
279
299
|
* Checks if the product is owned, expired, or available for purchase.
|
package/dist-js/index.js
CHANGED
|
@@ -136,22 +136,54 @@ async function getPurchaseHistory() {
|
|
|
136
136
|
return await invoke("plugin:iap|get_purchase_history");
|
|
137
137
|
}
|
|
138
138
|
/**
|
|
139
|
-
* Acknowledge a purchase (
|
|
140
|
-
*
|
|
141
|
-
*
|
|
139
|
+
* Acknowledge a non-consumable purchase (subscriptions, durable products).
|
|
140
|
+
*
|
|
141
|
+
* On Android this calls `BillingClient.acknowledgePurchase()` and is required
|
|
142
|
+
* within 3 days of purchase or Google will auto-refund. On iOS, macOS, and
|
|
143
|
+
* Windows this is a no-op — those stores handle acknowledgment automatically.
|
|
144
|
+
*
|
|
145
|
+
* For consumable products (credits, coins, gems) call {@link consumePurchase}
|
|
146
|
+
* instead. Never call both for the same purchase token.
|
|
142
147
|
*
|
|
143
148
|
* @param purchaseToken - Purchase token from the transaction
|
|
144
|
-
* @
|
|
149
|
+
* @throws Rejects if acknowledgment fails (e.g., Android billing client error)
|
|
145
150
|
* @example
|
|
146
151
|
* ```typescript
|
|
147
|
-
*
|
|
148
|
-
* if (result.success) {
|
|
149
|
-
* console.log('Purchase acknowledged');
|
|
150
|
-
* }
|
|
152
|
+
* await acknowledgePurchase(purchase.purchaseToken);
|
|
151
153
|
* ```
|
|
152
154
|
*/
|
|
153
155
|
async function acknowledgePurchase(purchaseToken) {
|
|
154
|
-
|
|
156
|
+
await invoke("plugin:iap|acknowledge_purchase", {
|
|
157
|
+
payload: {
|
|
158
|
+
purchaseToken,
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Consume a purchased consumable product so it can be purchased again.
|
|
164
|
+
*
|
|
165
|
+
* On Android this calls `BillingClient.consumeAsync()`, which acknowledges the
|
|
166
|
+
* purchase and removes ownership from the user's account. On Windows this calls
|
|
167
|
+
* `StoreContext.ReportConsumableFulfillmentAsync` with quantity 1. On iOS and
|
|
168
|
+
* macOS this is a no-op — StoreKit auto-allows re-purchase once `purchase()`
|
|
169
|
+
* has finished the transaction.
|
|
170
|
+
*
|
|
171
|
+
* Use this for consumables (credits, coins, gems). For non-consumables and
|
|
172
|
+
* subscriptions call {@link acknowledgePurchase} instead. Never call both for
|
|
173
|
+
* the same purchase token.
|
|
174
|
+
*
|
|
175
|
+
* @param purchaseToken - Purchase token from the transaction
|
|
176
|
+
* @throws Rejects if consumption fails (e.g., Android billing client error,
|
|
177
|
+
* Windows network/server error, or invalid token on Windows)
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* const result = await purchase('credits_100', 'inapp');
|
|
181
|
+
* await consumePurchase(result.purchaseToken);
|
|
182
|
+
* // user can now buy credits_100 again
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
async function consumePurchase(purchaseToken) {
|
|
186
|
+
await invoke("plugin:iap|consume_purchase", {
|
|
155
187
|
payload: {
|
|
156
188
|
purchaseToken,
|
|
157
189
|
},
|
|
@@ -206,4 +238,4 @@ async function onPurchaseUpdated(callback) {
|
|
|
206
238
|
return await addPluginListener("iap", "purchaseUpdated", callback);
|
|
207
239
|
}
|
|
208
240
|
|
|
209
|
-
export { PurchaseState, SubscriptionReplacementMode, acknowledgePurchase, getProductStatus, getProducts, getPurchaseHistory, initialize, onPurchaseUpdated, purchase, restorePurchases };
|
|
241
|
+
export { PurchaseState, SubscriptionReplacementMode, acknowledgePurchase, consumePurchase, 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.9.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "You",
|
|
6
6
|
"description": "A Tauri v2 plugin that enables In-App Purchases (IAP)",
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
"@vitest/coverage-v8": "^4.0.13",
|
|
41
41
|
"@vitest/ui": "^4.0.13",
|
|
42
42
|
"happy-dom": "^20.0.10",
|
|
43
|
-
"prettier": "3.8.
|
|
43
|
+
"prettier": "3.8.3",
|
|
44
44
|
"rollup": "^4.9.6",
|
|
45
45
|
"tslib": "^2.6.2",
|
|
46
|
-
"typescript": "^
|
|
46
|
+
"typescript": "^6.0.2",
|
|
47
47
|
"vitest": "^4.0.13"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|