capacitor-plugin-cdv-purchase 13.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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["esm/index.js","../build/entry.mjs"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\n// Set the marker so the shared store.js knows Capacitor native bridges are available\nif (typeof window !== 'undefined') {\n window.CdvPurchaseCapacitor = { installed: true };\n}\nconst PurchasePlugin = registerPlugin('PurchasePlugin');\nexport { PurchasePlugin };\n","// Capacitor bridge — sets CdvPurchaseCapacitor marker and registers native plugin\nexport { PurchasePlugin } from '../dist/esm/index.js';\n\n// Store runtime — executes the IIFE, creates window.CdvPurchase\nimport { CdvPurchase } from 'virtual:store-js';\n\n// Re-export the full namespace\nexport { CdvPurchase };\n\n// Convenience named exports\nexport const store = CdvPurchase.store;\nexport const Store = CdvPurchase.Store;\nexport const ProductType = CdvPurchase.ProductType;\nexport const Platform = CdvPurchase.Platform;\nexport const LogLevel = CdvPurchase.LogLevel;\nexport const ErrorCode = CdvPurchase.ErrorCode;\nexport const Logger = CdvPurchase.Logger;\nexport const Iaptic = CdvPurchase.Iaptic;\n"],"names":[],"mappings":";;AACA;AACA,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE;AACnC,IAAI,MAAM,CAAC,oBAAoB,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE;AACrD;AACK,MAAC,cAAc,GAAG,cAAc,CAAC,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACLtD;;AASA;AACY,MAAC,KAAK,GAAG,WAAW,CAAC;AACrB,MAAC,KAAK,GAAG,WAAW,CAAC;AACrB,MAAC,WAAW,GAAG,WAAW,CAAC;AAC3B,MAAC,QAAQ,GAAG,WAAW,CAAC;AACxB,MAAC,QAAQ,GAAG,WAAW,CAAC;AACxB,MAAC,SAAS,GAAG,WAAW,CAAC;AACzB,MAAC,MAAM,GAAG,WAAW,CAAC;AACtB,MAAC,MAAM,GAAG,WAAW,CAAC;;;;"}
@@ -0,0 +1,18 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'CapacitorPluginCdvPurchase'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.license = package['license']
10
+ s.homepage = package['repository']['url']
11
+ s.author = 'Jean-Christophe Hoelt'
12
+ s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
+ s.source_files = 'Sources/PurchasePlugin/**/*.{swift,h,m}'
14
+ s.ios.deployment_target = '13.0'
15
+ s.swift_version = '5.9'
16
+ s.dependency 'Capacitor'
17
+ s.frameworks = 'StoreKit'
18
+ end
@@ -0,0 +1,434 @@
1
+ import Foundation
2
+ import Capacitor
3
+ import StoreKit
4
+
5
+ @available(iOS 15.0, *)
6
+ private class SK2State {
7
+ var products: [String: Product] = [:]
8
+ var unfinishedTransactions: [String: Transaction] = [:]
9
+ var transactionObserverTask: Task<Void, Never>?
10
+ }
11
+
12
+ @objc(PurchasePlugin)
13
+ public class PurchasePlugin: CAPPlugin, CAPBridgedPlugin {
14
+
15
+ public let identifier = "PurchasePlugin"
16
+ public let jsName = "PurchasePlugin"
17
+ public let pluginMethods: [CAPPluginMethod] = [
18
+ CAPPluginMethod(name: "init", returnType: CAPPluginReturnPromise),
19
+ CAPPluginMethod(name: "load", returnType: CAPPluginReturnPromise),
20
+ CAPPluginMethod(name: "purchase", returnType: CAPPluginReturnPromise),
21
+ CAPPluginMethod(name: "finish", returnType: CAPPluginReturnPromise),
22
+ CAPPluginMethod(name: "canMakePayments", returnType: CAPPluginReturnPromise),
23
+ CAPPluginMethod(name: "restore", returnType: CAPPluginReturnPromise),
24
+ CAPPluginMethod(name: "manageSubscriptions", returnType: CAPPluginReturnPromise),
25
+ CAPPluginMethod(name: "manageBilling", returnType: CAPPluginReturnPromise),
26
+ CAPPluginMethod(name: "presentCodeRedemptionSheet", returnType: CAPPluginReturnPromise),
27
+ CAPPluginMethod(name: "refreshReceipts", returnType: CAPPluginReturnPromise),
28
+ CAPPluginMethod(name: "loadReceipts", returnType: CAPPluginReturnPromise),
29
+ ]
30
+
31
+ private var _sk2State: AnyObject?
32
+ private var debugEnabled = false
33
+
34
+ @available(iOS 15.0, *)
35
+ private var sk2: SK2State {
36
+ if let s = _sk2State as? SK2State { return s }
37
+ let s = SK2State()
38
+ _sk2State = s
39
+ return s
40
+ }
41
+
42
+ // MARK: - Lifecycle
43
+
44
+ override public func load() {
45
+ if #available(iOS 15.0, *) {
46
+ startTransactionObserver()
47
+ }
48
+ }
49
+
50
+ deinit {
51
+ if #available(iOS 15.0, *) {
52
+ sk2.transactionObserverTask?.cancel()
53
+ }
54
+ }
55
+
56
+ @available(iOS 15.0, *)
57
+ private func startTransactionObserver() {
58
+ sk2.transactionObserverTask = Task.detached { [weak self] in
59
+ for await result in Transaction.updates {
60
+ guard let self = self else { return }
61
+ await self.handleTransactionUpdate(result)
62
+ }
63
+ }
64
+ }
65
+
66
+ @available(iOS 15.0, *)
67
+ private func handleTransactionUpdate(_ result: VerificationResult<Transaction>) async {
68
+ let jwsRepresentation = result.jwsRepresentation
69
+ switch result {
70
+ case .verified(let transaction):
71
+ await emitTransactionUpdate(transaction, state: "PaymentTransactionStatePurchased",
72
+ jwsRepresentation: jwsRepresentation)
73
+ case .unverified(let transaction, _):
74
+ // Emit as Purchased — let JS layer handle verification
75
+ await emitTransactionUpdate(transaction, state: "PaymentTransactionStatePurchased",
76
+ jwsRepresentation: jwsRepresentation)
77
+ }
78
+ }
79
+
80
+ // MARK: - Plugin Methods
81
+
82
+ @objc func `init`(_ call: CAPPluginCall) {
83
+ guard #available(iOS 15.0, *) else {
84
+ call.reject("In-app purchases require iOS 15.0 or later")
85
+ return
86
+ }
87
+ debugEnabled = call.getBool("debug", false)
88
+ debugLog("init")
89
+
90
+ // Process any pending transactions
91
+ Task {
92
+ for await result in Transaction.currentEntitlements {
93
+ if case .verified(let transaction) = result {
94
+ self.sk2.unfinishedTransactions[String(transaction.id)] = transaction
95
+ }
96
+ }
97
+ call.resolve()
98
+ }
99
+ }
100
+
101
+ @objc func load(_ call: CAPPluginCall) {
102
+ guard #available(iOS 15.0, *) else {
103
+ call.reject("In-app purchases require iOS 15.0 or later")
104
+ return
105
+ }
106
+ guard let productIds = call.getArray("productIds") as? [String] else {
107
+ call.reject("productIds is required")
108
+ return
109
+ }
110
+ debugLog("load: \(productIds)")
111
+
112
+ Task {
113
+ do {
114
+ let storeProducts = try await Product.products(for: Set(productIds))
115
+ var validProducts: [[String: Any]] = []
116
+ var validIds = Set<String>()
117
+
118
+ for product in storeProducts {
119
+ sk2.products[product.id] = product
120
+ validProducts.append(productToDict(product))
121
+ validIds.insert(product.id)
122
+ }
123
+
124
+ let invalidIds = productIds.filter { !validIds.contains($0) }
125
+
126
+ call.resolve([
127
+ "validProducts": validProducts,
128
+ "invalidProductIds": invalidIds
129
+ ])
130
+ } catch {
131
+ call.reject("Failed to load products: \(error.localizedDescription)")
132
+ }
133
+ }
134
+ }
135
+
136
+ @objc func purchase(_ call: CAPPluginCall) {
137
+ guard #available(iOS 15.0, *) else {
138
+ call.reject("In-app purchases require iOS 15.0 or later")
139
+ return
140
+ }
141
+ guard let productId = call.getString("productId") else {
142
+ call.reject("productId is required")
143
+ return
144
+ }
145
+ debugLog("purchase: \(productId)")
146
+
147
+ guard let product = sk2.products[productId] else {
148
+ call.reject("Product not loaded: \(productId)")
149
+ return
150
+ }
151
+
152
+ Task {
153
+ do {
154
+ var options: Set<Product.PurchaseOption> = []
155
+ if let username = call.getString("applicationUsername") {
156
+ options.insert(.appAccountToken(
157
+ UUID(uuidString: username) ?? UUID()))
158
+ }
159
+
160
+ let result = try await product.purchase(options: options)
161
+ switch result {
162
+ case .success(let verification):
163
+ let jwsRepresentation = verification.jwsRepresentation
164
+ switch verification {
165
+ case .verified(let transaction):
166
+ await emitTransactionUpdate(transaction,
167
+ state: "PaymentTransactionStatePurchased",
168
+ jwsRepresentation: jwsRepresentation)
169
+ case .unverified(let transaction, _):
170
+ // Emit as Purchased — let JS handle verification
171
+ await emitTransactionUpdate(transaction,
172
+ state: "PaymentTransactionStatePurchased",
173
+ jwsRepresentation: jwsRepresentation)
174
+ }
175
+ call.resolve()
176
+ case .userCancelled:
177
+ notifyListeners("transactionUpdated", data: [
178
+ "state": "PaymentTransactionStateFailed",
179
+ "errorCode": 6777006,
180
+ "errorText": "Payment cancelled",
181
+ "productId": productId,
182
+ "transactionIdentifier": "",
183
+ ])
184
+ call.resolve()
185
+ case .pending:
186
+ notifyListeners("transactionUpdated", data: [
187
+ "state": "PaymentTransactionStateDeferred",
188
+ "productId": productId,
189
+ "transactionIdentifier": "",
190
+ ])
191
+ call.resolve()
192
+ @unknown default:
193
+ call.reject("Unknown purchase result")
194
+ }
195
+ } catch {
196
+ call.reject("Purchase failed: \(error.localizedDescription)")
197
+ }
198
+ }
199
+ }
200
+
201
+ @objc func finish(_ call: CAPPluginCall) {
202
+ guard #available(iOS 15.0, *) else {
203
+ call.reject("In-app purchases require iOS 15.0 or later")
204
+ return
205
+ }
206
+ guard let transactionId = call.getString("transactionId") else {
207
+ call.reject("transactionId is required")
208
+ return
209
+ }
210
+ debugLog("finish: \(transactionId)")
211
+
212
+ Task {
213
+ if let transaction = sk2.unfinishedTransactions[transactionId] {
214
+ await transaction.finish()
215
+ sk2.unfinishedTransactions.removeValue(forKey: transactionId)
216
+ notifyListeners("transactionUpdated", data: [
217
+ "state": "PaymentTransactionStateFinished",
218
+ "transactionIdentifier": transactionId,
219
+ "productId": transaction.productID,
220
+ ])
221
+ }
222
+ call.resolve()
223
+ }
224
+ }
225
+
226
+ @objc func canMakePayments(_ call: CAPPluginCall) {
227
+ guard #available(iOS 15.0, *) else {
228
+ call.resolve(["canMakePayments": false])
229
+ return
230
+ }
231
+ call.resolve(["canMakePayments": AppStore.canMakePayments])
232
+ }
233
+
234
+ @objc func restore(_ call: CAPPluginCall) {
235
+ guard #available(iOS 15.0, *) else {
236
+ call.reject("In-app purchases require iOS 15.0 or later")
237
+ return
238
+ }
239
+ debugLog("restore")
240
+ Task {
241
+ do {
242
+ try await AppStore.sync()
243
+ for await result in Transaction.currentEntitlements {
244
+ if case .verified(let transaction) = result {
245
+ await emitTransactionUpdate(transaction,
246
+ state: "PaymentTransactionStateRestored",
247
+ jwsRepresentation: result.jwsRepresentation)
248
+ }
249
+ }
250
+ notifyListeners("restoreCompleted", data: [:])
251
+ call.resolve()
252
+ } catch {
253
+ notifyListeners("restoreFailed", data: ["errorCode": 0])
254
+ call.reject("Restore failed: \(error.localizedDescription)")
255
+ }
256
+ }
257
+ }
258
+
259
+ @objc func manageSubscriptions(_ call: CAPPluginCall) {
260
+ guard #available(iOS 15.0, *) else {
261
+ call.reject("Managing subscriptions requires iOS 15.0 or later")
262
+ return
263
+ }
264
+ Task { @MainActor in
265
+ if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
266
+ try? await AppStore.showManageSubscriptions(in: scene)
267
+ }
268
+ call.resolve()
269
+ }
270
+ }
271
+
272
+ @objc func manageBilling(_ call: CAPPluginCall) {
273
+ // No direct equivalent in SK2; resolve silently
274
+ call.resolve()
275
+ }
276
+
277
+ @objc func presentCodeRedemptionSheet(_ call: CAPPluginCall) {
278
+ Task { @MainActor in
279
+ if #available(iOS 16.0, *) {
280
+ if let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene {
281
+ try? await AppStore.presentOfferCodeRedeemSheet(in: scene)
282
+ }
283
+ }
284
+ call.resolve()
285
+ }
286
+ }
287
+
288
+ @objc func refreshReceipts(_ call: CAPPluginCall) {
289
+ guard #available(iOS 16.0, *) else {
290
+ call.reject("refreshReceipts requires iOS 16.0 or later")
291
+ return
292
+ }
293
+ Task {
294
+ do {
295
+ let appTransaction = try await AppTransaction.shared
296
+ switch appTransaction {
297
+ case .verified(let transaction):
298
+ call.resolve(["receipt": [
299
+ "bundleIdentifier": transaction.bundleID,
300
+ "appVersion": transaction.appVersion,
301
+ ]])
302
+ case .unverified(_, _):
303
+ call.reject("App transaction verification failed")
304
+ }
305
+ } catch {
306
+ call.reject("Failed to refresh receipts: \(error.localizedDescription)")
307
+ }
308
+ }
309
+ }
310
+
311
+ @objc func loadReceipts(_ call: CAPPluginCall) {
312
+ // Same as refreshReceipts for SK2
313
+ refreshReceipts(call)
314
+ }
315
+
316
+ // MARK: - Helpers
317
+
318
+ @available(iOS 15.0, *)
319
+ private func emitTransactionUpdate(_ transaction: Transaction, state: String,
320
+ errorCode: Int? = nil, errorText: String? = nil,
321
+ jwsRepresentation: String? = nil) async {
322
+ let transactionId = String(transaction.id)
323
+ sk2.unfinishedTransactions[transactionId] = transaction
324
+
325
+ var data: [String: Any] = [
326
+ "state": state,
327
+ "transactionIdentifier": transactionId,
328
+ "productId": transaction.productID,
329
+ ]
330
+
331
+ if let errorCode = errorCode { data["errorCode"] = errorCode }
332
+ if let errorText = errorText { data["errorText"] = errorText }
333
+ // Only set originalTransactionIdentifier when it differs from the current ID
334
+ if transaction.originalID != transaction.id {
335
+ data["originalTransactionIdentifier"] = String(transaction.originalID)
336
+ }
337
+ // Use milliseconds-since-epoch to match SK2 bridge expectations
338
+ data["transactionDate"] = String(Int(transaction.purchaseDate.timeIntervalSince1970 * 1000))
339
+
340
+ if let expirationDate = transaction.expirationDate {
341
+ data["expirationDate"] = String(Int(expirationDate.timeIntervalSince1970 * 1000))
342
+ }
343
+ if let jws = jwsRepresentation {
344
+ data["jwsRepresentation"] = jws
345
+ }
346
+
347
+ notifyListeners("transactionUpdated", data: data)
348
+ }
349
+
350
+ @available(iOS 15.0, *)
351
+ private func productToDict(_ product: Product) -> [String: Any] {
352
+ var dict: [String: Any] = [
353
+ "id": product.id,
354
+ "title": product.displayName,
355
+ "description": product.description,
356
+ "price": product.displayPrice,
357
+ "priceMicros": NSDecimalNumber(decimal: product.price)
358
+ .multiplying(by: 1000000).int64Value,
359
+ "currency": product.priceFormatStyle.currencyCode,
360
+ "countryCode": {
361
+ if #available(iOS 16.0, *) {
362
+ return product.priceFormatStyle.locale.region?.identifier ?? ""
363
+ } else {
364
+ return Locale.current.regionCode ?? ""
365
+ }
366
+ }(),
367
+ ]
368
+
369
+ if let subscription = product.subscription {
370
+ let unit = subscription.subscriptionPeriod.unit
371
+ let value = subscription.subscriptionPeriod.value
372
+ dict["billingPeriod"] = value
373
+ dict["billingPeriodUnit"] = periodUnitToString(unit)
374
+ dict["group"] = subscription.subscriptionGroupID
375
+
376
+ // Introductory offer
377
+ if let intro = subscription.introductoryOffer {
378
+ dict["introPrice"] = intro.displayPrice
379
+ dict["introPriceMicros"] = NSDecimalNumber(decimal: intro.price)
380
+ .multiplying(by: 1000000).int64Value
381
+ dict["introPricePeriod"] = intro.period.value
382
+ dict["introPricePeriodUnit"] = periodUnitToString(intro.period.unit)
383
+ dict["introPricePaymentMode"] = paymentModeToString(intro.paymentMode)
384
+ }
385
+
386
+ // Promotional offers (discounts)
387
+ var discounts: [[String: Any]] = []
388
+ for offer in subscription.promotionalOffers {
389
+ discounts.append([
390
+ "id": offer.id ?? "",
391
+ "type": "Subscription",
392
+ "price": offer.displayPrice,
393
+ "priceMicros": NSDecimalNumber(decimal: offer.price)
394
+ .multiplying(by: 1000000).int64Value,
395
+ "period": offer.period.value,
396
+ "periodUnit": periodUnitToString(offer.period.unit),
397
+ "paymentMode": paymentModeToString(offer.paymentMode),
398
+ ])
399
+ }
400
+ if !discounts.isEmpty {
401
+ dict["discounts"] = discounts
402
+ }
403
+ }
404
+
405
+ return dict
406
+ }
407
+
408
+ @available(iOS 15.0, *)
409
+ private func periodUnitToString(_ unit: Product.SubscriptionPeriod.Unit) -> String {
410
+ switch unit {
411
+ case .day: return "Day"
412
+ case .week: return "Week"
413
+ case .month: return "Month"
414
+ case .year: return "Year"
415
+ @unknown default: return "Day"
416
+ }
417
+ }
418
+
419
+ @available(iOS 15.0, *)
420
+ private func paymentModeToString(_ mode: Product.SubscriptionOffer.PaymentMode) -> String {
421
+ switch mode {
422
+ case .payAsYouGo: return "PayAsYouGo"
423
+ case .payUpFront: return "PayUpFront"
424
+ case .freeTrial: return "FreeTrial"
425
+ default: return "PayAsYouGo"
426
+ }
427
+ }
428
+
429
+ private func debugLog(_ msg: String) {
430
+ if debugEnabled {
431
+ print("PurchasePlugin[debug]: \(msg)")
432
+ }
433
+ }
434
+ }
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "capacitor-plugin-cdv-purchase",
3
+ "version": "13.14.0",
4
+ "description": "In-App Purchases for Capacitor — iOS (StoreKit 2) and Android (Google Play Billing)",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.js",
7
+ "types": "types/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./types/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "capacitor": {
16
+ "ios": { "src": "ios" },
17
+ "android": { "src": "android" }
18
+ },
19
+ "peerDependencies": {
20
+ "@capacitor/core": "^6.0.0"
21
+ },
22
+ "devDependencies": {
23
+ "@capacitor/core": "^6.0.0",
24
+ "rollup": "^4.0.0",
25
+ "@rollup/plugin-node-resolve": "^16.0.0",
26
+ "typescript": "^5.0.0"
27
+ },
28
+ "scripts": {
29
+ "build": "tsc && rollup -c rollup.config.mjs",
30
+ "prepublishOnly": "npm run build"
31
+ },
32
+ "files": [
33
+ "dist/",
34
+ "types/",
35
+ "www/",
36
+ "android/",
37
+ "!android/build",
38
+ "ios/"
39
+ ],
40
+ "license": "MIT",
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "git+https://github.com/j3k0/cordova-plugin-purchase.git"
44
+ },
45
+ "keywords": [
46
+ "capacitor",
47
+ "capacitor-plugin",
48
+ "in-app-purchase",
49
+ "billing",
50
+ "storekit",
51
+ "storekit2",
52
+ "google-play",
53
+ "ios",
54
+ "android"
55
+ ]
56
+ }
@@ -0,0 +1,27 @@
1
+ /// <reference path="../www/store.d.ts" />
2
+
3
+ // Native bridge
4
+ import type { PurchasePluginPlugin } from '../dist/esm/definitions';
5
+ export declare const PurchasePlugin: PurchasePluginPlugin;
6
+ export type { PurchasePluginPlugin };
7
+
8
+ // Full namespace
9
+ export declare const CdvPurchase: typeof globalThis.CdvPurchase;
10
+
11
+ // Convenience value exports
12
+ export declare const store: CdvPurchase.Store;
13
+ export declare const Store: typeof CdvPurchase.Store;
14
+ export declare const ProductType: typeof CdvPurchase.ProductType;
15
+ export declare const Platform: typeof CdvPurchase.Platform;
16
+ export declare const LogLevel: typeof CdvPurchase.LogLevel;
17
+ export declare const ErrorCode: typeof CdvPurchase.ErrorCode;
18
+ export declare const Logger: typeof CdvPurchase.Logger;
19
+ export declare const Iaptic: typeof CdvPurchase.Iaptic;
20
+
21
+ // Convenience type re-exports
22
+ export type IError = CdvPurchase.IError;
23
+ export type Product = CdvPurchase.Product;
24
+ export type Offer = CdvPurchase.Offer;
25
+ export type Transaction = CdvPurchase.Transaction;
26
+ export type Receipt = CdvPurchase.Receipt;
27
+ export type VerifiedReceipt = CdvPurchase.VerifiedReceipt;
@@ -0,0 +1,3 @@
1
+ window.CdvPurchaseCapacitor = {
2
+ installed: true,
3
+ };