aboutsummaryrefslogtreecommitdiff
path: root/platform/iphone/in_app_store.mm
diff options
context:
space:
mode:
Diffstat (limited to 'platform/iphone/in_app_store.mm')
-rw-r--r--platform/iphone/in_app_store.mm264
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