Unity3d接入IOS內購__IOS

來源:互聯網
上載者:User

利用Unity3d製作完畢遊戲發布到appstore,有時會做遊戲內購買虛擬物品,也就是內購。

在Ios開發中叫做:In App Purchase,簡稱IAP

那麼如何在unity3d內嵌入IPA呢。幾經輾轉,多方搜尋,摸索出點經驗,分享給大家,如有疏漏,還請指教。

當然也有人們寫好的外掛程式可用,我覺得自己寫的才用著順手。

 

一、準備條件:

1、 申請蘋果開發人員帳號。後台先建立認證,在建立應用,填寫應用詳情,建立測試用的帳號,建立內購項目。

這雷根據需要建立consumable(每次都需要購買)或者non-consumable的(購買一次一直可用,就是如果買過可以恢複購買)內購項目。

如下我們建立了non-consumable類型,名稱“Package_2”,這個名稱僅能使用一次,即使刪除了也不能夠再次利用。


 

建立測試人員帳號,可以免費測試購買本開發人員帳號下面所有應用的物品:


 

2、簡單瞭解ios開發的Object-C語言,主要是用來做內購,詳細請百度:

3、簡單瞭解IPA

詳細請參見:StoreKit Guide(In App Purchase)翻譯

http://yarin.blog.51cto.com/1130898/549141

4、瞭解unity3d與ios通訊,詳細參見:為iOS建立外掛程式 Building Plugins for iOS

http://game.ceeger.com/Manual/PluginsForIOS.html

 

二、下面我們單獨建立一個例子來示範:

1、 建立工程,切換到ios平台、建立空gameobject,改名為Main,建立點擊按鈕觸發購買的指令碼,掛在Main上面。建立平台檔案,下面建立子檔案夾IOS。

2、 在設定裡面修改包名,改為你自己在appstore後台建立的名稱


IPADemo裡面編寫與ios通訊代碼以及購買代碼,其中內購商品名稱修改為自己appstore後台定義的:private stringproduct = "Package_2";

 

using UnityEngine;

using System.Collections;

using System.Collections.Generic;

using System.Runtime.InteropServices;

 

public class IPADemo : MonoBehaviour {

 

         publicList<string> productInfo = new List<string>();

 

         privatestring product = "Package_2";

        

         [DllImport("__Internal")]

         privatestatic extern void TestMsg();//測試資訊發送

        

         [DllImport("__Internal")]

         privatestatic extern void TestSendString(string s);//測試發送字串

        

         [DllImport("__Internal")]

         privatestatic extern void TestGetString();//測試接收字串

        

         [DllImport("__Internal")]

         privatestatic extern void InitIAPManager();//初始化

        

         [DllImport("__Internal")]

         privatestatic extern bool IsProductAvailable();//判斷是否可以購買

        

         [DllImport("__Internal")]

         privatestatic extern void RequstProductInfo(string s);//擷取商品資訊

        

         [DllImport("__Internal")]

         privatestatic extern void BuyProduct(string s);//購買商品

        

         //測試從xcode接收到的字串

         voidIOSToU(string s)

         {

                   Debug.Log("[MsgFrom ios]"+s);

         }

        

         //擷取product列表

         voidShowProductList(string s){

                   productInfo.Add(s);

         }

        

         //擷取商品回執

         voidProvideContent(string s)

         {

                   Debug.Log("[MsgFrom ios]proivideContent : "+s);

         }

         voidStart ()

         {

                   InitIAPManager();

         }

         voidUpdate ()

         {                          

         }

        

         voidOnGUI()

         {                

                   if(Btn("GetProducts")){

                            if(!IsProductAvailable())

                                     thrownew System.Exception("IAP not enabled");

                            productInfo= new List<string>();

                            RequstProductInfo(product);

                   }

                  

                   GUILayout.Space(40);

                  

                   for(inti=0; i<productInfo.Count; i++){

                            if(GUILayout.Button(productInfo[i],GUILayout.Height (100), GUILayout.MinWidth (200))){

                                     string[]cell = productInfo[i].Split('\t');

                                     Debug.Log("[Buy]"+cell[cell.Length-1]);

                                     BuyProduct(cell[cell.Length-1]);

                            }

                   }

         }

        

         boolBtn(string msg){

                   GUILayout.Space(100);

                   return       GUILayout.Button (msg,GUILayout.Width(200),GUILayout.Height(100));

         }

}

 

還需要在xcode裡面編寫內購代碼然後複製到平台下,ios檔案夾下:


只能在真機上才能出現內購窗,Unity中運行效果如下:


 

3、匯出ios工程,在mac上xcode中開啟:

4、加入依賴項,libz,storekit:


5、在真機上運行,首先獲得商品列表,然後點擊購買,然後在彈出的帳號密碼框裡面修改為沙箱測試帳號。即可測試購買成功。


 2個.h檔案分別為:

1、IAPInterface.h


#import <Foundation/Foundation.h>


@interface IAPInterface : NSObject


@end


2、IAPManager.h


#import <Foundation/Foundation.h>
#import <StoreKit/StoreKit.h>


@interface IAPManager : NSObject<SKProductsRequestDelegate, SKPaymentTransactionObserver>{
    SKProduct *proUpgradeProduct;
    SKProductsRequest *productsRequest;
}


-(void)attachObserver;
-(BOOL)CanMakePayment;
-(void)requestProductData:(NSString *)productIdentifiers;
-(void)buyRequest:(NSString *)productIdentifier;


@end


 2個.m檔案分別為:

1/IAPManager.m

#import "IAPManager.h"

@implementation IAPManager


-(void) attachObserver{
    NSLog(@"AttachObserver");
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}


-(BOOL) CanMakePayment{
    return [SKPaymentQueue canMakePayments];
}


-(void) requestProductData:(NSString *)productIdentifiers{
    NSArray *idArray = [productIdentifiers componentsSeparatedByString:@"\t"];
    NSSet *idSet = [NSSet setWithArray:idArray];
    [self sendRequest:idSet];
}


-(void)sendRequest:(NSSet *)idSet{
    SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:idSet];
    request.delegate = self;
    [request start];
}


-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    NSArray *products = response.products;
    
    for (SKProduct *p in products) {
        UnitySendMessage("Main", "ShowProductList", [[self productInfo:p] UTF8String]);
    }
    
    for(NSString *invalidProductId in response.invalidProductIdentifiers){
        NSLog(@"Invalid product id:%@",invalidProductId);
    }
    
    [request autorelease];
}


-(void)buyRequest:(NSString *)productIdentifier{
    SKPayment *payment = [SKPayment paymentWithProductIdentifier:productIdentifier];
    [[SKPaymentQueue defaultQueue] addPayment:payment];
}


-(NSString *)productInfo:(SKProduct *)product{
    NSArray *info = [NSArray arrayWithObjects:product.localizedTitle,product.localizedDescription,product.price,product.productIdentifier, nil];
    
    return [info componentsJoinedByString:@"\t"];
}


-(NSString *)transactionInfo:(SKPaymentTransaction *)transaction{
    
    return [self encode:(uint8_t *)transaction.transactionReceipt.bytes length:transaction.transactionReceipt.length];
    
    //return [[NSString alloc] initWithData:transaction.transactionReceipt encoding:NSASCIIStringEncoding];
}


-(NSString *)encode:(const uint8_t *)input length:(NSInteger) length{
    static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
    
    NSMutableData *data = [NSMutableData dataWithLength:((length+2)/3)*4];
    uint8_t *output = (uint8_t *)data.mutableBytes;
    
    for(NSInteger i=0; i<length; i+=3){
        NSInteger value = 0;
        for (NSInteger j= i; j<(i+3); j++) {
            value<<=8;
            
            if(j<length){
                value |=(0xff & input[j]);
            }
        }
        
        NSInteger index = (i/3)*4;
        output[index + 0] = table[(value>>18) & 0x3f];
        output[index + 1] = table[(value>>12) & 0x3f];
        output[index + 2] = (i+1)<length ? table[(value>>6) & 0x3f] : '=';
        output[index + 3] = (i+2)<length ? table[(value>>0) & 0x3f] : '=';
    }
    
    return [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
}


-(void) provideContent:(SKPaymentTransaction *)transaction{
    UnitySendMessage("Main", "ProvideContent", [[self transactionInfo:transaction] UTF8String]);
}


-(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];
                break;
            default:
                break;
        }
    }
}


-(void) completeTransaction:(SKPaymentTransaction *)transaction{
    NSLog(@"Comblete transaction : %@",transaction.transactionIdentifier);
    [self provideContent:transaction];
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}


-(void) failedTransaction:(SKPaymentTransaction *)transaction{
    NSLog(@"Failed transaction : %@",transaction.transactionIdentifier);
    
    if (transaction.error.code != SKErrorPaymentCancelled) {
        NSLog(@"!Cancelled");
    }
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}


-(void) restoreTransaction:(SKPaymentTransaction *)transaction{
    NSLog(@"Restore transaction : %@",transaction.transactionIdentifier);
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}




@end


2、#import "IAPInterface.h"
#import "IAPManager.h"


@implementation IAPInterface


void TestMsg(){
    NSLog(@"Msg received");


}


void TestSendString(void *p){
    NSString *list = [NSString stringWithUTF8String:p];
    NSArray *listItems = [list componentsSeparatedByString:@"\t"];
    
    for (int i =0; i<listItems.count; i++) {
        NSLog(@"msg %d : %@",i,listItems[i]);
    }
    
}


void TestGetString(){
    NSArray *test = [NSArray arrayWithObjects:@"t1",@"t2",@"t3", nil];
    NSString *join = [test componentsJoinedByString:@"\n"];
    
    
    UnitySendMessage("Main", "IOSToU", [join UTF8String]);
}


IAPManager *iapManager = nil;


void InitIAPManager(){
    iapManager = [[IAPManager alloc] init];
    [iapManager attachObserver];
    
}


bool IsProductAvailable(){
    return [iapManager CanMakePayment];
}


void RequstProductInfo(void *p){
    NSString *list = [NSString stringWithUTF8String:p];
    NSLog(@"productKey:%@",list);
    [iapManager requestProductData:list];
}


void BuyProduct(void *p){
    [iapManager buyRequest:[NSString stringWithUTF8String:p]];
}


@end


相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.