-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Summary: This diff enables us to get the candidate transactions for IAP (i.e. the transactions we should consider). We define a candidate transaction as a transaction that meets the following criteria: 1. The transaction has not been refunded or revoked 2. The purchase date of the transaction is newer than the last time we checked the transaction history 3. The transaction is finished (i.e. the products have been delivered to the user) 4. We have not already considered this transaction (i.e. it's not in the cache) Reviewed By: jjiang10 Differential Revision: D61942259 fbshipit-source-id: e4388b93530cd84920efd4fb181649fc279c5e19
- Loading branch information
1 parent
7d0a0b4
commit d86f396
Showing
8 changed files
with
256 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
FBSDKCoreKit/FBSDKCoreKit/AppEvents/Internal/IAP/Transaction+FBSDK.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
import Foundation | ||
import StoreKit | ||
|
||
@available(iOS 15.0, *) | ||
extension Transaction { | ||
static func getNewCandidateTransactions() async -> [VerificationResult<Transaction>] { | ||
let unfinishedTransactionIDs = await Transaction.unfinished.getValues().map { result in | ||
result.iapTransaction.transaction.id | ||
} | ||
let transactionsToConsider = await Transaction.all.getValues() | ||
|
||
let candidateTransactions = transactionsToConsider.filter { result in | ||
let transaction = result.iapTransaction.transaction | ||
let id = transaction.id | ||
var dateCheck = true | ||
if let candidateDate = IAPTransactionCache.shared.newCandidatesDate { | ||
dateCheck = transaction.purchaseDate >= candidateDate | ||
} | ||
return transaction.revocationDate == nil && | ||
dateCheck && | ||
!unfinishedTransactionIDs.contains(id) && | ||
!IAPTransactionCache.shared.contains(transactionID: id) | ||
} | ||
return candidateTransactions | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
89 changes: 89 additions & 0 deletions
89
FBSDKCoreKit/FBSDKCoreKitTests/Internal/AppEvents/IAP/IAPTests/TransactionTests.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
@testable import FBSDKCoreKit | ||
@testable import IAPTestsHostApp | ||
|
||
import StoreKitTest | ||
import XCTest | ||
|
||
@available(iOS 15.0, *) | ||
final class TransactionTests: StoreKitTestCase { | ||
|
||
func testGetAllTransactions() async { | ||
guard let products = try? await Product.products(for: Self.allIdentifiers) else { | ||
return | ||
} | ||
for product in products { | ||
guard let purchaseResult = try? await product.purchase() else { | ||
return | ||
} | ||
guard let transaction = try? getIAPTransactionForPurchaseResult(result: purchaseResult) else { | ||
return | ||
} | ||
await transaction.transaction.finish() | ||
} | ||
let transactions = await Transaction.all.getValues() | ||
XCTAssertEqual(transactions.count, products.count) | ||
} | ||
|
||
func testGetCurrentEntitlements() async { | ||
guard let products = try? await Product.products(for: Self.allIdentifiers) else { | ||
return | ||
} | ||
for product in products { | ||
guard let purchaseResult = try? await product.purchase() else { | ||
return | ||
} | ||
guard let transaction = try? getIAPTransactionForPurchaseResult(result: purchaseResult) else { | ||
return | ||
} | ||
await transaction.transaction.finish() | ||
} | ||
let transactions = await Transaction.currentEntitlements.getValues() | ||
XCTAssertEqual(transactions.count, products.count) | ||
} | ||
|
||
func testGetNewCandidateTransactions() async { | ||
guard let products = try? await Product.products(for: Self.allIdentifiers), | ||
products.count == Self.allIdentifiers.count else { | ||
return | ||
} | ||
guard let result0 = try? await products[0].purchase(), | ||
let transaction0 = try? getIAPTransactionForPurchaseResult(result: result0) else { | ||
return | ||
} | ||
await transaction0.transaction.finish() | ||
IAPTransactionCache.shared.newCandidatesDate = Date() | ||
guard let result1 = try? await products[1].purchase(), | ||
let transaction1 = try? getIAPTransactionForPurchaseResult(result: result1) else { | ||
return | ||
} | ||
await transaction1.transaction.finish() | ||
do { | ||
try testSession.refundTransaction(identifier: UInt(transaction1.transaction.id)) | ||
} catch { | ||
return | ||
} | ||
let result2 = try? await products[2].purchase() | ||
guard result2 != nil else { | ||
return | ||
} | ||
guard let result3 = try? await products[3].purchase(), | ||
let transaction3 = try? getIAPTransactionForPurchaseResult(result: result3) else { | ||
return | ||
} | ||
await transaction3.transaction.finish() | ||
var candidateTransactions = await Transaction.getNewCandidateTransactions() | ||
XCTAssertEqual(candidateTransactions.count, 1) | ||
XCTAssertEqual(candidateTransactions.first?.iapTransaction.transaction.id, transaction3.transaction.id) | ||
IAPTransactionCache.shared.addTransaction(transactionID: transaction3.transaction.id, eventName: .purchased) | ||
candidateTransactions = await Transaction.getNewCandidateTransactions() | ||
XCTAssertEqual(candidateTransactions.count, 0) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
d86f396
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@facebook-github-bot