Unityios平台IAP内购和沙箱测试流程详解(开发中遇到的坑)
Posted 天生爱赞美
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unityios平台IAP内购和沙箱测试流程详解(开发中遇到的坑)相关的知识,希望对你有一定的参考价值。
Unity ios内购
内购流程
- 1、在 AppStore 中创建相应的物品,创建内购沙盒测试账号
- 2、客户端从后台获取相应的物品 ID (当然也可以再客户端写死,但后期扩展性就受限制了)
- 3、依据相应的物品 ID 请求商品的相关信息
- 4、依据商品信息创建订单请求交易
- 5、依据返回的订单状态处理交易结果
- 6、请求后台再次验证订单状态
- 7、依据后台返回结果处理相关逻辑
2、创建内购物品以及沙盒测试账号
思路:
Unity调用iOS内购代码实现
效果图:
重要提示:
测试一定要用沙盒账号,否则无效!
流程
这里就不重复写了,直接上截图
OC代码:
IAPInterface(主要是实现Unity跟OC的IAP代码的一个交互作用,等于是一个中间桥梁)
#import <Foundation/Foundation.h>
@interface IAPInterface : NSObject
@end
#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 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]];
@end
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
IAPManager(真真的iOS的购买功能)
#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
#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];
-(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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
Unity中调用的C#代码
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")]
内购(IAP)详解
ios IAP 内购验证
IOS内购(IAP)的那些事
苹果内购和 Apple Pay
Apple开发如何在设备中切换IAP(内购)沙盒测试账户?
Apple开发如何在设备中切换IAP(内购)沙盒测试账户?