123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 |
- // Copyright (c) 2017 Amaplex Software, Inc.
- // Use of this source code is governed by the MIT license that can be
- // found in the LICENSE file.
- #include "atom/browser/mac/in_app_purchase_product.h"
- #include "base/bind.h"
- #include "base/strings/sys_string_conversions.h"
- #include "content/public/browser/browser_thread.h"
- #import <StoreKit/StoreKit.h>
- // ============================================================================
- // InAppPurchaseProduct
- // ============================================================================
- // --------------------------------- Interface --------------------------------
- @interface InAppPurchaseProduct : NSObject <SKProductsRequestDelegate> {
- @private
- in_app_purchase::InAppPurchaseProductsCallback callback_;
- }
- - (id)initWithCallback:
- (const in_app_purchase::InAppPurchaseProductsCallback&)callback;
- @end
- // ------------------------------- Implementation -----------------------------
- @implementation InAppPurchaseProduct
- /**
- * Init with a callback.
- *
- * @param callback - The callback that will be called to return the products.
- */
- - (id)initWithCallback:
- (const in_app_purchase::InAppPurchaseProductsCallback&)callback {
- if ((self = [super init])) {
- callback_ = callback;
- }
- return self;
- }
- /**
- * Return products.
- *
- * @param productIDs - The products' id to fetch.
- */
- - (void)getProducts:(NSSet*)productIDs {
- SKProductsRequest* productsRequest;
- productsRequest =
- [[SKProductsRequest alloc] initWithProductIdentifiers:productIDs];
- productsRequest.delegate = self;
- [productsRequest start];
- }
- /**
- * @see SKProductsRequestDelegate
- */
- - (void)productsRequest:(SKProductsRequest*)request
- didReceiveResponse:(SKProductsResponse*)response {
- // Release request object.
- [request release];
- // Get the products.
- NSArray* products = response.products;
- // Convert the products.
- std::vector<in_app_purchase::Product> converted;
- converted.reserve([products count]);
- for (SKProduct* product in products) {
- converted.push_back([self skProductToStruct:product]);
- }
- // Send the callback to the browser thread.
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(callback_, converted));
- [self release];
- }
- /**
- * Format local price.
- *
- * @param price - The price to format.
- * @param priceLocal - The local format.
- */
- - (NSString*)formatPrice:(NSDecimalNumber*)price
- withLocal:(NSLocale*)priceLocal {
- NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init];
- [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
- [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
- [numberFormatter setLocale:priceLocal];
- return [numberFormatter stringFromNumber:price];
- }
- /**
- * Convert a skProduct object to Product structure.
- *
- * @param product - The SKProduct object to convert.
- */
- - (in_app_purchase::Product)skProductToStruct:(SKProduct*)product {
- in_app_purchase::Product productStruct;
- // Product Identifier
- if (product.productIdentifier != nil) {
- productStruct.productIdentifier = [product.productIdentifier UTF8String];
- }
- // Product Attributes
- if (product.localizedDescription != nil) {
- productStruct.localizedDescription =
- [product.localizedDescription UTF8String];
- }
- if (product.localizedTitle != nil) {
- productStruct.localizedTitle = [product.localizedTitle UTF8String];
- }
- if (product.contentVersion != nil) {
- productStruct.contentVersion = [product.contentVersion UTF8String];
- }
- if (product.contentLengths != nil) {
- productStruct.contentLengths.reserve([product.contentLengths count]);
- for (NSNumber* contentLength in product.contentLengths) {
- productStruct.contentLengths.push_back([contentLength longLongValue]);
- }
- }
- // Pricing Information
- if (product.price != nil) {
- productStruct.price = [product.price doubleValue];
- if (product.priceLocale != nil) {
- productStruct.formattedPrice =
- [[self formatPrice:product.price withLocal:product.priceLocale]
- UTF8String];
- }
- }
- // Downloadable Content Information
- if (product.downloadable == true) {
- productStruct.downloadable = true;
- }
- return productStruct;
- }
- @end
- // ============================================================================
- // C++ in_app_purchase
- // ============================================================================
- namespace in_app_purchase {
- Product::Product() = default;
- Product::Product(const Product&) = default;
- Product::~Product() = default;
- void GetProducts(const std::vector<std::string>& productIDs,
- const InAppPurchaseProductsCallback& callback) {
- auto* iapProduct = [[InAppPurchaseProduct alloc] initWithCallback:callback];
- // Convert the products' id to NSSet.
- NSMutableSet* productsIDSet =
- [NSMutableSet setWithCapacity:productIDs.size()];
- for (auto& productID : productIDs) {
- [productsIDSet addObject:base::SysUTF8ToNSString(productID)];
- }
- // Fetch the products.
- [iapProduct getProducts:productsIDSet];
- }
- } // namespace in_app_purchase
|