@nosslabs/iap 5.0.0 → 7.0.0-next.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/CHANGELOG.md +43 -13
- package/README.md +7 -7
- package/dist/index.cjs +108 -233
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -7
- package/dist/index.d.ts +6 -7
- package/dist/index.js +108 -233
- package/dist/index.js.map +1 -1
- package/package.json +12 -11
package/dist/index.d.cts
CHANGED
|
@@ -968,9 +968,7 @@ interface IAP<TEntitlement extends EntitlementBase = EntitlementBase> {
|
|
|
968
968
|
*/
|
|
969
969
|
refresh(): Promise<void>;
|
|
970
970
|
/**
|
|
971
|
-
* Tear down. Removes event listeners and disposes the native adapter
|
|
972
|
-
* (which clears its `pendingFinish` map and removes the long-lived
|
|
973
|
-
* `.approved()` listener on cdv).
|
|
971
|
+
* Tear down. Removes event listeners and disposes the native adapter.
|
|
974
972
|
*
|
|
975
973
|
* NOTE 1: persisted entitlement cache is NOT cleared. If you're handling
|
|
976
974
|
* a logout for a multi-user app, also call your storage adapter's
|
|
@@ -980,10 +978,11 @@ interface IAP<TEntitlement extends EntitlementBase = EntitlementBase> {
|
|
|
980
978
|
*
|
|
981
979
|
* NOTE 2: calling `destroy()` while a `purchase()` is in flight may
|
|
982
980
|
* leave the result in an inconsistent state — the backend may have
|
|
983
|
-
* recorded the entitlement but the native `acknowledge()` call
|
|
984
|
-
*
|
|
985
|
-
*
|
|
986
|
-
* awaiting the in-flight
|
|
981
|
+
* recorded the entitlement but the native `acknowledge()` call may not
|
|
982
|
+
* have run yet. On Android this means Google auto-refunds in 3 days
|
|
983
|
+
* (the unfinished-transaction recovery on the next launch re-acks, but
|
|
984
|
+
* only if it runs within that window). Avoid by awaiting the in-flight
|
|
985
|
+
* `purchase()` before calling `destroy()`.
|
|
987
986
|
*/
|
|
988
987
|
destroy(): Promise<void>;
|
|
989
988
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -968,9 +968,7 @@ interface IAP<TEntitlement extends EntitlementBase = EntitlementBase> {
|
|
|
968
968
|
*/
|
|
969
969
|
refresh(): Promise<void>;
|
|
970
970
|
/**
|
|
971
|
-
* Tear down. Removes event listeners and disposes the native adapter
|
|
972
|
-
* (which clears its `pendingFinish` map and removes the long-lived
|
|
973
|
-
* `.approved()` listener on cdv).
|
|
971
|
+
* Tear down. Removes event listeners and disposes the native adapter.
|
|
974
972
|
*
|
|
975
973
|
* NOTE 1: persisted entitlement cache is NOT cleared. If you're handling
|
|
976
974
|
* a logout for a multi-user app, also call your storage adapter's
|
|
@@ -980,10 +978,11 @@ interface IAP<TEntitlement extends EntitlementBase = EntitlementBase> {
|
|
|
980
978
|
*
|
|
981
979
|
* NOTE 2: calling `destroy()` while a `purchase()` is in flight may
|
|
982
980
|
* leave the result in an inconsistent state — the backend may have
|
|
983
|
-
* recorded the entitlement but the native `acknowledge()` call
|
|
984
|
-
*
|
|
985
|
-
*
|
|
986
|
-
* awaiting the in-flight
|
|
981
|
+
* recorded the entitlement but the native `acknowledge()` call may not
|
|
982
|
+
* have run yet. On Android this means Google auto-refunds in 3 days
|
|
983
|
+
* (the unfinished-transaction recovery on the next launch re-acks, but
|
|
984
|
+
* only if it runs within that window). Avoid by awaiting the in-flight
|
|
985
|
+
* `purchase()` before calling `destroy()`.
|
|
987
986
|
*/
|
|
988
987
|
destroy(): Promise<void>;
|
|
989
988
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Capacitor } from '@capacitor/core';
|
|
2
|
-
import '
|
|
2
|
+
import { NativePurchases, PURCHASE_TYPE } from '@capgo/native-purchases';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { Preferences } from '@capacitor/preferences';
|
|
5
5
|
|
|
@@ -83,7 +83,7 @@ var init_errors = __esm({
|
|
|
83
83
|
NOT_INITIALIZED: "Call iap.initialize() before this method, or recreate the instance after destroy().",
|
|
84
84
|
// Native plugin
|
|
85
85
|
PLATFORM_NOT_SUPPORTED: "In-app purchases run on iOS/Android only. Web is no-op by design \u2014 guard your purchase UI behind Capacitor.isNativePlatform().",
|
|
86
|
-
BILLING_NOT_AVAILABLE: "
|
|
86
|
+
BILLING_NOT_AVAILABLE: "The store billing service is unavailable. Confirm @capgo/native-purchases is installed and `npx cap sync` has run; check the device sandbox/test account is signed in.",
|
|
87
87
|
PRODUCT_NOT_FOUND: "Ensure the productId is registered in App Store Connect / Play Console AND in your createIAP({ products }) config.",
|
|
88
88
|
USER_CANCELLED: "No action needed \u2014 the user dismissed the native purchase sheet.",
|
|
89
89
|
PURCHASE_PENDING: "Android only: payment is awaiting external clearance (e.g. cash payment, bank verification). The backend will receive a Google RTDN webhook when it clears; call iap.refresh() afterward.",
|
|
@@ -137,295 +137,170 @@ var init_platform = __esm({
|
|
|
137
137
|
}
|
|
138
138
|
});
|
|
139
139
|
|
|
140
|
-
// src/adapters/native/
|
|
140
|
+
// src/adapters/native/capgo/native-adapter.ts
|
|
141
141
|
var native_adapter_exports = {};
|
|
142
142
|
__export(native_adapter_exports, {
|
|
143
|
-
|
|
143
|
+
CapgoNativeAdapter: () => CapgoNativeAdapter
|
|
144
144
|
});
|
|
145
|
-
function getCdv() {
|
|
146
|
-
const candidate = globalThis.CdvPurchase;
|
|
147
|
-
if (!candidate || !candidate.store) {
|
|
148
|
-
throw new IAPError({
|
|
149
|
-
code: IAPErrorCode.BILLING_NOT_AVAILABLE,
|
|
150
|
-
message: "cordova-plugin-purchase is not available. Ensure the plugin is installed and `npx cap sync` has run."
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
return candidate;
|
|
154
|
-
}
|
|
155
|
-
function currentCdvPlatform() {
|
|
156
|
-
const cdv = getCdv();
|
|
157
|
-
const platform = getPlatform();
|
|
158
|
-
if (platform === "android") return cdv.Platform.GOOGLE_PLAY;
|
|
159
|
-
return cdv.Platform.APPLE_APPSTORE;
|
|
160
|
-
}
|
|
161
|
-
function mapProductType(type) {
|
|
162
|
-
const cdv = getCdv();
|
|
163
|
-
switch (type) {
|
|
164
|
-
case "subscription":
|
|
165
|
-
return cdv.ProductType.PAID_SUBSCRIPTION;
|
|
166
|
-
case "consumable":
|
|
167
|
-
return cdv.ProductType.CONSUMABLE;
|
|
168
|
-
default:
|
|
169
|
-
return cdv.ProductType.NON_CONSUMABLE;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
function inferProductType(tx, configured) {
|
|
173
|
-
const id = tx.products[0]?.id;
|
|
174
|
-
if (!id) return "product";
|
|
175
|
-
const match = configured.find((p) => p.id === id);
|
|
176
|
-
return match?.type ?? "product";
|
|
177
|
-
}
|
|
178
145
|
function normalizeProduct(p, type) {
|
|
179
|
-
const
|
|
180
|
-
const phase = offer?.pricingPhases?.[0];
|
|
181
|
-
const priceMicros = phase?.priceMicros?.toString() ?? "0";
|
|
182
|
-
const priceString = phase?.price ?? "";
|
|
183
|
-
const currency = phase?.currency ?? "";
|
|
146
|
+
const priceMicros = Math.round(p.price * 1e6).toString();
|
|
184
147
|
return {
|
|
185
|
-
id: p.
|
|
148
|
+
id: p.identifier,
|
|
186
149
|
type,
|
|
187
|
-
title: p.title
|
|
188
|
-
description: p.description
|
|
189
|
-
priceString,
|
|
150
|
+
title: p.title,
|
|
151
|
+
description: p.description,
|
|
152
|
+
priceString: p.priceString,
|
|
190
153
|
priceMicros,
|
|
191
|
-
currency
|
|
154
|
+
currency: p.currencyCode
|
|
192
155
|
};
|
|
193
156
|
}
|
|
194
|
-
function normalizeTransaction(tx, productType
|
|
195
|
-
const platform = tx
|
|
196
|
-
const
|
|
197
|
-
const
|
|
157
|
+
function normalizeTransaction(tx, productType) {
|
|
158
|
+
const platform = inferPlatform(tx);
|
|
159
|
+
const token = platform === "google" ? tx.purchaseToken ?? tx.transactionId : tx.transactionId;
|
|
160
|
+
const native = {
|
|
198
161
|
platform,
|
|
199
|
-
productId,
|
|
162
|
+
productId: tx.productIdentifier,
|
|
200
163
|
token,
|
|
201
164
|
productType,
|
|
202
165
|
raw: tx
|
|
203
166
|
};
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
167
|
+
return native;
|
|
168
|
+
}
|
|
169
|
+
function inferPlatform(tx) {
|
|
170
|
+
if (tx.purchaseToken !== void 0 || tx.purchaseState !== void 0 || tx.orderId !== void 0) {
|
|
171
|
+
return "google";
|
|
172
|
+
}
|
|
173
|
+
if (tx.receipt !== void 0 || tx.jwsRepresentation !== void 0) {
|
|
174
|
+
return "apple";
|
|
207
175
|
}
|
|
208
|
-
return
|
|
176
|
+
return getPlatform() === "android" ? "google" : "apple";
|
|
209
177
|
}
|
|
210
|
-
function
|
|
211
|
-
|
|
212
|
-
return
|
|
178
|
+
function inferProductType(tx) {
|
|
179
|
+
if (tx.productType === "subs") return "subscription";
|
|
180
|
+
return "product";
|
|
213
181
|
}
|
|
214
|
-
function
|
|
215
|
-
|
|
216
|
-
return tx.transactionId || null;
|
|
217
|
-
}
|
|
218
|
-
const googleTx = tx;
|
|
219
|
-
return googleTx.nativePurchase?.purchaseToken ?? googleTx.parentReceipt?.purchaseToken ?? tx.transactionId ?? null;
|
|
182
|
+
function mapToPluginPurchaseType(type) {
|
|
183
|
+
return type === "subscription" ? PURCHASE_TYPE.SUBS : PURCHASE_TYPE.INAPP;
|
|
220
184
|
}
|
|
221
|
-
function
|
|
222
|
-
|
|
223
|
-
const
|
|
224
|
-
|
|
185
|
+
function mapPurchaseError(error, productId) {
|
|
186
|
+
if (error instanceof IAPError) return error;
|
|
187
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
188
|
+
const lower = message.toLowerCase();
|
|
189
|
+
if (lower.includes("cancel")) {
|
|
225
190
|
return new IAPError({
|
|
226
191
|
code: IAPErrorCode.USER_CANCELLED,
|
|
227
|
-
message:
|
|
228
|
-
cause:
|
|
192
|
+
message: `Purchase of "${productId}" was cancelled.`,
|
|
193
|
+
cause: error
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
if (lower.includes("pending")) {
|
|
197
|
+
return new IAPError({
|
|
198
|
+
code: IAPErrorCode.PURCHASE_PENDING,
|
|
199
|
+
message: `Purchase of "${productId}" is pending external clearance.`,
|
|
200
|
+
cause: error
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
if (lower.includes("product not found")) {
|
|
204
|
+
return new IAPError({
|
|
205
|
+
code: IAPErrorCode.PRODUCT_NOT_FOUND,
|
|
206
|
+
message: `Product "${productId}" was not found in the store catalog.`,
|
|
207
|
+
cause: error
|
|
229
208
|
});
|
|
230
209
|
}
|
|
231
210
|
return new IAPError({
|
|
232
211
|
code: IAPErrorCode.STORE_ERROR,
|
|
233
|
-
message:
|
|
234
|
-
cause:
|
|
212
|
+
message: `Native purchase of "${productId}" failed.`,
|
|
213
|
+
cause: error
|
|
235
214
|
});
|
|
236
215
|
}
|
|
237
|
-
var
|
|
216
|
+
var CapgoNativeAdapter;
|
|
238
217
|
var init_native_adapter = __esm({
|
|
239
|
-
"src/adapters/native/
|
|
218
|
+
"src/adapters/native/capgo/native-adapter.ts"() {
|
|
240
219
|
init_errors();
|
|
241
220
|
init_platform();
|
|
242
|
-
|
|
243
|
-
products;
|
|
244
|
-
bootstrapped = false;
|
|
245
|
-
bootstrapping = null;
|
|
246
|
-
pendingFinish = /* @__PURE__ */ new Map();
|
|
247
|
-
/** Long-lived bootstrap-time .approved() listener — kept for dispose(). */
|
|
248
|
-
bootstrapApprovedHandler = null;
|
|
249
|
-
constructor(opts) {
|
|
250
|
-
this.products = opts.products;
|
|
251
|
-
}
|
|
221
|
+
CapgoNativeAdapter = class {
|
|
252
222
|
async isAvailable() {
|
|
253
223
|
try {
|
|
254
|
-
await
|
|
255
|
-
return
|
|
224
|
+
const result = await NativePurchases.isBillingSupported();
|
|
225
|
+
return result.isBillingSupported;
|
|
256
226
|
} catch {
|
|
257
227
|
return false;
|
|
258
228
|
}
|
|
259
229
|
}
|
|
260
230
|
async getProducts(requests) {
|
|
261
231
|
if (requests.length === 0) return [];
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
const
|
|
232
|
+
const inappIds = [];
|
|
233
|
+
const subsIds = [];
|
|
234
|
+
const requestById = /* @__PURE__ */ new Map();
|
|
265
235
|
for (const req of requests) {
|
|
266
|
-
|
|
267
|
-
if (
|
|
268
|
-
|
|
236
|
+
requestById.set(req.id, req.type);
|
|
237
|
+
if (req.type === "subscription") {
|
|
238
|
+
subsIds.push(req.id);
|
|
239
|
+
} else {
|
|
240
|
+
inappIds.push(req.id);
|
|
241
|
+
}
|
|
269
242
|
}
|
|
270
|
-
|
|
243
|
+
const [inapp, subs] = await Promise.all([
|
|
244
|
+
inappIds.length > 0 ? NativePurchases.getProducts({
|
|
245
|
+
productIdentifiers: inappIds,
|
|
246
|
+
productType: PURCHASE_TYPE.INAPP
|
|
247
|
+
}) : Promise.resolve({ products: [] }),
|
|
248
|
+
subsIds.length > 0 ? NativePurchases.getProducts({
|
|
249
|
+
productIdentifiers: subsIds,
|
|
250
|
+
productType: PURCHASE_TYPE.SUBS
|
|
251
|
+
}) : Promise.resolve({ products: [] })
|
|
252
|
+
]);
|
|
253
|
+
const all = [...inapp.products, ...subs.products];
|
|
254
|
+
return all.map((p) => normalizeProduct(p, requestById.get(p.identifier) ?? "product"));
|
|
271
255
|
}
|
|
272
256
|
async purchaseProduct(opts) {
|
|
273
|
-
const
|
|
274
|
-
const
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
code: IAPErrorCode.PRODUCT_NOT_FOUND,
|
|
285
|
-
message: `Product "${opts.productId}" has no purchasable offer${opts.androidPlanId ? ` (planId="${opts.androidPlanId}")` : ""}.`
|
|
257
|
+
const purchaseType = mapToPluginPurchaseType(opts.productType);
|
|
258
|
+
const isConsumable = opts.productType === "consumable";
|
|
259
|
+
let tx;
|
|
260
|
+
try {
|
|
261
|
+
tx = await NativePurchases.purchaseProduct({
|
|
262
|
+
productIdentifier: opts.productId,
|
|
263
|
+
productType: purchaseType,
|
|
264
|
+
planIdentifier: opts.androidPlanId,
|
|
265
|
+
appAccountToken: opts.appAccountToken,
|
|
266
|
+
isConsumable,
|
|
267
|
+
autoAcknowledgePurchases: false
|
|
286
268
|
});
|
|
269
|
+
} catch (error) {
|
|
270
|
+
throw mapPurchaseError(error, opts.productId);
|
|
287
271
|
}
|
|
288
|
-
return
|
|
289
|
-
let settled = false;
|
|
290
|
-
const cleanup = () => {
|
|
291
|
-
store.off(handleApproved);
|
|
292
|
-
};
|
|
293
|
-
const handleApproved = (tx) => {
|
|
294
|
-
if (settled) return;
|
|
295
|
-
if (!tx.products.some((p) => p.id === opts.productId)) return;
|
|
296
|
-
const token = transactionToken(tx);
|
|
297
|
-
if (!token) {
|
|
298
|
-
settled = true;
|
|
299
|
-
cleanup();
|
|
300
|
-
reject(
|
|
301
|
-
new IAPError({
|
|
302
|
-
code: IAPErrorCode.STORE_ERROR,
|
|
303
|
-
message: `Approved transaction for "${opts.productId}" has no token; cannot verify.`
|
|
304
|
-
})
|
|
305
|
-
);
|
|
306
|
-
return;
|
|
307
|
-
}
|
|
308
|
-
settled = true;
|
|
309
|
-
cleanup();
|
|
310
|
-
const normalized = normalizeTransaction(tx, opts.productType, token);
|
|
311
|
-
this.pendingFinish.set(token, tx);
|
|
312
|
-
resolve(normalized);
|
|
313
|
-
};
|
|
314
|
-
store.when().approved(handleApproved);
|
|
315
|
-
const additionalData = opts.appAccountToken ? { applicationUsername: opts.appAccountToken } : void 0;
|
|
316
|
-
void Promise.resolve(offer.order(additionalData)).then((err) => {
|
|
317
|
-
if (settled) return;
|
|
318
|
-
if (!err) return;
|
|
319
|
-
settled = true;
|
|
320
|
-
cleanup();
|
|
321
|
-
reject(mapOrderError(err, opts.productId));
|
|
322
|
-
}).catch((cause) => {
|
|
323
|
-
if (settled) return;
|
|
324
|
-
settled = true;
|
|
325
|
-
cleanup();
|
|
326
|
-
reject(
|
|
327
|
-
new IAPError({
|
|
328
|
-
code: IAPErrorCode.STORE_ERROR,
|
|
329
|
-
message: `order() rejected for ${opts.productId}.`,
|
|
330
|
-
cause
|
|
331
|
-
})
|
|
332
|
-
);
|
|
333
|
-
});
|
|
334
|
-
});
|
|
272
|
+
return normalizeTransaction(tx, opts.productType);
|
|
335
273
|
}
|
|
336
274
|
async getOwnedTransactions() {
|
|
337
|
-
const
|
|
338
|
-
|
|
339
|
-
const out = [];
|
|
340
|
-
for (const tx of store.localTransactions) {
|
|
341
|
-
if (tx.state !== getCdv().TransactionState.APPROVED) continue;
|
|
342
|
-
const token = transactionToken(tx);
|
|
343
|
-
if (!token) continue;
|
|
344
|
-
const normalized = normalizeTransaction(tx, inferProductType(tx, this.products), token);
|
|
345
|
-
this.pendingFinish.set(token, tx);
|
|
346
|
-
out.push(normalized);
|
|
347
|
-
}
|
|
348
|
-
return out;
|
|
275
|
+
const result = await NativePurchases.getPurchases();
|
|
276
|
+
return result.purchases.filter((tx) => tx.purchaseState === void 0 || tx.purchaseState === "1").map((tx) => normalizeTransaction(tx, inferProductType(tx)));
|
|
349
277
|
}
|
|
350
278
|
async acknowledge(transaction) {
|
|
351
|
-
const cdvTx = this.pendingFinish.get(transaction.token);
|
|
352
|
-
if (!cdvTx) {
|
|
353
|
-
return;
|
|
354
|
-
}
|
|
355
279
|
try {
|
|
356
|
-
await
|
|
357
|
-
|
|
280
|
+
await NativePurchases.acknowledgePurchase({
|
|
281
|
+
purchaseToken: transaction.token
|
|
282
|
+
});
|
|
283
|
+
} catch (error) {
|
|
358
284
|
throw new IAPError({
|
|
359
285
|
code: IAPErrorCode.STORE_ERROR,
|
|
360
|
-
message: `Failed to
|
|
361
|
-
cause,
|
|
286
|
+
message: `Failed to acknowledge transaction for ${transaction.productId}.`,
|
|
287
|
+
cause: error,
|
|
362
288
|
recoverable: true
|
|
363
289
|
});
|
|
364
290
|
}
|
|
365
|
-
this.pendingFinish.delete(transaction.token);
|
|
366
291
|
}
|
|
367
292
|
async manageSubscriptions() {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
293
|
+
try {
|
|
294
|
+
await NativePurchases.manageSubscriptions();
|
|
295
|
+
} catch (error) {
|
|
371
296
|
throw new IAPError({
|
|
372
297
|
code: IAPErrorCode.STORE_ERROR,
|
|
373
|
-
message:
|
|
298
|
+
message: "Failed to open the native subscription management UI.",
|
|
299
|
+
cause: error
|
|
374
300
|
});
|
|
375
301
|
}
|
|
376
302
|
}
|
|
377
303
|
async dispose() {
|
|
378
|
-
if (this.bootstrapApprovedHandler) {
|
|
379
|
-
try {
|
|
380
|
-
const cdv = globalThis.CdvPurchase;
|
|
381
|
-
cdv?.store?.off(this.bootstrapApprovedHandler);
|
|
382
|
-
} catch {
|
|
383
|
-
}
|
|
384
|
-
this.bootstrapApprovedHandler = null;
|
|
385
|
-
}
|
|
386
|
-
this.pendingFinish.clear();
|
|
387
|
-
this.bootstrapped = false;
|
|
388
|
-
this.bootstrapping = null;
|
|
389
|
-
}
|
|
390
|
-
// ----- internals -----
|
|
391
|
-
async ensureStore() {
|
|
392
|
-
await this.bootstrap();
|
|
393
|
-
return getCdv().store;
|
|
394
|
-
}
|
|
395
|
-
bootstrap() {
|
|
396
|
-
if (this.bootstrapped) return Promise.resolve();
|
|
397
|
-
if (this.bootstrapping) return this.bootstrapping;
|
|
398
|
-
this.bootstrapping = (async () => {
|
|
399
|
-
const cdv = getCdv();
|
|
400
|
-
const platform = currentCdvPlatform();
|
|
401
|
-
cdv.store.register(
|
|
402
|
-
this.products.map((p) => ({
|
|
403
|
-
id: p.id,
|
|
404
|
-
type: mapProductType(p.type),
|
|
405
|
-
platform
|
|
406
|
-
}))
|
|
407
|
-
);
|
|
408
|
-
const errors = await cdv.store.initialize([platform]);
|
|
409
|
-
if (errors && errors.length > 0) {
|
|
410
|
-
const first = errors[0];
|
|
411
|
-
throw new IAPError({
|
|
412
|
-
code: IAPErrorCode.BILLING_NOT_AVAILABLE,
|
|
413
|
-
message: first?.message ?? "cordova-plugin-purchase initialize() reported errors."
|
|
414
|
-
});
|
|
415
|
-
}
|
|
416
|
-
const handler = (tx) => {
|
|
417
|
-
const token = transactionToken(tx);
|
|
418
|
-
if (!token) return;
|
|
419
|
-
if (!this.pendingFinish.has(token)) {
|
|
420
|
-
this.pendingFinish.set(token, tx);
|
|
421
|
-
}
|
|
422
|
-
};
|
|
423
|
-
this.bootstrapApprovedHandler = handler;
|
|
424
|
-
cdv.store.when().approved(handler);
|
|
425
|
-
await cdv.store.update();
|
|
426
|
-
this.bootstrapped = true;
|
|
427
|
-
})();
|
|
428
|
-
return this.bootstrapping;
|
|
429
304
|
}
|
|
430
305
|
};
|
|
431
306
|
}
|
|
@@ -958,11 +833,11 @@ var WebStubAdapter = class {
|
|
|
958
833
|
};
|
|
959
834
|
|
|
960
835
|
// src/adapters/native/index.ts
|
|
961
|
-
async function selectNativeAdapter(
|
|
836
|
+
async function selectNativeAdapter() {
|
|
962
837
|
const platform = getPlatform();
|
|
963
838
|
if (platform === "ios" || platform === "android") {
|
|
964
839
|
const mod = await Promise.resolve().then(() => (init_native_adapter(), native_adapter_exports));
|
|
965
|
-
return new mod.
|
|
840
|
+
return new mod.CapgoNativeAdapter();
|
|
966
841
|
}
|
|
967
842
|
return new WebStubAdapter();
|
|
968
843
|
}
|
|
@@ -1900,7 +1775,7 @@ function createIAP(input) {
|
|
|
1900
1775
|
state.products = Object.freeze([...validated.data]);
|
|
1901
1776
|
state.logger.debug(`Resolved ${validated.data.length} product(s) from backend manifest.`);
|
|
1902
1777
|
}
|
|
1903
|
-
state.adapter = await selectNativeAdapter(
|
|
1778
|
+
state.adapter = await selectNativeAdapter();
|
|
1904
1779
|
const configGetAuthHeaders = state.config.backend.getAuthHeaders;
|
|
1905
1780
|
const getAuthHeaders = configGetAuthHeaders ? async () => configGetAuthHeaders() : async () => ({});
|
|
1906
1781
|
const sharedDeps = {
|