PHP群:95885625 Hbuilder+MUI群:81989597 站长QQ:634381967
    您现在的位置: 首页 > 开发编程 > Unity3D教程 > 正文

    Unity-iOS内购流程

    作者:张志勇来源:原创浏览:时间:2020-09-30 00:07:50我要评论
    导读:做手游想要上架都得经过内购这一步,虽然很多都是给苹果官方做样子的第一步账号登陆iTunes Connect 创建app在功能里边创建App内购买项目...
    做手游想要上架都得经过内购这一步,虽然很多都是给苹果官方做样子的
    第一步
    账号登陆iTunes Connect 创建app
    在功能里边创建App内购买项目
    这几项是必填的,其余的用于测试的话不用填
    Unity-iOS内购流程
     
    产品ID记下来等会要用
    价格:以后正式版用的时候要对比一下,右边有所有价格和货币
    创建完之后是这个样子,元数据丢失也可以用于测试,正式版的时候可以把图片什么的都加上就没问题了
     
    Unity-iOS内购流程
     
    第二步
    左上角点击用户和职能
    进来创建一个沙箱测试账号
    Unity-iOS内购流程
     OK第二步完成,网页的操作就到这里
     
    接下来进入Unity3D(最下边把代码粘贴上来,原谅我不会传文件在这里)
    2个必要文件
    IAPInterface的.h .m文件
    IAPManager的.h .m文件
    目录一定要放在Plugins下的IOS文件夹下,自己建
    然后场景内创建一个物体,组建创建一个脚本IAPExample
    Unity-iOS内购流程
     
    代码里边有public对象就是自己在第一步创建的内购项目
    package_02就是产品ID
    可以创建多个内购项目,比如6元=6000钻石,10元=100000钻石等
    只需要在这个挂载脚本上边修改size,然后产品ID填对就行
     
    最后就是生成xcode代码了,注意在Bundle identifier中填写正确
    生成之后在xcode运行到手机上
    在xcode中添加框架StoreKit. work
    注:
    1. 测试手机的UDID要添加在开发者账号
    2.ARC下使用非ARC文件要在文件后加-fno-objc-arc
    3.NOTURN报错,就把#define NORETURN __declspec(noreturn)
    修改为#define NORETURN __attribute__((noreturn))
    4.在游戏内登陆测试账号比较容易成功,外部我试了很多次都失败了,我也很奇怪,没找到原因
    5.如果测试过程中返回的错误信息是无法连接itnue,就换个开发者账号,同样没找到什么原因
     
     
    代码:

    IAPManager.h

    #import <Foundation/Foundation.h>

    #import <StoreKit/StoreKit.h>

     

    @interface IAPManager : NS <SKProductsRequestDelegate, SKPaymentTransactionObserver>{

        SKProduct *proUpgradeProduct;

        SKProductsRequest *productsRequest;

    }

     

    -(void)attachObserver;

    -(BOOL)CanMakePayment;

    -(void)requestProductData:(NSString *)productIdentifiers;

    -(void)buyRequest:(NSString *)productIdentifier;

     

     

    @end

     

    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 = [NSArrayarrayWith s:product.localized ,product.localizedDe ion,product.price,product.productIdentifier, nil];

        

        return [info componentsJoinedByString:@"\t"];

    }

     

    -(NSString *)transactionInfo:(SKPaymentTransaction *)transaction{

        

        return [self encode:(uint8_t *)transaction.transactionReceipt.byteslength: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

     

     

    IAPInterface.h

    #import <Foundation/Foundation.h>

     

    @interface IAPInterface : NS

     

    @end

     

    IAPInterface.m

    #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 arrayWith s:@"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

     

     

    最后一个IAPExample

    using UnityEngine;
    using System.Collections;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;

    public class IAPExample : MonoBehaviour {
        
        public List<string> productInfo = new List<string>();
        
        [DllImport("__Internal")]
        private static extern void TestMsg();//测试信息发送
        
        [DllImport("__Internal")]
        private static extern void TestSendString(string s);//测试发送字符串
        
        [DllImport("__Internal")]
        private static extern void TestGetString();//测试接收字符串
        
        [DllImport("__Internal")]
        private static extern void InitIAPManager();//初始化
        
        [DllImport("__Internal")]
        private static extern bool IsProductAvailable();//判断是否可以购买
        
        [DllImport("__Internal")]
        private static extern void RequstProductInfo(string s);//获取商品信息
        
        [DllImport("__Internal")]
        private static extern void BuyProduct(string s);//购买商品
        
        //测试从xcode接收到的字符串
        void IOSToU(string s){
            Debug.Log ("[MsgFrom ios]"+s);
        }
        
        //获取product列表
        void ShowProductList(string s){
            productInfo.Add (s);
        }
        bool back = false;
        //获取商品回执
        void ProvideContent(string s){
            Debug.Log ("[MsgFrom ios]proivideContent : "+s);
            back = true;
        }
        
        
        // Use this for initialization
        void Start () {
            InitIAPManager();
        }
        
        // Update is called once per 
        void Update () {
        
        }
        
        void OnGUI(){
            /*if(GUILayout.Button("Test 1",GUILayout.Width(200), GUILayout.Height(100)))
                TestMsg();
            
            GUILayout.Space (200);
            if(GUILayout.Button("Test 1",GUILayout.Width(200), GUILayout.Height(100)))
                TestSendString("This is a msg form unity3d\tt1\tt2\tt3\tt4");
            
            GUILayout.Space (200);
            if(GUILayout.Button("Test 1",GUILayout.Width(200), GUILayout.Height(100)))
                TestGetString();
            /********通信测试***********/
            
            if(Btn ("GetProducts")){
                if(!IsProductAvailable())
                    throw new System.Exception("IAP not enabled");
                productInfo = new List<string>();
    //            RequstProductInfo("com.dollar.one\tcom.dollar.two");
    //            RequstProductInfo("com.aladdin.fishpocker1");
                RequstProductInfo("com.shediao.fishing");
            }
            
            GUILayout.Space(40);

            if (back)
                GUI.Label (new Rect (10, 150, 100, 100), "Message back");

            for(int i=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]);
                    GUI.Label(new Rect (10, 10, 100, 200), string.Format("[Buy]{0}" ,cell[cell.Length-1]));
                }  
            }
        }
        
        bool Btn(string msg){
            GUILayout.Space (100);
            return     GUILayout.Button (msg,GUILayout.Width (200),GUILayout.Height(100));
        }
    }


    转载请注明(B5教程网)原文链接:https://b5.mxunkeji.com/content-130-6043-1.html
    相关热词搜索:
    下一篇:最后一页