From 133bef3deb14ab55470336a2201a79ca9e5dd2f8 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 10 Jan 2018 16:55:49 +0900 Subject: [PATCH] Turn addTransactionListener into transaction-updated event --- atom/browser/api/atom_api_in_app_purchase.cc | 10 +++-- atom/browser/api/atom_api_in_app_purchase.h | 8 +++- atom/browser/mac/in_app_purchase_observer.h | 26 +++++++++--- atom/browser/mac/in_app_purchase_observer.mm | 31 ++++++++++----- docs/api/in-app-purchase.md | 42 +++++++++++--------- 5 files changed, 80 insertions(+), 37 deletions(-) diff --git a/atom/browser/api/atom_api_in_app_purchase.cc b/atom/browser/api/atom_api_in_app_purchase.cc index 66ab3883010f..6c9d37941897 100644 --- a/atom/browser/api/atom_api_in_app_purchase.cc +++ b/atom/browser/api/atom_api_in_app_purchase.cc @@ -62,9 +62,7 @@ void InAppPurchase::BuildPrototype(v8::Isolate* isolate, mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("canMakePayments", &in_app_purchase::CanMakePayments) .SetMethod("getReceiptURL", &in_app_purchase::GetReceiptURL) - .SetMethod("purchaseProduct", &InAppPurchase::PurchaseProduct) - .SetMethod("addTransactionListener", - &in_app_purchase::AddTransactionObserver); + .SetMethod("purchaseProduct", &InAppPurchase::PurchaseProduct); } InAppPurchase::InAppPurchase(v8::Isolate* isolate) { @@ -83,6 +81,12 @@ void InAppPurchase::PurchaseProduct(const std::string& product_id, in_app_purchase::PurchaseProduct(product_id, quantity, callback); } +void InAppPurchase::OnTransactionUpdated( + const in_app_purchase::Payment& payment, + const in_app_purchase::Transaction& transaction) { + Emit("transaction-updated", payment, transaction); +} + } // namespace api } // namespace atom diff --git a/atom/browser/api/atom_api_in_app_purchase.h b/atom/browser/api/atom_api_in_app_purchase.h index b11ccbc6607a..6ab25cb69f16 100644 --- a/atom/browser/api/atom_api_in_app_purchase.h +++ b/atom/browser/api/atom_api_in_app_purchase.h @@ -16,7 +16,8 @@ namespace atom { namespace api { -class InAppPurchase: public mate::EventEmitter { +class InAppPurchase: public mate::EventEmitter, + public in_app_purchase::TransactionObserver { public: static mate::Handle Create(v8::Isolate* isolate); @@ -29,6 +30,11 @@ class InAppPurchase: public mate::EventEmitter { void PurchaseProduct(const std::string& product_id, mate::Arguments* args); + // TransactionObserver: + void OnTransactionUpdated( + const in_app_purchase::Payment& payment, + const in_app_purchase::Transaction& transaction) override; + private: DISALLOW_COPY_AND_ASSIGN(InAppPurchase); }; diff --git a/atom/browser/mac/in_app_purchase_observer.h b/atom/browser/mac/in_app_purchase_observer.h index fadd9037eb85..2e80cd48e9e5 100644 --- a/atom/browser/mac/in_app_purchase_observer.h +++ b/atom/browser/mac/in_app_purchase_observer.h @@ -8,6 +8,13 @@ #include #include "base/callback.h" +#include "base/memory/weak_ptr.h" + +#if defined(__OBJC__) +@class InAppTransactionObserver; +#else // __OBJC__ +class InAppTransactionObserver; +#endif // __OBJC__ namespace in_app_purchase { @@ -27,14 +34,23 @@ struct Transaction { std::string transactionState = ""; }; -// --------------------------- Typedefs --------------------------- +// --------------------------- Classes --------------------------- -typedef base::RepeatingCallback - InAppTransactionCallback; +class TransactionObserver { + public: + TransactionObserver(); + virtual ~TransactionObserver(); -// --------------------------- Functions --------------------------- + virtual void OnTransactionUpdated(const Payment& payment, + const Transaction& transaction) = 0; -void AddTransactionObserver(const InAppTransactionCallback& callback); + private: + InAppTransactionObserver* obeserver_; + + base::WeakPtrFactory weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(TransactionObserver); +}; } // namespace in_app_purchase diff --git a/atom/browser/mac/in_app_purchase_observer.mm b/atom/browser/mac/in_app_purchase_observer.mm index 1cd0ab9e075e..59b4aecc4f63 100644 --- a/atom/browser/mac/in_app_purchase_observer.mm +++ b/atom/browser/mac/in_app_purchase_observer.mm @@ -15,13 +15,20 @@ // InAppTransactionObserver // ============================================================================ +namespace { + +using InAppTransactionCallback = + base::RepeatingCallback; + +} // namespace + @interface InAppTransactionObserver : NSObject { @private - in_app_purchase::InAppTransactionCallback callback_; + InAppTransactionCallback callback_; } -- (id)initWithCallback: - (const in_app_purchase::InAppTransactionCallback&)callback; +- (id)initWithCallback:(const InAppTransactionCallback&)callback; @end @@ -33,8 +40,7 @@ * @param callback - The callback that will be called for each transaction * update. */ -- (id)initWithCallback: - (const in_app_purchase::InAppTransactionCallback&)callback { +- (id)initWithCallback:(const InAppTransactionCallback&)callback { if ((self = [super init])) { callback_ = callback; @@ -143,7 +149,8 @@ if (transaction.transactionState < 5) { transactionStruct.transactionState = [[@[ @"SKPaymentTransactionStatePurchasing", - @"SKPaymentTransactionStatePurchased", @"SKPaymentTransactionStateFailed", + @"SKPaymentTransactionStatePurchased", + @"SKPaymentTransactionStateFailed", @"SKPaymentTransactionStateRestored", @"SKPaymentTransactionStateDeferred" ] objectAtIndex:transaction.transactionState] UTF8String]; @@ -176,10 +183,14 @@ namespace in_app_purchase { -void AddTransactionObserver(const InAppTransactionCallback& callback) { - // This is leaked, but we should be fine since we don't have a way to remove - // callback and the inAppPurchase module is never unloaded. - [[InAppTransactionObserver alloc] initWithCallback:callback]; +TransactionObserver::TransactionObserver() : weak_ptr_factory_(this) { + obeserver_ = [[InAppTransactionObserver alloc] + initWithCallback:base::Bind(&TransactionObserver::OnTransactionUpdated, + weak_ptr_factory_.GetWeakPtr())]; +} + +TransactionObserver::~TransactionObserver() { + [obeserver_ release]; } } // namespace in_app_purchase diff --git a/docs/api/in-app-purchase.md b/docs/api/in-app-purchase.md index 9019e41c08e2..6eaa55961a76 100644 --- a/docs/api/in-app-purchase.md +++ b/docs/api/in-app-purchase.md @@ -1,29 +1,35 @@ # inAppPurchase _macOS_ -> In-App Purchase on Mac App Store. +> In-app purchases on Mac App Store. -Your application should add a listener before to purchase a product. If there are no listener attached to the queue, the payment queue does not synchronize its list of pending transactions with the Apple App Store. +Process: [Main](../glossary.md#main-process) + +## Events + +The `inAppPurchase` module emits the following events: + +### Event: 'transaction-updated' + +Emitted when a transaction has been updated. + +Returns: + +* `event` Event +* `payment` Object + * `productIdentifier` String + * `quantity` Integer +* `transaction` Object + * `transactionIdentifier` String + * `transactionDate` String + * `originalTransactionIdentifier` String + * `transactionState` String - The transaction sate (`"SKPaymentTransactionStatePurchasing"`, `"SKPaymentTransactionStatePurchased"`, `"SKPaymentTransactionStateFailed"`, `"SKPaymentTransactionStateRestored"`, or `"SKPaymentTransactionStateDeferred"`) + * `errorCode` Integer + * `errorMessage` String ## Methods The `inAppPurchase` module has the following methods: -### `inAppPurchase.addTransactionListener(listener)` - -* `listener` Function - Called when transactions are updated by the payment queue. - * `payment` Object - * `productIdentifier` String - * `quantity` Integer - * `transaction` Object - * `transactionIdentifier` String - * `transactionDate` String - * `originalTransactionIdentifier` String - * `transactionState` String - The transaction sate (`"SKPaymentTransactionStatePurchasing"`, `"SKPaymentTransactionStatePurchased"`, `"SKPaymentTransactionStateFailed"`, `"SKPaymentTransactionStateRestored"`, or `"SKPaymentTransactionStateDeferred"`) - * `errorCode` Integer - * `errorMessage` String - -Add a listener to transactions. - ### `inAppPurchase.purchaseProduct(productID, quantity, callback)` * `productID` String - The id of the product to purchase. (the id of `com.example.app.product1` is `product1`).