#import <StoreKit/StoreKit.h>
#import "Subscription.h"
#import "Base64EncDec.h"
#import "JSON.h"
@implementation Subscription
// レシートの復元処理
- (NSDictionary *)verifyReceipt:(NSString *)base64Receipt {
NSURL *url = [NSURL URLWithString:SUBSCRIPTION_URL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSString *json = [NSString stringWithFormat:@"{¥"receipt-data¥":¥"%@¥", ¥"password¥":¥"%@¥"}", base64Receipt, SHARED_SECRET];
[request setHTTPBody:[json dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPMethod:@"POST"];
NSError *error;
NSURLResponse *response;
NSData *decodeData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *receipt = [[NSString alloc] initWithData:decodeData encoding:NSUTF8StringEncoding];
NSDictionary *dict = [receipt JSONValue];
[receipt release];
return dict;
}
// レシートデータの必要な項目をアプリ内に保存
- (NSInteger)savePurchaseInfo:(NSDictionary *)dict {
NSNumber *status = [dict objectForKey:@"status"];
if ([status isEqual:[NSNumber numberWithInt:0]] == NO) {
return [status integerValue];
}
// レシートデータをアプリ内に保存
NSDictionary *receiptDict = [dict objectForKey:@"latest_receipt_info"];
NSNumber *expired = [receiptDict objectForKey:@"expires_date"];
NSString *latestReceipt = [dict objectForKey:@"latest_receipt"];
// :
completed = YES;
return</code> <code>0;
}
// レシートのデコードと保存
- (BOOL)decodeReceiptWithTransaction:(NSString *)_receipt isRestore:(BOOL)_isRestore {
NSDictionary *dict = [self verifyReceipt:_receipt];
NSInteger code = [self savePurchaseInfo:dict];
if (code != 0) {
return</code> <code>NO;
} else {
if (_isRestore) {
restored = YES;
}
return</code> <code>YES;
}
}
// プロダクトの取得で呼び出されるデリゲート
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
if (response == nil) {
return;
}
for (SKProduct *product in response.products ) {
SKPayment *payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
}
- (void)failedTransaction:(SKPaymentTransaction *)transaction {
if (!showedAlert) {
showedAlert = YES;
switch ([transaction.error code]) {
case SKErrorUnknown:
// 購入処理を中止
break;
case SKErrorClientInvalid:
// 不正なクライアント
break;
case SKErrorPaymentCancelled:
// 購入処理をキャンセル
break;
case SKErrorPaymentInvalid:
// 不正な購入
break;
case SKErrorPaymentNotAllowed:
// 購入が許可されていない
break;
default:
break;
}
}
}
// 購入(リストア)トランザクション
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchasing: {
// 購入中の処理
break;
}
case SKPaymentTransactionStatePurchased: {
// 購入成功時の処理
[self decodeReceiptWithTransaction:[transaction.transactionReceipt stringEncodedWithBase64] isRestore:NO];
[queue finishTransaction:transaction];
break;
}
case SKPaymentTransactionStateFailed: {
// 購入失敗時の処理
[self failedTransaction:transaction];
[queue finishTransaction:transaction];
break;
}
case SKPaymentTransactionStateRestored: {
// 購入履歴復元時の処理
[self decodeReceiptWithTransaction:[transaction.transactionReceipt stringEncodedWithBase64] isRestore:YES];
[queue finishTransaction:transaction];
break;
}
}
}
// 購入(リストア)成功時の終了処理
if (restored || completed) {
// :
}
}
// リストア成功時の処理
- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
restored = YES;
// :
}
// リストア失敗時の処理
- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error {
// :
}
// 課金処理(クライアントから呼び出されるメソッド)
- (void) subscribe {
completed = NO;
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
productIds = [NSSet setWithObject:"プロダクトID"];
skRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:productIds];
skRequest.delegate = self;
[skRequest start];
}
// リストア処理(クライアントから呼び出されるメソッド)
- (void)restore {
restored = NO;
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
[[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
}
- (void) dealloc {
[[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
[super dealloc];
}
@end