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 3d189c6b6b4..aab9bfe4598 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,8 @@ ## NEXT * 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.0 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..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) + 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 } 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..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 @@ -121,7 +121,10 @@ extension on SK2TransactionMessage { // receipt isn’t necessary with SK2 as a Transaction can only be returned // from validated purchases. verificationData: PurchaseVerificationData( - localVerificationData: '', serverVerificationData: '', source: ''), + 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. 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 5df44552fe7..23acddf5aad 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.6.0 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', () {