Unity调用iOS原生内购

Unity在5.x以后的版本,都附带了各种平台的IAP(内购),网上一搜Unity IAP,就一大堆如何如何接入的教程,据说还挺方便的。本人也是用Unity 5.x,也曾经用了一下Unity的IAP,那为何现在还要讨论调用iOS原生的IAP呢?

在这里不得不吐槽一下Unity的IAP,虽然它目的是更加方便的让游戏接入支付,但接入过程,感觉也不是那么的顺利的。可能本人水平问题,接入这东西整整花费了一周时间(服务器+客户端)。首先文档挺简略的,另外,就是网上教程都是单机向,没涉及服务器验证。

还有的是,IAP是集成到Service上的,也就是说,用Unity IAP就得开Service,就得实时联网,倘若断网什么的,就会报一大堆的错误!即使是导入了package的。。。当然对于电信的同学来说,应该不存在这问题,本人也是在电信环境下,工作的很好的。但最近换了移动网络,一直连不上Service,我不得不一些宏把调用IAP的代码屏蔽掉。。。

说到导入package,我简直无力吐槽,它就不会给你分一下平台,各种平台的东西都导进来,我本来只想接iOS的,结果包里面包含了啥安卓,Tizen,小米,乱七八糟。。。

还有的是,如果协同工作,一起工作的小伙伴,还必须加入项目的组织,这对于独立开发者来说,挺不方便的。

鉴于以上种种槽点,我把Unity IAP怒删了。。。重新接入iOS原生的IAP。可能是因为只有老版本的Unity,才需要用原生的。文章也挺少的了。只有以下两篇文章:

https://www.cnblogs.com/weiqiangwaideshijie/p/9103407.html

https://blog.csdn.net/dingxiaowei2013/article/details/52988354

上面两篇文章写的两位大兄弟,其实代码差不多了,我也抄了大部分。实际调试过程中,发现不少问题,首先代码有点不简洁,另外就是支付回执处理有问题。这里把我的贴出来分享一下。(代码是通的,Unity部分涉及到许多游戏逻辑,就不贴了。)

IAPUnity.m

#import "IAPManager.h"

#import <Foundation/Foundation.h>

#if defined(__cplusplus)

extern "C" {

#endif

// 判定商品是否有效

bool IsProductAvailable(){

return [[IAPManager shareInstance] CanMakePayment];

}

// 请求获得商品信息

void RequestProductInfo(char* p){

NSString* list = [NSString stringWithUTF8String:p];

[[IAPManager shareInstance] requestProductData:list];

}

// 购买商品

void BuyProduct(char* p){

[[IAPManager shareInstance] buyRequest:[NSString stringWithUTF8String:p]];

}

// 处理一些未完成支付

void HandlePaymentQueue(){

[[IAPManager shareInstance] handlePaymentQueue];

}

#if defined(__cplusplus)

}

#endif

这里面的函数,主要是供Unity调用的。购买商品调BuyProduct就可以了。注意的是,调BuyProduct之前最好调一下 HandlePaymentQueue,用来关闭一些未完成订单,以免购买相同的商品的时候,苹果弹出说商品已购买,需要恢复之类的提示。RequestProductInfo 其实这个是用来做验证用的了,调不调也行。

IAPManager.h

#import <Foundation/Foundation.h>

#import <StoreKit/StoreKit.h>

@interface IAPManager : NSObject<SKProductsRequestDelegate, SKPaymentTransactionObserver>{

SKProduct *proUpgradeProduct;

SKProductsRequest *productsRequest;

}

+(id)shareInstance;

-(void)attachObserver;

-(BOOL)CanMakePayment;

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

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

-(void)handlePaymentQueue;

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

@end

这个只是一个头文件。

IAPManager.m

#import "IAPManager.h"

static IAPManager* instance = nil;

@implementation IAPManager

+(id)shareInstance{

if (instance == nil){

instance = [[[self class] alloc] init];

[instance attachObserver];

}

return instance;

}

// 处理一些未完成的支付

-(void)handlePaymentQueue{

NSArray* transactions = [SKPaymentQueue defaultQueue].transactions;

if (transactions.count > 0) {

// NSLog(@"transactions.count = %lu", (unsigned long)transactions.count);

for(SKPaymentTransaction* transaction in transactions){

if (transaction.transactionState == SKPaymentTransactionStatePurchased){

[[SKPaymentQueue defaultQueue] finishTransaction:transaction];

}

}

}

}

-(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("xxx", "AddProduct", [[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:@","];

}

// 处理支付队列

-(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;

}

}

}

// 支付动作转字符串

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

NSArray* info = [NSArray arrayWithObjects:transaction.payment.productIdentifier,

transaction.transactionIdentifier,

[transaction.transactionReceipt base64Encoding],

nil];

return [info componentsJoinedByString:@","];

}

// 支付完成回调

-(void) completeTransaction:(SKPaymentTransaction*)transaction{

NSLog(@"Complete transaction: transactionIdentifier = %@\n", transaction.transactionIdentifier);

[[SKPaymentQueue defaultQueue] finishTransaction:transaction];

// 直接调用Unity

UnitySendMessage("xxxx",

"OnSucess",

[[self transactionInfo:transaction] UTF8String]);

}

// 支付失败回调

-(void) failedTransaction:(SKPaymentTransaction*)transaction{

NSLog(@"Failed transaction: %@", transaction.transactionIdentifier);

if (transaction.error.code != SKErrorPaymentCancelled) {

NSLog(@"!Cancelled");

}

[[SKPaymentQueue defaultQueue] finishTransaction:transaction];

UnitySendMessage("xxxx", "OnFailed", "");

}

-(void) restoreTransaction:(SKPaymentTransaction*) transaction{

NSLog(@"Restore transaction: %@", transaction.transactionIdentifier);

[[SKPaymentQueue defaultQueue] finishTransaction:transaction];

}

@end

这里面主要注册一些Unity的回调函数。xxx是对应Unity里面绑定支付代码的某个GameObject的名字。

这个里面

猜你喜欢

转载自blog.csdn.net/gtd138/article/details/81327905