#if __OSX__ #include "stdneb.h" #include "ALStoreKit.h" //#import "GTMBase64.h" #include #include "util/array.h" #include "util/string.h" #include "util/dictionary.h" using namespace NALSystem; @implementation ALStoreKit @synthesize m_pStoreKitDelegate; @synthesize transactionResults; - (id) init { self = [super init]; if (self) { m_pStoreKitDelegate = NULL; transactionResults = [[NSMutableArray alloc] init]; [[SKPaymentQueue defaultQueue] addTransactionObserver:self]; priceRequest = NULL; buyRequest = NULL; NSLog(@"Transaction Observer added !"); } return self; } - (void) startWithProductIdentifiers:(NSArray *)productIdentifiers { NSLog(@"Send product request to App Store, Product Identifiers:\n %@",productIdentifiers); if ([SKPaymentQueue canMakePayments]) { if ([productIdentifiers count] > 0) { buyRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithArray:productIdentifiers]]; buyRequest.delegate = self; [buyRequest start]; //[buyRequest release]; } } else { std::string error("This device is not able or allowed to make payments"); std::cout<onStoreKitPurchaseFailedWithError("","",ALSystem::SKErrorPaymentNotAllowed,error.c_str()); } } } - (void)requestPrice:(NSArray *)productIdentifiers { NSLog(@"Reques price for Product Identifiers:\n %@",productIdentifiers); if ([productIdentifiers count] > 0) { priceRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithArray:productIdentifiers]]; priceRequest.delegate = self; [priceRequest start]; //[priceRequest release]; } } - (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response { NSArray *myProduct = response.products; NSLog(@"Receive product response:"); for(SKProduct *product in myProduct){ NSLog(@"Product Identifier: %@" , product.productIdentifier); NSLog(@"Product Title: %@" , product.localizedTitle); NSLog(@"Product Description: %@" , product.localizedDescription); NSLog(@"Product Price: %@%@" , [product.priceLocale objectForKey:NSLocaleCurrencySymbol],product.price); } NSLog(@"Total Product Quantity: %d", [myProduct count]); //request if (request == priceRequest) { Util::Dictionary priceMap; for (SKProduct *product in myProduct) { NSString* price = [NSString stringWithFormat:@"%@%@",[product.priceLocale objectForKey:NSLocaleCurrencySymbol],product.price]; std::string priceStd = price.UTF8String; priceMap.Add(product.productIdentifier.UTF8String, priceStd.c_str()); } for (NSString* invalidID in response.invalidProductIdentifiers) { NSLog(@"Product Identifier: %@ is invalid, price = 0",invalidID); priceMap.Add(invalidID.UTF8String, "0"); } if (priceMap.Size() > 0) { m_pStoreKitDelegate->onStoreKitGetProductPrice(priceMap); } } else if (request == buyRequest) { //buy if ([response.invalidProductIdentifiers count] > 0) { NSArray* invalidProductIdentifiers = response.invalidProductIdentifiers; // std::vectorinvalidIDVector; for (NSString* invalidID in invalidProductIdentifiers) { NSLog(@"Invalid Product Identifier: %@",invalidID); // invalidIDVector.push_back([invalidID UTF8String]); if (self.m_pStoreKitDelegate) { self.m_pStoreKitDelegate->onStoreKitValidateProductIDFailed([invalidID UTF8String]); } } } NSArray *products = response.products; for (SKProduct *product in products) { NSLog(@"Add product %@ to payment queue", product.productIdentifier); [[SKPaymentQueue defaultQueue] addPayment:[SKPayment paymentWithProduct:product]]; } } } - (void)request:(SKRequest *)request didFailWithError:(NSError *)error { NSString* errorStr = [NSString stringWithFormat:@"Product request failed. error description: %@",[error localizedDescription]]; NSLog(@"%@", errorStr); std::string stdError([errorStr UTF8String]); if (self.m_pStoreKitDelegate) { self.m_pStoreKitDelegate->onStoreKitPurchaseFailedWithError("","",ALSystem::SKErrorRequestFailed,stdError.c_str()); } } - (void)requestDidFinish:(SKRequest *)request { if (priceRequest == request) { NSLog(@"price request finished"); priceRequest = NULL; } if (buyRequest == request) { NSLog(@"buy request finished"); buyRequest = NULL; } } #pragma mark payments - (NSString*)base64forData:(NSData*)theData { const uint8_t* input = (const uint8_t*)[theData bytes]; NSInteger length = [theData length]; static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4]; uint8_t* output = (uint8_t*)data.mutableBytes; NSInteger i; for (i=0; i < length; i += 3) { NSInteger value = 0; NSInteger j; for (j = i; j < (i + 3); j++) { value <<= 8; if (j < length) { value |= (0xFF & input[j]); } } NSInteger theIndex = (i / 3) * 4; output[theIndex + 0] = table[(value >> 18) & 0x3F]; output[theIndex + 1] = table[(value >> 12) & 0x3F]; output[theIndex + 2] = (i + 1) < length ? table[(value >> 6) & 0x3F] : '='; output[theIndex + 3] = (i + 2) < length ? table[(value >> 0) & 0x3F] : '='; } //return [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease]; return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]; } - (void) completedPurchaseTransaction: (SKPaymentTransaction *) transaction { // NSString* orgTransactionReceipt = [[[NSString alloc] initWithData:transaction.transactionReceipt encoding:[NSString defaultCStringEncoding]] autorelease]; NSString* orgTransactionReceipt = [[NSString alloc] initWithData:transaction.transactionReceipt encoding:[NSString defaultCStringEncoding]]; NSLog(@"Transaction succeed! productIdentifier: %@. transactionIdentifier: %@.",transaction.payment.productIdentifier, transaction.transactionIdentifier); NSLog(@"transactionReceipt: %@",orgTransactionReceipt); NSString* transactionReceiptStr = [NSString stringWithFormat:@"%@",[self base64forData:transaction.transactionReceipt]]; [transactionResults addObject:transaction]; const std::string productIdentifier([transaction.payment.productIdentifier UTF8String]); const std::string transactionIdentifier([transaction.transactionIdentifier UTF8String]); const std::string transactionReceipt([transactionReceiptStr UTF8String]); if (m_pStoreKitDelegate != NULL) { m_pStoreKitDelegate->onStoreKitPurchaseSucceed(productIdentifier.c_str(), transactionIdentifier.c_str(), transactionReceipt.c_str()); } } - (void) handleFailedTransaction: (SKPaymentTransaction *) transaction { std::string error([[transaction.error description] UTF8String]); ALSystem::SK_ERROR errorType; switch (transaction.error.code) { case SKErrorUnknown: errorType = ALSystem::SKErrorUnknown; break; case SKErrorClientInvalid: errorType = ALSystem::SKErrorClientInvalid; break; case SKErrorPaymentCancelled: errorType = ALSystem::SKErrorPaymentCancelled; break; case SKErrorPaymentNotAllowed: errorType = ALSystem::SKErrorPaymentNotAllowed; break; default: errorType = ALSystem::SKErrorUnknown; break; } NSLog(@"Transaction failed : %@, %@, %d, %@",transaction.transactionIdentifier,transaction.payment.productIdentifier, transaction.error.code, [transaction.error description]); [self.transactionResults addObject:transaction]; if (self.m_pStoreKitDelegate != NULL) { self.m_pStoreKitDelegate->onStoreKitPurchaseFailedWithError([transaction.payment.productIdentifier UTF8String],[transaction.transactionIdentifier UTF8String], errorType, error.c_str()); } } - (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions { NSLog(@"Payment queue updated, a transaction state changed."); for (SKPaymentTransaction *transaction in transactions) { switch (transaction.transactionState) { case SKPaymentTransactionStatePurchased: //交易完成 NSLog(@"Handle a purchased transaction..."); [self completedPurchaseTransaction:transaction]; break; case SKPaymentTransactionStateRestored: //Transaction was restored from user's purchase history NSLog(@"Handle a restored transaction..."); [self completedPurchaseTransaction:transaction]; break; case SKPaymentTransactionStateFailed: NSLog(@"Handle a failed transaction..."); [self handleFailedTransaction:transaction]; //交易失败 break; case SKPaymentTransactionStatePurchasing: //商品添加进列表 NSLog(@"Product %@ added to payment queue!",transaction.payment.productIdentifier); break; default: NSLog(@"Unknown transaction state."); break; } } } - (void) repurchase { NSLog(@"repurchase"); [[SKPaymentQueue defaultQueue] restoreCompletedTransactions]; } - (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue { } - (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error { } - (void)paymentQueue:(SKPaymentQueue *)queue removedTransactions:(NSArray *)transactions { } - (void)finishTransaction:(NSString *)aTransactionID { for (SKPaymentTransaction *transaction in transactionResults) { if ([transaction.transactionIdentifier isEqualToString:aTransactionID]) { [[SKPaymentQueue defaultQueue] finishTransaction: transaction]; NSLog(@"Finish transaction: transaction ID: %@, product ID: %@",transaction.transactionIdentifier,transaction.payment.productIdentifier); [transactionResults removeObject:transaction]; break; } } } - (void)dealloc { //[transactionResults release]; transactionResults = nil; [[SKPaymentQueue defaultQueue] removeTransactionObserver:self]; //[super dealloc]; } @end #endif