123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- // 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.h"
- #include "base/bind.h"
- #include "base/strings/sys_string_conversions.h"
- #include "content/public/browser/browser_thread.h"
- #import <CommonCrypto/CommonCrypto.h>
- #import <StoreKit/StoreKit.h>
- // ============================================================================
- // InAppPurchase
- // ============================================================================
- // --------------------------------- Interface --------------------------------
- @interface InAppPurchase : NSObject <SKProductsRequestDelegate> {
- @private
- in_app_purchase::InAppPurchaseCallback callback_;
- NSInteger quantity_;
- }
- - (id)initWithCallback:(const in_app_purchase::InAppPurchaseCallback&)callback
- quantity:(NSInteger)quantity;
- - (void)purchaseProduct:(NSString*)productID;
- @end
- // ------------------------------- Implementation -----------------------------
- @implementation InAppPurchase
- /**
- * Init with a callback.
- *
- * @param callback - The callback that will be called when the payment is added
- * to the queue.
- */
- - (id)initWithCallback:(const in_app_purchase::InAppPurchaseCallback&)callback
- quantity:(NSInteger)quantity {
- if ((self = [super init])) {
- callback_ = callback;
- quantity_ = quantity;
- }
- return self;
- }
- /**
- * Start the in-app purchase process.
- *
- * @param productID - The id of the product to purchase (the id of
- * com.example.app.product1 is product1).
- */
- - (void)purchaseProduct:(NSString*)productID {
- // Retrieve the product information. (The products request retrieves,
- // information about valid products along with a list of the invalid product
- // identifiers, and then calls its delegate to process the result).
- SKProductsRequest* productsRequest;
- productsRequest = [[SKProductsRequest alloc]
- initWithProductIdentifiers:[NSSet setWithObject:productID]];
- productsRequest.delegate = self;
- [productsRequest start];
- }
- /**
- * Process product informations and start the payment.
- *
- * @param request - The product request.
- * @param response - The informations about the list of products.
- */
- - (void)productsRequest:(SKProductsRequest*)request
- didReceiveResponse:(SKProductsResponse*)response {
- // Release request object.
- [request release];
- // Get the first product.
- NSArray* products = response.products;
- SKProduct* product = [products count] == 1 ? [products firstObject] : nil;
- // Return if the product is not found or invalid.
- if (product == nil) {
- [self runCallback:false];
- return;
- }
- // Start the payment process.
- [self checkout:product];
- }
- /**
- * Submit a payment request to the App Store.
- *
- * @param product - The product to purchase.
- */
- - (void)checkout:(SKProduct*)product {
- // Add the payment to the transaction queue. (The observer will be called
- // when the transaction is finished).
- SKMutablePayment* payment = [SKMutablePayment paymentWithProduct:product];
- payment.quantity = quantity_;
- [[SKPaymentQueue defaultQueue] addPayment:payment];
- // Notify that the payment has been added to the queue with success.
- [self runCallback:true];
- }
- /**
- * Submit a payment request to the App Store.
- *
- * @param product - The product to purchase.
- */
- - (void)runCallback:(bool)isProductValid {
- if (callback_) {
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(callback_, isProductValid));
- }
- // Release this delegate.
- [self release];
- }
- @end
- // ============================================================================
- // C++ in_app_purchase
- // ============================================================================
- namespace in_app_purchase {
- bool CanMakePayments() {
- return [SKPaymentQueue canMakePayments];
- }
- void FinishAllTransactions() {
- for (SKPaymentTransaction* transaction in SKPaymentQueue.defaultQueue
- .transactions) {
- [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
- }
- }
- void FinishTransactionByDate(const std::string& date) {
- // Create the date formatter.
- NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
- NSLocale* enUSPOSIXLocale =
- [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
- [dateFormatter setLocale:enUSPOSIXLocale];
- [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZZZ"];
- // Remove the transaction.
- NSString* transactionDate = base::SysUTF8ToNSString(date);
- for (SKPaymentTransaction* transaction in SKPaymentQueue.defaultQueue
- .transactions) {
- if ([transactionDate
- isEqualToString:[dateFormatter
- stringFromDate:transaction.transactionDate]]) {
- [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
- }
- }
- }
- std::string GetReceiptURL() {
- NSURL* receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];
- if (receiptURL != nil) {
- return [[receiptURL absoluteString] UTF8String];
- } else {
- return "";
- }
- }
- void PurchaseProduct(const std::string& productID,
- int quantity,
- const InAppPurchaseCallback& callback) {
- auto* iap =
- [[InAppPurchase alloc] initWithCallback:callback quantity:quantity];
- [iap purchaseProduct:base::SysUTF8ToNSString(productID)];
- }
- } // namespace in_app_purchase
|