参考:http://blog.sina.com.cn/s/blog_4a2183a60101lc8a.html
http://blog.csdn.net/shenjie12345678/article/details/40978977
http://blog.csdn.net/xiaominghimi/article/details/6937097
http://blog.csdn.net/shenjie12345678/article/details/41120637
Unity的assets下新建Plugins/IOS 添加TestAlertView.h TestAlertView.m IAPInterface.h IAPInterface.m IAPManager.h IAPManager.m文件
购买确认弹出框:
#import <UIKit/UIKit.h>
static NSString *productId = nil;
@interface TestAlertView : UIViewController<UIAlertViewDelegate>
-(void)setProductId:(NSString *)proId;
-(NSString*)getProductId;
@end
//
// TestAlertView.m
// Unity-iPhone
//
// Created by macmini3 on 16/1/27.
//
//
#import "TestAlertView.h"
//#import "TestSingleton.h"
#import "IAPInterface.h"
@interface TestAlertView ()
@end
@implementation TestAlertView
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)setProductId:(NSString *)id
{
productId = id;
NSLog(@">>>>>>>>>>ID %@",productId);
}
-(NSString *)getProductId
{
return productId;
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
//判断点击的是哪一个按钮事件
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
switch (buttonIndex) {
case 1:
NSLog(@">>确认购买");
IAPInterface *test = [IAPInterface alloc];
[test Confirm];
[test release];
break;
case 0:
NSLog(@">>取消");
IAPInterface *test1 = [IAPInterface alloc];
[test1 Cancel];
[test1 release];
break;
default:
break;
}
}
@end
购买接口:
//
// UJSInterface.h
// Unity-iPhone
//
// Created by MacMini on 14-5-15.
//
//
#import <Foundation/Foundation.h>
@interface IAPInterface : NSObject
{
IAPInterface *mySelf;
}
-(void)Confirm;
-(void)Cancel;
@end
//
// UJSInterface.m
// Unity-iPhone
//
// Created by MacMini on 14-5-15.
//
//
#import "IAPInterface.h"
#import "IAPManager.h"
#import "TestAlertView.h"
//#import "TestSingleton.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){
UnitySendMessage("Main", "PopBuyingMask", "");
NSString *list = [NSString stringWithUTF8String:p];
NSLog(@"productKey:%@",list);
[iapManager requestProductData:list];
}
-(void)Confirm
{
TestAlertView *productId = [TestAlertView alloc];
NSLog(@"============购买 %@",[productId getProductId]);
// NSString *name = [NSString stringWithFormat:@"com.test.TestIAP_20"];
NSString *name = [NSString alloc];
name = [productId getProductId];
[productId release];
[iapManager buyRequest:name];
}
-(void)Cancel
{
//通知Unity用户取消了购买支付
NSLog(@"============取消");
UnitySendMessage("Main", "PayFailure", "");
}
//调用IOS的弹出框不需要从Unity发送购买产品消息
void BuyProduct(void *p){
[iapManager buyRequest:[NSString stringWithUTF8String:p]];
}
@end
购买管理:
//
// IAPManager.h
// Unity-iPhone
//
// Created by MacMini on 14-5-16.
//
//
#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
//
// IAPManager.m
// Unity-iPhone
//
// Created by MacMini on 14-5-16.
//
//
#import "IAPManager.h"
#import "TestAlertView.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];
}
TestAlertView *mySelf = nil;
NSArray *products;
-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
products = response.products;
[products retain];
for (SKProduct *p in products) {
//在此由Store kit返回当前要购买的产品的详细信息,通过TestAlertView警告框弹出来,显示确认或者取消
//1、当点击确认的时候,在TestAlertView中调用IAPInterface中的confirm方法,然后调用buyProduct方法。
//2、当点击取消时,在TestAlertView中调用IAPInterface中的cancel方法,不做任何处理。
mySelf = [TestAlertView alloc];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:[p localizedTitle]
message:[p localizedDescription]
delegate:mySelf
cancelButtonTitle:@"取消"
otherButtonTitles:@"确定", nil];
[alert show];
[alert release];
[mySelf setProductId:[p productIdentifier]];
}
for(NSString *invalidProductId in response.invalidProductIdentifiers){
NSLog(@"Invalid product id:%@",invalidProductId);
}
[request autorelease];
}
-(void)buyRequest:(NSString *)productIdentifier{
NSLog(@"发送购买产品请求!");
for (SKProduct *p in products) {
SKPayment *payment = [SKPayment paymentWithProduct:p];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}
[products release];
}
-(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];
}
-(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];
}
//给Unity发送成功的交易订单
-(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);
//交易失败取消Unity中的购买遮罩
UnitySendMessage("Main", "HideBuyingMask", "");
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脚本:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
public class ClickBtn : MonoBehaviour {
//遮罩动画
public GameObject mask;
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);
// BuyProduct("com.test.TestIAP_20");
}
/// <summary>
/// 获取商品回执,将商品回执传送给服务器,服务器和App Store验证之后,向客户端推送道具或者钻石
/// </summary>
void ProvideContent(string s){
Debug.Log ("[MsgFrom ios]proivideContent : "+s);
Debug.Log (">>>>>>>>>>>>>>>>>>>>>>>>>支付成功,向服务器请求发货!!!");
//可以在获得app Store返回交易号时,不隐藏购买遮罩,直到服务器和app Store确认之后再取消遮罩
HideBuyingMask ();
}
void Start () {
mask.SetActive (false);
InitIAPManager();
}
/// <summary>
/// 支付失败后,隐藏遮罩
/// </summary>
void PayFailure(){
HideBuyingMask ();
Debug.Log (">>>>>>>>>>>>>>>>>>>>>>>>支付失败!!!");
}
/// <summary>
/// 在购买过程中显示遮罩,防止玩家再次点击购买按钮
/// </summary>
void PopBuyingMask(){
mask.SetActive (true);
Debug.Log (">>>>>>>>>>>>>>>>>>>>>>>>>弹出购买遮罩!!!!");
}
/// <summary>
/// 购买成功后 或者 支付失败时隐藏购买遮罩
/// </summary>
void HideBuyingMask(){
mask.SetActive (false);
Debug.Log (">>>>>>>>>>>>>>>>隐藏购买遮罩!!!!");
}
/// <summary>
/// 点击购买按钮时,通过调用Store kit框架给app Store发送购买消息
/// </summary>
public void OnClick(){
Debug.Log (">>>>>>click>>>>>>");
if (IsProductAvailable ()) {
productInfo = new List<string> ();
RequstProductInfo ("com.test.TestIAP_20");
} else {
Debug.Log (">>>>>>>>>>>>>>>>>>>>>>>>>余额不足,不能支付!!!");
}
}
}