// iOSInAppPlugin.h


#import <StoreKit/StoreKit.h>

@interface iOSInAppPlugin : NSObject<
///< 상품 정보를 얻어올  쓰는 딜리게이트
SKProductsRequestDelegate,
///< 상품 구매 관련 옵저버
SKPaymentTransactionObserver>

+ (iOSInAppPlugin*) sharediOSInAppPlugin;
- (BOOL) initInApp;
- (void) requestProductData:(NSString*)strProductId;

- (void) completeTransaction:(SKPaymentTransaction*)transaction;
- (void) restoreTransaction:(SKPaymentTransaction*)transaction;
- (void) failedTransaction:(SKPaymentTransaction*)transaction;

- (void) restoreCompletedTransactions;

@end




// iOSInAppPlugin.m


#import "iOSInAppPlugin.h"

extern "C"
{
    void iOSInAppInit()
    {
        [[iOSInAppPlugin sharediOSInAppPlugininitInApp];
    }
    void iOSBuyItem(const char* pszProductId)
    {
        NSString* strProductId = [NSString stringWithUTF8String:pszProductId];
        [[iOSInAppPlugin sharediOSInAppPluginrequestProductData:strProductId];
    }
    void iOSRestoreCompletedTransactions()
    {
        [[iOSInAppPlugin sharediOSInAppPluginrestoreCompletedTransactions];
    }
}

@implementation iOSInAppPlugin

+ (iOSInAppPlugin*) sharediOSInAppPlugin
{
    static iOSInAppPlugin* pInstance;
    if(pInstance == NULL)
    {
        pInstance = [[iOSInAppPlugin allocinit];
    }
    return pInstance;
}

- (BOOL) initInApp
{
    ///< 인앱 결제 시스템을 사용 가능한지 체크
    if( [SKPaymentQueue canMakePayments] == NO )
        return NO;
    
    ///< Product 결제 진행에 필요한 딜리게이트 등록
    [[SKPaymentQueue defaultQueueaddTransactionObserver:self];
    
    NSLog(@"InAppPurchase init OK");
    return true;
}

///< 아이템 정보 요청
- (void) requestProductData:(NSString*)strProductId
{
    ///< iTunes Connect 설정한 Product ID
    NSSet* productIdentifiers = [NSSet setWithObject:strProductId];
    SKProductsRequest* request = [[SKProductsRequest alloc]initWithProductIdentifiers:productIdentifiers];
    request.delegate = self;
    [request start];
    NSLog(@"requestProductData %@", strProductId);
}

///< 아이템 정보 요청 결과 callback
- (void) productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
    NSLog@"InAppPurchase didReceiveResponse" );
    forSKProduct* product in response.products )
    {
        if( product != nil )
        {
            NSLog(@"InAppPurchase Product title: %@", product.localizedTitle);
            NSLog(@"InAppPurchase Product description: %@", product.localizedDescription);
            NSLog(@"InAppPurchase Product price: %@", product.price);
            //product.priceLocale
            NSLog(@"InAppPurchase Product id: %@", product.productIdentifier);
            
            ///< 구매 요청
            
            SKPayment* payment = [SKPayment paymentWithProduct:product];
            //payment.quantity = 10;
            [[SKPaymentQueue defaultQueueaddPayment:payment];
        }
    }
    
    [request release];
    
    for (NSString *invalidProductId in response.invalidProductIdentifiers)
    {
        NSLog(@"InAppPurchase Invalid product id: %@", invalidProductId);
    }
}

///< 새로운 거래가 발생하거나 갱신될  호출된다.
- (void) paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray*)transactions
{
    for (SKPaymentTransaction *transaction in transactions)
    {
        switch (transaction.transactionState)
        {
                ///< 서버에 거래 처리중
            case SKPaymentTransactionStatePurchasing:
                NSLog(@"InAppPurchase SKPaymentTransactionStatePurchasing");
                break;
                ///< 구매 완료
            case SKPaymentTransactionStatePurchased:
                [self completeTransaction:transaction];
                break;
                ///< 거래 실패 또는 취소
            case SKPaymentTransactionStateFailed:
                [self failedTransaction:transaction];
                break;
                ///< 재구매
            case SKPaymentTransactionStateRestored:
                [self restoreTransaction:transaction];
                break;
        }
    }
}

- (void) completeTransaction:(SKPaymentTransaction *)transaction
{
    NSLog(@"InAppPurchase completeTransaction");
    NSLog(@"InAppPurchase Transaction Identifier : %@", transaction.transactionIdentifier );
    NSLog(@"InAppPurchase Transaction Data : %@", transaction.transactionDate );
    ///< 구매 완료  아이템 인벤등 게임쪽  처리 진행
    /* 빌트 인 모델
    const char* pszProductId = [[[transaction payment] productIdentifier] UTF8String];
    UnitySendMessage("iOSManager", "ResultBuyItem", pszProductId);
     */
   
    NSString* strReceipt = [[NSString alloc]initWithBytes:transaction.transactionReceipt.byteslength:transaction.transactionReceipt.length encoding:NSUTF8StringEncoding];
    
    UnitySendMessage("iOSManager""ResultBuyItem", [strReceipt UTF8String]);

    // Remove the transaction from the payment queue.
    [[SKPaymentQueue defaultQueuefinishTransaction:transaction];
}

- (void) restoreTransaction:(SKPaymentTransaction *)transaction
{
    NSLog(@"InAppPurchase restoreTransaction");
    const char* pszRestoreProductId = [transaction.originalTransaction.payment.productIdentifier UTF8String];
    UnitySendMessage("iOSManager""ResultRestoreItem", pszRestoreProductId);
    [[SKPaymentQueue defaultQueuefinishTransaction:transaction];
}

- (void) failedTransaction:(SKPaymentTransaction *)transaction
{
    NSLog(@"InAppPurchase failedTransaction.");
    const char* pszResult = 0;
    if( transaction.error.code != SKErrorPaymentCancelled )
    {
        pszResult = "faileIAP";
        NSLog(@"InAppPurchase failedTransaction SKErrorDomain - %d", transaction.error.code );
    }
    else
    {
        pszResult = "cancelIAP";
        NSLog(@"InAppPurchase failedTransaction SKErrorPaymentCancelled");
    }
    UnitySendMessage("iOSManager""ResultBuyItem", pszResult);
    [[SKPaymentQueue defaultQueuefinishTransaction:transaction];
}

// 비소모성 아이템 복원 요청
- (void) restoreCompletedTransactions
{
    [[SKPaymentQueue defaultQueuerestoreCompletedTransactions];
}

@end



// iOSManager.cs


using UnityEngine;

using System.Runtime.InteropServices;

public class iOSManager : MonoBehaviour 
{
static iOSManager _instance;
private string strLog = "Unity3D iOS In App Purchase Sample";
public string strPostMsg = string.Empty;
[DllImport("__Internal")]
private static extern void iOSInAppInit();
[DllImport("__Internal")]
private static extern void iOSBuyItem(string strProductId);
[DllImport("__Internal")]
private static extern void iOSRestoreCompletedTransactions();
public static iOSManager GetInstance()
{
if( _instance == null )
{
_instance = new GameObject("iOSManager").AddComponent<iOSManager>();
}
return _instance;
}
public void InAppInit()
{
iOSInAppInit();
}

public void BuyItem(string strProductId)
{
iOSBuyItem(strProductId);
}
public void ResultBuyItem(string strResult)
{
// strResult is transaction.transactionReceipt or faileIAP or cancelIAP.
SetLog("ResultBuyItem " + strResult);
}
public void RestoreCompletedTransactions()
{
iOSRestoreCompletedTransactions();
}
public void ResultRestoreItem(string strRestoreItemId)
{
SetLog("ResultRestoreItem " + strRestoreItemId);
}

public void SetLog(string _strLog)
{
strLog = _strLog;
}
public string GetLog()
{
return strLog;
}
}

출처 : http://westwoodforever.blogspot.kr/2013/10/unity3d-integration-ios-in-app-purchase.html#links


+ Recent posts