- (void) purchase:(NSString *)productId
// 製品情報を取得、複数のID渡せますが、この記事では単品のみ対応します
NSSet* products = [[NSSet alloc] initWithObjects: productId, nil];
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers: products];
// AppControllerはSKProductsRequestDelegateを継承しているので、selfにします
productsRequest.delegate = self;
// このメソードはSKProductsRequestDelegateの一部
- (void) productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
if (response.products.count == 0) {
for (NSString *invalidProductId in response.invalidProductIdentifiers)
NSLog(@"Invalid product id: %@" , invalidProductId);
NSArray* products = response.products;
SKProduct *product = [products firstObject];
SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addPayment:payment];
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
// 全てのtransactionをイテレートする
// この記事では成功と失敗しか処理をしませんが、全て考慮する必要がある
for (SKPaymentTransaction *transaction in transactions) {
NSString* productId = transaction.payment.productIdentifier;
switch (transaction.transactionState) {
// Call the appropriate custom method for the transaction state.
case SKPaymentTransactionStatePurchasing:
case SKPaymentTransactionStateDeferred:
case SKPaymentTransactionStateFailed:
[self purchaseFail:transaction];
NSLog(@"failed!!! %i %@", [transaction.error code], [transaction.error localizedDescription]);
case SKPaymentTransactionStatePurchased:
[self purchaseOk:transaction];
case SKPaymentTransactionStateRestored:
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
NSLog(@"Unexpected transaction state %@", @(transaction.transactionState));
- (void) purchaseFail:(SKPaymentTransaction *)transaction
// cocos2d-xのDirectorで「purchase:fail」のeventを発行
// idをUserDataとしてeventに保存
auto event = new cocos2d::EventCustom("purchase:fail");
NSString* error = [transaction.error localizedDescription];
std::string err = [error UTF8String];
event->setUserData(&err);
cocos2d::Director::getInstance()->getEventDispatcher()->dispatchEvent(event);
- (void) purchaseOk:(SKPaymentTransaction *)transaction
// cocos2d-xのDirectorで「purchase:ok」のeventを発行
// idをUserDataとしてeventに保存
auto event = new cocos2d::EventCustom("purchase:ok");
NSString* productId = transaction.payment.productIdentifier;
std::string str = [productId UTF8String];
event->setUserData(&str);
_pendingTransaction = transaction;
cocos2d::Director::getInstance()->getEventDispatcher()->dispatchEvent(event);