Turn InAppPurchase into an EventEmitter
This commit is contained in:
parent
400bfb3c5a
commit
ac6f895f64
8 changed files with 123 additions and 90 deletions
|
@ -15,47 +15,92 @@
|
||||||
|
|
||||||
namespace mate {
|
namespace mate {
|
||||||
|
|
||||||
v8::Local<v8::Value> Converter<in_app_purchase::Payment>::ToV8(
|
template <>
|
||||||
v8::Isolate* isolate,
|
struct Converter<in_app_purchase::Payment> {
|
||||||
const in_app_purchase::Payment& payment) {
|
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||||
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
const in_app_purchase::Payment& payment) {
|
||||||
dict.SetHidden("simple", true);
|
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
||||||
dict.Set("productIdentifier", payment.productIdentifier);
|
dict.SetHidden("simple", true);
|
||||||
dict.Set("quantity", payment.quantity);
|
dict.Set("productIdentifier", payment.productIdentifier);
|
||||||
return dict.GetHandle();
|
dict.Set("quantity", payment.quantity);
|
||||||
}
|
return dict.GetHandle();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
v8::Local<v8::Value> Converter<in_app_purchase::Transaction>::ToV8(
|
template <>
|
||||||
v8::Isolate* isolate,
|
struct Converter<in_app_purchase::Transaction> {
|
||||||
const in_app_purchase::Transaction& transaction) {
|
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||||
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
const in_app_purchase::Transaction& val) {
|
||||||
dict.SetHidden("simple", true);
|
mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate);
|
||||||
dict.Set("transactionIdentifier", transaction.transactionIdentifier);
|
dict.SetHidden("simple", true);
|
||||||
dict.Set("transactionDate", transaction.transactionDate);
|
dict.Set("transactionIdentifier", val.transactionIdentifier);
|
||||||
dict.Set("originalTransactionIdentifier",
|
dict.Set("transactionDate", val.transactionDate);
|
||||||
transaction.originalTransactionIdentifier);
|
dict.Set("originalTransactionIdentifier",
|
||||||
dict.Set("transactionState", transaction.transactionState);
|
val.originalTransactionIdentifier);
|
||||||
|
dict.Set("transactionState", val.transactionState);
|
||||||
|
dict.Set("errorCode", val.errorCode);
|
||||||
|
dict.Set("errorMessage", val.errorMessage);
|
||||||
|
return dict.GetHandle();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
dict.Set("errorCode", transaction.errorCode);
|
|
||||||
dict.Set("errorMessage", transaction.errorMessage);
|
|
||||||
|
|
||||||
return dict.GetHandle();
|
|
||||||
}
|
|
||||||
} // namespace mate
|
} // namespace mate
|
||||||
|
|
||||||
|
namespace atom {
|
||||||
|
|
||||||
|
namespace api {
|
||||||
|
|
||||||
|
// static
|
||||||
|
mate::Handle<InAppPurchase> InAppPurchase::Create(v8::Isolate* isolate) {
|
||||||
|
return mate::CreateHandle(isolate, new InAppPurchase(isolate));
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void InAppPurchase::BuildPrototype(v8::Isolate* isolate,
|
||||||
|
v8::Local<v8::FunctionTemplate> prototype) {
|
||||||
|
prototype->SetClassName(mate::StringToV8(isolate, "InAppPurchase"));
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
InAppPurchase::InAppPurchase(v8::Isolate* isolate) {
|
||||||
|
Init(isolate);
|
||||||
|
}
|
||||||
|
|
||||||
|
InAppPurchase::~InAppPurchase() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void InAppPurchase::PurchaseProduct(const std::string& product_id,
|
||||||
|
mate::Arguments* args) {
|
||||||
|
int quantity = 1;
|
||||||
|
in_app_purchase::InAppPurchaseCallback callback;
|
||||||
|
args->GetNext(&quantity);
|
||||||
|
args->GetNext(&callback);
|
||||||
|
in_app_purchase::PurchaseProduct(product_id, quantity, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace api
|
||||||
|
|
||||||
|
} // namespace atom
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
using atom::api::InAppPurchase;
|
||||||
|
|
||||||
void Initialize(v8::Local<v8::Object> exports,
|
void Initialize(v8::Local<v8::Object> exports,
|
||||||
v8::Local<v8::Value> unused,
|
v8::Local<v8::Value> unused,
|
||||||
v8::Local<v8::Context> context,
|
v8::Local<v8::Context> context,
|
||||||
void* priv) {
|
void* priv) {
|
||||||
mate::Dictionary dict(context->GetIsolate(), exports);
|
|
||||||
#if defined(OS_MACOSX)
|
#if defined(OS_MACOSX)
|
||||||
dict.SetMethod("canMakePayments", &in_app_purchase::CanMakePayments);
|
v8::Isolate* isolate = context->GetIsolate();
|
||||||
dict.SetMethod("getReceiptURL", &in_app_purchase::GetReceiptURL);
|
mate::Dictionary dict(isolate, exports);
|
||||||
dict.SetMethod("purchaseProduct", &in_app_purchase::PurchaseProduct);
|
dict.Set("inAppPurchase", InAppPurchase::Create(isolate));
|
||||||
dict.SetMethod("addTransactionListener",
|
dict.Set("InAppPurchase",
|
||||||
&in_app_purchase::AddTransactionObserver);
|
InAppPurchase::GetConstructor(isolate)->GetFunction());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,30 +7,34 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "atom/browser/api/event_emitter.h"
|
||||||
#include "atom/browser/mac/in_app_purchase.h"
|
#include "atom/browser/mac/in_app_purchase.h"
|
||||||
#include "atom/browser/mac/in_app_purchase_observer.h"
|
#include "atom/browser/mac/in_app_purchase_observer.h"
|
||||||
#include "native_mate/dictionary.h"
|
#include "native_mate/handle.h"
|
||||||
|
|
||||||
namespace mate {
|
namespace atom {
|
||||||
|
|
||||||
template <>
|
namespace api {
|
||||||
struct Converter<in_app_purchase::Payment> {
|
|
||||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
class InAppPurchase: public mate::EventEmitter<InAppPurchase> {
|
||||||
const in_app_purchase::Payment& val);
|
public:
|
||||||
static bool FromV8(v8::Isolate* isolate,
|
static mate::Handle<InAppPurchase> Create(v8::Isolate* isolate);
|
||||||
v8::Local<v8::Value> val,
|
|
||||||
in_app_purchase::Payment* out);
|
static void BuildPrototype(v8::Isolate* isolate,
|
||||||
|
v8::Local<v8::FunctionTemplate> prototype);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit InAppPurchase(v8::Isolate* isolate);
|
||||||
|
~InAppPurchase() override;
|
||||||
|
|
||||||
|
void PurchaseProduct(const std::string& product_id, mate::Arguments* args);
|
||||||
|
|
||||||
|
private:
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(InAppPurchase);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
} // namespace api
|
||||||
struct Converter<in_app_purchase::Transaction> {
|
|
||||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
|
||||||
const in_app_purchase::Transaction& val);
|
|
||||||
static bool FromV8(v8::Isolate* isolate,
|
|
||||||
v8::Local<v8::Value> val,
|
|
||||||
in_app_purchase::Transaction* out);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace mate
|
} // namespace atom
|
||||||
|
|
||||||
#endif // ATOM_BROWSER_API_ATOM_API_IN_APP_PURCHASE_H_
|
#endif // ATOM_BROWSER_API_ATOM_API_IN_APP_PURCHASE_H_
|
||||||
|
|
|
@ -22,7 +22,7 @@ bool CanMakePayments(void);
|
||||||
std::string GetReceiptURL(void);
|
std::string GetReceiptURL(void);
|
||||||
|
|
||||||
void PurchaseProduct(const std::string& productID,
|
void PurchaseProduct(const std::string& productID,
|
||||||
const int quantity,
|
int quantity,
|
||||||
const InAppPurchaseCallback& callback);
|
const InAppPurchaseCallback& callback);
|
||||||
|
|
||||||
} // namespace in_app_purchase
|
} // namespace in_app_purchase
|
||||||
|
|
|
@ -146,9 +146,9 @@ std::string GetReceiptURL() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PurchaseProduct(const std::string& productID,
|
void PurchaseProduct(const std::string& productID,
|
||||||
const int quantity,
|
int quantity,
|
||||||
const InAppPurchaseCallback& callback) {
|
const InAppPurchaseCallback& callback) {
|
||||||
auto iap =
|
auto* iap =
|
||||||
[[InAppPurchase alloc] initWithCallback:callback quantity:quantity];
|
[[InAppPurchase alloc] initWithCallback:callback quantity:quantity];
|
||||||
|
|
||||||
[iap purchaseProduct:base::SysUTF8ToNSString(productID)];
|
[iap purchaseProduct:base::SysUTF8ToNSString(productID)];
|
||||||
|
|
|
@ -177,6 +177,8 @@
|
||||||
namespace in_app_purchase {
|
namespace in_app_purchase {
|
||||||
|
|
||||||
void AddTransactionObserver(const InAppTransactionCallback& callback) {
|
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];
|
[[InAppTransactionObserver alloc] initWithCallback:callback];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
# inAppPurchase _macOS_
|
# inAppPurchase _macOS_
|
||||||
|
|
||||||
|
> In-App Purchase 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.
|
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.
|
||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
|
|
||||||
The `inAppPurchase` module has the following methods:
|
The `inAppPurchase` module has the following methods:
|
||||||
|
|
||||||
### `inAppPurchase.addTransactionListener(listener)`
|
### `inAppPurchase.addTransactionListener(listener)`
|
||||||
|
|
||||||
* `listener` Function - Called when transactions are updated by the payment queue.
|
* `listener` Function - Called when transactions are updated by the payment queue.
|
||||||
* `payment` Object
|
* `payment` Object
|
||||||
* `productIdentifier` String
|
* `productIdentifier` String
|
||||||
* `quantity` Integer
|
* `quantity` Integer
|
||||||
|
@ -19,9 +21,11 @@ The `inAppPurchase` module has the following methods:
|
||||||
* `transactionState` String - The transaction sate (`"SKPaymentTransactionStatePurchasing"`, `"SKPaymentTransactionStatePurchased"`, `"SKPaymentTransactionStateFailed"`, `"SKPaymentTransactionStateRestored"`, or `"SKPaymentTransactionStateDeferred"`)
|
* `transactionState` String - The transaction sate (`"SKPaymentTransactionStatePurchasing"`, `"SKPaymentTransactionStatePurchased"`, `"SKPaymentTransactionStateFailed"`, `"SKPaymentTransactionStateRestored"`, or `"SKPaymentTransactionStateDeferred"`)
|
||||||
* `errorCode` Integer
|
* `errorCode` Integer
|
||||||
* `errorMessage` String
|
* `errorMessage` String
|
||||||
|
|
||||||
|
Add a listener to transactions.
|
||||||
|
|
||||||
### `inAppPurchase.purchaseProduct(productID, quantity, callback)`
|
### `inAppPurchase.purchaseProduct(productID, quantity, callback)`
|
||||||
|
|
||||||
* `productID` String - The id of the product to purchase. (the id of `com.example.app.product1` is `product1`).
|
* `productID` String - The id of the product to purchase. (the id of `com.example.app.product1` is `product1`).
|
||||||
* `quantity` Integer (optional) - The number of items the user wants to purchase.
|
* `quantity` Integer (optional) - The number of items the user wants to purchase.
|
||||||
* `callback` Function (optional) - The callback called when the payment is added to the PaymentQueue. (You should add a listener with `inAppPurchase.addTransactionsListener` to get the transaction status).
|
* `callback` Function (optional) - The callback called when the payment is added to the PaymentQueue. (You should add a listener with `inAppPurchase.addTransactionsListener` to get the transaction status).
|
||||||
|
@ -33,4 +37,4 @@ Returns `true` if the user can make a payment and `false` otherwise.
|
||||||
|
|
||||||
### `inAppPurchase.getReceiptURL()`
|
### `inAppPurchase.getReceiptURL()`
|
||||||
|
|
||||||
Returns `String`, the path to the receipt.
|
Returns `String`, the path to the receipt.
|
||||||
|
|
|
@ -1,39 +1,10 @@
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const binding = process.atomBinding('in_app_purchase')
|
const {EventEmitter} = require('events')
|
||||||
const v8Util = process.atomBinding('v8_util')
|
const {inAppPurchase, InAppPurchase} = process.atomBinding('in_app_purchase')
|
||||||
|
|
||||||
module.exports = {
|
// inAppPurchase is an EventEmitter.
|
||||||
|
Object.setPrototypeOf(InAppPurchase.prototype, EventEmitter.prototype)
|
||||||
|
EventEmitter.call(inAppPurchase)
|
||||||
|
|
||||||
canMakePayments: function () {
|
module.exports = inAppPurchase
|
||||||
return binding.canMakePayments()
|
|
||||||
},
|
|
||||||
|
|
||||||
getReceiptURL: function () {
|
|
||||||
return binding.getReceiptURL()
|
|
||||||
},
|
|
||||||
|
|
||||||
purchaseProduct: function (productID, quantity = 1, callback) {
|
|
||||||
if (typeof productID !== 'string') {
|
|
||||||
throw new TypeError('productID must be a string')
|
|
||||||
}
|
|
||||||
if (typeof quantity === 'function') {
|
|
||||||
quantity = 1
|
|
||||||
callback = quantity
|
|
||||||
}
|
|
||||||
return binding.purchaseProduct(productID, quantity, callback)
|
|
||||||
},
|
|
||||||
|
|
||||||
addTransactionListener: function (callback) {
|
|
||||||
if (typeof callback !== 'function') {
|
|
||||||
throw new TypeError('callback must be a function')
|
|
||||||
}
|
|
||||||
return binding.addTransactionListener(callback)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark standard asynchronous functions.
|
|
||||||
v8Util.setHiddenValue(
|
|
||||||
module.exports.purchaseProduct, 'asynchronous', true)
|
|
||||||
v8Util.setHiddenValue(
|
|
||||||
module.exports.addTransactionListener, 'asynchronous', true)
|
|
||||||
|
|
|
@ -22,4 +22,11 @@ describe('inAppPurchase module', () => {
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('purchaseProduct() accepts optional arguments', (done) => {
|
||||||
|
inAppPurchase.purchaseProduct('non-exist', () => {
|
||||||
|
inAppPurchase.purchaseProduct('non-exist', 1)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue