您的位置:首页 > 移动开发

iOS-OC-内购In-App Purchases

2016-07-07 09:33 375 查看


公司项目要做会员功能,支付方式我采用的是内购In-App Purchases。说实话,我真的不想用苹果的内购功能,不说苹果要收百分之三十的手续费,就说它那么多的坑,我是真的不想往里面跳啊,但公司担心用支付宝、微信支付等方式苹果不让上架,做个开关的话又怕突然下架、甚至封掉开发者帐号。所以,这个坑我就只有跳了, 俗话说:我不入地狱,谁入地狱???!!!

话不多说,开始!

itunes connect里面的就不说了,我只说程序里面的代码部分。

首先要导入StoreKit.framework。引用 #import

{
BOOL      startBuyAppleProduct;
}


添加监听,这个最好写在- (void)viewDidLoad { }中。

[[SKPaymentQueue defaultQueue] addTransactionObserver:self];


当点某一个按钮的时候先去检测用户是否打开手机内购功能,如果打开了就执行requestProductData:方法请求商品数据,否则提示用户。ProductID是在itunes connect中设置的产品ID。

- (void)performPayFunctionOnIos
{
if([SKPaymentQueue canMakePayments]){
[self requestProductData:ProductID];
}else{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:@"您的手机没有打开内购功能" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil];
[alert addAction:cancel];
[self presentViewController:alert animated:YES completion:nil];
}
}


添加产品ID,设置代理并发起请求。请求是从的苹果的服务器请求产品的数据.

- (void)requestProductData:(NSString*)productString{
startBuyAppleProduct = YES; //这里把它设为YES,表明是你发起的请求。
NSArray*product = [[NSArray alloc] initWithObjects:productString,nil];
NSSet*nsset = [NSSet setWithArray:product];
SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:nsset];
request.delegate=self;
[request start];
}


添加代理方法

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSArray*product = response.products;
if([product count] ==0){
NSLog(@"没有商品");
return;
}
SKProduct *p = nil;
for (SKProduct *pro in product) {
if ([pro.productIdentifier isEqualToString:ProductID]) {
p = pro;
}
}
SKPayment *payment = [SKPayment paymentWithProduct:p];
[[SKPaymentQueue defaultQueue] addPayment:payment];
}

- (void)request:(SKRequest*)request didFailWithError:(NSError*)error {
NSLog(@"商品信息请求错误:%@", error);
}

- (void)requestDidFinish:(SKRequest*)request {
NSLog(@"请求结束");
}


添加监听方法

- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transaction {
for(SKPaymentTransaction *tran in transaction){

switch(tran.transactionState) {

case SKPaymentTransactionStatePurchased:
// 这里要用最开始就定义的BOOL值startBuyAppleProduct来判断下是否是你本次发起的内购,
不是就跳过验证。
不知道为什么每次进这个控制器,它就会走这个监听方法,不在其它的case里判断是因为其它的并没有做什么逻辑处理。
if (startBuyAppleProduct) {
[self verifyFinishedTransaction:tran];
}
[self restoreTransaction:tran];
NSLog(@"交易完成");
break;

case SKPaymentTransactionStatePurchasing:
NSLog(@"商品添加进列表");
break;

case SKPaymentTransactionStateRestored:
NSLog(@"已经购买过商品");
[self restoreTransaction:tran];
break;

case SKPaymentTransactionStateFailed:
NSLog(@"交易失败");
[self restoreTransaction:tran];
break;

default:
NSLog(@"other");
[self restoreTransaction:tran];
break;
}
}
}


- (void)restoreTransaction:(SKPaymentTransaction *)transaction {
//  取消订单,或者说是恢复订单
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
// 每次都要把startBuyAppleProduct设置为NO,不然购买成功就不会验证
startBuyAppleProduct = NO;
}


// 验证
- (void)verifyFinishedTransaction:(SKPaymentTransaction *)transaction {
if (transaction.transactionState == SKPaymentTransactionStatePurchased) {
NSString * productIdentifier = transaction.payment.productIdentifier;
NSLog(@"%@",transaction.transactionIdentifier);
NSString *receipt = [[NSData dataWithContentsOfURL:[[NSBundle mainBundle] appStoreReceiptURL] ] base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithCarriageReturn];
if ([productIdentifier length] > 0) {
// 向自己的服务器验证购买凭证,用post的方式把receipt传给服务器就可以了。

}
}
}


因为苹果审核的时候是用的测试服务器, 但我们又不知道它的审核什么时间通过,所以最好先验证苹果的测试服务器,如果返回的是21007,再向正式的服务器发起验证。

测试服务器验证链接

https://sandbox.itunes.apple.com/verifyReceipt

正式服务器验证链接

https://buy.itunes.apple.com/verifyReceipt

验证返回的数据其中status为0,也就是”status”:0时就是验证成功了。这个要记住!记住!记住!并不是非零即真!这里零才是真!!!

7. 最后就是移除监听。

-(void)dealloc{
[[SKPaymentQueue defaultQueue]  removeTransactionObserver:self];
}


看嘛,这就弄完了, 应该没有什么问题,我们就假如没有问题。������

希望能给各位一点帮助。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  苹果 支付 iOS 内购 iap