feat: enable explicit IAP restoration (#21461)
This commit is contained in:
parent
53957d47d6
commit
dba8a0caa8
7 changed files with 43 additions and 23 deletions
|
@ -40,11 +40,17 @@ Retrieves the product descriptions.
|
|||
|
||||
### `inAppPurchase.canMakePayments()`
|
||||
|
||||
Returns `Boolean`, whether a user can make a payment.
|
||||
Returns `Boolean` - whether a user can make a payment.
|
||||
|
||||
### `inAppPurchase.restoreCompletedTransactions()`
|
||||
|
||||
Restores finished transactions. This method can be called either to install purchases on additional devices, or to restore purchases for an application that the user deleted and reinstalled.
|
||||
|
||||
[The payment queue](https://developer.apple.com/documentation/storekit/skpaymentqueue?language=objc) delivers a new transaction for each previously completed transaction that can be restored. Each transaction includes a copy of the original transaction.
|
||||
|
||||
### `inAppPurchase.getReceiptURL()`
|
||||
|
||||
Returns `String`, the path to the receipt.
|
||||
Returns `String` - the path to the receipt.
|
||||
|
||||
### `inAppPurchase.finishAllTransactions()`
|
||||
|
||||
|
|
|
@ -85,6 +85,8 @@ void InAppPurchase::BuildPrototype(v8::Isolate* isolate,
|
|||
prototype->SetClassName(gin::StringToV8(isolate, "InAppPurchase"));
|
||||
gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("canMakePayments", &in_app_purchase::CanMakePayments)
|
||||
.SetMethod("restoreCompletedTransactions",
|
||||
&in_app_purchase::RestoreCompletedTransactions)
|
||||
.SetMethod("getReceiptURL", &in_app_purchase::GetReceiptURL)
|
||||
.SetMethod("purchaseProduct", &InAppPurchase::PurchaseProduct)
|
||||
.SetMethod("finishAllTransactions",
|
||||
|
|
|
@ -17,13 +17,15 @@ typedef base::OnceCallback<void(bool isProductValid)> InAppPurchaseCallback;
|
|||
|
||||
// --------------------------- Functions ---------------------------
|
||||
|
||||
bool CanMakePayments(void);
|
||||
bool CanMakePayments();
|
||||
|
||||
void FinishAllTransactions(void);
|
||||
void RestoreCompletedTransactions();
|
||||
|
||||
void FinishAllTransactions();
|
||||
|
||||
void FinishTransactionByDate(const std::string& date);
|
||||
|
||||
std::string GetReceiptURL(void);
|
||||
std::string GetReceiptURL();
|
||||
|
||||
void PurchaseProduct(const std::string& productID,
|
||||
int quantity,
|
||||
|
|
|
@ -141,6 +141,10 @@ bool CanMakePayments() {
|
|||
return [SKPaymentQueue canMakePayments];
|
||||
}
|
||||
|
||||
void RestoreCompletedTransactions() {
|
||||
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
|
||||
}
|
||||
|
||||
void FinishAllTransactions() {
|
||||
for (SKPaymentTransaction* transaction in SKPaymentQueue.defaultQueue
|
||||
.transactions) {
|
||||
|
|
|
@ -51,7 +51,7 @@ class TransactionObserver {
|
|||
const std::vector<Transaction>& transactions) = 0;
|
||||
|
||||
private:
|
||||
InAppTransactionObserver* obeserver_;
|
||||
InAppTransactionObserver* observer_;
|
||||
|
||||
base::WeakPtrFactory<TransactionObserver> weak_ptr_factory_;
|
||||
|
||||
|
|
|
@ -183,14 +183,14 @@ Transaction::Transaction(const Transaction&) = default;
|
|||
Transaction::~Transaction() = default;
|
||||
|
||||
TransactionObserver::TransactionObserver() : weak_ptr_factory_(this) {
|
||||
obeserver_ = [[InAppTransactionObserver alloc]
|
||||
observer_ = [[InAppTransactionObserver alloc]
|
||||
initWithCallback:base::BindRepeating(
|
||||
&TransactionObserver::OnTransactionsUpdated,
|
||||
weak_ptr_factory_.GetWeakPtr())];
|
||||
}
|
||||
|
||||
TransactionObserver::~TransactionObserver() {
|
||||
[obeserver_ release];
|
||||
[observer_ release];
|
||||
}
|
||||
|
||||
} // namespace in_app_purchase
|
||||
|
|
|
@ -6,9 +6,14 @@ describe('inAppPurchase module', function () {
|
|||
|
||||
this.timeout(3 * 60 * 1000)
|
||||
|
||||
it('canMakePayments() does not throw', () => {
|
||||
it('canMakePayments() returns a boolean', () => {
|
||||
const canMakePayments = inAppPurchase.canMakePayments()
|
||||
expect(canMakePayments).to.be.a('boolean')
|
||||
})
|
||||
|
||||
it('restoreCompletedTransactions() does not throw', () => {
|
||||
expect(() => {
|
||||
inAppPurchase.canMakePayments()
|
||||
inAppPurchase.restoreCompletedTransactions()
|
||||
}).to.not.throw()
|
||||
})
|
||||
|
||||
|
@ -29,22 +34,23 @@ describe('inAppPurchase module', function () {
|
|||
})
|
||||
|
||||
// The following three tests are disabled because they hit Apple servers, and
|
||||
// Apple started blocking requests from AWS IPs (we think), so they fail on
|
||||
// CI.
|
||||
// Apple started blocking requests from AWS IPs (we think), so they fail on CI.
|
||||
// TODO: find a way to mock out the server requests so we can test these APIs
|
||||
// without relying on a remote service.
|
||||
xit('purchaseProduct() fails when buying invalid product', async () => {
|
||||
const success = await inAppPurchase.purchaseProduct('non-exist', 1)
|
||||
expect(success).to.be.false('failed to purchase non-existent product')
|
||||
})
|
||||
xdescribe('handles product purchases', () => {
|
||||
it('purchaseProduct() fails when buying invalid product', async () => {
|
||||
const success = await inAppPurchase.purchaseProduct('non-exist', 1)
|
||||
expect(success).to.be.false('failed to purchase non-existent product')
|
||||
})
|
||||
|
||||
xit('purchaseProduct() accepts optional arguments', async () => {
|
||||
const success = await inAppPurchase.purchaseProduct('non-exist')
|
||||
expect(success).to.be.false('failed to purchase non-existent product')
|
||||
})
|
||||
it('purchaseProduct() accepts optional arguments', async () => {
|
||||
const success = await inAppPurchase.purchaseProduct('non-exist')
|
||||
expect(success).to.be.false('failed to purchase non-existent product')
|
||||
})
|
||||
|
||||
xit('getProducts() returns an empty list when getting invalid product', async () => {
|
||||
const products = await inAppPurchase.getProducts(['non-exist'])
|
||||
expect(products).to.be.an('array').of.length(0)
|
||||
it('getProducts() returns an empty list when getting invalid product', async () => {
|
||||
const products = await inAppPurchase.getProducts(['non-exist'])
|
||||
expect(products).to.be.an('array').of.length(0)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue