京城游戏人-Day11: Unity 中实现 IAP 内购(内付费)
来源:互联网 发布:黑社会2 知乎 编辑:程序博客网 时间:2024/05/28 03:02
京城游戏人-Day11: Unity 中实现 IAP 内购(内付费)
-
- 作者:大锐哥
- 地址:http://blog.csdn.net/prevention
-
一、先说基本流程
- 在 iTunes Connect 中创建 IAP(In-App Purchase)
- 编写 Objective-C 的代码
- 编写 Unity C# 的代码
- 生成 iOS 工程,并在 Xcode 中调试
其中在 iTunes Connect 中的操作,与研发关系不大,这里省略。
二、编写 Objective-C 代码
创建两个类,分别是 IAPInterface,主要用于两种语言之间的交互调用。另一个是 IAPManager。注意这两个类的名字叫什么并不重要。
2.1 IAPInterface.h
#import <Foundation/Foundation.h>@interface IAPInterface : NSObject@end
2.2 IAPInterface.m
#import "IAPInterface.h"#import "IAPManager.h"@implementation IAPInterface...@end
其中...
包括如下方法。
// Unity to iOSvoid TestMsg() { NSLog(@"Msg recved"); }// Unity to iOSvoid TestSendString(void *p) { NSString *list = [NSString stringWithUTF8String:p]; NSArray *listItems = [list componentsSeparateByString:@"\t"]; for (int i = 0; i < listItems.count; ++i) { NSLog(@"msg %d: %@", i, listItems[i]); }}// iOS to Unityvoid 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]];}
2.3 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.4 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
三、Unity 的 C# 代码
先在 Unity 中创建一个名为Main
的Empty Object
。并创建如下脚本,添加为Main
的组件。该脚本名称随意。
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); } //获取商品回执 void ProvideContent(string s){ Debug.Log ("[MsgFrom ios]proivideContent : "+s); } // Use this for initialization void Start () { InitIAPManager(); } // Update is called once per frame 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("test"); // 获取商品信息!InApp 的 ID,可以用 \n 搞 n 个 } GUILayout.Space(40); 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]); // 购买! } } } bool Btn(string msg){ GUILayout.Space (100); return GUILayout.Button (msg,GUILayout.Width (200),GUILayout.Height(100)); }}
-
- 作者:大锐哥
- 地址:http://blog.csdn.net/prevention
-
0 0
- 京城游戏人-Day11: Unity 中实现 IAP 内购(内付费)
- 京城游戏人-Day18: Unity 中如何进行 iOS 内购结果的验证?
- IOS应用内付费(IAP)代码实现
- IOS应用内付费(IAP)代码实现
- IOS应用内付费(IAP)代码实现
- IAP应用内付费怎么实现?
- Cocos2d-x使用iOS游戏内付费IAP(C++篇)
- Cocos2d-x使用iOS游戏内付费IAP(C++篇)
- Cocos2d-x使用iOS游戏内付费IAP(C++篇)
- Cocos2d-x使用iOS游戏内付费IAP(C++篇)
- Cocos2d-x使用iOS游戏内付费IAP(C++篇)
- Cocos2d-x使用iOS游戏内付费IAP(C++篇)
- Cocos2d-x使用iOS游戏内付费IAP
- Cocos2d-x使用iOS游戏内付费IAP(C++篇)
- unity3d 游戏内付费
- 游戏内付费
- (转)iOS应用内付费(IAP)开发步骤列表
- iOS 应用内付费(IAP)开发步骤
- 标签的使用(二)
- [PAT]1012. The Best Rank (25)
- IME 消息 函数 常量
- 来来来,一步一步带你使用Git和GitHub(详细讲解.gitignore)
- 使用pyinstaller打包Python3.5+PyQt5.6项目生成exe文件
- 京城游戏人-Day11: Unity 中实现 IAP 内购(内付费)
- Tomcat8.x Request、Response创建的地方
- 京城游戏人-Day12: Unity 中 UI 随屏幕大小等比缩放
- poj 2187
- 同余方程组求解
- 用C语言改写C++的类
- 51Nod-1100-斜率最大
- Ubuntu14.10环境下MySQL5.6.23源码安装MySQL安装小结
- 四大CPU体系结构ARM、X86/Atom、MIPS、PowerPC