diff options
Diffstat (limited to 'platform/iphone/in_app_store.mm')
| -rw-r--r-- | platform/iphone/in_app_store.mm | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/platform/iphone/in_app_store.mm b/platform/iphone/in_app_store.mm new file mode 100644 index 000000000..316e619e1 --- /dev/null +++ b/platform/iphone/in_app_store.mm @@ -0,0 +1,264 @@ +/*************************************************************************/ +/* in_app_store.mm */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* http://www.godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ +#ifdef STOREKIT_ENABLED + +#include "in_app_store.h" + +extern "C" { +#import <StoreKit/StoreKit.h> +}; + +@interface SKProduct (LocalizedPrice) +@property (nonatomic, readonly) NSString *localizedPrice; +@end + +//----------------------------------// +// SKProduct extension +//----------------------------------// +@implementation SKProduct (LocalizedPrice) +- (NSString *)localizedPrice +{ + NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init]; + [numberFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4]; + [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; + [numberFormatter setLocale:self.priceLocale]; + NSString *formattedString = [numberFormatter stringFromNumber:self.price]; + [numberFormatter release]; + return formattedString; +} +@end + + +InAppStore* InAppStore::instance = NULL; + +void InAppStore::_bind_methods() { + ObjectTypeDB::bind_method(_MD("request_product_info"),&InAppStore::request_product_info); + ObjectTypeDB::bind_method(_MD("purchase"),&InAppStore::purchase); + + ObjectTypeDB::bind_method(_MD("get_pending_event_count"),&InAppStore::get_pending_event_count); + ObjectTypeDB::bind_method(_MD("pop_pending_event"),&InAppStore::pop_pending_event); +}; + +@interface ProductsDelegate : NSObject<SKProductsRequestDelegate> { + +}; + +@end + +@implementation ProductsDelegate + +- (void)productsRequest:(SKProductsRequest*)request didReceiveResponse:(SKProductsResponse*)response { + + NSArray* products = response.products; + Dictionary ret; + ret["type"] = "product_info"; + ret["result"] = "ok"; + StringArray titles; + StringArray descriptions; + RealArray prices; + StringArray ids; + StringArray localized_prices; + + for (int i=0; i<[products count]; i++) { + + SKProduct* product = [products objectAtIndex:i]; + + const char* str = [product.localizedTitle UTF8String]; + titles.push_back(String::utf8(str != NULL ? str : "")); + + str = [product.localizedDescription UTF8String]; + descriptions.push_back(String::utf8(str != NULL ? str : "")); + prices.push_back([product.price doubleValue]); + ids.push_back(String::utf8([product.productIdentifier UTF8String])); + localized_prices.push_back(String::utf8([product.localizedPrice UTF8String])); + }; + ret["titles"] = titles; + ret["descriptions"] = descriptions; + ret["prices"] = prices; + ret["ids"] = ids; + ret["localized_prices"] = localized_prices; + + StringArray invalid_ids; + + for (NSString* ipid in response.invalidProductIdentifiers) { + + invalid_ids.push_back(String::utf8([ipid UTF8String])); + }; + ret["invalid_ids"] = invalid_ids; + + InAppStore::get_singleton()->_post_event(ret); + + [request release]; +}; + +@end + +Error InAppStore::request_product_info(Variant p_params) { + + Dictionary params = p_params; + ERR_FAIL_COND_V(!params.has("product_ids"), ERR_INVALID_PARAMETER); + + StringArray pids = params["product_ids"]; + printf("************ request product info! %i\n", pids.size()); + + NSMutableArray* array = [[[NSMutableArray alloc] initWithCapacity:pids.size()] autorelease]; + for (int i=0; i<pids.size(); i++) { + printf("******** adding %ls to product list\n", pids[i].c_str()); + NSString* pid = [[[NSString alloc] initWithUTF8String:pids[i].utf8().get_data()] autorelease]; + [array addObject:pid]; + }; + + NSSet* products = [[[NSSet alloc] initWithArray:array] autorelease]; + SKProductsRequest* request = [[SKProductsRequest alloc] initWithProductIdentifiers:products]; + + ProductsDelegate *delegate = [[ProductsDelegate alloc] init]; + + request.delegate = delegate; + [request start]; + + return OK; +}; + +@interface TransObserver : NSObject<SKPaymentTransactionObserver> { + +}; +@end + +@implementation TransObserver + +- (void)paymentQueue:(SKPaymentQueue*)queue updatedTransactions:(NSArray*) transactions { + + printf("transactions updated!\n"); + for (SKPaymentTransaction* transaction in transactions) { + + switch (transaction.transactionState) { + + case SKPaymentTransactionStatePurchased: { + printf("status purchased!\n"); + String pid = String::utf8([transaction.payment.productIdentifier UTF8String]); + InAppStore::get_singleton()->_record_purchase(pid); + Dictionary ret; + ret["type"] = "purchase"; + ret["result"] = "ok"; + ret["product_id"] = pid; + InAppStore::get_singleton()->_post_event(ret); + [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; + } break; + case SKPaymentTransactionStateFailed: { + printf("status transaction failed!\n"); + String pid = String::utf8([transaction.payment.productIdentifier UTF8String]); + Dictionary ret; + ret["type"] = "purchase"; + ret["result"] = "error"; + ret["product_id"] = pid; + InAppStore::get_singleton()->_post_event(ret); + [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; + } break; + case SKPaymentTransactionStateRestored: { + printf("status transaction restored!\n"); + String pid = String::utf8([transaction.originalTransaction.payment.productIdentifier UTF8String]); + InAppStore::get_singleton()->_record_purchase(pid); + [[SKPaymentQueue defaultQueue] finishTransaction:transaction]; + } break; + + default: + printf("status default %i!\n", (int)transaction.transactionState); + + break; + }; + }; +}; + +@end + + +Error InAppStore::purchase(Variant p_params) { + + ERR_FAIL_COND_V(![SKPaymentQueue canMakePayments], ERR_UNAVAILABLE); + if (![SKPaymentQueue canMakePayments]) + return ERR_UNAVAILABLE; + + printf("purchasing!\n"); + Dictionary params = p_params; + ERR_FAIL_COND_V(!params.has("product_id"), ERR_INVALID_PARAMETER); + + NSString *pid = [[[NSString alloc] initWithUTF8String:String(params["product_id"]).utf8().get_data()] autorelease]; + SKPayment *payment = [SKPayment paymentWithProductIdentifier:pid]; + SKPaymentQueue* defq = [SKPaymentQueue defaultQueue]; + [defq addPayment:payment]; + printf("purchase sent!\n"); + + return OK; +}; + + +int InAppStore::get_pending_event_count() { + return pending_events.size(); +}; + +Variant InAppStore::pop_pending_event() { + + Variant front = pending_events.front()->get(); + pending_events.pop_front(); + + return front; +}; + +void InAppStore::_post_event(Variant p_event) { + + pending_events.push_back(p_event); +}; + +void InAppStore::_record_purchase(String product_id) { + + String skey = "purchased/"+product_id; + NSString* key = [[[NSString alloc] initWithUTF8String:skey.utf8().get_data()] autorelease]; + [[NSUserDefaults standardUserDefaults] setBool:YES forKey:key]; + [[NSUserDefaults standardUserDefaults] synchronize]; +}; + +InAppStore* InAppStore::get_singleton() { + + return instance; +}; + +InAppStore::InAppStore() { + ERR_FAIL_COND(instance != NULL); + instance = this; + + TransObserver* observer = [[TransObserver alloc] init]; + [[SKPaymentQueue defaultQueue] addTransactionObserver:observer]; +}; + +InAppStore::~InAppStore() { + +}; + + +#endif |
