From 8c340b0ba7955036c0464e1d0b2b5545b2fb28c9 Mon Sep 17 00:00:00 2001 From: Shaun Panjabi Date: Sun, 18 May 2025 09:49:21 -0700 Subject: [PATCH 01/13] add jsonRepresentation to SK2PurchaseDetails --- .../in_app_purchase/in_app_purchase_storekit/CHANGELOG.md | 4 ++++ .../src/store_kit_2_wrappers/sk2_transaction_wrapper.dart | 1 + .../lib/src/types/app_store_purchase_details.dart | 6 +++++- .../in_app_purchase/in_app_purchase_storekit/pubspec.yaml | 2 +- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md index cf6651bbf22..8e2aa758ced 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.4.1 + +* Add `jsonRepresentation` to `SK2PurchaseDetails` + ## 0.4.0 * **BREAKING CHANGE:** StoreKit 2 is now the default for all devices that support it. diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_transaction_wrapper.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_transaction_wrapper.dart index 5fb6cee8969..975ac49e9e8 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_transaction_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_transaction_wrapper.dart @@ -129,6 +129,7 @@ extension on SK2TransactionMessage { // Any failed transaction will simply not be returned. status: restoring ? PurchaseStatus.restored : PurchaseStatus.purchased, purchaseID: id.toString(), + jsonRepresentation: jsonRepresentation, ); } } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/app_store_purchase_details.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/app_store_purchase_details.dart index 335ff6ad264..7641d9729e8 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/app_store_purchase_details.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/app_store_purchase_details.dart @@ -87,7 +87,11 @@ class SK2PurchaseDetails extends PurchaseDetails { required super.purchaseID, required super.verificationData, required super.transactionDate, - required super.status}); + required super.status, + required this.jsonRepresentation}); + + /// The json representation of a transaction + final String? jsonRepresentation; @override bool get pendingCompletePurchase => status == PurchaseStatus.purchased; diff --git a/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml index c615f5eb4d5..300cc04a1cb 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml @@ -2,7 +2,7 @@ name: in_app_purchase_storekit description: An implementation for the iOS and macOS platforms of the Flutter `in_app_purchase` plugin. This uses the StoreKit Framework. repository: https://github.com/flutter/packages/tree/main/packages/in_app_purchase/in_app_purchase_storekit issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+in_app_purchase%22 -version: 0.4.0 +version: 0.4.1 environment: sdk: ^3.4.0 From d942b58fd1bb64cb38f549a3156567504ad4e5b3 Mon Sep 17 00:00:00 2001 From: Shaun Panjabi Date: Sun, 18 May 2025 10:56:28 -0700 Subject: [PATCH 02/13] repurpose purchase verification data --- .../InAppPurchasePlugin+StoreKit2.swift | 2 +- .../sk2_transaction_wrapper.dart | 36 +++++++++---------- .../src/types/app_store_purchase_details.dart | 6 +--- 3 files changed, 20 insertions(+), 24 deletions(-) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/InAppPurchasePlugin+StoreKit2.swift b/packages/in_app_purchase/in_app_purchase_storekit/darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/InAppPurchasePlugin+StoreKit2.swift index 5ce366c8ccb..690c25f45ad 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/InAppPurchasePlugin+StoreKit2.swift +++ b/packages/in_app_purchase/in_app_purchase_storekit/darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/InAppPurchasePlugin+StoreKit2.swift @@ -59,7 +59,7 @@ extension InAppPurchasePlugin: InAppPurchase2API { case .success(let verification): switch verification { case .verified(let transaction): - self.sendTransactionUpdate(transaction: transaction) + self.sendTransactionUpdate(transaction: transaction, receipt: verification.jwsRepresentation) completion(.success(result.convertToPigeon())) case .unverified(_, let error): completion(.failure(error)) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_transaction_wrapper.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_transaction_wrapper.dart index 975ac49e9e8..fb7997c36e3 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_transaction_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_transaction_wrapper.dart @@ -109,28 +109,28 @@ extension on SK2TransactionMessage { productId: productId, purchaseDate: purchaseDate, expirationDate: expirationDate, - appAccountToken: appAccountToken, - jsonRepresentation: jsonRepresentation); + appAccountToken: appAccountToken); } PurchaseDetails convertToDetails() { return SK2PurchaseDetails( - productID: productId, - // in SK2, as per Apple - // https://developer.apple.com/documentation/foundation/nsbundle/1407276-appstorereceipturl - // receipt isn’t necessary with SK2 as a Transaction can only be returned - // from validated purchases. - verificationData: PurchaseVerificationData( - localVerificationData: '', serverVerificationData: '', source: ''), - transactionDate: purchaseDate, - // Note that with SK2, any transactions that *can* be returned will - // require to be finished, and are already purchased. - // So set this as purchased for all transactions initially. - // Any failed transaction will simply not be returned. - status: restoring ? PurchaseStatus.restored : PurchaseStatus.purchased, - purchaseID: id.toString(), - jsonRepresentation: jsonRepresentation, - ); + productID: productId, + // in SK2, as per Apple + // https://developer.apple.com/documentation/foundation/nsbundle/1407276-appstorereceipturl + // receipt isn’t necessary with SK2 as a Transaction can only be returned + // from validated purchases. + verificationData: PurchaseVerificationData( + localVerificationData: jsonRepresentation ?? '', + // receiptData is the JWS representation of the transaction + serverVerificationData: receiptData ?? '', + source: kIAPSource), + transactionDate: purchaseDate, + // Note that with SK2, any transactions that *can* be returned will + // require to be finished, and are already purchased. + // So set this as purchased for all transactions initially. + // Any failed transaction will simply not be returned. + status: restoring ? PurchaseStatus.restored : PurchaseStatus.purchased, + purchaseID: id.toString()); } } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/app_store_purchase_details.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/app_store_purchase_details.dart index 7641d9729e8..335ff6ad264 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/app_store_purchase_details.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/types/app_store_purchase_details.dart @@ -87,11 +87,7 @@ class SK2PurchaseDetails extends PurchaseDetails { required super.purchaseID, required super.verificationData, required super.transactionDate, - required super.status, - required this.jsonRepresentation}); - - /// The json representation of a transaction - final String? jsonRepresentation; + required super.status}); @override bool get pendingCompletePurchase => status == PurchaseStatus.purchased; From 7224cc7787314c6846cb06e8479e6e2878c93dc8 Mon Sep 17 00:00:00 2001 From: Shaun Panjabi Date: Sun, 18 May 2025 11:00:34 -0700 Subject: [PATCH 03/13] cleanup --- .../sk2_transaction_wrapper.dart | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_transaction_wrapper.dart b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_transaction_wrapper.dart index fb7997c36e3..fe44700815e 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_transaction_wrapper.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_transaction_wrapper.dart @@ -109,28 +109,30 @@ extension on SK2TransactionMessage { productId: productId, purchaseDate: purchaseDate, expirationDate: expirationDate, - appAccountToken: appAccountToken); + appAccountToken: appAccountToken, + jsonRepresentation: jsonRepresentation); } PurchaseDetails convertToDetails() { return SK2PurchaseDetails( - productID: productId, - // in SK2, as per Apple - // https://developer.apple.com/documentation/foundation/nsbundle/1407276-appstorereceipturl - // receipt isn’t necessary with SK2 as a Transaction can only be returned - // from validated purchases. - verificationData: PurchaseVerificationData( - localVerificationData: jsonRepresentation ?? '', - // receiptData is the JWS representation of the transaction - serverVerificationData: receiptData ?? '', - source: kIAPSource), - transactionDate: purchaseDate, - // Note that with SK2, any transactions that *can* be returned will - // require to be finished, and are already purchased. - // So set this as purchased for all transactions initially. - // Any failed transaction will simply not be returned. - status: restoring ? PurchaseStatus.restored : PurchaseStatus.purchased, - purchaseID: id.toString()); + productID: productId, + // in SK2, as per Apple + // https://developer.apple.com/documentation/foundation/nsbundle/1407276-appstorereceipturl + // receipt isn’t necessary with SK2 as a Transaction can only be returned + // from validated purchases. + verificationData: PurchaseVerificationData( + localVerificationData: jsonRepresentation ?? '', + // receiptData is the JWS representation of the transaction + serverVerificationData: receiptData ?? '', + source: kIAPSource), + transactionDate: purchaseDate, + // Note that with SK2, any transactions that *can* be returned will + // require to be finished, and are already purchased. + // So set this as purchased for all transactions initially. + // Any failed transaction will simply not be returned. + status: restoring ? PurchaseStatus.restored : PurchaseStatus.purchased, + purchaseID: id.toString(), + ); } } From a339ec73ce1b8136a6c5b525fddf0ec0eaf01e91 Mon Sep 17 00:00:00 2001 From: Shaun Panjabi Date: Sun, 18 May 2025 11:07:35 -0700 Subject: [PATCH 04/13] update changelog --- packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md index 8e2aa758ced..13f40b3cefb 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md @@ -1,6 +1,7 @@ ## 0.4.1 -* Add `jsonRepresentation` to `SK2PurchaseDetails` +* Add `jwsRepresentation` to `SK2PurchaseDetails` as `serverVerificationData` +* Add `jsonRepresentation` to `SK2PurchaseDetails` as `localVerificationData` ## 0.4.0 From a9a2c5e405a7a5a3c624db775a498ced99839717 Mon Sep 17 00:00:00 2001 From: Shaun Panjabi Date: Sun, 18 May 2025 11:28:00 -0700 Subject: [PATCH 05/13] add test --- .../test/fakes/fake_storekit_platform.dart | 4 ++- ...app_purchase_storekit_2_platform_test.dart | 32 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/test/fakes/fake_storekit_platform.dart b/packages/in_app_purchase/in_app_purchase_storekit/test/fakes/fake_storekit_platform.dart index f854e78f613..74efa8cbdc0 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/test/fakes/fake_storekit_platform.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/test/fakes/fake_storekit_platform.dart @@ -413,5 +413,7 @@ SK2TransactionMessage createPendingTransaction(String id, {int quantity = 1}) { originalId: 2, productId: id, purchaseDate: 'purchaseDate', - appAccountToken: 'appAccountToken'); + appAccountToken: 'appAccountToken', + receiptData: 'receiptData', + jsonRepresentation: 'jsonRepresentation'); } diff --git a/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart b/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart index 9277127d60f..ed6108f41a7 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart @@ -153,6 +153,38 @@ void main() { purchaseParam: purchaseParam, autoConsume: false), throwsA(isInstanceOf())); }); + + test( + 'buying consumable, should get PurchaseVerificationData with serverVerificationData and localVerificationData', + () async { + final List details = []; + final Completer> completer = + Completer>(); + final Stream> stream = + iapStoreKitPlatform.purchaseStream; + + late StreamSubscription> subscription; + subscription = stream.listen((List purchaseDetailsList) { + details.addAll(purchaseDetailsList); + if (purchaseDetailsList.first.status == PurchaseStatus.purchased) { + completer.complete(details); + subscription.cancel(); + } + }); + final AppStorePurchaseParam purchaseParam = AppStorePurchaseParam( + productDetails: + AppStoreProduct2Details.fromSK2Product(dummyProductWrapper), + applicationUserName: 'appName'); + await iapStoreKitPlatform.buyConsumable(purchaseParam: purchaseParam); + + final List result = await completer.future; + expect(result.length, 1); + expect(result.first.productID, dummyProductWrapper.id); + expect( + result.first.verificationData.serverVerificationData, 'receiptData'); + expect(result.first.verificationData.localVerificationData, + 'jsonRepresentation'); + }); }); group('restore purchases', () { From 4ab2f23609ba968f2fa829553f6770440c658458 Mon Sep 17 00:00:00 2001 From: Shaun Panjabi Date: Sun, 18 May 2025 11:47:39 -0700 Subject: [PATCH 06/13] add missing receipt data --- .../StoreKit2/InAppPurchasePlugin+StoreKit2.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/InAppPurchasePlugin+StoreKit2.swift b/packages/in_app_purchase/in_app_purchase_storekit/darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/InAppPurchasePlugin+StoreKit2.swift index 690c25f45ad..0d1f3e9e88c 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/InAppPurchasePlugin+StoreKit2.swift +++ b/packages/in_app_purchase/in_app_purchase_storekit/darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/InAppPurchasePlugin+StoreKit2.swift @@ -59,7 +59,8 @@ extension InAppPurchasePlugin: InAppPurchase2API { case .success(let verification): switch verification { case .verified(let transaction): - self.sendTransactionUpdate(transaction: transaction, receipt: verification.jwsRepresentation) + self.sendTransactionUpdate( + transaction: transaction, receipt: "\(verification.jwsRepresentation)") completion(.success(result.convertToPigeon())) case .unverified(_, let error): completion(.failure(error)) @@ -191,7 +192,8 @@ extension InAppPurchasePlugin: InAppPurchase2API { for await verificationResult in Transaction.updates { switch verificationResult { case .verified(let transaction): - self?.sendTransactionUpdate(transaction: transaction) + self?.sendTransactionUpdate( + transaction: transaction, receipt: "\(verificationResult.jwsRepresentation)") case .unverified: break } From f747fda231320194d6c126afd7a9ff4a35eb69b5 Mon Sep 17 00:00:00 2001 From: Shaun Panjabi Date: Mon, 2 Jun 2025 16:49:46 -0700 Subject: [PATCH 07/13] add 0.4.1 version --- packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md index aab9bfe4598..c465dae8371 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md @@ -1,4 +1,4 @@ -## NEXT +## 0.4.1 * Updates minimum supported SDK version to Flutter 3.27/Dart 3.6. * Add `jwsRepresentation` to `SK2PurchaseDetails` as `serverVerificationData` From b6bd713a595c9aedb1d5fe4cae2eae8259305f1f Mon Sep 17 00:00:00 2001 From: Shaun Panjabi Date: Mon, 2 Jun 2025 17:08:06 -0700 Subject: [PATCH 08/13] merge test group --- .../test/in_app_purchase_storekit_2_platform_test.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart b/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart index 928644e6907..04f05303e60 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart @@ -185,9 +185,7 @@ void main() { expect(result.first.verificationData.localVerificationData, 'jsonRepresentation'); }); - }); - group('purchase param', () { test('should process Sk2PurchaseParam with winBackOfferId only', () async { final Sk2PurchaseParam purchaseParam = Sk2PurchaseParam( productDetails: From 7e9261b801dfed786ef5f592a9539a5250bb7de4 Mon Sep 17 00:00:00 2001 From: Shaun Panjabi Date: Mon, 2 Jun 2025 17:25:54 -0700 Subject: [PATCH 09/13] version 0.4.2 --- .../in_app_purchase/in_app_purchase_storekit/CHANGELOG.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md index 786b7adac0a..fda05e6a8c8 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md @@ -1,8 +1,11 @@ -## 0.4.1 +## 0.4.2 -* Updates minimum supported SDK version to Flutter 3.27/Dart 3.6. * Add `jwsRepresentation` to `SK2PurchaseDetails` as `serverVerificationData` * Add `jsonRepresentation` to `SK2PurchaseDetails` as `localVerificationData` + +## 0.4.1 + +* Updates minimum supported SDK version to Flutter 3.27/Dart 3.6. * Adds **Win Back Offers** support for StoreKit2: - Includes new `isWinBackOfferEligible` function for eligibility verification * Adds **Promotional Offers** support in StoreKit2 purchases From 2a1d2a5d5d5b10cfb935f3d965c434eaeee1bb8c Mon Sep 17 00:00:00 2001 From: Shaun Panjabi Date: Mon, 2 Jun 2025 17:34:53 -0700 Subject: [PATCH 10/13] bump pubspec --- packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml b/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml index 23acddf5aad..b353b6fe3dc 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml +++ b/packages/in_app_purchase/in_app_purchase_storekit/pubspec.yaml @@ -2,7 +2,7 @@ name: in_app_purchase_storekit description: An implementation for the iOS and macOS platforms of the Flutter `in_app_purchase` plugin. This uses the StoreKit Framework. repository: https://github.com/flutter/packages/tree/main/packages/in_app_purchase/in_app_purchase_storekit issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+in_app_purchase%22 -version: 0.4.1 +version: 0.4.2 environment: sdk: ^3.6.0 From 221861d39bdfe90e260caf630f32cf2e6006211d Mon Sep 17 00:00:00 2001 From: Shaun Panjabi Date: Thu, 5 Jun 2025 20:04:02 -0700 Subject: [PATCH 11/13] Add more detail to CHANGELOG comment --- .../in_app_purchase/in_app_purchase_storekit/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md b/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md index fda05e6a8c8..f952dbc0617 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md +++ b/packages/in_app_purchase/in_app_purchase_storekit/CHANGELOG.md @@ -1,7 +1,7 @@ ## 0.4.2 -* Add `jwsRepresentation` to `SK2PurchaseDetails` as `serverVerificationData` -* Add `jsonRepresentation` to `SK2PurchaseDetails` as `localVerificationData` +* Add [jwsRepresentation](https://developer.apple.com/documentation/storekit/verificationresult/jwsrepresentation-21vgo) to `SK2PurchaseDetails` as `serverVerificationData` for secure server-side purchase verification. Use this JSON Web Signature (JWS) value to perform your own JWS verification on your server. +* Add [jsonRepresentation](https://developer.apple.com/documentation/storekit/transaction/jsonrepresentation) to `SK2PurchaseDetails` as `localVerificationData` for local transaction debugging and verification. ## 0.4.1 From 7e4cae2d2ae91f276866d31ad973dcaae64fabb8 Mon Sep 17 00:00:00 2001 From: Shaun Panjabi Date: Thu, 5 Jun 2025 20:04:29 -0700 Subject: [PATCH 12/13] Remove unnecessary string interpolation --- .../StoreKit2/InAppPurchasePlugin+StoreKit2.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/InAppPurchasePlugin+StoreKit2.swift b/packages/in_app_purchase/in_app_purchase_storekit/darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/InAppPurchasePlugin+StoreKit2.swift index a2896a6ef73..bb9bfff7c6e 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/InAppPurchasePlugin+StoreKit2.swift +++ b/packages/in_app_purchase/in_app_purchase_storekit/darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/InAppPurchasePlugin+StoreKit2.swift @@ -89,7 +89,7 @@ extension InAppPurchasePlugin: InAppPurchase2API { switch verification { case .verified(let transaction): self.sendTransactionUpdate( - transaction: transaction, receipt: "\(verification.jwsRepresentation)") + transaction: transaction, receipt: verification.jwsRepresentation) completion(.success(result.convertToPigeon())) case .unverified(_, let error): completion(.failure(error)) @@ -286,7 +286,7 @@ extension InAppPurchasePlugin: InAppPurchase2API { switch verificationResult { case .verified(let transaction): self?.sendTransactionUpdate( - transaction: transaction, receipt: "\(verificationResult.jwsRepresentation)") + transaction: transaction, receipt: verificationResult.jwsRepresentation) case .unverified: break } From 2d464a82beb9927260648758fa11016daff729a5 Mon Sep 17 00:00:00 2001 From: Shaun Panjabi Date: Tue, 10 Jun 2025 08:45:13 -0700 Subject: [PATCH 13/13] switch to late final --- .../test/in_app_purchase_storekit_2_platform_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart b/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart index 04f05303e60..20da75f241b 100644 --- a/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart +++ b/packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart @@ -163,7 +163,7 @@ void main() { final Stream> stream = iapStoreKitPlatform.purchaseStream; - late StreamSubscription> subscription; + late final StreamSubscription> subscription; subscription = stream.listen((List purchaseDetailsList) { details.addAll(purchaseDetailsList); if (purchaseDetailsList.first.status == PurchaseStatus.purchased) {