http://blog.sina.com.cn/s/blog_4a2183a60101lc8a.html
这几天做app的内购功能,发现网上找的资料都很老了,基本都是2012年以前的,而且基本都是针对有Object-C基础的写的。作为一个从来没有接触过Object-C和XCode的家伙傻逗表示看起来压力山大。教程基本都是纯Object-C代码,涉及到跟Unity交互的很少,也是花了我不少时间。而且都没有demo!下载的插件又复杂的要死根本看不懂。后来经过不懈的google终于在三天里实现了iap,于是写个总结方便那些跟我一样的纯Object-C新手。
教程已经解释的很清楚的我就不再博客里重复了,主要是整理整个完整的流程然后针对教程没有提到的情况做些讲解。
第一步是申请苹果开发者账号,99刀一年。然后设置你的项目,内功功能并申请一个测试账号用来在sandbox里测试。详细教程请点击
【iOS开发必收藏】详解iOS应用程序内使用IAP/StoreKit付费、沙盒(SandBox)测试、创建测试账号流程!
这里遇到了第一个问题,
itunesconnection 连不上-.-
解决方法:
Itunesconnect 打不开 解决办法
然后是第二个问题如何填写BankInfo 还有CNAPS是什么哪里查
CNAPS地址是银行的一个唯一代码,
网上很多教程里给的地址都打不开,这个是绝对可用的
点击:
查询开户银行的现代化支付行号
再有就是网银点开里面有个啥银行资料的也有支付行号,不过是几个excel文档要自己搜索,真小气。
ShaDou开户银行遇到点问题,银行发票上的开户银行和网银上的开户银行居然不一致,后来打银行电话得到的那个银行名字查不到支付行号,google也查不到那家银行,估计是改过名字或者搬过家信息没同步更新吧。反正用找到行号填写账户名是可以用的。
填写账户名的时候填中文名的
汉语拼音就可以了,这个也是教程里没提到的。之前填了中文不认,然后打电话给银行银行说什么要开外币账户才有英文账号,其实不用。汉语拼音就可以了。
Xcode代码最开始我参考的是这篇:
unity 嵌入iOS的IAP
不过这篇是2011年的,写的不是很清楚,有些函数也是被Xcode弃用了的旧代码,中间出了些错误页不知道怎么解决。
于是我花了好久终于找到一篇满意的:
Store Kit Guide(In App Purchase)翻译
这篇有iap流程的图解,每个函数都说的很详细,不过在看这个之前我已经通过前面的学习熟悉了Object-C的基本语法,所以看起来终于不会一头雾水了。
Object-C语法简介看这里
之前看很多教程里还有一个错误就是说 iOS跟 Unity通信必须用.mm也就是Object-C++脚本,后来我看了下文档发现不用。误会估计是中文文档翻译的时候造成的,里面有个.mm格式的例子:
为iOS创建插件 Building Plugins for iOS。然后很多人就以为必须用.mm格式才可以跟Unity通信。 不是的,看原版就知道Object-C的.m格式也可以用,而且不用写 extern "C" , 更方便直接就可以用,所以U官方也就没给例子。大家直接用.m的就可以了。
iOS 跟 Unity 通信的话 一个是函数可以返回基本的 int bool之类的,还有一个就是UnitySendMessage函数,可以传字符串。
然后一个就是导入库,使用内购功能需要在XCode 里面导入 StoreKit 库。导入方法:
ios Xcode 如何导入类库
坑爹的就是每次编译xcode都需要导入一次......
demo下载地址
百度网盘 :
里面包含一个cs 文件
IAPExample.cs 使用例子,脚本
四个插件文件在Plugin/IOS下面
IAPInterface.h
IAPInterface.m Object-C 文件, unity跟xcode的接口
IAPManager.h
IAPManager.m Object-C 文件,处理内购并回调unity函数。
处理过程参考的
Store Kit Guide(In App Purchase)翻译里的内容。
调用外部函数应该不用说了吧?
using System.Runtime.InteropServices;
然后
[DllImport("__Internal")]
private static extern xxx XXX(xx);
不会的同学看Unity手册 :
Building Plugins for iOS
我写了几个我认为常用的接口
Object-C 接口
IAPInterface.m
C#语言:
高亮代码由发芽网提供
void InitIAPManager();
//初始化,设置事件监听
bool IsProductAvailable(); //返回玩家是否开启IAP内购
void RequstProductInfo( void *p); //输入商品key列表获取商品信息
void BuyProduct( void *p); //输入商品key 购买商品
bool IsProductAvailable(); //返回玩家是否开启IAP内购
void RequstProductInfo( void *p); //输入商品key列表获取商品信息
void BuyProduct( void *p); //输入商品key 购买商品
iOS 返回到Unity的接口
IAPExample.cs
C#语言:
高亮代码由发芽网提供
void ShowProductList(
string s);
//获取xcode返回的一个product信息
void ProvideContent( string s); //获取xcode返回的商品回执
void ProvideContent( string s); //获取xcode返回的商品回执
至于错误提示可以根据需要是直接由Xcode做还是返回到Untiy之类的处理。
我是直接在Xcode里做了。想要在unity里处理的同学就照着这个自己写就好了.
因为技术有限,所以做的比较糙。这个工程只能编译后在真机上连接xcode跑,u里是跑不起来的。
详细功能在IAPManager.m里实现,IAPInterface.m是给Unity调用的接口。
C#语言:
高亮代码由发芽网提供
1 IAPManager *iapManager = nil;
2
3 void InitIAPManager(){
4 iapManager = [[IAPManager alloc] init];
5 [iapManager attachObserver];
6
7 }
2
3 void InitIAPManager(){
4 iapManager = [[IAPManager alloc] init];
5 [iapManager attachObserver];
6
7 }
InitIAPManager函数初始化了一个IAPManager类,同时调用了IAPManager的attachObserver函数,添加了一个监听事件。这个推荐在游戏开始的时候就调用,教程里面有说可以处理之前未完成的消息。
IsProductAvailable 很简单不说了。
C#语言:
高亮代码由发芽网提供
1
void RequstProductInfo(
void *p){
2 NSString *list = [NSString stringWithUTF8String:p];
3 NSLog(@"productKey:%@",list);
4 [iapManager requestProductData:list];
5 }
2 NSString *list = [NSString stringWithUTF8String:p];
3 NSLog(@"productKey:%@",list);
4 [iapManager requestProductData:list];
5 }
RequestProductInfo 这里涉及到把 u 的string字符串转成xcode常用的NSString字符串。 U的脚本需要是UTF8格式如果你直接把商品的Key写在里面。
我设计的格式是用"\t"制表符分割每个key,使用方法:
1
RequstProductInfo
(
"com.dollar.one\tcom.dollar.two"
);
这边com.dllar.one 和com.dollar.two是我在itunesconnect里设置的两个商品的key,需要改成你们自己的key,用\t分割每个key。
当苹果返回商品信息时,IPAManager会呼叫Unity场景中物体名为“Main”的身上的脚本的
void ShowProductList(string s) 函数,并返回一个商品信息,商品信息参数用\t分割。如果你输入了多个key,就会收到多条ShowProductList信息。实测3g连app延迟大概在1秒~3秒左右。如果你的key错了会在xcode的调试的那个地方报出来而不会收到ShowProduct回调。
C#语言:
高亮代码由发芽网提供
1
void BuyProduct(
void *p){
2 [iapManager buyRequest:[NSString stringWithUTF8String:p]];
3 }
2 [iapManager buyRequest:[NSString stringWithUTF8String:p]];
3 }
BuyProduct函数用来购买一个商品,需要传入一个商品的key,然后IPAManager会呼叫Unity场景中物体名为“Main”的身上的脚本的 void ProvideContent(string s) 函数, 并返回苹果给的商品匿名回执。这个回执很多教程里都没说,其实要什么base64 重新code一下才能用,我已经写到IPAManager里面处理好了。这个回执需要你自己去跟苹果的服务器确认是否是真实的,防止越狱玩家用 IAP free之类的插件作弊。
回执处理流程看这里:
Verify an App Store Transaction Receipt 【苹果服务端验证一个应用程序商店交易收据有效性】 以及
iPhone In App Purchase购买完成时验证transactionReceipt。错误信息一样是打印在xcode的调试台里了。
还有就是注意如果你用的是测试账号,需要去
sandbox.itunes.apple.com/verifyReceipt验证,而不是去
buy.itunes.apple.com/verifyReceipt 验证。如果你提交app审核,苹果也是用的测试账号,这样就需要你自己去判断回执是不是测试账号。如何判断看这里:
IOS 内支付那点事
推荐用自己的服务器发送。 如果用unity的话有可能被破解。
Unity发送验证
C#语言:
高亮代码由发芽网提供
1
string json = "{\"receipt-data\":\"+YourReceiptCodeBase64+\"}";
2 WWWForm wwwForm = new WWWForm();
3 wwwForm.AddField("receipt",json);
4 WWW www = new WWW("https://sandbox.itunes.apple.com/verifyReceipt", wwwForm);
2 WWWForm wwwForm = new WWWForm();
3 wwwForm.AddField("receipt",json);
4 WWW www = new WWW("https://sandbox.itunes.apple.com/verifyReceipt", wwwForm);
一旦你确定回执是正确的,就可以把商品提供给玩家了。
整个购买流程测试大概要2~15秒都有可能。另外就是跟苹果连的时候一开始经常会连不上,各种错误返回之类的,估计是连美国服务器不稳定,不过过一会就好了。一旦玩家点了一个商品,最好做个处理界面不要让玩家重复点击,不然经常返回这个商品已购买但是未提供之类的错误。等待个15秒如果苹果没有响应再弹个连接失败之类的。
有什么不清楚的地方大家可以给我留言,我会持续更新。