mirror of
https://github.com/id-Software/Wolf3D-iOS.git
synced 2026-03-19 16:39:49 +01:00
351 lines
9.8 KiB
Objective-C
351 lines
9.8 KiB
Objective-C
/*
|
|
|
|
Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
|
|
|
|
This file is part of the WOLF3D iOS v2.1 GPL Source Code.
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
#import <Foundation/Foundation.h>
|
|
|
|
#import <StoreKit/StoreKit.h>
|
|
#import <StoreKit/SKPaymentTransaction.h>
|
|
#import <StoreKit/SKError.h>
|
|
|
|
#import <UIKit/UIAlertView.h>
|
|
|
|
#import "iphone_store.h"
|
|
|
|
|
|
@interface MyStoreObserver : NSObject<SKProductsRequestDelegate, SKPaymentTransactionObserver> {
|
|
|
|
}
|
|
|
|
// SKProductsRequestDelegate methods
|
|
- (void)productsRequest: (SKProductsRequest *)request didReceiveResponse: (SKProductsResponse *)response;
|
|
|
|
// SKPaymentTransactionObserver methods
|
|
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions;
|
|
- (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions;
|
|
|
|
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error;
|
|
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue;
|
|
|
|
// MyStoreObserver methods
|
|
- (void)completeTransaction:(SKPaymentTransaction *)transaction;
|
|
- (void)failedTransaction:(SKPaymentTransaction *)transaction;
|
|
- (void)restoreTransaction:(SKPaymentTransaction *)transaction;
|
|
- (void)finalizeTransaction:(SKPaymentTransaction *)transaction;
|
|
|
|
@end
|
|
|
|
// The single instance of the store observer. This is created in InAppPurchaseInit and released
|
|
// in InAppPurchaseShutdown.
|
|
static MyStoreObserver *storeObserver;
|
|
|
|
// Flag to indicate whether a purchase is in progress or not. This is set to true in
|
|
// InAppPurchaseStartPurchase and false when the request either succeeds or fails.
|
|
static bool isInProgress = false;
|
|
|
|
static InAppPurchaseCallbackPtr clientCallback;
|
|
|
|
@implementation MyStoreObserver
|
|
|
|
/*
|
|
========================
|
|
productsRequest:didReceiveResponse
|
|
|
|
Called by the system when the application gets product information about an In-App Purchase.
|
|
========================
|
|
*/
|
|
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
|
|
{
|
|
NSArray *myProduct = response.products;
|
|
|
|
// For now, immediately request payment for any items the user has requested.
|
|
for (SKProduct *product in myProduct)
|
|
{
|
|
SKPayment *payment = [SKPayment paymentWithProductIdentifier:[product productIdentifier]];
|
|
[[SKPaymentQueue defaultQueue] addPayment:payment];
|
|
}
|
|
|
|
// We should handle the case of an empty array, this seems to occur if we send a request
|
|
// with a nonexistant product ID, but there may be other cases.
|
|
// TODO: Need a timeout to be even more robust.
|
|
if ( [myProduct count] == 0 ) {
|
|
if ( clientCallback ) {
|
|
clientCallback( IAP_FAILURE );
|
|
}
|
|
}
|
|
|
|
[request autorelease];
|
|
}
|
|
|
|
/*
|
|
========================
|
|
paymentQueue:updatedTransactions
|
|
|
|
Called by the system when purchase requests are updated.
|
|
========================
|
|
*/
|
|
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
|
|
{
|
|
for (SKPaymentTransaction *transaction in transactions)
|
|
{
|
|
switch (transaction.transactionState)
|
|
{
|
|
case SKPaymentTransactionStatePurchased:
|
|
[self completeTransaction:transaction];
|
|
break;
|
|
case SKPaymentTransactionStateFailed:
|
|
[self failedTransaction:transaction];
|
|
break;
|
|
case SKPaymentTransactionStateRestored:
|
|
[self restoreTransaction:transaction];
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions
|
|
{
|
|
|
|
}
|
|
|
|
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
|
|
{
|
|
|
|
}
|
|
|
|
|
|
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue
|
|
{
|
|
|
|
}
|
|
|
|
/*
|
|
========================
|
|
completeTransaction
|
|
|
|
Called by updatedTransactions when a request is completed.
|
|
========================
|
|
*/
|
|
- (void)completeTransaction:(SKPaymentTransaction *)transaction
|
|
{
|
|
[self finalizeTransaction:transaction];
|
|
}
|
|
|
|
/*
|
|
========================
|
|
failedTransaction
|
|
|
|
Called by updatedTransactions when a request fails.
|
|
========================
|
|
*/
|
|
- (void)failedTransaction:(SKPaymentTransaction *)transaction
|
|
{
|
|
if (transaction.error.code != SKErrorPaymentCancelled)
|
|
{
|
|
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"In-App Purchase error"
|
|
message:[transaction.error localizedDescription]
|
|
delegate:nil
|
|
cancelButtonTitle:@"OK"
|
|
otherButtonTitles:nil];
|
|
|
|
[alert show];
|
|
[alert release];
|
|
}
|
|
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
|
|
|
|
isInProgress = false;
|
|
|
|
if ( clientCallback ) {
|
|
clientCallback( IAP_FAILURE );
|
|
}
|
|
}
|
|
|
|
/*
|
|
========================
|
|
restoreTransaction
|
|
|
|
Called by updatedTransactions when a request is restored. This can behave identically to
|
|
completeTransaction.
|
|
========================
|
|
*/
|
|
- (void)restoreTransaction:(SKPaymentTransaction *)transaction
|
|
{
|
|
[self finalizeTransaction:transaction.originalTransaction];
|
|
}
|
|
|
|
/*
|
|
========================
|
|
finalizeTransaction
|
|
|
|
This method actually delivers the purchased item to the user. Currently, this means setting
|
|
a key in NSUserDefaults equal to the product ID to TRUE.
|
|
========================
|
|
*/
|
|
- (void)finalizeTransaction:(SKPaymentTransaction *)transaction
|
|
{
|
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
|
|
NSString *productID = transaction.payment.productIdentifier;
|
|
|
|
[defaults setBool:TRUE forKey:productID];
|
|
|
|
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
|
|
|
|
isInProgress = false;
|
|
|
|
if ( clientCallback ) {
|
|
clientCallback( IAP_SUCCESS );
|
|
}
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
========================
|
|
InAppPurchaseInit
|
|
|
|
Creates the instance of the payment observer and adds it to the payment queue. This should be
|
|
called at application launch.
|
|
========================
|
|
*/
|
|
void InAppPurchaseInit(void) {
|
|
if ( !storeObserver ) {
|
|
storeObserver = [[MyStoreObserver alloc] init];
|
|
|
|
// Add the observer here in case purchase requests were interrupted last time.
|
|
[[SKPaymentQueue defaultQueue] addTransactionObserver:storeObserver];
|
|
}
|
|
|
|
}
|
|
|
|
void InAppPurchaseShutdown(void) {
|
|
[storeObserver release];
|
|
storeObserver = nil;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
InAppPurchaseStartPurchase
|
|
|
|
If payments are enabled, starts an In-App Purchase transaction for the given product identifier.
|
|
If payments are not enabled, reminds the user that they can be enabled.
|
|
If a request is currently in progress, nothing happens, as only one request at a time is
|
|
allowed.
|
|
========================
|
|
*/
|
|
void InAppPurchaseStartPurchase( const char * productIdentifier ) {
|
|
// Only allow one request at a time.
|
|
if ( isInProgress ) {
|
|
return;
|
|
}
|
|
|
|
if ( [SKPaymentQueue canMakePayments] ) {
|
|
// Start transaction.
|
|
if ( storeObserver == nil ) {
|
|
printf( "In-App Purchase system not initialized. Can't purchase anything!\n" );
|
|
return;
|
|
}
|
|
|
|
isInProgress = true;
|
|
|
|
// convert the C string to an NSString.
|
|
NSString *productKey = [[NSString alloc] initWithCString:productIdentifier
|
|
encoding:NSASCIIStringEncoding];
|
|
|
|
SKProductsRequest *request= [[SKProductsRequest alloc] initWithProductIdentifiers: [NSSet setWithObject: productKey]];
|
|
|
|
// The set retains the string, so we can release it now.
|
|
[productKey release];
|
|
|
|
request.delegate = storeObserver;
|
|
[request start];
|
|
} else {
|
|
// User has disabled In-App purchases in settings. Kindly remind him that he can
|
|
// enable purchases again.
|
|
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"In-App Purchases are disabled"
|
|
message:@"You can enable In-App purchases in your device's settings."
|
|
delegate:nil
|
|
cancelButtonTitle:@"OK"
|
|
otherButtonTitles:nil];
|
|
|
|
[alert show];
|
|
[alert release];
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
========================
|
|
InAppPurchaseHasPurchased
|
|
|
|
Queries the standard NSUserDefaults object for a boolean key equal to the product identifier.
|
|
If this key is true, the user has purchased the product. If the key is false, the user has
|
|
not purchased the product.
|
|
========================
|
|
*/
|
|
bool InAppPurchaseHasPurchased( const char * productIdentifier ) {
|
|
// Convert the C string to an NSString for use with NSUserDefaults.
|
|
NSString *productKey = [[NSString alloc] initWithCString:productIdentifier
|
|
encoding:NSASCIIStringEncoding];
|
|
|
|
// Purchase records are stored in the standardUserDefaults, with a key equal to the product
|
|
// identifier.
|
|
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
|
BOOL hasProduct = [defaults boolForKey:productKey];
|
|
|
|
// This string was alloced above, but since it isn't needed anymore, it must be released.
|
|
[productKey release];
|
|
|
|
// Convert Objective-C BOOL type to standard C99 _Bool type.
|
|
return ( hasProduct )? true: false;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
InAppPurchaseIsInProgress
|
|
|
|
Returns true if an In-App Purchase request is currently pending. Only one request can be active
|
|
at a time.
|
|
========================
|
|
*/
|
|
bool InAppPurchaseIsInProgress( void ) {
|
|
return isInProgress;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
InAppPurchaseSetCallback
|
|
|
|
Sets a functino pointer to be called when the in-app purchase transaction in complete, either
|
|
successfully or unsuccessfully.
|
|
========================
|
|
*/
|
|
void InAppPurchaseSetCallback( InAppPurchaseCallbackPtr function ) {
|
|
clientCallback = function;
|
|
}
|
|
|