Skip to content

Commit 8381a28

Browse files
committed
Add JWS representation support to unfinishedTransactions
Previously returned nil for receipt data, now properly includes jwsRepresentation for server-side verification.
1 parent 80fcee2 commit 8381a28

File tree

4 files changed

+27
-18
lines changed

4 files changed

+27
-18
lines changed

packages/in_app_purchase/in_app_purchase_storekit/darwin/in_app_purchase_storekit/Sources/in_app_purchase_storekit/StoreKit2/InAppPurchasePlugin+StoreKit2.swift

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,16 @@ extension InAppPurchasePlugin: InAppPurchase2API {
238238
Task {
239239
@MainActor in
240240
do {
241-
let transactionsMsgs = await rawUnfinishedTransactions().map {
242-
$0.convertToPigeon(receipt: nil)
241+
var transactionsMsgs: [SK2TransactionMessage] = []
242+
for await verificationResult in Transaction.unfinished {
243+
switch verificationResult {
244+
case .verified(let transaction):
245+
transactionsMsgs.append(
246+
transaction.convertToPigeon(receipt: verificationResult.jwsRepresentation)
247+
)
248+
case .unverified:
249+
break
250+
}
243251
}
244252
completion(.success(transactionsMsgs))
245253
}
@@ -378,20 +386,6 @@ extension InAppPurchasePlugin: InAppPurchase2API {
378386
return transactions
379387
}
380388

381-
/// Helper function that fetches and unwraps all verified unfinished transactions
382-
func rawUnfinishedTransactions() async -> [Transaction] {
383-
var transactions: [Transaction] = []
384-
for await verificationResult in Transaction.unfinished {
385-
switch verificationResult {
386-
case .verified(let transaction):
387-
transactions.append(transaction)
388-
case .unverified:
389-
break
390-
}
391-
}
392-
return transactions
393-
}
394-
395389
/// Helper function to fetch specific transaction
396390
func fetchTransaction(by id: UInt64) async throws -> Transaction? {
397391
for await result in Transaction.all {

packages/in_app_purchase/in_app_purchase_storekit/lib/src/store_kit_2_wrappers/sk2_transaction_wrapper.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class SK2Transaction {
2727
this.subscriptionGroupID,
2828
this.price,
2929
this.error,
30+
this.receiptData,
3031
this.jsonRepresentation,
3132
});
3233

@@ -63,7 +64,11 @@ class SK2Transaction {
6364
/// Any error returned from StoreKit
6465
final SKError? error;
6566

66-
/// The json representation of a transaction
67+
/// The JWS (JSON Web Signature) representation of the transaction.
68+
/// This is the jwsRepresentation from StoreKit used for server-side verification.
69+
final String? receiptData;
70+
71+
/// The json representation of a transaction.
6772
final String? jsonRepresentation;
6873

6974
/// Wrapper around [Transaction.finish]
@@ -122,6 +127,7 @@ extension on SK2TransactionMessage {
122127
purchaseDate: purchaseDate,
123128
expirationDate: expirationDate,
124129
appAccountToken: appAccountToken,
130+
receiptData: receiptData,
125131
jsonRepresentation: jsonRepresentation,
126132
);
127133
}

packages/in_app_purchase/in_app_purchase_storekit/test/fakes/fake_storekit_platform.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ class FakeStoreKit2Platform implements InAppPurchase2API {
458458
originalId: 123,
459459
productId: 'product_id',
460460
purchaseDate: '12-12',
461+
receiptData: 'fake_jws_representation',
461462
),
462463
]);
463464
}

packages/in_app_purchase/in_app_purchase_storekit/test/in_app_purchase_storekit_2_platform_test.dart

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,15 @@ void main() {
675675
expect(transactions.first.id, '123');
676676
expect(transactions.first.productId, 'product_id');
677677
});
678+
679+
test('should expose receiptData (JWS) in unfinished transactions', () async {
680+
final List<SK2Transaction> transactions =
681+
await SK2Transaction.unfinishedTransactions();
682+
683+
expect(transactions, isNotEmpty);
684+
expect(transactions.first.receiptData, isNotNull);
685+
expect(transactions.first.receiptData, 'fake_jws_representation');
686+
});
678687
});
679688

680689
group('appAccountToken exposure', () {
@@ -707,7 +716,6 @@ void main() {
707716
),
708717
transactionDate: '2025-11-15',
709718
status: PurchaseStatus.purchased,
710-
appAccountToken: null,
711719
);
712720

713721
expect(details.appAccountToken, isNull);

0 commit comments

Comments
 (0)